static int mod_bootstrap(CONF_SECTION *conf, void *instance)
{
	REDIS_INST *inst = instance;

	INFO("rlm_redis: libhiredis version: %i.%i.%i", HIREDIS_MAJOR, HIREDIS_MINOR, HIREDIS_PATCH);

	inst->xlat_name = cf_section_name2(conf);
	if (!inst->xlat_name) inst->xlat_name = cf_section_name1(conf);

	xlat_register(inst->xlat_name, redis_xlat, NULL, inst);

	return 0;
}
Beispiel #2
0
static int mod_bootstrap(CONF_SECTION *conf, void *instance)
{
	rlm_perl_t	*inst = instance;

	char const	*xlat_name;

	xlat_name = cf_section_name2(conf);
	if (!xlat_name) xlat_name = cf_section_name1(conf);

	xlat_register(xlat_name, perl_xlat, NULL, inst);

	return 0;
}
Beispiel #3
0
static int mod_instantiate(CONF_SECTION *conf, void *instance)
{
	char const *name;
	rlm_soh_t *inst = instance;

	name = cf_section_name2(conf);
	if (!name) name = cf_section_name1(conf);
	inst->xlat_name = name;
	if (!inst->xlat_name) return -1;
	xlat_register(inst->xlat_name, soh_xlat, NULL, inst);

	return 0;
}
Beispiel #4
0
static int mod_bootstrap(void *instance, CONF_SECTION *conf)
{
	rlm_date_t *inst = instance;

	inst->xlat_name = cf_section_name2(conf);
	if (!inst->xlat_name) {
		inst->xlat_name = cf_section_name1(conf);
	}

	xlat_register(inst, inst->xlat_name, xlat_date_convert, NULL, NULL, 0, XLAT_DEFAULT_BUF_LEN, true);

	return 0;
}
Beispiel #5
0
static int mod_bootstrap(void *instance, CONF_SECTION *conf)
{
	char const	*name;
	rlm_soh_t	*inst = instance;

	name = cf_section_name2(conf);
	if (!name) name = cf_section_name1(conf);
	inst->xlat_name = name;
	if (!inst->xlat_name) return -1;

	xlat_register(inst, inst->xlat_name, soh_xlat, NULL, NULL, 0, XLAT_DEFAULT_BUF_LEN, true);

	return 0;
}
Beispiel #6
0
static int mod_instantiate(CONF_SECTION *conf, void *instance)
{
	rlm_idn_t *inst = instance;
	char const *xlat_name;

	xlat_name = cf_section_name2(conf);
	if (!xlat_name) {
		xlat_name = cf_section_name1(conf);
	}

	inst->xlat_name = xlat_name;

	xlat_register(inst->xlat_name, xlat_idna, NULL, inst);

	return 0;
}
static int mod_bootstrap(CONF_SECTION *conf, void *instance)
{
	rlm_cache_t *inst = instance;

	inst->cs = conf;

	inst->xlat_name = cf_section_name2(conf);
	if (!inst->xlat_name) inst->xlat_name = cf_section_name1(conf);

	/*
	 *	Register the cache xlat function
	 */
	xlat_register(inst->xlat_name, cache_xlat, NULL, inst);

	return 0;
}
Beispiel #8
0
static int redis_instantiate(CONF_SECTION *conf, void **instance)
{
    REDIS_INST *inst;
    const char *xlat_name;

    /*
     *	Set up a storage area for instance data
     */
    inst = rad_malloc(sizeof (REDIS_INST));
    if (!inst) {
        return -1;
    }
    memset(inst, 0, sizeof (*inst));

    /*
     *	If the configuration parameters can't be parsed, then
     *	fail.
     */
    if (cf_section_parse(conf, inst, module_config) < 0) {
        free(inst);
        return -1;
    }

    xlat_name = cf_section_name2(conf);

    if (!xlat_name)
        xlat_name = cf_section_name1(conf);

    inst->xlat_name = strdup(xlat_name);
    xlat_register(inst->xlat_name, (RAD_XLAT_FUNC)redis_xlat, inst);

    inst->pool = fr_connection_pool_init(conf, inst,
                                         redis_create_conn, NULL,
                                         redis_delete_conn);
    if (!inst->pool) {
        redis_detach(inst);
        return -1;
    }

    inst->redis_query = rlm_redis_query;
    inst->redis_finish_query = rlm_redis_finish_query;
    inst->redis_escape_func = redis_escape_func;

    *instance = inst;

    return 0;
}
/*
 *	Do any per-module initialization that is separate to each
 *	configured instance of the module.  e.g. set up connections
 *	to external databases, read configuration files, set up
 *	dictionary entries, etc.
 *
 *	If configuration information is given in the config section
 *	that must be referenced in later calls, store a handle to it
 *	in *instance otherwise put a null pointer there.
 */
static int mod_bootstrap(void *instance, UNUSED CONF_SECTION *conf)
{
	xlat_register(instance, "attr_by_num", xlat_dict_attr_by_num, NULL, NULL, 0, 0, true);
	xlat_register(instance, "attr_by_oid", xlat_dict_attr_by_oid, NULL, NULL, 0, 0, true);
	xlat_register(instance, "vendor", xlat_vendor, NULL, NULL, 0, 0, true);
	xlat_register(instance, "vendor_num", xlat_vendor_num, NULL, NULL, 0, 0, true);
	xlat_register(instance, "attr", xlat_attr, NULL, NULL, 0, 0, true);
	xlat_register(instance, "attr_num", xlat_attr_num, NULL, NULL, 0, 0, true);

	return 0;
}
Beispiel #10
0
/*
 *	Create instance for our module. Allocate space for
 *	instance structure and read configuration parameters
 */
static int mschap_instantiate(CONF_SECTION *conf, void **instance)
{
	rlm_mschap_t *inst;

	inst = *instance = rad_malloc(sizeof(*inst));
	if (!inst) {
		return -1;
	}
	memset(inst, 0, sizeof(*inst));

	if (cf_section_parse(conf, inst, module_config) < 0) {
		free(inst);
		return -1;
	}

	/*
	 *	This module used to support SMB Password files, but it
	 *	made it too complicated.  If the user tries to
	 *	configure an SMB Password file, then die, with an
	 *	error message.
	 */
	if (inst->passwd_file) {
		radlog(L_ERR, "rlm_mschap: SMB password file is no longer supported in this module.  Use rlm_passwd module instead");
		mschap_detach(inst);
		return -1;
	}

	/*
	 *	Create the dynamic translation.
	 */
	inst->xlat_name = cf_section_name2(conf);
	if (!inst->xlat_name) inst->xlat_name = cf_section_name1(conf);
	inst->xlat_name = strdup(inst->xlat_name);
	xlat_register(inst->xlat_name, mschap_xlat, inst);

	/*
	 *	For backwards compatibility
	 */
	if (!dict_valbyname(PW_AUTH_TYPE, inst->xlat_name)) {
		inst->auth_type = "MS-CHAP";
	} else {
		inst->auth_type = inst->xlat_name;
	}

	return 0;
}
Beispiel #11
0
/*
 *	Do any per-module initialization that is separate to each
 *	configured instance of the module.  e.g. set up connections
 *	to external databases, read configuration files, set up
 *	dictionary entries, etc.
 *
 *	If configuration information is given in the config section
 *	that must be referenced in later calls, store a handle to it
 *	in *instance otherwise put a null pointer there.
 */
static int mod_instantiate(CONF_SECTION *conf, void *instance)
{
	rlm_rest_t *inst = instance;
	char const *xlat_name;

	xlat_name = cf_section_name2(conf);
	if (!xlat_name) {
		xlat_name = cf_section_name1(conf);
	}

	inst->xlat_name = xlat_name;

	/*
	 *	Register the rest xlat function
	 */
	xlat_register(inst->xlat_name, rest_xlat, rest_uri_escape, inst);

	/*
	 *	Parse sub-section configs.
	 */
	if (
		(parse_sub_section(conf, &inst->authorize, RLM_COMPONENT_AUTZ) < 0) ||
		(parse_sub_section(conf, &inst->authenticate, RLM_COMPONENT_AUTH) < 0) ||
		(parse_sub_section(conf, &inst->accounting, RLM_COMPONENT_ACCT) < 0) ||

/* @todo add behaviour for checksimul */
/*		(parse_sub_section(conf, &inst->checksimul, RLM_COMPONENT_SESS) < 0) || */
		(parse_sub_section(conf, &inst->post_auth, RLM_COMPONENT_POST_AUTH) < 0))
	{
		return -1;
	}

	/*
	 *	Initialise REST libraries.
	 */
	if (rest_init(inst) < 0) {
		return -1;
	}

	inst->conn_pool = fr_connection_pool_module_init(conf, inst, mod_conn_create, mod_conn_alive, NULL);
	if (!inst->conn_pool) {
		return -1;
	}

	return 0;
}
Beispiel #12
0
static int soh_instantiate(CONF_SECTION *conf, void **instance)
{
	const char *name;
	rlm_soh_t *inst;

	*instance = inst = talloc_zero(conf, rlm_soh_t);
	if (!inst) return -1;

	if (cf_section_parse(conf, inst, module_config) < 0) {
		return -1;
	}

	name = cf_section_name2(conf);
	if (!name) name = cf_section_name1(conf);
	inst->xlat_name = name;
	if (!inst->xlat_name) return -1;
	xlat_register(inst->xlat_name, soh_xlat, inst);

	return 0;
}
static int mod_instantiate(CONF_SECTION *conf, void *instance)
{
	REDIS_INST *inst = instance;

	inst->xlat_name = cf_section_name2(conf);

	if (!inst->xlat_name)
		inst->xlat_name = cf_section_name1(conf);

	xlat_register(inst->xlat_name, redis_xlat, NULL, inst); /* FIXME! */

	inst->pool = fr_connection_pool_init(conf, inst, mod_conn_create, NULL, mod_conn_delete, NULL);
	if (!inst->pool) {
		return -1;
	}

	inst->redis_query = rlm_redis_query;
	inst->redis_finish_query = rlm_redis_finish_query;

	return 0;
}
Beispiel #14
0
static int redis_instantiate(CONF_SECTION *conf, void **instance)
{
	REDIS_INST *inst;
	const char *xlat_name;

	/*
	 *	Set up a storage area for instance data
	 */
	*instance = inst = talloc_zero(conf, REDIS_INST);
	if (!inst) return -1;

	/*
	 *	If the configuration parameters can't be parsed, then
	 *	fail.
	 */
	if (cf_section_parse(conf, inst, module_config) < 0) {
		return -1;
	}

	xlat_name = cf_section_name2(conf);

	if (!xlat_name)
		xlat_name = cf_section_name1(conf);

	xlat_register(inst->xlat_name, redis_xlat, inst);

	inst->pool = fr_connection_pool_init(conf, inst,
					     redis_create_conn, NULL,
					     redis_delete_conn);
	if (!inst->pool) {
		return -1;
	}

	inst->redis_query = rlm_redis_query;
	inst->redis_finish_query = rlm_redis_finish_query;
	inst->redis_escape_func = redis_escape_func;

	return 0;
}
Beispiel #15
0
static int rlm_sql_instantiate(CONF_SECTION * conf, void **instance)
{
	SQL_INST *inst;
	char *xlat_name;

	inst = rad_malloc(sizeof(SQL_INST));
	memset(inst, 0, sizeof(SQL_INST));

	inst->config = rad_malloc(sizeof(SQL_CONFIG));
	memset(inst->config, 0, sizeof(SQL_CONFIG));

	/*
	 * If the configuration parameters can't be parsed, then
	 * fail.
	 */
	if (cf_section_parse(conf, inst->config, module_config) < 0) {
		rlm_sql_detach(inst);
		return -1;
	}

	xlat_name = cf_section_name2(conf);
	if (xlat_name == NULL)
		xlat_name = cf_section_name1(conf);
	if (xlat_name){
		inst->config->xlat_name = strdup(xlat_name);
		xlat_register(xlat_name, sql_xlat, inst);
	}

	if (inst->config->num_sql_socks > MAX_SQL_SOCKS) {
		radlog(L_ERR | L_CONS, "rlm_sql (%s): sql_instantiate: number of sqlsockets cannot exceed MAX_SQL_SOCKS, %d",
		       inst->config->xlat_name, MAX_SQL_SOCKS);
		rlm_sql_detach(inst);
		return -1;
	}

	/*
	 *	Sanity check for crazy people.
	 */
	if (strncmp(inst->config->sql_driver, "rlm_sql_", 8) != 0) {
		radlog(L_ERR, "rlm_sql (%s): \"%s\" is NOT an SQL driver!",
		       inst->config->xlat_name, inst->config->sql_driver);
		rlm_sql_detach(inst);
		return -1;
	}

	inst->handle = lt_dlopenext(inst->config->sql_driver);
	if (inst->handle == NULL) {
		radlog(L_ERR, "rlm_sql (%s): Could not link driver %s: %s",
		       inst->config->xlat_name, inst->config->sql_driver,
		       lt_dlerror());
		radlog(L_ERR, "rlm_sql (%s): Make sure it (and all its dependent libraries!) are in the search path of your system's ld.",
		       inst->config->xlat_name);
		rlm_sql_detach(inst);
		return -1;
	}

	inst->module = (rlm_sql_module_t *) lt_dlsym(inst->handle, inst->config->sql_driver);
	if (!inst->module) {
		radlog(L_ERR, "rlm_sql (%s): Could not link symbol %s: %s",
		       inst->config->xlat_name, inst->config->sql_driver,
		       lt_dlerror());
		rlm_sql_detach(inst);
		return -1;
	}

	radlog(L_INFO, "rlm_sql (%s): Driver %s (module %s) loaded and linked",
	       inst->config->xlat_name, inst->config->sql_driver,
	       inst->module->name);
	radlog(L_INFO, "rlm_sql (%s): Attempting to connect to %s@%s:%s/%s",
	       inst->config->xlat_name, inst->config->sql_login,
	       inst->config->sql_server, inst->config->sql_port,
	       inst->config->sql_db);

	if (sql_init_socketpool(inst) < 0) {
		rlm_sql_detach(inst);
		return -1;
	}
	paircompare_register(PW_SQL_GROUP, PW_USER_NAME, sql_groupcmp, inst);

	if (inst->config->do_clients){
		if (generate_sql_clients(inst) == -1){
			radlog(L_ERR, "rlm_sql (%s): generate_sql_clients() returned error",inst->config->xlat_name);
			rlm_sql_detach(inst);
			return -1;
		}
	}
	allowed_chars = inst->config->allowed_chars;

	*instance = inst;

	return RLM_MODULE_OK;
}
Beispiel #16
0
/** Instantiate the module
 *
 * Creates a new instance of the module reading parameters from a configuration section.
 *
 * @param conf to parse.
 * @param instance Where to write pointer to configuration data.
 * @return 0 on success < 0 on failure.
 */
static int mod_instantiate(CONF_SECTION *conf, void *instance)
{
	CONF_SECTION *options;
	ldap_instance_t *inst = instance;

	inst->cs = conf;

	options = cf_section_sub_find(conf, "options");
	if (!options || !cf_pair_find(options, "chase_referrals")) {
		inst->chase_referrals_unset = true;	 /* use OpenLDAP defaults */
	}

	inst->xlat_name = cf_section_name2(conf);
	if (!inst->xlat_name) {
		inst->xlat_name = cf_section_name1(conf);
	}

	/*
	 *	If the configuration parameters can't be parsed, then fail.
	 */
	if ((parse_sub_section(inst, conf, &inst->accounting, RLM_COMPONENT_ACCT) < 0) ||
	    (parse_sub_section(inst, conf, &inst->postauth, RLM_COMPONENT_POST_AUTH) < 0)) {
		LDAP_ERR("Failed parsing configuration");

		goto error;
	}

	/*
	 *	Sanity checks for cacheable groups code.
	 */
	if (inst->cacheable_group_name && inst->groupobj_membership_filter) {
		if (!inst->groupobj_name_attr) {
			LDAP_ERR("Directive 'group.name_attribute' must be set if cacheable group names are enabled");

			goto error;
		}
	}

	/*
	 *	Check for URLs.  If they're used and the library doesn't support them, then complain.
	 */
	inst->is_url = 0;
	if (ldap_is_ldap_url(inst->server)) {
#ifdef HAVE_LDAP_INITIALIZE
		inst->is_url = 1;
		inst->port = 0;
#else
		LDAP_ERR("Directive 'server' is in URL form but ldap_initialize() is not available");
		goto error;
#endif
	}

	/*
	 *	Workaround for servers which support LDAPS but not START TLS
	 */
	if (inst->port == LDAPS_PORT || inst->tls_mode) {
		inst->tls_mode = LDAP_OPT_X_TLS_HARD;
	} else {
		inst->tls_mode = 0;
	}

#if LDAP_SET_REBIND_PROC_ARGS != 3
	/*
	 *	The 2-argument rebind doesn't take an instance variable.  Our rebind function needs the instance
	 *	variable for the username, password, etc.
	 */
	if (inst->rebind == true) {
		LDAP_ERR("Cannot use 'rebind' directive as this version of libldap does not support the API "
			 "that we need");

		goto error;
	}
#endif

	/*
	 *	Convert scope strings to enumerated constants
	 */
	inst->userobj_scope = fr_str2int(ldap_scope, inst->userobj_scope_str, -1);
	if (inst->userobj_scope < 0) {
		LDAP_ERR("Invalid 'user.scope' value \"%s\", expected 'sub', 'one', 'base' or 'children'",
			 inst->userobj_scope_str);
		goto error;
	}

	inst->groupobj_scope = fr_str2int(ldap_scope, inst->groupobj_scope_str, -1);
	if (inst->groupobj_scope < 0) {
		LDAP_ERR("Invalid 'group.scope' value \"%s\", expected 'sub', 'one', 'base' or 'children'",
			 inst->groupobj_scope_str);
		goto error;
	}

	inst->clientobj_scope = fr_str2int(ldap_scope, inst->clientobj_scope_str, -1);
	if (inst->clientobj_scope < 0) {
		LDAP_ERR("Invalid 'client.scope' value \"%s\", expected 'sub', 'one', 'base' or 'children'",
			 inst->clientobj_scope_str);
		goto error;
	}

	if (inst->tls_require_cert_str) {
#ifdef LDAP_OPT_X_TLS_NEVER
		/*
		 *	Convert cert strictness to enumerated constants
		 */
		inst->tls_require_cert = fr_str2int(ldap_tls_require_cert, inst->tls_require_cert_str, -1);
		if (inst->tls_require_cert < 0) {
			LDAP_ERR("Invalid 'tls.require_cert' value \"%s\", expected 'never', 'demand', 'allow', "
				 "'try' or 'hard'", inst->tls_require_cert_str);
			goto error;
		}
#else
		LDAP_ERR("Modifying 'tls.require_cert' is not supported by current version of libldap. "
			 "Please upgrade libldap and rebuild this module");

		goto error;
#endif
	}
	/*
	 *	Build the attribute map
	 */
	if (rlm_ldap_map_verify(inst, &(inst->user_map)) < 0) {
		goto error;
	}

	/*
	 *	Group comparison checks.
	 */
	if (cf_section_name2(conf)) {
		ATTR_FLAGS flags;
		char buffer[256];

		snprintf(buffer, sizeof(buffer), "%s-Ldap-Group",
			 inst->xlat_name);
		memset(&flags, 0, sizeof(flags));

		if (dict_addattr(buffer, -1, 0, PW_TYPE_STRING, flags) < 0) {
			LDAP_ERR("Error creating group attribute: %s", fr_strerror());

			return -1;
		}
		inst->group_da = dict_attrbyname(buffer);
		if (!inst->group_da) {
			LDAP_ERR("Failed creating attribute %s", buffer);

			goto error;
		}

		paircompare_register(inst->group_da, dict_attrbyvalue(PW_USER_NAME, 0), false, rlm_ldap_groupcmp, inst);
	/*
	 *	Were the default instance
	 */
	} else {
		inst->group_da = dict_attrbyvalue(PW_LDAP_GROUP, 0);
		paircompare_register(dict_attrbyvalue(PW_LDAP_GROUP, 0), dict_attrbyvalue(PW_USER_NAME, 0),
				false, rlm_ldap_groupcmp, inst);
	}

	xlat_register(inst->xlat_name, ldap_xlat, rlm_ldap_escape_func, inst);

	/*
	 *	Setup the cache attribute
	 */
	if (inst->cache_attribute) {
		ATTR_FLAGS flags;
		memset(&flags, 0, sizeof(flags));

		if (dict_addattr(inst->cache_attribute, -1, 0, PW_TYPE_STRING, flags) < 0) {
			LDAP_ERR("Error creating cache attribute: %s", fr_strerror());

			return -1;
		}
		inst->cache_da = dict_attrbyname(inst->cache_attribute);
	} else {
		inst->cache_da = inst->group_da;	/* Default to the group_da */
	}

	/*
	 *	Initialize the socket pool.
	 */
	inst->pool = fr_connection_pool_init(inst->cs, inst, mod_conn_create, NULL, mod_conn_delete, NULL);
	if (!inst->pool) {
		return -1;
	}

	/*
	 *	Bulk load dynamic clients.
	 */
	if (inst->do_clients) {
		if (rlm_ldap_load_clients(inst) < 0) {
			LDAP_ERR("Error loading clients");

			return -1;
		}
	}

	return 0;

error:
	return -1;
}
Beispiel #17
0
/** Register an xlat function.
 *
 * @param[in] name xlat name.
 * @param[in] func xlat function to be called.
 * @param[in] escape function to sanitize any sub expansions passed to the xlat function.
 * @param[in] instance of module that's registering the xlat function.
 * @return 0 on success, -1 on failure
 */
int xlat_register(char const *name, RAD_XLAT_FUNC func, RADIUS_ESCAPE_STRING escape, void *instance)
{
	xlat_t	*c;
	xlat_t	my_xlat;
	rbnode_t *node;

	if (!name || !*name) {
		DEBUG("xlat_register: Invalid xlat name");
		return -1;
	}

	/*
	 *	First time around, build up the tree...
	 *
	 *	FIXME: This code should be hoisted out of this function,
	 *	and into a global "initialization".  But it isn't critical...
	 */
	if (!xlat_root) {
#ifdef WITH_UNLANG
		int i;
#endif

		xlat_root = rbtree_create(xlat_cmp, NULL, 0);
		if (!xlat_root) {
			DEBUG("xlat_register: Failed to create tree");
			return -1;
		}

#ifdef WITH_UNLANG
		for (i = 0; xlat_foreach_names[i] != NULL; i++) {
			xlat_register(xlat_foreach_names[i],
				      xlat_foreach, NULL, &xlat_inst[i]);
			c = xlat_find(xlat_foreach_names[i]);
			rad_assert(c != NULL);
			c->internal = true;
		}
#endif

#define XLAT_REGISTER(_x) xlat_register(STRINGIFY(_x), xlat_ ## _x, NULL, NULL); \
		c = xlat_find(STRINGIFY(_x)); \
		rad_assert(c != NULL); \
		c->internal = true

		XLAT_REGISTER(integer);
		XLAT_REGISTER(strlen);
		XLAT_REGISTER(length);
		XLAT_REGISTER(hex);
		XLAT_REGISTER(string);
		XLAT_REGISTER(xlat);
		XLAT_REGISTER(module);
		XLAT_REGISTER(debug_attr);

		xlat_register("debug", xlat_debug, NULL, &xlat_inst[0]);
		c = xlat_find("debug");
		rad_assert(c != NULL);
		c->internal = true;
	}

	/*
	 *	If it already exists, replace the instance.
	 */
	strlcpy(my_xlat.name, name, sizeof(my_xlat.name));
	my_xlat.length = strlen(my_xlat.name);
	c = rbtree_finddata(xlat_root, &my_xlat);
	if (c) {
		if (c->internal) {
			DEBUG("xlat_register: Cannot re-define internal xlat");
			return -1;
		}

		c->func = func;
		c->escape = escape;
		c->instance = instance;
		return 0;
	}

	/*
	 *	Doesn't exist.  Create it.
	 */
	c = talloc_zero(xlat_root, xlat_t);

	c->func = func;
	c->escape = escape;
	strlcpy(c->name, name, sizeof(c->name));
	c->length = strlen(c->name);
	c->instance = instance;

	node = rbtree_insert_node(xlat_root, c);
	if (!node) {
		talloc_free(c);
		return -1;
	}

	/*
	 *	Ensure that the data is deleted when the node is
	 *	deleted.
	 *
	 *	@todo: Maybe this should be the other way around...
	 *	when a thing IN the tree is deleted, it's automatically
	 *	removed from the tree.  But for now, this works.
	 */
	(void) talloc_steal(node, c);
	return 0;
}
Beispiel #18
0
/*
 *	Do any per-module initialization that is separate to each
 *	configured instance of the module.  e.g. set up connections
 *	to external databases, read configuration files, set up
 *	dictionary entries, etc.
 *
 *	If configuration information is given in the config section
 *	that must be referenced in later calls, store a handle to it
 *	in *instance otherwise put a null pointer there.
 */
static int mod_instantiate(CONF_SECTION *conf, void *instance)
{
	char const *p;
	rlm_exec_t	*inst = instance;

	inst->xlat_name = cf_section_name2(conf);
	if (!inst->xlat_name) {
		inst->xlat_name = cf_section_name1(conf);
		inst->bare = 1;
	}

	xlat_register(inst->xlat_name, exec_xlat, rlm_exec_shell_escape, inst);

	if (inst->input) {
		p = inst->input;
		inst->input_list = radius_list_name(&p, PAIR_LIST_UNKNOWN);
		if ((inst->input_list == PAIR_LIST_UNKNOWN) || (*p != '\0')) {
			cf_log_err_cs(conf, "Invalid input list '%s'", inst->input);
			return -1;
		}
	}

	if (inst->output) {
		p = inst->output;
		inst->output_list = radius_list_name(&p, PAIR_LIST_UNKNOWN);
		if ((inst->output_list == PAIR_LIST_UNKNOWN) || (*p != '\0')) {
			cf_log_err_cs(conf, "Invalid output list '%s'", inst->output);
			return -1;
		}
	}

	/*
	 *	Sanity check the config.  If we're told to NOT wait,
	 *	then the output pairs must not be defined.
	 */
	if (!inst->wait &&
	    (inst->output != NULL)) {
		cf_log_err_cs(conf, "Cannot read output pairs if wait = no");
		return -1;
	}

	/*
	 *	Get the packet type on which to execute
	 */
	if (!inst->packet_type) {
		inst->packet_code = 0;
	} else {
		DICT_VALUE	*dval;

		dval = dict_valbyname(PW_PACKET_TYPE, 0, inst->packet_type);
		if (!dval) {
			cf_log_err_cs(conf, "Unknown packet type %s: See list of VALUEs for Packet-Type in "
				      "share/dictionary", inst->packet_type);
			return -1;
		}
		inst->packet_code = dval->value;
	}

	/*
	 *	Get the time to wait before killing the child
	 */
	if (!inst->timeout) {
		inst->timeout = EXEC_TIMEOUT;
	}
	if (inst->timeout < 1) {
		cf_log_err_cs(conf, "Timeout '%d' is too small (minimum: 1)", inst->timeout);
		return -1;
	}
	/*
	 *	Blocking a request longer than 30 seconds isn't going to help anyone.
	 */
	if (inst->timeout > 30) {
		cf_log_err_cs(conf, "Timeout '%d' is too large (maximum: 30)", inst->timeout);
		return -1;
	}

	return 0;
}
/*
 *	Register the xlats
 */
static int mod_instantiate(UNUSED CONF_SECTION *conf, void *instance)
{
	xlat_register("unpack", unpack_xlat, NULL, instance);

	return 0;
}
/*
 *	Instantiate the module.
 */
static int mod_instantiate(CONF_SECTION *conf, void *instance)
{
	rlm_cache_t *inst = instance;

	inst->cs = conf;

	inst->xlat_name = cf_section_name2(conf);
	if (!inst->xlat_name) {
		inst->xlat_name = cf_section_name1(conf);
	}

	/*
	 *	Register the cache xlat function
	 */
	xlat_register(inst->xlat_name, cache_xlat, NULL, inst);

	/*
	 *	Sanity check for crazy people.
	 */
	if (strncmp(inst->driver_name, "rlm_cache_", 8) != 0) {
		ERROR("%s: \"%s\" is NOT an Cache driver!", inst->xlat_name, inst->driver_name);
		return -1;
	}

	/*
	 *	Load the appropriate driver for our database
	 */
	inst->handle = lt_dlopenext(inst->driver_name);
	if (!inst->handle) {
		ERROR("Could not link driver %s: %s", inst->driver_name, dlerror());
		ERROR("Make sure it (and all its dependent libraries!) are in the search path of your system's ld");
		return -1;
	}

	inst->module = (cache_module_t *) dlsym(inst->handle, inst->driver_name);
	if (!inst->module) {
		ERROR("Could not link symbol %s: %s", inst->driver_name, dlerror());
		return -1;
	}

	DEBUG3("Driver %s loaded successfully", inst->module->name);

	/*
	 *	Non optional fields and callbacks
	 */
	rad_assert(inst->module->name);
	rad_assert(inst->module->find);
	rad_assert(inst->module->insert);
	rad_assert(inst->module->expire);

	if (inst->module->mod_instantiate) {
		CONF_SECTION *cs;
		char const *name;

		name = strrchr(inst->driver_name, '_');
		if (!name) {
			name = inst->driver_name;
		} else {
			name++;
		}

		cs = cf_section_sub_find(conf, name);
		if (!cs) {
			cs = cf_section_alloc(conf, name, NULL);
			if (!cs) return -1;
		}

		/*
		 *	It's up to the driver to register a destructor (using talloc)
		 *
		 *	Should write its instance data in inst->driver,
		 *	and parent it off of inst.
		 */
		if (inst->module->mod_instantiate(cs, inst) < 0) return -1;
	}

	rad_assert(inst->key && *inst->key);

	if (inst->ttl == 0) {
		cf_log_err_cs(conf, "Must set 'ttl' to non-zero");
		return -1;
	}

	if (inst->epoch != 0) {
		cf_log_err_cs(conf, "Must not set 'epoch' in the configuration files");
		return -1;
	}

	/*
	 *	Make sure the users don't screw up too badly.
	 */
	if (map_afrom_cs(&inst->maps, cf_section_sub_find(inst->cs, "update"),
			 PAIR_LIST_REQUEST, PAIR_LIST_REQUEST, cache_verify, NULL, MAX_ATTRMAP) < 0) {
		return -1;
	}

	if (!inst->maps) {
		cf_log_err_cs(inst->cs, "Cache config must contain an update section, and "
			      "that section must not be empty");

		return -1;
	}
	return 0;
}
Beispiel #21
0
/*
 *	Read config files.
 *
 *	This function can ONLY be called from the main server process.
 */
int read_mainconfig(int reload)
{
	const char *p = NULL;
	CONF_PAIR *cp;
	CONF_SECTION *cs;
	struct stat statbuf;
	cached_config_t *cc;
	char buffer[1024];

	if (reload != 0) {
		radlog(L_ERR, "Reload is not implemented");
		return -1;
	}

	if (stat(radius_dir, &statbuf) < 0) {
		radlog(L_ERR, "Errors reading %s: %s",
		       radius_dir, strerror(errno));
		return -1;
	}

#ifdef S_IWOTH
	if ((statbuf.st_mode & S_IWOTH) != 0) {
		radlog(L_ERR, "Configuration directory %s is globally writable.  Refusing to start due to insecure configuration.",
		       radius_dir);
	  return -1;
	}
#endif

#ifdef S_IROTH
	if (0 && (statbuf.st_mode & S_IROTH) != 0) {
		radlog(L_ERR, "Configuration directory %s is globally readable.  Refusing to start due to insecure configuration.",
		       radius_dir);
		return -1;
	}
#endif

	radlog(L_INFO, "Starting - reading configuration files ...");

	/* Read the configuration file */
	snprintf(buffer, sizeof(buffer), "%.200s/%.50s.conf",
		 radius_dir, mainconfig.name);
	if ((cs = cf_file_read(buffer)) == NULL) {
		radlog(L_ERR, "Errors reading or parsing %s", buffer);
		return -1;
	}

	/*
	 *	If there was no log destination set on the command line,
	 *	set it now.
	 */
	if (mainconfig.radlog_dest == RADLOG_NULL) {
		if (cf_section_parse(cs, NULL, serverdest_config) < 0) {
			fprintf(stderr, "radiusd: Error: Failed to parse log{} section.\n");
			cf_file_free(cs);
			return -1;
		}
		
		if (!radlog_dest) {
			fprintf(stderr, "radiusd: Error: No log destination specified.\n");
			cf_file_free(cs);
			return -1;
		}
		
		mainconfig.radlog_dest = fr_str2int(str2dest, radlog_dest,
						    RADLOG_NUM_DEST);
		if (mainconfig.radlog_dest == RADLOG_NUM_DEST) {
			fprintf(stderr, "radiusd: Error: Unknown log_destination %s\n",
				radlog_dest);
			cf_file_free(cs);
			return -1;
		}
		
		if (mainconfig.radlog_dest == RADLOG_SYSLOG) {
			/*
			 *	Make sure syslog_facility isn't NULL
			 *	before using it
			 */
			if (!syslog_facility) {
				fprintf(stderr, "radiusd: Error: Syslog chosen but no facility was specified\n");
				cf_file_free(cs);
				return -1;
			}
			mainconfig.syslog_facility = fr_str2int(syslog_str2fac, syslog_facility, -1);
			if (mainconfig.syslog_facility < 0) {
				fprintf(stderr, "radiusd: Error: Unknown syslog_facility %s\n",
					syslog_facility);
				cf_file_free(cs);
				return -1;
			}

#ifdef HAVE_SYSLOG_H
			/*
			 *	Call openlog only once, when the
			 *	program starts.
			 */
			openlog(progname, LOG_PID, mainconfig.syslog_facility);
#endif

		} else if (mainconfig.radlog_dest == RADLOG_FILES) {
			if (!mainconfig.log_file) {
				fprintf(stderr, "radiusd: Error: Specified \"files\" as a log destination, but no log filename was given!\n");
				cf_file_free(cs);
				return -1;
			}
		}
	}

#ifdef HAVE_SETUID
	/*
	 *	Switch users as early as possible.
	 */
	if (!switch_users(cs)) exit(1);
#endif

	/*
	 *	Open the log file AFTER switching uid / gid.  If we
	 *	did switch uid/gid, then the code in switch_users()
	 *	took care of setting the file permissions correctly.
	 */
	if ((mainconfig.radlog_dest == RADLOG_FILES) &&
	    (mainconfig.radlog_fd < 0)) {
		mainconfig.radlog_fd = open(mainconfig.log_file,
					    O_WRONLY | O_APPEND | O_CREAT, 0640);
		if (mainconfig.radlog_fd < 0) {
			fprintf(stderr, "radiusd: Failed to open log file %s: %s\n", mainconfig.log_file, strerror(errno));
			cf_file_free(cs);
			return -1;
		}
	}

	/* Initialize the dictionary */
	cp = cf_pair_find(cs, "dictionary");
	if (cp) p = cf_pair_value(cp);
	if (!p) p = radius_dir;
	DEBUG2("including dictionary file %s/%s", p, RADIUS_DICTIONARY);
	if (dict_init(p, RADIUS_DICTIONARY) != 0) {
		radlog(L_ERR, "Errors reading dictionary: %s",
				fr_strerror());
		return -1;
	}

	/*
	 *	This allows us to figure out where, relative to
	 *	radiusd.conf, the other configuration files exist.
	 */
	if (cf_section_parse(cs, NULL, server_config) < 0) {
		return -1;
	}

	/*
	 *	We ignore colourization of output until after the
	 *	configuration files have been parsed.
	 */
	if (do_colourise) {
		p = getenv("TERM");
		if (!p || !isatty(mainconfig.radlog_fd) ||
		    (strstr(p, "xterm") == 0)) {
			mainconfig.colourise = FALSE;
		} else {
			mainconfig.colourise = TRUE;
		}
		p = NULL;
	}
	
	if (mainconfig.max_request_time == 0) mainconfig.max_request_time = 100;
	if (mainconfig.reject_delay > 5) mainconfig.reject_delay = 5;
	if (mainconfig.cleanup_delay > 5) mainconfig.cleanup_delay =5;

	/*
	 *	Free the old configuration items, and replace them
	 *	with the new ones.
	 *
	 *	Note that where possible, we do atomic switch-overs,
	 *	to ensure that the pointers are always valid.
	 */
	rad_assert(mainconfig.config == NULL);
	mainconfig.config = cs;

	DEBUG2("%s: #### Loading Realms and Home Servers ####", mainconfig.name);
	if (!realms_init(cs)) {
		return -1;
	}

	DEBUG2("%s: #### Loading Clients ####", mainconfig.name);
	if (!clients_parse_section(cs)) {
		return -1;
	}

	/*
	 *  Register the %{config:section.subsection} xlat function.
	 */
	xlat_register("config", xlat_config, NULL);
	xlat_register("client", xlat_client, NULL);

	/*
	 *	Starting the server, WITHOUT "-x" on the
	 *	command-line: use whatever is in the config
	 *	file.
	 */
	if (debug_flag == 0) {
		debug_flag = mainconfig.debug_level;
	}
	fr_debug_flag = debug_flag;

	/*
	 *  Go update our behaviour, based on the configuration
	 *  changes.
	 */

	/*
	 *	Sanity check the configuration for internal
	 *	consistency.
	 */
	if (mainconfig.reject_delay > mainconfig.cleanup_delay) {
		mainconfig.reject_delay = mainconfig.cleanup_delay;
	}
	if (mainconfig.reject_delay < 0) mainconfig.reject_delay = 0;

	/*  Reload the modules.  */
	if (setup_modules(reload, mainconfig.config) < 0) {
		return -1;
	}

	if (chroot_dir) {
		if (chdir(radlog_dir) < 0) {
			radlog(L_ERR, "Failed to 'chdir %s' after chroot: %s",
			       radlog_dir, strerror(errno));
			return -1;
		}
	}

	cc = rad_malloc(sizeof(*cc));
	memset(cc, 0, sizeof(*cc));

	cc->cs = cs;
	rad_assert(cs_cache == NULL);
	cs_cache = cc;

	return 0;
}
Beispiel #22
0
/*
 *	Do any per-module initialization that is separate to each
 *	configured instance of the module.  e.g. set up connections
 *	to external databases, read configuration files, set up
 *	dictionary entries, etc.
 *
 *	If configuration information is given in the config section
 *	that must be referenced in later calls, store a handle to it
 *	in *instance otherwise put a null pointer there.
 */
static int exec_instantiate(CONF_SECTION *conf, void **instance)
{
	rlm_exec_t	*inst;
	const char	*xlat_name;

	/*
	 *	Set up a storage area for instance data
	 */

	inst = rad_malloc(sizeof(rlm_exec_t));
	if (!inst)
		return -1;
	memset(inst, 0, sizeof(rlm_exec_t));

	/*
	 *	If the configuration parameters can't be parsed, then
	 *	fail.
	 */
	if (cf_section_parse(conf, inst, module_config) < 0) {
		radlog(L_ERR, "rlm_exec: Failed parsing the configuration");
		exec_detach(inst);
		return -1;
	}

	/*
	 *	No input pairs defined.  Why are we executing a program?
	 */
	if (!inst->input) {
		radlog(L_ERR, "rlm_exec: Must define input pairs for external program.");
		exec_detach(inst);
		return -1;
	}

	/*
	 *	Sanity check the config.  If we're told to NOT wait,
	 *	then the output pairs must not be defined.
	 */
	if (!inst->wait &&
	    (inst->output != NULL)) {
		radlog(L_ERR, "rlm_exec: Cannot read output pairs if wait=no");
		exec_detach(inst);
		return -1;
	}

	/*
	 *	Get the packet type on which to execute
	 */
	if (!inst->packet_type) {
		inst->packet_code = 0;
	} else {
		DICT_VALUE	*dval;

		dval = dict_valbyname(PW_PACKET_TYPE, 0, inst->packet_type);
		if (!dval) {
			radlog(L_ERR, "rlm_exec: Unknown packet type %s: See list of VALUEs for Packet-Type in share/dictionary", inst->packet_type);
			exec_detach(inst);
			return -1;
		}
		inst->packet_code = dval->value;
	}

	xlat_name = cf_section_name2(conf);
	if (xlat_name == NULL) {
		xlat_name = cf_section_name1(conf);
		inst->bare = 1;
	}
	if (xlat_name){
		inst->xlat_name = strdup(xlat_name);
		xlat_register(xlat_name, exec_xlat, inst);
	}

	*instance = inst;

	return 0;
}
Beispiel #23
0
/*
 *	Do any per-module initialization that is separate to each
 *	configured instance of the module.  e.g. set up connections
 *	to external databases, read configuration files, set up
 *	dictionary entries, etc.
 *
 *	If configuration information is given in the config section
 *	that must be referenced in later calls, store a handle to it
 *	in *instance otherwise put a null pointer there.
 *
 *	Boyan:
 *	Setup a hashes wich we will use later
 *	parse a module and give him a chance to live
 *
 */
static int mod_instantiate(CONF_SECTION *conf, void *instance)
{
	rlm_perl_t       *inst = instance;
	AV		*end_AV;

	char **embed;
	char **envp = NULL;
	char const *xlat_name;
	int exitstatus = 0, argc=0;

	MEM(embed = talloc_zero_array(inst, char *, 4));

	/*
	 *	Create pthread key. This key will be stored in instance
	 */

#ifdef USE_ITHREADS
	pthread_mutex_init(&inst->clone_mutex, NULL);

	inst->thread_key = rad_malloc(sizeof(*inst->thread_key));
	memset(inst->thread_key,0,sizeof(*inst->thread_key));

	rlm_perl_make_key(inst->thread_key);
#endif

	char arg[] = "0";

	embed[0] = NULL;
	if (inst->perl_flags) {
		embed[1] = inst->perl_flags;
		embed[2] = inst->module;
		embed[3] = arg;
		argc = 4;
	} else {
		embed[1] = inst->module;
		embed[2] = arg;
		argc = 3;
	}

	PERL_SYS_INIT3(&argc, &embed, &envp);

	if ((inst->perl = perl_alloc()) == NULL) {
		ERROR("rlm_perl: No memory for allocating new perl !");
		return (-1);
	}

	perl_construct(inst->perl);

#ifdef USE_ITHREADS
	PL_perl_destruct_level = 2;

	{
		dTHXa(inst->perl);
	}
	PERL_SET_CONTEXT(inst->perl);
#endif

#if PERL_REVISION >= 5 && PERL_VERSION >=8
	PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
#endif

	exitstatus = perl_parse(inst->perl, xs_init, argc, embed, NULL);

	end_AV = PL_endav;
	PL_endav = Nullav;

	if(!exitstatus) {
		perl_run(inst->perl);
	} else {
		ERROR("rlm_perl: perl_parse failed: %s not found or has syntax errors. \n", inst->module);
		return (-1);
	}

	PL_endav = end_AV;

	xlat_name = cf_section_name2(conf);
	if (!xlat_name)
		xlat_name = cf_section_name1(conf);
	if (xlat_name) {
		xlat_register(xlat_name, perl_xlat, NULL, inst);
	}

	return 0;
}
Beispiel #24
0
/*
 *	Read config files.
 *
 *	This function can ONLY be called from the main server process.
 */
int main_config_init(void)
{
	char const *p = NULL;
	CONF_SECTION *cs;
	struct stat statbuf;
	cached_config_t *cc;
	char buffer[1024];

	if (stat(radius_dir, &statbuf) < 0) {
		ERROR("Errors reading %s: %s",
		       radius_dir, fr_syserror(errno));
		return -1;
	}

#ifdef S_IWOTH
	if ((statbuf.st_mode & S_IWOTH) != 0) {
		ERROR("Configuration directory %s is globally writable.  Refusing to start due to insecure configuration.",
		       radius_dir);
	  return -1;
	}
#endif

#ifdef S_IROTH
	if (0 && (statbuf.st_mode & S_IROTH) != 0) {
		ERROR("Configuration directory %s is globally readable.  Refusing to start due to insecure configuration.",
		       radius_dir);
		return -1;
	}
#endif
	INFO("Starting - reading configuration files ...");

	/*
	 *	We need to load the dictionaries before reading the
	 *	configuration files.  This is because of the
	 *	pre-compilation in conffile.c.  That should probably
	 *	be fixed to be done as a second stage.
	 */
	if (!main_config.dictionary_dir) {
		main_config.dictionary_dir = talloc_typed_strdup(NULL, DICTDIR);
	}

	/*
	 *	Read the distribution dictionaries first, then
	 *	the ones in raddb.
	 */
	DEBUG2("including dictionary file %s/%s", main_config.dictionary_dir, RADIUS_DICTIONARY);
	if (dict_init(main_config.dictionary_dir, RADIUS_DICTIONARY) != 0) {
		ERROR("Errors reading dictionary: %s",
		      fr_strerror());
		return -1;
	}

#define DICT_READ_OPTIONAL(_d, _n) \
do {\
	switch (dict_read(_d, _n)) {\
	case -1:\
		ERROR("Errors reading %s/%s: %s", _d, _n, fr_strerror());\
		return -1;\
	case 0:\
		DEBUG2("including dictionary file %s/%s", _d,_n);\
		break;\
	default:\
		break;\
	}\
} while (0)

	/*
	 *	Try to load protocol-specific dictionaries.  It's OK
	 *	if they don't exist.
	 */
#ifdef WITH_DHCP
	DICT_READ_OPTIONAL(main_config.dictionary_dir, "dictionary.dhcp");
#endif

#ifdef WITH_VMPS
	DICT_READ_OPTIONAL(main_config.dictionary_dir, "dictionary.vqp");
#endif

	/*
	 *	It's OK if this one doesn't exist.
	 */
	DICT_READ_OPTIONAL(radius_dir, RADIUS_DICTIONARY);

	/* Read the configuration file */
	snprintf(buffer, sizeof(buffer), "%.200s/%.50s.conf",
		 radius_dir, main_config.name);
	if ((cs = cf_file_read(buffer)) == NULL) {
		ERROR("Errors reading or parsing %s", buffer);
		return -1;
	}

	/*
	 *	If there was no log destination set on the command line,
	 *	set it now.
	 */
	if (default_log.dst == L_DST_NULL) {
		if (cf_section_parse(cs, NULL, serverdest_config) < 0) {
			fprintf(stderr, "radiusd: Error: Failed to parse log{} section.\n");
			cf_file_free(cs);
			return -1;
		}

		if (!radlog_dest) {
			fprintf(stderr, "radiusd: Error: No log destination specified.\n");
			cf_file_free(cs);
			return -1;
		}

		default_log.dst = fr_str2int(log_str2dst, radlog_dest,
					      L_DST_NUM_DEST);
		if (default_log.dst == L_DST_NUM_DEST) {
			fprintf(stderr, "radiusd: Error: Unknown log_destination %s\n",
				radlog_dest);
			cf_file_free(cs);
			return -1;
		}

		if (default_log.dst == L_DST_SYSLOG) {
			/*
			 *	Make sure syslog_facility isn't NULL
			 *	before using it
			 */
			if (!syslog_facility) {
				fprintf(stderr, "radiusd: Error: Syslog chosen but no facility was specified\n");
				cf_file_free(cs);
				return -1;
			}
			main_config.syslog_facility = fr_str2int(syslog_str2fac, syslog_facility, -1);
			if (main_config.syslog_facility < 0) {
				fprintf(stderr, "radiusd: Error: Unknown syslog_facility %s\n",
					syslog_facility);
				cf_file_free(cs);
				return -1;
			}

#ifdef HAVE_SYSLOG_H
			/*
			 *	Call openlog only once, when the
			 *	program starts.
			 */
			openlog(progname, LOG_PID, main_config.syslog_facility);
#endif

		} else if (default_log.dst == L_DST_FILES) {
			if (!main_config.log_file) {
				fprintf(stderr, "radiusd: Error: Specified \"files\" as a log destination, but no log filename was given!\n");
				cf_file_free(cs);
				return -1;
			}
		}
	}

#ifdef HAVE_SETUID
	/*
	 *	Switch users as early as possible.
	 */
	if (!switch_users(cs)) fr_exit(1);
#endif

	/*
	 *	Open the log file AFTER switching uid / gid.  If we
	 *	did switch uid/gid, then the code in switch_users()
	 *	took care of setting the file permissions correctly.
	 */
	if ((default_log.dst == L_DST_FILES) &&
	    (default_log.fd < 0)) {
		default_log.fd = open(main_config.log_file,
					    O_WRONLY | O_APPEND | O_CREAT, 0640);
		if (default_log.fd < 0) {
			fprintf(stderr, "radiusd: Failed to open log file %s: %s\n", main_config.log_file, fr_syserror(errno));
			cf_file_free(cs);
			return -1;
		}
	}

	/*
	 *	This allows us to figure out where, relative to
	 *	radiusd.conf, the other configuration files exist.
	 */
	if (cf_section_parse(cs, NULL, server_config) < 0) {
		return -1;
	}

	/*
	 *	We ignore colourization of output until after the
	 *	configuration files have been parsed.
	 */
	p = getenv("TERM");
	if (do_colourise && p && isatty(default_log.fd) && strstr(p, "xterm")) {
		default_log.colourise = true;
	} else {
		default_log.colourise = false;
	}

	/*
	 *	Starting the server, WITHOUT "-x" on the
	 *	command-line: use whatever is in the config
	 *	file.
	 */
	if (debug_flag == 0) {
		debug_flag = main_config.debug_level;
	}
	fr_debug_flag = debug_flag;

	FR_INTEGER_COND_CHECK("max_request_time", main_config.max_request_time, (main_config.max_request_time != 0), 100);
	FR_INTEGER_BOUND_CHECK("reject_delay", main_config.reject_delay, <=, 10);
	FR_INTEGER_BOUND_CHECK("cleanup_delay", main_config.cleanup_delay, <=, 10);

	/*
	 * Set default initial request processing delay to 1/3 of a second.
	 * Will be updated by the lowest response window across all home servers,
	 * if it is less than this.
	 */
	main_config.init_delay.tv_sec = 0;
	main_config.init_delay.tv_usec = 1000000 / 3;

	/*
	 *	Free the old configuration items, and replace them
	 *	with the new ones.
	 *
	 *	Note that where possible, we do atomic switch-overs,
	 *	to ensure that the pointers are always valid.
	 */
	rad_assert(main_config.config == NULL);
	root_config = main_config.config = cs;

	DEBUG2("%s: #### Loading Realms and Home Servers ####", main_config.name);
	if (!realms_init(cs)) {
		return -1;
	}

	DEBUG2("%s: #### Loading Clients ####", main_config.name);
	if (!clients_parse_section(cs, false)) {
		return -1;
	}

	/*
	 *  Register the %{config:section.subsection} xlat function.
	 */
	xlat_register("config", xlat_config, NULL, NULL);
	xlat_register("client", xlat_client, NULL, NULL);
	xlat_register("getclient", xlat_getclient, NULL, NULL);

	/*
	 *  Go update our behaviour, based on the configuration
	 *  changes.
	 */

	/*
	 *	Sanity check the configuration for internal
	 *	consistency.
	 */
	FR_INTEGER_BOUND_CHECK("reject_delay", main_config.reject_delay, <=, main_config.cleanup_delay);

	if (chroot_dir) {
		if (chdir(radlog_dir) < 0) {
			ERROR("Failed to 'chdir %s' after chroot: %s",
			       radlog_dir, fr_syserror(errno));
			return -1;
		}
	}

	cc = talloc_zero(NULL, cached_config_t);
	if (!cc) return -1;

	cc->cs = talloc_steal(cc ,cs);
	rad_assert(cs_cache == NULL);
	cs_cache = cc;

	/* Clear any unprocessed configuration errors */
	(void) fr_strerror();

	return 0;
}
Beispiel #25
0
static int mod_instantiate(CONF_SECTION *conf, void *instance)
{
	rlm_sql_t *inst = instance;

	/*
	 *	Hack...
	 */
	inst->config = &inst->myconfig;
	inst->cs = conf;

	inst->config->xlat_name = cf_section_name2(conf);
	if (!inst->config->xlat_name) {
		inst->config->xlat_name = cf_section_name1(conf);
	} else {
		char *group_name;
		DICT_ATTR const *da;
		ATTR_FLAGS flags;

		/*
		 *	Allocate room for <instance>-SQL-Group
		 */
		group_name = talloc_typed_asprintf(inst, "%s-SQL-Group", inst->config->xlat_name);
		DEBUG("rlm_sql (%s): Creating new attribute %s",
		      inst->config->xlat_name, group_name);

		memset(&flags, 0, sizeof(flags));
		if (dict_addattr(group_name, -1, 0, PW_TYPE_STRING, flags) < 0) {
			ERROR("rlm_sql (%s): Failed to create "
			       "attribute %s: %s", inst->config->xlat_name, group_name,
			       fr_strerror());
			return -1;
		}

		da = dict_attrbyname(group_name);
		if (!da) {
			ERROR("rlm_sql (%s): Failed to create "
			       "attribute %s", inst->config->xlat_name, group_name);
			return -1;
		}

		if (inst->config->groupmemb_query &&
		    inst->config->groupmemb_query[0]) {
			DEBUG("rlm_sql (%s): Registering sql_groupcmp for %s",
			      inst->config->xlat_name, group_name);
			paircompare_register(da, dict_attrbyvalue(PW_USER_NAME, 0),
					     false, sql_groupcmp, inst);
		}
	}

	rad_assert(inst->config->xlat_name);

	/*
	 *	If the configuration parameters can't be parsed, then fail.
	 */
	if ((parse_sub_section(conf, inst, &inst->config->accounting, RLM_COMPONENT_ACCT) < 0) ||
	    (parse_sub_section(conf, inst, &inst->config->postauth, RLM_COMPONENT_POST_AUTH) < 0)) {
		cf_log_err_cs(conf, "Invalid configuration");
		return -1;
	}

	/*
	 *	Cache the SQL-User-Name DICT_ATTR, so we can be slightly
	 *	more efficient about creating SQL-User-Name attributes.
	 */
	inst->sql_user = dict_attrbyname("SQL-User-Name");
	if (!inst->sql_user) {
		return -1;
	}

	/*
	 *	Export these methods, too.  This avoids RTDL_GLOBAL.
	 */
	inst->sql_set_user		= sql_set_user;
	inst->sql_get_socket		= sql_get_socket;
	inst->sql_release_socket	= sql_release_socket;
	inst->sql_escape_func		= sql_escape_func;
	inst->sql_query			= rlm_sql_query;
	inst->sql_select_query		= rlm_sql_select_query;
	inst->sql_fetch_row		= rlm_sql_fetch_row;

	/*
	 *	Register the SQL xlat function
	 */
	xlat_register(inst->config->xlat_name, sql_xlat, sql_escape_func, inst);

	/*
	 *	Sanity check for crazy people.
	 */
	if (strncmp(inst->config->sql_driver_name, "rlm_sql_", 8) != 0) {
		ERROR("rlm_sql (%s): \"%s\" is NOT an SQL driver!",
		       inst->config->xlat_name, inst->config->sql_driver_name);
		return -1;
	}

	/*
	 *	Load the appropriate driver for our database
	 */
	inst->handle = lt_dlopenext(inst->config->sql_driver_name);
	if (!inst->handle) {
		ERROR("Could not link driver %s: %s",
		       inst->config->sql_driver_name,
		       dlerror());
		ERROR("Make sure it (and all its dependent libraries!)"
		       "are in the search path of your system's ld");
		return -1;
	}

	inst->module = (rlm_sql_module_t *) dlsym(inst->handle,
						  inst->config->sql_driver_name);
	if (!inst->module) {
		ERROR("Could not link symbol %s: %s",
		       inst->config->sql_driver_name,
		       dlerror());
		return -1;
	}

	if (inst->module->mod_instantiate) {
		CONF_SECTION *cs;
		char const *name;

		name = strrchr(inst->config->sql_driver_name, '_');
		if (!name) {
			name = inst->config->sql_driver_name;
		} else {
			name++;
		}

		cs = cf_section_sub_find(conf, name);
		if (!cs) {
			cs = cf_section_alloc(conf, name, NULL);
			if (!cs) {
				return -1;
			}
		}

		/*
		 *	It's up to the driver to register a destructor
		 */
		if (inst->module->mod_instantiate(cs, inst->config) < 0) {
			return -1;
		}
	}

	inst->lf = fr_logfile_init(inst);
	if (!inst->lf) {
		cf_log_err_cs(conf, "Failed creating log file context");
		return -1;
	}

	INFO("rlm_sql (%s): Driver %s (module %s) loaded and linked",
	       inst->config->xlat_name, inst->config->sql_driver_name,
	       inst->module->name);

	/*
	 *	Initialise the connection pool for this instance
	 */
	INFO("rlm_sql (%s): Attempting to connect to database \"%s\"",
	       inst->config->xlat_name, inst->config->sql_db);

	if (sql_socket_pool_init(inst) < 0) return -1;

	if (inst->config->groupmemb_query &&
	    inst->config->groupmemb_query[0]) {
		paircompare_register(dict_attrbyvalue(PW_SQL_GROUP, 0),
				dict_attrbyvalue(PW_USER_NAME, 0), false, sql_groupcmp, inst);
	}

	if (inst->config->do_clients) {
		if (generate_sql_clients(inst) == -1){
			ERROR("Failed to load clients from SQL");
			return -1;
		}
	}

	return RLM_MODULE_OK;
}
/*
 *	Do any per-module initialization that is separate to each
 *	configured instance of the module.  e.g. set up connections
 *	to external databases, read configuration files, set up
 *	dictionary entries, etc.
 *
 *	If configuration information is given in the config section
 *	that must be referenced in later calls, store a handle to it
 *	in *instance otherwise put a null pointer there.
 *
 *	Boyan:
 *	Setup a hashes wich we will use later
 *	parse a module and give him a chance to live
 *
 */
static int perl_instantiate(CONF_SECTION *conf, void **instance)
{
	PERL_INST       *inst = (PERL_INST *) instance;
	HV		*rad_reply_hv;
	HV		*rad_check_hv;
	HV		*rad_config_hv;
	HV		*rad_request_hv;
#ifdef WITH_PROXY
	HV		*rad_request_proxy_hv;
	HV		*rad_request_proxy_reply_hv;
#endif
	AV		*end_AV;

	char **embed;
        char **envp = NULL;
	const char *xlat_name;
	int exitstatus = 0, argc=0;

        embed = rad_malloc(4 * sizeof(char *));
        memset(embed, 0, 4 *sizeof(char *));
	/*
	 *	Set up a storage area for instance data
	 */
	inst = rad_malloc(sizeof(PERL_INST));
	memset(inst, 0, sizeof(PERL_INST));

	/*
	 *	If the configuration parameters can't be parsed, then
	 *	fail.
	 */
	if (cf_section_parse(conf, inst, module_config) < 0) {
		free(embed);
		free(inst);
		return -1;
	}
	
	/*
	 *	Create pthread key. This key will be stored in instance
	 */

#ifdef USE_ITHREADS
	pthread_mutex_init(&inst->clone_mutex, NULL);

	inst->thread_key = rad_malloc(sizeof(*inst->thread_key));
	memset(inst->thread_key,0,sizeof(*inst->thread_key));
	
	rlm_perl_make_key(inst->thread_key);
#endif

	char arg[] = "0";
	
	embed[0] = NULL;
	if (inst->perl_flags) {
		embed[1] = inst->perl_flags;
		embed[2] = inst->module;
		embed[3] = arg;
		argc = 4;
	} else {
		embed[1] = inst->module;
		embed[2] = arg;
		argc = 3;
	}

        PERL_SYS_INIT3(&argc, &embed, &envp);
#ifdef USE_ITHREADS
	if ((inst->perl = perl_alloc()) == NULL) {
		radlog(L_DBG, "rlm_perl: No memory for allocating new perl !");
		free(embed);
		free(inst);
		return (-1);
	}

	perl_construct(inst->perl);
	PL_perl_destruct_level = 2;

	{
	dTHXa(inst->perl);
	}
	PERL_SET_CONTEXT(inst->perl);
#else
	if ((inst->perl = perl_alloc()) == NULL) {
		radlog(L_ERR, "rlm_perl: No memory for allocating new perl !");
		free(embed);
		free(inst);
		return -1;
	}

	perl_construct(inst->perl);
#endif

#if PERL_REVISION >= 5 && PERL_VERSION >=8
	PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
#endif

	exitstatus = perl_parse(inst->perl, xs_init, argc, embed, NULL);

	end_AV = PL_endav;
	PL_endav = Nullav;

        newXS("radiusd::radlog",XS_radiusd_radlog, "rlm_perl");

	if(!exitstatus) {
		exitstatus = perl_run(inst->perl);
	} else {
		radlog(L_ERR,"rlm_perl: perl_parse failed: %s not found or has syntax errors. \n", inst->module);
		free(embed);
		free(inst);
		return (-1);
	}

	PL_endav = end_AV;

	rad_reply_hv = newHV();
	rad_check_hv = newHV();
	rad_config_hv = newHV();
	rad_request_hv = newHV();
#ifdef WITH_PROXY
	rad_request_proxy_hv = newHV();
	rad_request_proxy_reply_hv = newHV();
#endif

	rad_reply_hv = get_hv("RAD_REPLY",1);
        rad_check_hv = get_hv("RAD_CHECK",1);
	rad_config_hv = get_hv("RAD_CONFIG",1);
        rad_request_hv = get_hv("RAD_REQUEST",1);
#ifdef WITH_PROXY
	rad_request_proxy_hv = get_hv("RAD_REQUEST_PROXY",1);
	rad_request_proxy_reply_hv = get_hv("RAD_REQUEST_PROXY_REPLY",1);
#endif

	xlat_name = cf_section_name2(conf);
	if (xlat_name == NULL)
		xlat_name = cf_section_name1(conf);
	if (xlat_name){
		inst->xlat_name = strdup(xlat_name);
		xlat_register(xlat_name, perl_xlat, inst);
	}

	*instance = inst;

	return 0;
}
Beispiel #27
0
/** Instantiate the module
 *
 * Creates a new instance of the module reading parameters from a configuration section.
 *
 * @param conf to parse.
 * @param instance Where to write pointer to configuration data.
 * @return 0 on success < 0 on failure.
 */
static int mod_instantiate(CONF_SECTION *conf, void *instance)
{
	static bool version_done;

	CONF_SECTION *options;
	ldap_instance_t *inst = instance;

	inst->cs = conf;

	options = cf_section_sub_find(conf, "options");
	if (!options || !cf_pair_find(options, "chase_referrals")) {
		inst->chase_referrals_unset = true;	 /* use OpenLDAP defaults */
	}

	inst->xlat_name = cf_section_name2(conf);
	if (!inst->xlat_name) {
		inst->xlat_name = cf_section_name1(conf);
	}


	/*
	 *	Only needs to be done once, prevents races in environment
	 *	initialisation within libldap.
	 *
	 *	See: https://github.com/arr2036/ldapperf/issues/2
	 */
#ifdef HAVE_LDAP_INITIALIZE
	ldap_initialize(&inst->handle, "");
#else
	inst->handle = ldap_init("", 0);
#endif

	/*
	 *	Get version info from the LDAP API.
	 */
	if (!version_done) {
		static LDAPAPIInfo info;	/* static to quiet valgrind about this being uninitialised */
		int ldap_errno;

		version_done = true;

		ldap_errno = ldap_get_option(NULL, LDAP_OPT_API_INFO, &info);
		if (ldap_errno == LDAP_OPT_SUCCESS) {
			if (strcmp(info.ldapai_vendor_name, LDAP_VENDOR_NAME) != 0) {
				WARN("rlm_ldap: libldap vendor changed since the server was built");
				WARN("rlm_ldap: linked: %s, built: %s", info.ldapai_vendor_name, LDAP_VENDOR_NAME);
			}

			if (info.ldapai_vendor_version != LDAP_VENDOR_VERSION) {
				WARN("rlm_ldap: libldap version changed since the server was built");
				WARN("rlm_ldap: linked: %i, built: %i",
				     info.ldapai_vendor_version, LDAP_VENDOR_VERSION);
			}

			INFO("rlm_ldap: libldap vendor: %s, version: %i", info.ldapai_vendor_name,
			     info.ldapai_vendor_version);

			ldap_memfree(info.ldapai_vendor_name);
			ldap_memfree(info.ldapai_extensions);
		} else {
			DEBUG("rlm_ldap: Falling back to build time libldap version info.  Query for LDAP_OPT_API_INFO "
			      "returned: %i", ldap_errno);
			INFO("rlm_ldap: libldap vendor: %s, version: %i.%i.%i", LDAP_VENDOR_NAME,
			     LDAP_VENDOR_VERSION_MAJOR, LDAP_VENDOR_VERSION_MINOR, LDAP_VENDOR_VERSION_PATCH);
		}
	}

	/*
	 *	If the configuration parameters can't be parsed, then fail.
	 */
	if ((parse_sub_section(inst, conf, &inst->accounting, RLM_COMPONENT_ACCT) < 0) ||
	    (parse_sub_section(inst, conf, &inst->postauth, RLM_COMPONENT_POST_AUTH) < 0)) {
		cf_log_err_cs(conf, "Failed parsing configuration");

		goto error;
	}

	/*
	 *	Sanity checks for cacheable groups code.
	 */
	if (inst->cacheable_group_name && inst->groupobj_membership_filter) {
		if (!inst->groupobj_name_attr) {
			cf_log_err_cs(conf, "Directive 'group.name_attribute' must be set if cacheable "
				      "group names are enabled");

			goto error;
		}
	}

	/*
	 *	Split original server value out into URI, server and port
	 *	so whatever initialization function we use later will have
	 *	the server information in the format it needs.
	 */
	if (ldap_is_ldap_url(inst->server)) {
		LDAPURLDesc *ldap_url;
		int port;

		if (ldap_url_parse(inst->server, &ldap_url)){
			cf_log_err_cs(conf, "Parsing LDAP URL \"%s\" failed", inst->server);
			return -1;
		}

		/*
		 *	Figure out the port from the URL
		 */
		if (ldap_url->lud_port == 0) {
			if (strcmp(ldap_url->lud_scheme, "ldaps://") == 0) {
				if (inst->start_tls == true) {
				start_tls_error:
					cf_log_err_cs(conf, "ldaps:// scheme is not compatible with 'start_tls'");
					return -1;
				}
				port = 636;
			} else {
				port = 384;
			}
		} else {
			port = ldap_url->lud_port;
		}

		inst->uri = inst->server;
		inst->server = talloc_strdup(inst, ldap_url->lud_host);

		if ((inst->port != 384) && (port != inst->port)) {
			WARN("Non-default 'port' directive %i set to %i by LDAP URI", inst->port, port);
		}
		inst->port = port;

		/*
		 *	@todo We could set a few other top level
		 *	directives using the URL, like base_dn
		 *	and scope.
		 */

		ldap_free_urldesc(ldap_url);
	/*
	 *	We need to construct an LDAP URI
	 */
	} else {
		switch (inst->port) {
		default:
		case 384:
			inst->uri = talloc_asprintf(inst, "ldap://%s:%i/", inst->server, inst->port);
			break;

		case 636:
			if (inst->start_tls == true) goto start_tls_error;
			inst->uri = talloc_asprintf(inst, "ldaps://%s:%i/", inst->server, inst->port);
			break;
		}
	}

#ifdef LDAP_OPT_X_TLS_NEVER
	/*
	 *	Workaround for servers which support LDAPS but not START TLS
	 */
	if (inst->port == LDAPS_PORT || inst->tls_mode) {
		inst->tls_mode = LDAP_OPT_X_TLS_HARD;
	} else {
		inst->tls_mode = 0;
	}
#endif

	/*
	 *	Convert dereference strings to enumerated constants
	 */
	if (inst->dereference_str) {
		inst->dereference = fr_str2int(ldap_dereference, inst->dereference_str, -1);
		if (inst->dereference < 0) {
			cf_log_err_cs(conf, "Invalid 'dereference' value \"%s\", expected 'never', 'searching', "
				      "'finding' or 'always'", inst->dereference_str);
			goto error;
		}
	}

#if LDAP_SET_REBIND_PROC_ARGS != 3
	/*
	 *	The 2-argument rebind doesn't take an instance variable.  Our rebind function needs the instance
	 *	variable for the username, password, etc.
	 */
	if (inst->rebind == true) {
		cf_log_err_cs(conf, "Cannot use 'rebind' directive as this version of libldap "
			      "does not support the API that we need");

		goto error;
	}
#endif

	/*
	 *	Convert scope strings to enumerated constants
	 */
	inst->userobj_scope = fr_str2int(ldap_scope, inst->userobj_scope_str, -1);
	if (inst->userobj_scope < 0) {
		cf_log_err_cs(conf, "Invalid 'user.scope' value \"%s\", expected 'sub', 'one'"
#ifdef LDAP_SCOPE_CHILDREN
			      ", 'base' or 'children'"
#else
			      " or 'base'"
#endif
			 , inst->userobj_scope_str);
		goto error;
	}

	inst->groupobj_scope = fr_str2int(ldap_scope, inst->groupobj_scope_str, -1);
	if (inst->groupobj_scope < 0) {
		cf_log_err_cs(conf, "Invalid 'group.scope' value \"%s\", expected 'sub', 'one'"
#ifdef LDAP_SCOPE_CHILDREN
			      ", 'base' or 'children'"
#else
			      " or 'base'"
#endif
			 , inst->groupobj_scope_str);
		goto error;
	}

	inst->clientobj_scope = fr_str2int(ldap_scope, inst->clientobj_scope_str, -1);
	if (inst->clientobj_scope < 0) {
		cf_log_err_cs(conf, "Invalid 'client.scope' value \"%s\", expected 'sub', 'one'"
#ifdef LDAP_SCOPE_CHILDREN
			      ", 'base' or 'children'"
#else
			      " or 'base'"
#endif
			 , inst->clientobj_scope_str);
		goto error;
	}

	if (inst->tls_require_cert_str) {
#ifdef LDAP_OPT_X_TLS_NEVER
		/*
		 *	Convert cert strictness to enumerated constants
		 */
		inst->tls_require_cert = fr_str2int(ldap_tls_require_cert, inst->tls_require_cert_str, -1);
		if (inst->tls_require_cert < 0) {
			cf_log_err_cs(conf, "Invalid 'tls.require_cert' value \"%s\", expected 'never', "
				      "'demand', 'allow', 'try' or 'hard'", inst->tls_require_cert_str);
			goto error;
		}
#else
		cf_log_err_cs(conf, "Modifying 'tls.require_cert' is not supported by current "
			      "version of libldap. Please upgrade or substitute current libldap and "
			      "rebuild this module");

		goto error;
#endif
	}
	/*
	 *	Build the attribute map
	 */
	if (map_afrom_cs(&inst->user_map, cf_section_sub_find(inst->cs, "update"),
			 PAIR_LIST_REPLY, PAIR_LIST_REQUEST, rlm_ldap_map_verify, inst,
			 LDAP_MAX_ATTRMAP) < 0) {
		return -1;
	}

	/*
	 *	Group comparison checks.
	 */
	if (cf_section_name2(conf)) {
		static ATTR_FLAGS flags;
		char buffer[256];

		snprintf(buffer, sizeof(buffer), "%s-Ldap-Group", inst->xlat_name);
		if (dict_addattr(buffer, -1, 0, PW_TYPE_STRING, flags) < 0) {
			LDAP_ERR("Error creating group attribute: %s", fr_strerror());

			return -1;
		}
		inst->group_da = dict_attrbyname(buffer);
		if (!inst->group_da) {
			LDAP_ERR("Failed creating attribute %s", buffer);

			goto error;
		}

		paircompare_register(inst->group_da, dict_attrbyvalue(PW_USER_NAME, 0), false, rlm_ldap_groupcmp, inst);
	/*
	 *	Were the default instance
	 */
	} else {
		inst->group_da = dict_attrbyvalue(PW_LDAP_GROUP, 0);
		paircompare_register(dict_attrbyvalue(PW_LDAP_GROUP, 0), dict_attrbyvalue(PW_USER_NAME, 0),
				false, rlm_ldap_groupcmp, inst);
	}

	xlat_register(inst->xlat_name, ldap_xlat, rlm_ldap_escape_func, inst);

	/*
	 *	Setup the cache attribute
	 */
	if (inst->cache_attribute) {
		static ATTR_FLAGS flags;

		if (dict_addattr(inst->cache_attribute, -1, 0, PW_TYPE_STRING, flags) < 0) {
			LDAP_ERR("Error creating cache attribute: %s", fr_strerror());

			goto error;
		}
		inst->cache_da = dict_attrbyname(inst->cache_attribute);
	} else {
		inst->cache_da = inst->group_da;	/* Default to the group_da */
	}

	/*
	 *	Initialize the socket pool.
	 */
	inst->pool = fr_connection_pool_module_init(inst->cs, inst, mod_conn_create, NULL, NULL);
	if (!inst->pool) goto error;

	/*
	 *	Bulk load dynamic clients.
	 */
	if (inst->do_clients) {
		CONF_SECTION *cs;

		cs = cf_section_sub_find(inst->cs, "client");
		if (!cs) {
			cf_log_err_cs(conf, "Told to load clients but no client section found");
			goto error;
		}

		cs = cf_section_sub_find(cs, "attribute");
		if (!cs) {
			cf_log_err_cs(conf, "Told to load clients but no attribute section found");
			goto error;
		}

		if (rlm_ldap_client_load(inst, cs) < 0) {
			cf_log_err_cs(conf, "Error loading clients");

			return -1;
		}
	}

	return 0;

error:
	return -1;
}
Beispiel #28
0
/**
 * @brief Register an xlat function.
 *
 * @param module xlat name
 * @param func xlat function to be called
 * @param instance argument to xlat function
 * @return 0 on success, -1 on failure
 */
int xlat_register(const char *module, RAD_XLAT_FUNC func, void *instance)
{
	xlat_t	*c;
	xlat_t	my_xlat;

	if (!module || !*module) {
		DEBUG("xlat_register: Invalid module name");
		return -1;
	}

	/*
	 *	First time around, build up the tree...
	 *
	 *	FIXME: This code should be hoisted out of this function,
	 *	and into a global "initialization".  But it isn't critical...
	 */
	if (!xlat_root) {
		int i;
#ifdef HAVE_REGEX_H
		char buffer[2];
#endif

		xlat_root = rbtree_create(xlat_cmp, free, 0);
		if (!xlat_root) {
			DEBUG("xlat_register: Failed to create tree.");
			return -1;
		}

		/*
		 *	Register the internal packet xlat's.
		 */
		for (i = 0; internal_xlat[i] != NULL; i++) {
			xlat_register(internal_xlat[i], xlat_packet, &xlat_inst[i]);
			c = xlat_find(internal_xlat[i]);
			rad_assert(c != NULL);
			c->internal = TRUE;
		}

#ifdef WITH_UNLANG
		for (i = 0; xlat_foreach_names[i] != NULL; i++) {
			xlat_register(xlat_foreach_names[i],
				      xlat_foreach, &xlat_inst[i]);
			c = xlat_find(xlat_foreach_names[i]);
			rad_assert(c != NULL);
			c->internal = TRUE;
		}
#endif

		/*
		 *	New name: "control"
		 */
		xlat_register("control", xlat_packet, &xlat_inst[0]);
		c = xlat_find("control");
		rad_assert(c != NULL);
		c->internal = TRUE;

#define XLAT_REGISTER(_x) xlat_register(Stringify(_x), xlat_ ## _x, NULL); \
		c = xlat_find(Stringify(_x)); \
		rad_assert(c != NULL); \
		c->internal = TRUE

		XLAT_REGISTER(integer);
		XLAT_REGISTER(hex);
		XLAT_REGISTER(base64);
		XLAT_REGISTER(string);
		XLAT_REGISTER(module);

#ifdef HAVE_REGEX_H
		/*
		 *	Register xlat's for regexes.
		 */
		buffer[1] = '\0';
		for (i = 0; i <= REQUEST_MAX_REGEX; i++) {
			buffer[0] = '0' + i;
			xlat_register(buffer, xlat_regex, &xlat_inst[i]);
			c = xlat_find(buffer);
			rad_assert(c != NULL);
			c->internal = TRUE;
		}
#endif /* HAVE_REGEX_H */


		xlat_register("debug", xlat_debug, &xlat_inst[0]);
		c = xlat_find("debug");
		rad_assert(c != NULL);
		c->internal = TRUE;
	}

	/*
	 *	If it already exists, replace the instance.
	 */
	strlcpy(my_xlat.module, module, sizeof(my_xlat.module));
	my_xlat.length = strlen(my_xlat.module);
	c = rbtree_finddata(xlat_root, &my_xlat);
	if (c) {
		if (c->internal) {
			DEBUG("xlat_register: Cannot re-define internal xlat");
			return -1;
		}

		c->do_xlat = func;
		c->instance = instance;
		return 0;
	}

	/*
	 *	Doesn't exist.  Create it.
	 */
	c = rad_malloc(sizeof(*c));
	memset(c, 0, sizeof(*c));

	c->do_xlat = func;
	strlcpy(c->module, module, sizeof(c->module));
	c->length = strlen(c->module);
	c->instance = instance;

	rbtree_insert(xlat_root, c);

	return 0;
}
Beispiel #29
0
/*
 *	Do any per-module initialization that is separate to each
 *	configured instance of the module.  e.g. set up connections
 *	to external databases, read configuration files, set up
 *	dictionary entries, etc.
 *
 *	If configuration information is given in the config section
 *	that must be referenced in later calls, store a handle to it
 *	in *instance otherwise put a null pointer there.
 */
static int mod_instantiate(CONF_SECTION *conf, void *instance)
{
	rlm_expr_t *inst = instance;

	inst->xlat_name = cf_section_name2(conf);
	if (!inst->xlat_name) {
		inst->xlat_name = cf_section_name1(conf);
	}

	xlat_register(inst->xlat_name, expr_xlat, NULL, inst);

	/*
	 *	FIXME: unregister these, too
	 */
	xlat_register("rand", rand_xlat, NULL, inst);
	xlat_register("randstr", randstr_xlat, NULL, inst);
	xlat_register("urlquote", urlquote_xlat, NULL, inst);
	xlat_register("escape", escape_xlat, NULL, inst);
	xlat_register("tolower", lc_xlat, NULL, inst);
	xlat_register("toupper", uc_xlat, NULL, inst);
	xlat_register("md5", md5_xlat, NULL, inst);
	xlat_register("sha1", sha1_xlat, NULL, inst);
#ifdef HAVE_OPENSSL_EVP_H
	xlat_register("sha256", sha256_xlat, NULL, inst);
	xlat_register("sha512", sha512_xlat, NULL, inst);
#endif
	xlat_register("hmacmd5", hmac_md5_xlat, NULL, inst);
	xlat_register("hmacsha1", hmac_sha1_xlat, NULL, inst);
	xlat_register("base64", base64_xlat, NULL, inst);
	xlat_register("base64tohex", base64_to_hex_xlat, NULL, inst);

	/*
	 *	Initialize various paircompare functions
	 */
	pair_builtincompare_add(instance);
	return 0;
}
Beispiel #30
0
/*
 *	Do any per-module initialization that is separate to each
 *	configured instance of the module.  e.g. set up connections
 *	to external databases, read configuration files, set up
 *	dictionary entries, etc.
 *
 *	If configuration information is given in the config section
 *	that must be referenced in later calls, store a handle to it
 *	in *instance otherwise put a null pointer there.
 *
 *	Setup a hashes wich we will use later
 *	parse a module and give him a chance to live
 *
 */
static int mod_instantiate(CONF_SECTION *conf, void *instance)
{
	rlm_perl_t       *inst = instance;
	AV		*end_AV;

	char const **embed_c;	/* Stupid Perl and lack of const consistency */
	char **embed;
	char **envp = NULL;
	char const *xlat_name;
	int exitstatus = 0, argc=0;

	MEM(embed_c = talloc_zero_array(inst, char const *, 4));
	memcpy(&embed, &embed_c, sizeof(embed));
	/*
	 *	Create pthread key. This key will be stored in instance
	 */

#ifdef USE_ITHREADS
	pthread_mutex_init(&inst->clone_mutex, NULL);

	inst->thread_key = rad_malloc(sizeof(*inst->thread_key));
	memset(inst->thread_key,0,sizeof(*inst->thread_key));

	rlm_perl_make_key(inst->thread_key);
#endif

	char arg[] = "0";

	embed_c[0] = NULL;
	if (inst->perl_flags) {
		embed_c[1] = inst->perl_flags;
		embed_c[2] = inst->module;
		embed_c[3] = arg;
		argc = 4;
	} else {
		embed_c[1] = inst->module;
		embed_c[2] = arg;
		argc = 3;
	}

	PERL_SYS_INIT3(&argc, &embed, &envp);

	if ((inst->perl = perl_alloc()) == NULL) {
		ERROR("rlm_perl: No memory for allocating new perl !");
		return (-1);
	}

	perl_construct(inst->perl);

#ifdef USE_ITHREADS
	PL_perl_destruct_level = 2;

	{
		dTHXa(inst->perl);
	}
	PERL_SET_CONTEXT(inst->perl);
#endif

#if PERL_REVISION >= 5 && PERL_VERSION >=8
	PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
#endif

	exitstatus = perl_parse(inst->perl, xs_init, argc, embed, NULL);

	end_AV = PL_endav;
	PL_endav = Nullav;

	if(!exitstatus) {
		perl_run(inst->perl);
	} else {
		ERROR("rlm_perl: perl_parse failed: %s not found or has syntax errors. \n", inst->module);
		return (-1);
	}

	PL_endav = end_AV;

	xlat_name = cf_section_name2(conf);
	if (!xlat_name)
		xlat_name = cf_section_name1(conf);
	if (xlat_name) {
		xlat_register(xlat_name, perl_xlat, NULL, inst);
	}

	/* parse perl configuration sub-section */
	CONF_SECTION *cs;
	cs = cf_section_sub_find(conf, "config");
	if (cs) {
		DEBUG("rlm_perl (%s): parsing 'config' section...", xlat_name);

		inst->rad_perlconf_hv = get_hv("RAD_PERLCONF",1);
		perl_parse_config(cs, 0, inst->rad_perlconf_hv);

		DEBUG("rlm_perl (%s): done parsing 'config'.", xlat_name);
	}

	return 0;
}