*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*
- * Copyright 2000 The FreeRADIUS server project
+ * Copyright 2003 The FreeRADIUS server project
* Copyright 2000 Alan DeKok <aland@ox.org>
* Copyright 2000 Alan Curry <pacman@world.std.com>
*/
static const char rcsid[] = "$Id$";
-#include "autoconf.h"
-#include "libradius.h"
+#include <freeradius-devel/autoconf.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "radiusd.h"
-#include "modpriv.h"
-#include "modules.h"
-#include "modcall.h"
-#include "conffile.h"
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modpriv.h>
+#include <freeradius-devel/modules.h>
+#include <freeradius-devel/modcall.h>
+#include <freeradius-devel/conffile.h>
#include "ltdl.h"
-#include "rad_assert.h"
-
-/*
- * Internal list of all of the modules we have loaded.
- */
-static module_list_t *module_list = NULL;
-
-/*
- * Internal list of each module instance.
- */
-static module_instance_t *module_instance_list = NULL;
+#include <freeradius-devel/rad_assert.h>
typedef struct indexed_modcallable {
struct indexed_modcallable *next;
*/
static indexed_modcallable *components[RLM_COMPONENT_COUNT];
+static rbtree_t *module_tree = NULL;
+
+typedef struct section_type_value_t {
+ const char *section;
+ const char *typename;
+ int attr;
+} section_type_value_t;
+
+
/*
- * The component names.
- *
- * Hmm... we probably should be getting these from the configuration
- * file, too.
+ * Ordered by component
*/
-const char *component_names[RLM_COMPONENT_COUNT] =
-{
- "authenticate",
- "authorize",
- "preacct",
- "accounting",
- "session",
- "pre-proxy",
- "post-proxy",
- "post-auth"
+static const section_type_value_t section_type_value[RLM_COMPONENT_COUNT] = {
+ { "authenticate", "Auth-Type", PW_AUTH_TYPE },
+ { "authorize", "Autz-Type", PW_AUTZ_TYPE },
+ { "preacct", "Pre-Acct-Type", PW_PRE_ACCT_TYPE },
+ { "accounting", "Acct-Type", PW_ACCT_TYPE },
+ { "session", "Session-Type", PW_SESSION_TYPE },
+ { "pre-proxy", "Pre-Proxy-Type", PW_PRE_PROXY_TYPE },
+ { "post-proxy", "Post-Proxy-Type", PW_POST_PROXY_TYPE },
+ { "post-auth", "Post-Auth-Type", PW_POST_AUTH_TYPE },
};
-static const char *subcomponent_names[RLM_COMPONENT_COUNT] =
-{
- "authtype",
- "autztype",
- "preacctype",
- "acctype",
- "sesstype",
- "pre-proxytype",
- "post-proxytype",
- "post-authtype"
+/*
+ * Delete ASAP.
+ */
+static const section_type_value_t old_section_type_value[] = {
+ { "authenticate", "authtype", PW_AUTH_TYPE },
+ { "authorize", "autztype", PW_AUTZ_TYPE },
+ { "preacct", "Pre-Acct-Type", PW_PRE_ACCT_TYPE },/* unused */
+ { "accounting", "acctype", PW_ACCT_TYPE },
+ { "session", "sesstype", PW_SESSION_TYPE },
+ { "pre-proxy", "Pre-Proxy-Type", PW_PRE_PROXY_TYPE }, /* unused */
+ { "post-proxy", "Post-Proxy-Type", PW_POST_PROXY_TYPE }, /* unused */
+ { "post-auth", "post-authtype", PW_POST_AUTH_TYPE }
};
+
static void indexed_modcallable_free(indexed_modcallable **cf)
{
indexed_modcallable *c, *next;
*cf = NULL;
}
-static void instance_list_free(module_instance_t **i)
+/*
+ * Free a module instance.
+ */
+static void module_instance_free(void *data)
{
- module_instance_t *c, *next;
+ module_instance_t *this = data;
- c = *i;
- while (c) {
- next = c->next;
- if(c->entry->module->detach)
- (c->entry->module->detach)(c->insthandle);
-#if HAVE_PTHREAD_H
- if (c->mutex) {
- /*
- * FIXME
- * The mutex MIGHT be locked...
- * we'll check for that later, I guess.
- */
- pthread_mutex_destroy(c->mutex);
- free(c->mutex);
- }
-#endif
- free(c);
- c = next;
+ if (this->entry->module->detach)
+ (this->entry->module->detach)(this->insthandle);
+#ifdef HAVE_PTHREAD_H
+ if (this->mutex) {
+ /*
+ * FIXME
+ * The mutex MIGHT be locked...
+ * we'll check for that later, I guess.
+ */
+ pthread_mutex_destroy(this->mutex);
+ free(this->mutex);
}
- *i = NULL;
+#endif
+ free(this);
+}
+
+
+/*
+ * Compare two module entries
+ */
+static int module_entry_cmp(const void *one, const void *two)
+{
+ const module_entry_t *a = one;
+ const module_entry_t *b = two;
+
+ return strcmp(a->name, b->name);
}
/*
- * Remove all of the modules.
+ * Free a module entry.
+ */
+static void module_entry_free(void *data)
+{
+ module_entry_t *this = data;
+
+ lt_dlclose(this->handle); /* ignore any errors */
+ free(this);
+}
+
+
+/*
+ * Remove the module lists.
*/
int detach_modules(void)
{
- module_list_t *ml, *next;
int i;
/*
indexed_modcallable_free(&components[i]);
}
- instance_list_free(&module_instance_list);
-
- ml = module_list;
- while (ml) {
- next = ml->next;
- if (ml->module->destroy)
- (ml->module->destroy)();
- lt_dlclose(ml->handle); /* ignore any errors */
- free(ml);
- ml = next;
- }
-
- module_list = NULL;
-
return 0;
}
/*
* Find a module on disk or in memory, and link to it.
*/
-static module_list_t *linkto_module(const char *module_name,
- const char *cffilename, int cflineno)
+static module_entry_t *linkto_module(const char *module_name,
+ const char *cffilename, int cflineno)
{
- module_list_t *node;
+ module_entry_t myentry;
+ module_entry_t *node;
lt_dlhandle handle;
char module_struct[256];
char *p;
+ const void *module;
- /*
- * Look through the global module library list for the
- * named module.
- */
- for (node = module_list; node != NULL; node = node->next) {
- /*
- * Found the named module. Return it.
- */
- if (strcmp(node->name, module_name) == 0)
- return node;
-
- }
+ strNcpy(myentry.name, module_name, sizeof(myentry.name));
+ node = rbtree_finddata(module_tree, &myentry);
+ if (node) return node;
/*
* Keep the handle around so we can dlclose() it.
handle = lt_dlopenext(module_name);
if (handle == NULL) {
radlog(L_ERR|L_CONS, "%s[%d] Failed to link to module '%s':"
- " %s\n", cffilename, cflineno, module_name, lt_dlerror());
+ " %s\n", cffilename, cflineno, module_name, lt_dlerror());
return NULL;
}
- /* make room for the module type */
- node = (module_list_t *) rad_malloc(sizeof(module_list_t));
-
- /* fill in the module structure */
- node->next = NULL;
- node->handle = handle;
- strNcpy(node->name, module_name, sizeof(node->name));
-
/*
* Link to the module's rlm_FOO{} module structure.
+ *
+ * The module_name variable has the version number
+ * embedded in it, and we don't want that here.
*/
- /* module_name has the version embedded; strip it. */
strcpy(module_struct, module_name);
p = strrchr(module_struct, '-');
- if (p)
- *p = '\0';
- node->module = (module_t *) lt_dlsym(node->handle, module_struct);
- if (!node->module) {
+ if (p) *p = '\0';
+
+ DEBUG3(" (Loaded %s, checking if it's valid)", module_name);
+
+ /*
+ * libltld MAY core here, if the handle it gives us contains
+ * garbage data.
+ */
+ module = lt_dlsym(handle, module_struct);
+ if (!module) {
radlog(L_ERR|L_CONS, "%s[%d] Failed linking to "
"%s structure in %s: %s\n",
cffilename, cflineno,
module_name, cffilename, lt_dlerror());
- lt_dlclose(node->handle); /* ignore any errors */
- free(node);
+ lt_dlclose(handle);
return NULL;
}
-
- /* call the modules initialization */
- if (node->module->init && (node->module->init)() < 0) {
- radlog(L_ERR|L_CONS, "%s[%d] Module initialization failed.\n",
- cffilename, cflineno);
- lt_dlclose(node->handle); /* ignore any errors */
- free(node);
+ /*
+ * Before doing anything else, check if it's sane.
+ */
+ if ((*(const uint32_t *) module) != RLM_MODULE_MAGIC_NUMBER) {
+ lt_dlclose(handle);
+ radlog(L_ERR|L_CONS, "%s[%d] Invalid version in module '%s'",
+ cffilename, cflineno, module_name);
return NULL;
+
}
+ /* make room for the module type */
+ node = rad_malloc(sizeof(*node));
+ memset(node, 0, sizeof(*node));
+ strNcpy(node->name, module_name, sizeof(node->name));
+ node->module = module;
+ node->handle = handle;
+
DEBUG("Module: Loaded %s ", node->module->name);
- node->next = module_list;
- module_list = node;
+ /*
+ * Add the module as "rlm_foo-version" to the configuration
+ * section.
+ */
+ if (!rbtree_insert(module_tree, node)) {
+ radlog(L_ERR, "Failed to cache module %s", module_name);
+ lt_dlclose(handle);
+ free(node);
+ return NULL;
+ }
return node;
}
/*
* Find a module instance.
*/
-module_instance_t *find_module_instance(const char *instname)
+module_instance_t *find_module_instance(CONF_SECTION *modules,
+ const char *instname)
{
- CONF_SECTION *cs, *inst_cs;
+ CONF_SECTION *cs;
const char *name1, *name2;
- module_instance_t *node, **last;
+ module_instance_t *node;
char module_name[256];
- /*
- * Look through the global module instance list for the
- * named module.
- */
- last = &module_instance_list;
- for (node = module_instance_list; node != NULL; node = node->next) {
- /*
- * Found the named instance. Return it.
- */
- if (strcmp(node->name, instname) == 0)
- return node;
-
- /*
- * Keep a pointer to the last entry to update...
- */
- last = &node->next;
- }
-
- /*
- * Instance doesn't exist yet. Try to find the
- * corresponding configuration section and create it.
- */
-
- /*
- * Look for the 'modules' configuration section.
- */
- cs = cf_section_find("modules");
- if (cs == NULL) {
- radlog(L_ERR|L_CONS, "ERROR: Cannot find a 'modules' section in the configuration file.\n");
- return NULL;
- }
+ if (!modules) return NULL;
/*
* Module instances are declared in the modules{} block
* name2 from the config section, or name1 if there was
* no name2.
*/
- name1 = name2 = NULL;
- for(inst_cs=cf_subsection_find_next(cs, NULL, NULL);
- inst_cs != NULL;
- inst_cs=cf_subsection_find_next(cs, inst_cs, NULL)) {
- name1 = cf_section_name1(inst_cs);
- name2 = cf_section_name2(inst_cs);
- if ( (name2 && !strcmp(name2, instname)) ||
- (!name2 && !strcmp(name1, instname)) )
- break;
- }
- if (inst_cs == NULL) {
+ cs = cf_section_sub_find_name2(modules, NULL, instname);
+ if (cs == NULL) {
radlog(L_ERR|L_CONS, "ERROR: Cannot find a configuration entry for module \"%s\".\n", instname);
return NULL;
}
/*
- * Found the configuration entry.
+ * If there's already a module instance, return it.
*/
- node = rad_malloc(sizeof(*node));
- node->next = NULL;
- node->insthandle = NULL;
-
+ node = cf_data_find(cs, "instance");
+ if (node) return node;
+
+ name1 = cf_section_name1(cs);
+ name2 = cf_section_name2(cs);
+
/*
- * Link to the module by name: rlm_FOO-major.minor
+ * Found the configuration entry.
*/
- if (strncmp(name1, "rlm_", 4)) {
-#if 0
- snprintf(module_name, sizeof(module_name), "rlm_%s-%d.%d",
- name1, RADIUSD_MAJOR_VERSION, RADIUSD_MINOR_VERSION);
-#else
- snprintf(module_name, sizeof(module_name), "rlm_%s",
- name1);
-#endif
- } else {
- strNcpy(module_name, name1, sizeof(module_name));
+ node = rad_malloc(sizeof(*node));
+ memset(node, 0, sizeof(*node));
- }
+ node->insthandle = NULL;
/*
- * FIXME: "radiusd.conf" is wrong here; must find cf filename
+ * Names in the "modules" section aren't prefixed
+ * with "rlm_", so we add it here.
*/
- node->entry = linkto_module(module_name, "radiusd.conf",
- cf_section_lineno(inst_cs));
+ snprintf(module_name, sizeof(module_name), "rlm_%s", name1);
+
+ node->entry = linkto_module(module_name,
+ mainconfig.radiusd_conf,
+ cf_section_lineno(cs));
if (!node->entry) {
free(node);
/* linkto_module logs any errors */
return NULL;
}
-
+
/*
* Call the module's instantiation routine.
*/
if ((node->entry->module->instantiate) &&
- ((node->entry->module->instantiate)(inst_cs,
- &node->insthandle) < 0)) {
+ ((node->entry->module->instantiate)(cs, &node->insthandle) < 0)) {
radlog(L_ERR|L_CONS,
- "radiusd.conf[%d]: %s: Module instantiation failed.\n",
- cf_section_lineno(inst_cs), instname);
+ "%s[%d]: %s: Module instantiation failed.\n",
+ mainconfig.radiusd_conf, cf_section_lineno(cs),
+ instname);
free(node);
return NULL;
}
*/
strNcpy(node->name, instname, sizeof(node->name));
-#if HAVE_PTHREAD_H
+#ifdef HAVE_PTHREAD_H
/*
* If we're threaded, check if the module is thread-safe.
*
node->mutex = NULL;
}
-#endif
- *last = node;
+#endif
+ cf_data_add(cs, "instance", node, module_instance_free);
DEBUG("Module: Instantiated %s (%s) ", name1, node->name);
-
+
return node;
}
return NULL;
}
+/*
+ * Create a new sublist.
+ */
static indexed_modcallable *new_sublist(int comp, int idx)
{
indexed_modcallable **head = &components[comp];
/* It is an error to try to create a sublist that already
* exists. It would almost certainly be caused by accidental
* duplication in the config file.
- *
+ *
* index 0 is the exception, because it is used when we want
* to collect _all_ listed modules under a single index by
* default, which is currently the case in all components
this = lookup_by_index(components[comp], idx);
if (!this) {
+ if (idx != 0) DEBUG2(" ERROR: Unknown value specified for %s. Cannot perform requested action.",
+ section_type_value[comp].typename);
/* Return a default value appropriate for the component */
switch(comp) {
case RLM_COMPONENT_AUTZ: return RLM_MODULE_NOTFOUND;
default: return RLM_MODULE_FAIL;
}
}
+
+ DEBUG2(" Processing the %s section of %s",
+ section_type_value[comp].section, mainconfig.radiusd_conf);
return modcall(comp, this->modulelist, request);
}
-/* Load a flat module list, as found inside an authtype{} block */
-static void load_subcomponent_section(CONF_SECTION *cs, int comp, const char *filename)
+/*
+ * Load a sub-module list, as found inside an Auth-Type foo {}
+ * block
+ */
+static int load_subcomponent_section(CONF_SECTION *cs, int comp,
+ const char *filename)
{
- int idx;
indexed_modcallable *subcomp;
modcallable *ml;
DICT_VALUE *dval;
+ const char *name2 = cf_section_name2(cs);
- static int meaningless_counter = 1;
+ rad_assert(comp >= RLM_COMPONENT_AUTH);
+ rad_assert(comp <= RLM_COMPONENT_COUNT);
- ml = compile_modgroup(comp, cs, filename);
-
- /* We must assign a numeric index to this subcomponent. For
- * auth, it is generated and placed in the dictionary by
- * new_sectiontype_value(). The others are just numbers that are pulled
- * out of thin air, and the names are neither put into the dictionary
- * nor checked for uniqueness, but all that could be fixed in a few
- * minutes, if anyone finds a real use for indexed config of
- * components other than auth. */
- dval = NULL;
- if (comp==RLM_COMPONENT_AUTH) {
- dval = dict_valbyname(PW_AUTHTYPE, cf_section_name2(cs));
- } else if (comp == RLM_COMPONENT_AUTZ) {
- dval = dict_valbyname(PW_AUTZTYPE, cf_section_name2(cs));
- } else if (comp == RLM_COMPONENT_ACCT) {
- dval = dict_valbyname(PW_ACCTTYPE, cf_section_name2(cs));
- } else if (comp == RLM_COMPONENT_SESS) {
- dval = dict_valbyname(PW_SESSTYPE, cf_section_name2(cs));
- } else if (comp == RLM_COMPONENT_POST_AUTH) {
- dval = dict_valbyname(PW_POSTAUTHTYPE, cf_section_name2(cs));
+ /*
+ * Sanity check.
+ */
+ if (!name2) {
+ radlog(L_ERR|L_CONS,
+ "%s[%d]: No name specified for %s block",
+ filename, cf_section_lineno(cs),
+ section_type_value[comp].typename);
+ return 1;
}
- if (dval) {
- idx = dval->value;
- } else {
- idx = meaningless_counter++;
+ /*
+ * Compile the group.
+ */
+ ml = compile_modgroup(comp, cs, filename);
+ if (!ml) {
+ return 0;
+ }
+
+ /*
+ * We must assign a numeric index to this subcomponent.
+ * It is generated and placed in the dictionary by
+ * setup_modules(), when it loads the sections. If it
+ * isn't found, it's a serious error.
+ */
+ dval = dict_valbyname(section_type_value[comp].attr, name2);
+ if (!dval) {
+ radlog(L_ERR|L_CONS,
+ "%s[%d] %s %s Not previously configured",
+ filename, cf_section_lineno(cs),
+ section_type_value[comp].typename, name2);
+ modcallable_free(&ml);
+ return 0;
}
- subcomp = new_sublist(comp, idx);
+ subcomp = new_sublist(comp, dval->value);
if (!subcomp) {
radlog(L_ERR|L_CONS,
- "%s[%d] %s %s already configured - skipping",
- filename, cf_section_lineno(cs),
- subcomponent_names[comp], cf_section_name2(cs));
+ "%s[%d] %s %s already configured - skipping",
+ filename, cf_section_lineno(cs),
+ section_type_value[comp].typename, name2);
modcallable_free(&ml);
- return;
+ return 1;
}
subcomp->modulelist = ml;
+ return 1; /* OK */
}
-static void load_component_section(CONF_SECTION *cs, int comp, const char *filename)
+static int load_component_section(CONF_SECTION *cs, int comp,
+ const char *filename)
{
modcallable *this;
CONF_ITEM *modref;
- int modreflineno;
int idx;
indexed_modcallable *subcomp;
const char *modname;
- char *visiblename;
-
- for (modref=cf_item_find_next(cs, NULL);
- modref != NULL;
- modref=cf_item_find_next(cs, modref)) {
+ const char *visiblename;
+ /*
+ * Loop over the entries in the named section.
+ */
+ for (modref = cf_item_find_next(cs, NULL);
+ modref != NULL;
+ modref = cf_item_find_next(cs, modref)) {
+ /*
+ * Look for Auth-Type foo {}, which are special
+ * cases of named sections, and allowable ONLY
+ * at the top-level.
+ *
+ * i.e. They're not allowed in a "group" or "redundant"
+ * subsection.
+ */
if (cf_item_is_section(modref)) {
+ const char *sec_name;
CONF_SECTION *scs;
scs = cf_itemtosection(modref);
- if (strcmp(cf_section_name1(scs),
- subcomponent_names[comp]) == 0) {
- load_subcomponent_section(scs, comp, filename);
+ sec_name = cf_section_name1(scs);
+
+ if (strcmp(sec_name,
+ section_type_value[comp].typename) == 0) {
+ if (!load_subcomponent_section(scs, comp,
+ filename)) {
+ return -1; /* FIXME: memleak? */
+ }
continue;
}
- modreflineno = cf_section_lineno(scs);
+ /*
+ * Allow old names, too.
+ */
+ if (strcmp(sec_name,
+ old_section_type_value[comp].typename) == 0) {
+ if (!load_subcomponent_section(scs, comp,
+ filename)) {
+ return -1; /* FIXME: memleak? */
+ }
+ continue;
+ }
} else {
CONF_PAIR *cp;
cp = cf_itemtopair(modref);
- modreflineno = cf_pair_lineno(cp);
}
+ /*
+ * Try to compile one entry.
+ */
this = compile_modsingle(comp, modref, filename, &modname);
+ if (!this) {
+ radlog(L_ERR|L_CONS,
+ "%s[%d] Failed to parse %s section.\n",
+ filename, cf_section_lineno(cs),
+ cf_section_name1(cs));
+ return -1;
+ }
if (comp == RLM_COMPONENT_AUTH) {
DICT_VALUE *dval;
- dval = dict_valbyname(PW_AUTHTYPE, modname);
- rad_assert(dval != NULL);
+ dval = dict_valbyname(PW_AUTH_TYPE, modname);
+ if (!dval) {
+ /*
+ * It's a section, but nothing we
+ * recognize. Die!
+ */
+ radlog(L_ERR|L_CONS, "%s[%d] Unknown Auth-Type \"%s\" in %s section.",
+ filename, cf_section_lineno(cs),
+ modname, section_type_value[comp].section);
+ return -1;
+ }
idx = dval->value;
} else {
/* See the comment in new_sublist() for explanation
subcomp = new_sublist(comp, idx);
if (subcomp == NULL) {
- radlog(L_ERR|L_CONS,
+ radlog(L_INFO|L_CONS,
"%s %s %s already configured - skipping",
- filename, subcomponent_names[comp],
+ filename, section_type_value[comp].typename,
modname);
modcallable_free(&this);
continue;
if (visiblename == NULL)
visiblename = cf_section_name1(cs);
add_to_modcallable(&subcomp->modulelist, this,
- comp, visiblename);
+ comp, visiblename);
}
-}
-typedef struct section_type_value_t {
- const char *section;
- const char *typename;
- int attr;
-} section_type_value_t;
+ return 0;
+}
-static const section_type_value_t section_type_value[] = {
- { "authorize", "autztype", PW_AUTZTYPE },
- { "authenticate", "authtype", PW_AUTHTYPE },
- { "accounting", "accttype", PW_ACCTTYPE },
- { "session", "sesstype", PW_SESSTYPE },
- { "post-auth", "post-authtype", PW_POSTAUTHTYPE },
- { NULL, NULL, 0 }
-};
/*
* Parse the module config sections, and load
* Libtool makes your life a LOT easier, especially with libltdl.
* see: http://www.gnu.org/software/libtool/
*/
-int setup_modules(void)
+int setup_modules(int reload)
{
- int comp;
- CONF_SECTION *cs;
-
- /*
- * FIXME: This should be pulled from somewhere else.
- */
- const char *filename="radiusd.conf";
+ int comp;
+ CONF_SECTION *cs, *modules;
+ int do_component[RLM_COMPONENT_COUNT];
+ rad_listen_t *listener;
/*
- * No current list of modules: Go initialize libltdl.
+ * If necessary, initialize libltdl.
*/
- if (!module_list) {
+ if (!reload) {
/*
* Set the default list of preloaded symbols.
* This is used to initialize libltdl's list of
- * preloaded modules.
+ * preloaded modules.
*
* i.e. Static modules.
*/
if (lt_dlinit() != 0) {
radlog(L_ERR|L_CONS, "Failed to initialize libraries: %s\n",
lt_dlerror());
- exit(1); /* FIXME */
-
+ return -1;
}
/*
* any location on the disk.
*/
lt_dlsetsearchpath(radlib_dir);
-
+
DEBUG2("Module: Library search path is %s",
lt_dlgetsearchpath());
components[comp] = NULL;
}
+ /*
+ * Set up the internal module struct.
+ */
+ module_tree = rbtree_create(module_entry_cmp,
+ module_entry_free, 0);
+ if (!module_tree) {
+ radlog(L_ERR|L_CONS, "Failed to initialize modules\n");
+ return -1;
+ }
+
+
} else {
detach_modules();
}
/*
+ * Figure out which sections to load.
+ */
+ memset(do_component, 0, sizeof(do_component));
+ for (listener = mainconfig.listen;
+ listener != NULL;
+ listener = listener->next) {
+ switch (listener->type) {
+ case RAD_LISTEN_AUTH:
+ do_component[RLM_COMPONENT_AUTZ] = 1;
+ do_component[RLM_COMPONENT_AUTH] = 1;
+ do_component[RLM_COMPONENT_POST_AUTH] = 1;
+ do_component[RLM_COMPONENT_SESS] = 1;
+ break;
+
+ case RAD_LISTEN_DETAIL: /* just like acct */
+ case RAD_LISTEN_ACCT:
+ do_component[RLM_COMPONENT_PREACCT] = 1;
+ do_component[RLM_COMPONENT_ACCT] = 1;
+ break;
+
+ case RAD_LISTEN_PROXY:
+ do_component[RLM_COMPONENT_PRE_PROXY] = 1;
+ do_component[RLM_COMPONENT_POST_PROXY] = 1;
+ break;
+
+ default:
+ rad_assert(0 == 1);
+ break;
+ }
+ }
+
+ for (comp = RLM_COMPONENT_AUTH; comp < RLM_COMPONENT_COUNT; comp++) {
+ /*
+ * Have the debugging messages all in one place.
+ */
+ if (!do_component[comp]) {
+ DEBUG2("modules: Not loading %s{} section",
+ section_type_value[comp].section);
+ }
+ }
+
+ /*
* Create any DICT_VALUE's for the types. See
* 'doc/configurable_failover' for examples of 'authtype'
* used to create new Auth-Type values. In order to
* let the user create new names, we've got to look for
* those names, and create DICT_VALUE's for them.
*/
- for (comp = 0; section_type_value[comp].section != NULL; comp++) {
+ for (comp = RLM_COMPONENT_AUTH; comp < RLM_COMPONENT_COUNT; comp++) {
+ int value;
const char *name2;
DICT_ATTR *dattr;
DICT_VALUE *dval;
- CONF_SECTION *sub;
+ CONF_SECTION *sub, *next;
+ CONF_PAIR *cp;
/*
- * Big-time YUCK
+ * Not needed, don't load it.
*/
- static int my_value = 32767;
-
+ if (!do_component[comp]) {
+ continue;
+ }
cs = cf_section_find(section_type_value[comp].section);
+
if (!cs) continue;
sub = NULL;
* See if there's a sub-section by that
* name.
*/
- sub = cf_subsection_find_next(cs, sub,
- section_type_value[comp].typename);
- if (!sub) continue;
+ next = cf_subsection_find_next(cs, sub,
+ section_type_value[comp].typename);
+
+ /*
+ * Allow some old names, too.
+ */
+ if (!next && (comp <= 4)) {
+ next = cf_subsection_find_next(cs, sub,
+ old_section_type_value[comp].typename);
+ }
+ sub = next;
/*
* If so, look for it to define a new
name2 = cf_section_name2(sub);
if (!name2) continue;
+
/*
* If the value already exists, don't
* create it again.
* Find the attribute for the value.
*/
dattr = dict_attrbyvalue(section_type_value[comp].attr);
- if (!dattr) continue;
+ if (!dattr) {
+ radlog(L_ERR, "%s[%d]: No such attribute %s",
+ mainconfig.radiusd_conf,
+ cf_section_lineno(sub),
+ section_type_value[comp].typename);
+ continue;
+ }
/*
- * Finally, create the new attribute.
+ * Create a new unique value with a
+ * meaningless number. You can't look at
+ * it from outside of this code, so it
+ * doesn't matter. The only requirement
+ * is that it's unique.
*/
- if (dict_addvalue(name2, dattr->name, my_value++) < 0) {
+ do {
+ value = lrad_rand() & 0x00ffffff;
+ } while (dict_valbyattr(dattr->attr, value));
+
+ if (dict_addvalue(name2, dattr->name, value) < 0) {
radlog(L_ERR, "%s", librad_errstr);
- exit(1);
+ return -1;
}
} while (sub != NULL);
+
+ /*
+ * Loop over the non-sub-sections, too.
+ */
+ cp = NULL;
+ do {
+ /*
+ * See if there's a conf-pair by that
+ * name.
+ */
+ cp = cf_pair_find_next(cs, cp, NULL);
+ if (!cp) break;
+
+
+ /*
+ * If the value already exists, don't
+ * create it again.
+ */
+ name2 = cf_pair_attr(cp);
+ dval = dict_valbyname(section_type_value[comp].attr,
+ name2);
+ if (dval) continue;
+
+ /*
+ * Find the attribute for the value.
+ */
+ dattr = dict_attrbyvalue(section_type_value[comp].attr);
+ if (!dattr) {
+ radlog(L_ERR, "%s[%d]: No such attribute %s",
+ mainconfig.radiusd_conf,
+ cf_section_lineno(sub),
+ section_type_value[comp].typename);
+ continue;
+ }
+
+ /*
+ * Finally, create the new attribute.
+ */
+ do {
+ value = lrad_rand() & 0x00ffffff;
+ } while (dict_valbyattr(dattr->attr, value));
+ if (dict_addvalue(name2, dattr->name, value) < 0) {
+ radlog(L_ERR, "%s", librad_errstr);
+ return -1;
+ }
+ } while (cp != NULL);
} /* over the sections which can have redundent sub-sections */
/*
+ * Remember where the modules were stored.
+ */
+ modules = cf_section_find("modules");
+ if (!modules) {
+ radlog(L_ERR, "Cannot find a \"modules\" section in the configuration file!");
+ return -1;
+ }
+
+ /*
* Look for the 'instantiate' section, which tells us
* the instantiation order of the modules, and also allows
* us to load modules with no authorize/authenticate/etc.
/*
* Loop over the items in the 'instantiate' section.
*/
- for (ci=cf_item_find_next(cs, NULL); ci != NULL; ci=cf_item_find_next(cs, ci)) {
+ for (ci=cf_item_find_next(cs, NULL);
+ ci != NULL;
+ ci=cf_item_find_next(cs, ci)) {
+
+ /*
+ * Skip sections. They'll be handled
+ * later, if they're referenced at all...
+ */
if (cf_item_is_section(ci)) {
- radlog(L_ERR|L_CONS,
- "%s[%d] Subsection for module instantiate is not allowed\n", filename,
-
- cf_section_lineno(cf_itemtosection(ci)));
- exit(1);
+ continue;
}
-
+
cp = cf_itemtopair(ci);
name = cf_pair_attr(cp);
- module = find_module_instance(name);
+ module = find_module_instance(modules, name);
if (!module) {
- exit(1);
+ return -1;
}
} /* loop over items in the subsection */
} /* if there's an 'instantiate' section. */
* configuration section, and loading it.
*/
for (comp = 0; comp < RLM_COMPONENT_COUNT; ++comp) {
- cs = cf_section_find(component_names[comp]);
- if (cs == NULL)
+ cs = cf_section_find(section_type_value[comp].section);
+ if (cs == NULL)
continue;
-
- load_component_section(cs, comp, filename);
+
+ if (!do_component[comp]) {
+ continue;
+ }
+
+ if (load_component_section(cs, comp, mainconfig.radiusd_conf) < 0) {
+ return -1;
+ }
}
return 0;
int module_authorize(int autz_type, REQUEST *request)
{
/*
- * We have a proxied packet, and we've been told
- * to NOT pass proxied packets through 'authorize'
- * a second time. So stop.
+ * Older versions of the server would pass proxy requests
+ * through the 'authorize' sections twice; once when the
+ * packet was received from the NAS, and again after the
+ * reply was received from the home server. Now that we
+ * have a 'post_proxy' section, the replies from the home
+ * server should be sent through that, instead of through
+ * the 'authorize' section again.
*/
- if ((request->proxy != NULL &&
- mainconfig.post_proxy_authorize == FALSE)) {
+ if (request->proxy != NULL) {
DEBUG2(" authorize: Skipping authorize in post-proxy stage");
return RLM_MODULE_NOOP;
}
/*
* Do pre-proxying for ALL configured sessions
*/
-int module_pre_proxy(REQUEST *request)
+int module_pre_proxy(int type, REQUEST *request)
{
- return indexed_modcall(RLM_COMPONENT_PRE_PROXY, 0, request);
+ return indexed_modcall(RLM_COMPONENT_PRE_PROXY, type, request);
}
/*
* Do post-proxying for ALL configured sessions
*/
-int module_post_proxy(REQUEST *request)
+int module_post_proxy(int type, REQUEST *request)
{
- return indexed_modcall(RLM_COMPONENT_POST_PROXY, 0, request);
+ return indexed_modcall(RLM_COMPONENT_POST_PROXY, type, request);
}
/*