コード例 #1
0
ファイル: mainconfig.c プロジェクト: janetuk/freeradius
/*
 *	Xlat for %{client:foo}
 */
static ssize_t xlat_client(UNUSED void *instance, REQUEST *request, char const *fmt, char *out, size_t outlen)
{
	char const *value = NULL;
	CONF_PAIR *cp;

	if (!fmt || !out || (outlen < 1)) return 0;

	if (!request->client) {
		RWDEBUG("No client associated with this request");
		*out = '\0';
		return 0;
	}

	cp = cf_pair_find(request->client->cs, fmt);
	if (!cp || !(value = cf_pair_value(cp))) {
		if (strcmp(fmt, "shortname") == 0 && request->client->shortname) {
			value = request->client->shortname;
		}
		else if (strcmp(fmt, "nas_type") == 0 && request->client->nas_type) {
			value = request->client->nas_type;
		} else {
			*out = '\0';
			return 0;
		}
	}

	strlcpy(out, value, outlen);

	return strlen(out);
}
コード例 #2
0
ファイル: mainconfig.c プロジェクト: xunmengdeganjue/workTest
/*
 *	Xlat for %{listen:foo}
 */
static ssize_t xlat_listen(UNUSED void *instance, REQUEST *request,
			   char const *fmt, char *out, size_t outlen)
{
	char const *value = NULL;
	CONF_PAIR *cp;

	if (!fmt || !out || (outlen < 1)) return 0;

	if (!request->listener) {
		RWDEBUG("No listener associated with this request");
		*out = '\0';
		return 0;
	}

	cp = cf_pair_find(request->listener->cs, fmt);
	if (!cp || !(value = cf_pair_value(cp))) {
		RDEBUG("Listener does not contain config item \"%s\"", fmt);
		*out = '\0';
		return 0;
	}

	strlcpy(out, value, outlen);

	return strlen(out);
}
コード例 #3
0
/*
 *	Xlat for %{client:foo}
 */
static size_t xlat_client(UNUSED void *instance, REQUEST *request,
                          char *fmt, char *out,
                          size_t outlen,
                          UNUSED RADIUS_ESCAPE_STRING func)
{
    const char *value = NULL;
    CONF_PAIR *cp;

    if (!fmt || !out || (outlen < 1)) return 0;

    if (!request || !request->client) {
        *out = '\0';
        return 0;
    }

    cp = cf_pair_find(request->client->cs, fmt);
    if (!cp || !(value = cf_pair_value(cp))) {
        *out = '\0';
        return 0;
    }

    strlcpy(out, value, outlen);

    return strlen(out);
}
コード例 #4
0
ファイル: mainconfig.c プロジェクト: kzorba/freeradius-server
/*
 *	Xlat for %{client:foo}
 */
static ssize_t xlat_client(UNUSED void *instance, REQUEST *request, char const *fmt, char *out, size_t outlen)
{
	char const *value = NULL;
	CONF_PAIR *cp;

	if (!fmt || !out || (outlen < 1)) return 0;

	if (!request->client) {
		RWDEBUG("No client associated with this request");
		*out = '\0';
		return 0;
	}

	cp = cf_pair_find(request->client->cs, fmt);
	if (!cp || !(value = cf_pair_value(cp))) {
		if (strcmp(fmt, "shortname") == 0) {
			strlcpy(out, request->client->shortname, outlen);
			return strlen(out);
		}
		RDEBUG("Client does not contain config item \"%s\"", fmt);
		*out = '\0';
		return 0;
	}

	strlcpy(out, value, outlen);

	return strlen(out);
}
コード例 #5
0
/*
 *	Find the client definition.
 */
static rlm_rcode_t mod_authorize(UNUSED void *instance,
				 REQUEST *request)
{
	size_t length;
	const char *value;
	CONF_PAIR *cp;
	RADCLIENT *c;
	char buffer[2048];

	/*
	 *	Ensure we're only being called from the main thread,
	 *	with fake packets.
	 */
	if ((request->packet->src_port != 0) || (request->packet->vps != NULL) ||
	    (request->parent != NULL)) {
		RDEBUG("Improper configuration");
		return RLM_MODULE_NOOP;
	}

	if (!request->client || !request->client->cs) {
		RDEBUG("Unknown client definition");
		return RLM_MODULE_NOOP;
	}

	cp = cf_pair_find(request->client->cs, "directory");
	if (!cp) {
		RDEBUG("No directory configuration in the client");
		return RLM_MODULE_NOOP;
	}

	value = cf_pair_value(cp);
	if (!value) {
		RDEBUG("No value given for the directory entry in the client.");
		return RLM_MODULE_NOOP;
	}

	length = strlen(value);
	if (length > (sizeof(buffer) - 256)) {
		RDEBUG("Directory name too long");
		return RLM_MODULE_NOOP;
	}

	memcpy(buffer, value, length + 1);
	ip_ntoh(&request->packet->src_ipaddr,
		buffer + length, sizeof(buffer) - length - 1);

	/*
	 *	Read the buffer and generate the client.
	 */
	c = client_read(buffer, (request->client->server != NULL), TRUE);
	if (!c) return RLM_MODULE_FAIL;

	/*
	 *	Replace the client.  This is more than a bit of a
	 *	hack.
	 */
	request->client = c;

	return RLM_MODULE_OK;
}
コード例 #6
0
ファイル: rlm_perl.c プロジェクト: geaaru/freeradius-server
/*
 *	Parse a configuration section, and populate a HV.
 *	This function is recursively called (allows to have nested hashes.)
 */
static void perl_parse_config(CONF_SECTION *cs, int lvl, HV *rad_hv)
{
	if (!cs || !rad_hv) return;

	int indent_section = (lvl + 1) * 4;
	int indent_item = (lvl + 2) * 4;

	DEBUG("%*s%s {", indent_section, " ", cf_section_name1(cs));

	CONF_ITEM *ci = NULL;

	while ((ci = cf_item_next(cs, ci))) {
		/*
		 *  This is a section.
		 *  Create a new HV, store it as a reference in current HV,
		 *  Then recursively call perl_parse_config with this section and the new HV.
		 */
		if (cf_item_is_section(ci)) {
			CONF_SECTION	*sub_cs = cf_item_to_section(ci);
			char const	*key = cf_section_name1(sub_cs); /* hash key */
			HV		*sub_hv;
			SV		*ref;

			if (!key) continue;

			if (hv_exists(rad_hv, key, strlen(key))) {
				WARN("Ignoring duplicate config section '%s'", key);
				continue;
			}

			sub_hv = newHV();
			ref = newRV_inc((SV*) sub_hv);

			(void)hv_store(rad_hv, key, strlen(key), ref, 0);

			perl_parse_config(sub_cs, lvl + 1, sub_hv);
		} else if (cf_item_is_pair(ci)){
			CONF_PAIR	*cp = cf_item_to_pair(ci);
			char const	*key = cf_pair_attr(cp);	/* hash key */
			char const	*value = cf_pair_value(cp);	/* hash value */

			if (!key || !value) continue;

			/*
			 *  This is an item.
			 *  Store item attr / value in current HV.
			 */
			if (hv_exists(rad_hv, key, strlen(key))) {
				WARN("Ignoring duplicate config item '%s'", key);
				continue;
			}

			(void)hv_store(rad_hv, key, strlen(key), newSVpvn(value, strlen(value)), 0);

			DEBUG("%*s%s = %s", indent_item, " ", key, value);
		}
	}

	DEBUG("%*s}", indent_section, " ");
}
コード例 #7
0
static int rediswho_accounting(void * instance, REQUEST * request)
{
	int rcode;
	VALUE_PAIR * vp;
	DICT_VALUE *dv;
	CONF_SECTION *cs;
	const char *insert, *trim, *expire;
	rlm_rediswho_t *inst = (rlm_rediswho_t *) instance;
	REDISSOCK *dissocket;

	vp = pairfind(request->packet->vps, PW_ACCT_STATUS_TYPE, 0, TAG_ANY);
	if (!vp) {
		RDEBUG("Could not find account status type in packet.");
		return RLM_MODULE_NOOP;
	}

	dv = dict_valbyattr(vp->attribute, vp->vendor, vp->vp_integer);
	if (!dv) {
		RDEBUG("Unknown Acct-Status-Type %u", vp->vp_integer);
		return RLM_MODULE_NOOP;
	}

	cs = cf_section_sub_find(inst->cs, dv->name);
	if (!cs) {
		RDEBUG("No subsection %s", dv->name);
		return RLM_MODULE_NOOP;
	}

	dissocket = fr_connection_get(inst->redis_inst->pool);
	if (!dissocket) {
		RDEBUG("cannot allocate redis connection");
		return RLM_MODULE_FAIL;
	}

	insert = cf_pair_value(cf_pair_find(cs, "insert"));
	trim = cf_pair_value(cf_pair_find(cs, "trim"));
	expire = cf_pair_value(cf_pair_find(cs, "expire"));

	rcode = rediswho_accounting_all(&dissocket, inst, request,
					insert,
					trim,
					expire);

	if (dissocket) fr_connection_release(inst->redis_inst->pool, dissocket);

	return rcode;
}
コード例 #8
0
ファイル: rlm_client.c プロジェクト: geaaru/freeradius-server
static int _map_proc_client_get_vp(TALLOC_CTX *ctx, VALUE_PAIR **out, REQUEST *request,
				   vp_map_t const *map, void *uctx)
{
	client_get_vp_ctx_t	*client = uctx;
	VALUE_PAIR		*head = NULL, *vp;
	fr_cursor_t		cursor;
	fr_dict_attr_t const	*da;
	CONF_PAIR const		*cp;

	rad_assert(ctx != NULL);

	fr_cursor_init(&cursor, &head);

	/*
	 *	FIXME: allow multiple entries.
	 */
	if (map->lhs->type == TMPL_TYPE_ATTR) {
		da = map->lhs->tmpl_da;
	} else {
		char *attr;

		if (tmpl_aexpand(ctx, &attr, request, map->lhs, NULL, NULL) <= 0) {
			RWDEBUG("Failed expanding string");
			return -1;
		}

		da = fr_dict_attr_by_name(request->dict, attr);
		if (!da) {
			RWDEBUG("No such attribute '%s'", attr);
			return -1;
		}

		talloc_free(attr);
	}

	for (cp = client->cp;
	     cp;
	     cp = cf_pair_find_next(client->cs, cp, client->field)) {
		char const *value = cf_pair_value(cp);

		MEM(vp = fr_pair_afrom_da(ctx, da));
		if (fr_pair_value_from_str(vp, value, talloc_array_length(value) - 1, '\0', false) < 0) {
			RWDEBUG("Failed parsing value \"%pV\" for attribute %s: %s", fr_box_strvalue(value),
				map->lhs->tmpl_da->name, fr_strerror());
			fr_pair_list_free(&head);
			talloc_free(vp);
			return -1;
		}

		vp->op = map->op;
		fr_cursor_append(&cursor, vp);

		if (map->op != T_OP_ADD) break;	/* Create multiple attribute for multiple CONF_PAIRs */
	}

	*out = head;

	return 0;
}
コード例 #9
0
ファイル: valuepair.c プロジェクト: anlaneg/freeradius-server
/** Convert CONFIG_PAIR to VALUE_PAIR_MAP.
 *
 * Treats the left operand as a
 * @verbatim<request>.<list>.<attribute>@endverbatim reference and the right
 * operand as a module specific value.
 *
 * The left operand will be pre-parsed into request ref, dst list, and da,
 * the right operand will be left as a string.
 *
 * Return must be freed with radius_mapfree.
 *
 * @param[in] cp to convert to map.
 * @param[in] request_def The default request to insert unqualified
 *	attributes into.
 * @param[in] list_def The default list to insert unqualified attributes into.
 * @return VALUE_PAIR_MAP if successful or NULL on error.
 */
VALUE_PAIR_MAP *radius_cp2map(CONF_PAIR *cp, request_refs_t request_def,
			      pair_lists_t list_def)
{
	VALUE_PAIR_MAP *map;
	const char *attr;
	const char *value;
	
	map = rad_malloc(sizeof(VALUE_PAIR_MAP));
	memset(map, 0, sizeof(VALUE_PAIR_MAP));
     
	attr = cf_pair_attr(cp);
	
	map->dst = radius_attr2tmpl(attr, request_def, list_def);
	if (!map->dst){
		goto error;
	}

	value = cf_pair_value(cp);
	if (!value) {
		radlog(L_ERR, "Missing attribute name");
		
		goto error;
	}
	
	map->src = radius_str2tmpl(value);
	if (!map->src) {
		goto error;
	}
	
	map->op_token = cf_pair_operator(cp);
	
	/*
	 *	Infer whether we need to expand the mapping values
	 *	The old style attribute map allowed the user to specify
	 *	whether the LDAP value should be expanded. 
	 *	We can't really support that easily, but equivalent
	 *	functionality should be available with %{eval:}
	 */
	switch (cf_pair_value_type(cp))
	{
		case T_BARE_WORD:
		case T_SINGLE_QUOTED_STRING:
			map->src->do_xlat = FALSE;
		break;
		case T_BACK_QUOTED_STRING:
		case T_DOUBLE_QUOTED_STRING:
			map->src->do_xlat = TRUE;		
		break;
		default:
			rad_assert(0);
			goto error;
	}
	
	return map;
	
	error:
		radius_mapfree(&map);
		return NULL;
}
コード例 #10
0
/** Iterate over all client attribute pairs and create client pair data using JSON element names
 *
 * If we hit a CONF_SECTION we recurse and process its CONF_PAIRS as well to support nested
 * configurations sections.
 *
 * @param client The new client config section using the mapped names.
 * @param map    The client attribute section from the module configuration.
 * @param json   JSON object representation of a client document fetched from Couchbase.
 * @param docid  Document id.
 * @return       Returns 0 on success, -1 on error.
 */
int _mod_client_map_section(CONF_SECTION *client, CONF_SECTION const *map,
			    json_object *json, char const *docid)
{
	CONF_ITEM const *ci;

	for (ci = cf_item_find_next(map, NULL); ci != NULL; ci = cf_item_find_next(map, ci)) {
		CONF_PAIR const *cp;
		char const *attribute;
		char const *element;
		json_object *jval;

		/*
		 * Recursively process map subsection
		 */
		if (cf_item_is_section(ci)) {
			CONF_SECTION *cs, *cc;    /* local scoped for new section */

			cs = cf_itemtosection(ci);
			cc = cf_section_alloc(client, cf_section_name1(cs), cf_section_name2(cs));
			if (!cc) return -1;

			cf_section_add(client, cc);

			if (_mod_client_map_section(cc, cs, json, docid) != 0) {
				return -1;
			}
			/* continue on to the next item */
			continue;
		}

		/* create pair from item and get attribute name and value */
		cp = cf_itemtopair(ci);
		attribute = cf_pair_attr(cp);
		element = cf_pair_value(cp);

		/* attempt to find element in json object */
		if (!json_object_object_get_ex(json, element, &jval)) {
			/* skip this item */
			continue;
		}

		/* allocate config pair */
		cp = cf_pair_alloc(client, attribute, json_object_get_string(jval), T_OP_SET, T_SINGLE_QUOTED_STRING);

		/* check pair */
		if (!cp) {
			ERROR("rlm_couchbase: failed allocating config pair '%s' = '%s'", attribute, json_object_get_string(jval));
			return -1;
		}

		/* add pair to section */
		cf_item_add(client, cf_pairtoitem(cp));
	}

	/* return success */
	return 0;
}
コード例 #11
0
/** Build a JSON object map from the configuration "map" section
 *
 * Parse the "map" section from the module configuration file and store this
 * as a JSON object (key/value list) in the module instance.  This map will be
 * used to lookup and map attributes for all incoming accounting requests.
 *
 * @param  conf     Configuration section.
 * @param  instance The module instance.
 * @return          Returns 0 on success, -1 on error.
 */
int mod_build_attribute_element_map(CONF_SECTION *conf, void *instance)
{
	rlm_couchbase_t *inst = instance;   /* our module instance */
	CONF_SECTION *cs;                   /* module config section */
	CONF_ITEM *ci;                      /* config item */
	CONF_PAIR *cp;                      /* conig pair */
	const char *attribute, *element;    /* attribute and element names */

	/* find map section */
	cs = cf_section_sub_find(conf, "map");

	/* check section */
	if (!cs) {
		ERROR("rlm_couchbase: failed to find 'map' section in config");
		/* fail */
		return -1;
	}

	/* create attribute map object */
	inst->map = json_object_new_object();

	/* parse update section */
	for (ci = cf_item_find_next(cs, NULL); ci != NULL; ci = cf_item_find_next(cs, ci)) {
		/* validate item */
		if (!cf_item_is_pair(ci)) {
			ERROR("rlm_couchbase: failed to parse invalid item in 'map' section");
			/* free map */
			if (inst->map) {
				json_object_put(inst->map);
			}
			/* fail */
			return -1;
		}

		/* get value pair from item */
		cp = cf_itemtopair(ci);

		/* get pair name (element name) */
		element = cf_pair_attr(cp);

		/* get pair value (attribute name) */
		attribute = cf_pair_value(cp);

		/* add pair name and value */
		json_object_object_add(inst->map, attribute, json_object_new_string(element));

		/* debugging */
		DEBUG("rlm_couchbase: added attribute '%s' to element '%s' map to object", attribute, element);
	}

	/* debugging */
	DEBUG("rlm_couchbase: built attribute to element map %s", json_object_to_json_string(inst->map));

	/* return */
	return 0;
}
コード例 #12
0
static int rad_load_transforms(struct Protocol *prot, CONF_SECTION *cf)
{
	CONF_PAIR *cp;
	int option_exists = 0;
	int i = 0;

	rad_assert(prot);
	rad_assert(cf);

	DEBUG(IKEv2_LOG_PREFIX "Begin load transforms");

	while(config_transforms[i].name)
	{
		uint8_t id;
		uint16_t keylen;

		for(cp = cf_pair_find(cf,config_transforms[i].name);
		    cp;
		    cp = cf_pair_find_next(cf,cp,config_transforms[i].name)) {
			if (TransformFromName(cf_pair_value(cp),config_transforms[i].type,&id,&keylen)) {
				ERROR(IKEv2_LOG_PREFIX "Unsupported %s transform: %s ",
				      config_transforms[i].name,cf_pair_value(cp));
				return -1;
			}

			if (!AddTransform(prot,config_transforms[i].type,id,keylen)) {
				ERROR(IKEv2_LOG_PREFIX "Problem with transform %s:%s",
				      config_transforms[i].name,cf_pair_value(cp));
				return -1;
			}
			option_exists |= config_transforms[i].exist_flag;
		}
		i++;
	}

	if ((option_exists & OPT_NEEDED) != OPT_NEEDED) {
		ERROR(IKEv2_LOG_PREFIX "Not all mandatory transforms are set properly");
		DEBUG(IKEv2_LOG_PREFIX "Option flags: 0x%02X",option_exists);

		return -1;
	}
	return 0;
}
コード例 #13
0
static int virtual_server_parse(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent,
				CONF_ITEM *ci, UNUSED CONF_PARSER const *rule)
{
	CONF_SECTION	*server_cs;

	if (virtual_server_has_namespace(&server_cs, cf_pair_value(cf_item_to_pair(ci)),
					 dict_eap_aka, ci) < 0) return -1;

	if (mod_section_compile(out, server_cs) < 0) return -1;

	return 0;
}
コード例 #14
0
ファイル: mainconfig.c プロジェクト: archsh/freeradius-server
/*
 *	Xlat for %{getclient:<ipaddr>.foo}
 */
static ssize_t xlat_getclient(UNUSED void *instance, REQUEST *request, char const *fmt, char *out, size_t outlen)
{
	char const *value = NULL;
	char buffer[INET6_ADDRSTRLEN], *q;
	char const *p = fmt;
	fr_ipaddr_t ip;
	CONF_PAIR *cp;
	RADCLIENT *client = NULL;

	if (!fmt || !out || (outlen < 1)) return 0;

	q = strrchr(p, '.');
	if (!q || (q == p) || (((size_t)(q - p)) > sizeof(buffer))) {
		REDEBUG("Invalid client string");
		goto error;
	}

	strlcpy(buffer, p, (q + 1) - p);
	memset(&ip, 0, sizeof(ip));

	if (ip_ptonx(buffer, &ip) <= 0) {
		REDEBUG("\"%s\" is not a valid IPv4 or IPv6 address", buffer);
		goto error;
	}

	fmt = q + 1;

	client = client_find(NULL, &ip, IPPROTO_IP);
	if (!client) {
		RDEBUG("No client found with IP \"%s\"", buffer);
		*out = '\0';
		return 0;
	}

	cp = cf_pair_find(client->cs, fmt);
	if (!cp || !(value = cf_pair_value(cp))) {
		if (strcmp(fmt, "shortname") == 0) {
			strlcpy(out, request->client->shortname, outlen);
			return strlen(out);
		}
		RDEBUG("Client does not contain config item \"%s\"", fmt);
		*out = '\0';
		return 0;
	}

	strlcpy(out, value, outlen);
	return strlen(out);

error:
	*out = '\0';
	return -1;
}
コード例 #15
0
ファイル: rlm_client.c プロジェクト: geaaru/freeradius-server
/*
 *	Xlat for %{client:[<ipaddr>.]foo}
 */
static ssize_t xlat_client(TALLOC_CTX *ctx, char **out, UNUSED size_t outlen,
			   UNUSED void const *mod_inst, UNUSED void const *xlat_inst,
			   REQUEST *request, char const *fmt)
{
	char const	*value = NULL;
	char		buffer[INET6_ADDRSTRLEN], *q;
	char const	*p = fmt;
	fr_ipaddr_t	ip;
	CONF_PAIR	*cp;
	RADCLIENT	*client = NULL;

	*out = NULL;

	q = strrchr(p, '.');
	if (q) {
		strlcpy(buffer, p, (q + 1) - p);
		if (fr_inet_pton(&ip, buffer, -1, AF_UNSPEC, false, true) < 0) goto request_client;

		p = q + 1;

		client = client_find(NULL, &ip, IPPROTO_IP);
		if (!client) {
			RDEBUG("No client found with IP \"%s\"", buffer);
			return 0;
		}
	} else {
	request_client:
		client = request->client;
		if (!client) {
			RERROR("No client associated with this request");

			return -1;
		}
	}

	cp = cf_pair_find(client->cs, p);
	if (!cp || !(value = cf_pair_value(cp))) {
		if (strcmp(fmt, "shortname") == 0 && request->client->shortname) {
			value = request->client->shortname;
		}
		else if (strcmp(fmt, "nas_type") == 0 && request->client->nas_type) {
			value = request->client->nas_type;
		}
		if (!value) return 0;
	}

	*out = talloc_typed_strdup(ctx, value);
	return talloc_array_length(*out) - 1;
}
コード例 #16
0
/** Set which types of packets we can parse
 *
 * @param[in] ctx	to allocate data in (instance of rlm_radius).
 * @param[out] out	Where to write the parsed data.
 * @param[in] parent	Base structure address.
 * @param[in] ci	#CONF_PAIR specifying the name of the type module.
 * @param[in] rule	unused.
 * @return
 *	- 0 on success.
 *	- -1 on failure.
 */
static int type_parse(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent,
		      CONF_ITEM *ci, UNUSED CONF_PARSER const *rule)
{
	char const		*type_str = cf_pair_value(cf_item_to_pair(ci));
	CONF_SECTION		*cs = cf_item_to_section(cf_parent(ci));
	fr_dict_enum_t const	*type_enum;
	uint32_t		code;

	/*
	 *	Must be the RADIUS module
	 */
	rad_assert(cs && (strcmp(cf_section_name1(cs), "radius") == 0));

	/*
	 *	Allow the process module to be specified by
	 *	packet type.
	 */
	type_enum = fr_dict_enum_by_alias(attr_packet_type, type_str, -1);
	if (!type_enum) {
	invalid_code:
		cf_log_err(ci, "Unknown or invalid RADIUS packet type '%s'", type_str);
		return -1;
	}

	code = type_enum->value->vb_uint32;

	/*
	 *	Status-Server packets cannot be proxied.
	 */
	if (code == FR_CODE_STATUS_SERVER) {
		cf_log_err(ci, "Invalid setting of 'type = Status-Server'.  Status-Server packets cannot be proxied.");
		return -1;
	}

	if (!code ||
	    (code >= FR_MAX_PACKET_CODE) ||
	    (!type_interval_config[code].name)) goto invalid_code;

	/*
	 *	If we're doing async proxying, push the timers for the
	 *	various packet types.
	 */
	cf_section_rule_push(cs, &type_interval_config[code]);

	memcpy(out, &code, sizeof(code));

	return 0;
}
コード例 #17
0
ファイル: mod.c プロジェクト: arr2036/freeradius-server
/** Handle client value processing for client_map_section()
 *
 * @param  out  Character output
 * @param  cp   Configuration pair
 * @param  data The client data
 * @return      Returns 0 on success, -1 on error.
 */
static int _get_client_value(char **out, CONF_PAIR const *cp, void *data)
{
	json_object *jval;

	if (!json_object_object_get_ex((json_object *)data, cf_pair_value(cp), &jval)) {
		*out = NULL;
		return 0;
	}

	if (!jval) return -1;

	*out = talloc_strdup(NULL, json_object_get_string(jval));
	if (!*out) return -1;

	return 0;
}
コード例 #18
0
ファイル: mainconfig.c プロジェクト: Gejove/freeradius-server
/*
 *	Xlat for %{config:section.subsection.attribute}
 */
static size_t xlat_config(void *instance, REQUEST *request,
			  const char *fmt, char *out,
			  size_t outlen)
{
	const char *value;
	CONF_PAIR *cp;
	CONF_ITEM *ci;
	char buffer[1024];

	request = request;	/* -Wunused */
	instance = instance;	/* -Wunused */

	/*
	 *	Expand it safely.
	 */
	if (!radius_xlat(buffer, sizeof(buffer), fmt, request, config_escape_func, NULL)) {
		return 0;
	}

	ci = cf_reference_item(request->root->config,
			       request->root->config, buffer);
	if (!ci || !cf_item_is_pair(ci)) {
		*out = '\0';
		return 0;
	}

	cp = cf_itemtopair(ci);

	/*
	 *  Ensure that we only copy what's necessary.
	 *
	 *  If 'outlen' is too small, then the output is chopped to fit.
	 */
	value = cf_pair_value(cp);
	if (!value) {
		out[0] = '\0';
		return 0;
	}

	if (outlen > strlen(value)) {
		outlen = strlen(value) + 1;
	}

	strlcpy(out, value, outlen);

	return strlen(out);
}
コード例 #19
0
/** Allow for Status-Server ping checks
 *
 * @param[in] ctx	to allocate data in (instance of proto_radius).
 * @param[out] out	Where to write our parsed data.
 * @param[in] parent	Base structure address.
 * @param[in] ci	#CONF_PAIR specifying the name of the type module.
 * @param[in] rule	unused.
 * @return
 *	- 0 on success.
 *	- -1 on failure.
 */
static int status_check_type_parse(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent,
				   CONF_ITEM *ci, UNUSED CONF_PARSER const *rule)
{
	char const		*type_str = cf_pair_value(cf_item_to_pair(ci));
	CONF_SECTION		*cs = cf_item_to_section(cf_parent(ci));
	fr_dict_enum_t const	*type_enum;
	uint32_t		code;

	/*
	 *	Allow the process module to be specified by
	 *	packet type.
	 */
	type_enum = fr_dict_enum_by_alias(attr_packet_type, type_str, -1);
	if (!type_enum) {
	invalid_code:
		cf_log_err(ci, "Unknown or invalid RADIUS packet type '%s'", type_str);
		return -1;
	}

	code = type_enum->value->vb_uint32;

	/*
	 *	Cheat, and re-use the "type" array for allowed packet
	 *	types.
	 */
	if (!code ||
	    (code >= FR_MAX_PACKET_CODE) ||
	    (!type_interval_config[code].name)) goto invalid_code;

	/*
	 *	Add irt / mrt / mrd / mrc parsing, in the parent
	 *	configuration section.
	 */
	cf_section_rule_push(cf_item_to_section(cf_parent(cs)), &type_interval_config[code]);

	memcpy(out, &code, sizeof(code));

	/*
	 *	Nothing more to do here, so we stop.
	 */
	if (code == FR_CODE_STATUS_SERVER) return 0;

	cf_section_rule_push(cs, status_check_update_config);

	return 0;
}
コード例 #20
0
/** Iterate over pairs in mapping section creating equivalent client pairs from LDAP values
 *
 * If we hit a CONF_SECTION we recurse and process its CONF_PAIRS too.
 *
 * @param[in] inst rlm_ldap configuration.
 * @param[out] client config section.
 * @param[in] map section.
 * @param[in] conn LDAP connection.
 * @param[in] entry returned from search.
 * @return 0 on success else -1 on error.
 */
static int rlm_ldap_client_map_section(ldap_instance_t const *inst, CONF_SECTION *client,
				       CONF_SECTION const *map, ldap_handle_t *conn,
				       LDAPMessage *entry)
{
	CONF_ITEM const *ci;

	for (ci = cf_item_find_next(map, NULL);
	     ci != NULL;
	     ci = cf_item_find_next(map, ci)) {
	     	CONF_PAIR const *cp;
	     	char **value;
		char const *attr;

		/*
		 *	Recursively process map subsection
		 */
		if (cf_item_is_section(ci)) {
			CONF_SECTION *cs, *cc;

			cs = cf_itemtosection(ci);
			cc = cf_section_alloc(client, cf_section_name1(cs), cf_section_name2(cs));
			if (!cc) return -1;

			cf_section_add(client, cc);

			if (rlm_ldap_client_map_section(inst, cc, cs, conn, entry) < 0) return -1;
			continue;
		}

		cp = cf_itemtopair(ci);
		attr = cf_pair_attr(cp);

		value = ldap_get_values(conn->handle, entry, cf_pair_value(cp));
		if (!value) continue;

		cp = cf_pair_alloc(client, attr, value[0], T_OP_SET, T_SINGLE_QUOTED_STRING);
		if (!cp) {
			LDAP_ERR("Failed allocing pair \"%s\" = \"%s\"", attr, value[0]);
			return -1;
		}
		cf_item_add(client, cf_pairtoitem(cp));
	}

	return 0;
}
コード例 #21
0
ファイル: mainconfig.c プロジェクト: kzorba/freeradius-server
/*
 *	Xlat for %{config:section.subsection.attribute}
 */
static ssize_t xlat_config(UNUSED void *instance, REQUEST *request, char const *fmt, char *out, size_t outlen)
{
	char const *value;
	CONF_PAIR *cp;
	CONF_ITEM *ci;
	char buffer[1024];

	/*
	 *	Expand it safely.
	 */
	if (radius_xlat(buffer, sizeof(buffer), request, fmt, config_escape_func, NULL) < 0) {
		return 0;
	}

	ci = cf_reference_item(request->root->config,
			       request->root->config, buffer);
	if (!ci || !cf_item_is_pair(ci)) {
		REDEBUG("Config item \"%s\" does not exist", fmt);
		*out = '\0';
		return -1;
	}

	cp = cf_itemtopair(ci);

	/*
	 *  Ensure that we only copy what's necessary.
	 *
	 *  If 'outlen' is too small, then the output is chopped to fit.
	 */
	value = cf_pair_value(cp);
	if (!value) {
		out[0] = '\0';
		return 0;
	}

	if (outlen > strlen(value)) {
		outlen = strlen(value) + 1;
	}

	strlcpy(out, value, outlen);

	return strlen(out);
}
コード例 #22
0
/*
 *	Write accounting information to this module's database.
 */
static int sql_log_accounting(void *instance, REQUEST *request)
{
	int		ret;
	char		querystr[MAX_QUERY_LEN];
	const char	*cfquery;
	rlm_sql_log_t	*inst = (rlm_sql_log_t *)instance;
	VALUE_PAIR	*pair;
	DICT_VALUE	*dval;
	CONF_PAIR	*cp;

	rad_assert(request != NULL);
	rad_assert(request->packet != NULL);

	RDEBUG("Processing sql_log_accounting");

	/* Find the Acct Status Type. */
	if ((pair = pairfind(request->packet->vps, PW_ACCT_STATUS_TYPE)) == NULL) {
		radlog_request(L_ERR, 0, request, "Packet has no account status type");
		return RLM_MODULE_INVALID;
	}

	/* Search the query in conf section of the module */
	if ((dval = dict_valbyattr(PW_ACCT_STATUS_TYPE, pair->vp_integer)) == NULL) {
		radlog_request(L_ERR, 0, request, "Unsupported Acct-Status-Type = %d",
			       pair->vp_integer);
		return RLM_MODULE_NOOP;
	}
	if ((cp = cf_pair_find(inst->conf_section, dval->name)) == NULL) {
		RDEBUG("Couldn't find an entry %s in the config section",
		       dval->name);
		return RLM_MODULE_NOOP;
	}
	cfquery = cf_pair_value(cp);

	/* Xlat the query */
	ret = sql_xlat_query(inst, request, cfquery, querystr, sizeof(querystr));
	if (ret != RLM_MODULE_OK)
		return ret;

	/* Write query into sql-relay file */
	return sql_log_write(inst, request, querystr);
}
コード例 #23
0
ファイル: mainconfig.c プロジェクト: janetuk/freeradius
/*
 *	Xlat for %{listen:foo}
 */
static ssize_t xlat_listen(UNUSED void *instance, REQUEST *request,
			   char const *fmt, char *out, size_t outlen)
{
	char const *value = NULL;
	CONF_PAIR *cp;

	if (!fmt || !out || (outlen < 1)) return 0;

	if (!request->listener) {
		RWDEBUG("No listener associated with this request");
		*out = '\0';
		return 0;
	}

#ifdef WITH_TLS
	/*
	 *	Look for TLS certificate data.
	 */
	if (strncmp(fmt, "TLS-", 4) == 0) {
		VALUE_PAIR *vp;
		listen_socket_t *sock = request->listener->data;

		for (vp = sock->certs; vp != NULL; vp = vp->next) {
			if (strcmp(fmt, vp->da->name) == 0) {
				return vp_prints_value(out, outlen, vp, 0);
			}
		}
	}
#endif

	cp = cf_pair_find(request->listener->cs, fmt);
	if (!cp || !(value = cf_pair_value(cp))) {
		RDEBUG("Listener does not contain config item \"%s\"", fmt);
		*out = '\0';
		return 0;
	}

	strlcpy(out, value, outlen);

	return strlen(out);
}
コード例 #24
0
/** Wrapper around dl_instance
 *
 * @param[in] ctx	to allocate data in (instance of proto_radius).
 * @param[out] out	Where to write a dl_instance_t containing the module handle and instance.
 * @param[in] parent	Base structure address.
 * @param[in] ci	#CONF_PAIR specifying the name of the type module.
 * @param[in] rule	unused.
 * @return
 *	- 0 on success.
 *	- -1 on failure.
 */
static int transport_parse(TALLOC_CTX *ctx, void *out, UNUSED void *parent,
			   CONF_ITEM *ci, UNUSED CONF_PARSER const *rule)
{
	char const	*name = cf_pair_value(cf_item_to_pair(ci));
	dl_instance_t	*parent_inst;
	CONF_SECTION	*cs = cf_item_to_section(cf_parent(ci));
	CONF_SECTION	*transport_cs;

	transport_cs = cf_section_find(cs, name, NULL);

	/*
	 *	Allocate an empty section if one doesn't exist
	 *	this is so defaults get parsed.
	 */
	if (!transport_cs) transport_cs = cf_section_alloc(cs, cs, name, NULL);

	parent_inst = cf_data_value(cf_data_find(cs, dl_instance_t, "rlm_radius"));
	rad_assert(parent_inst);

	return dl_instance(ctx, out, transport_cs, parent_inst, name, DL_TYPE_SUBMODULE);
}
コード例 #25
0
/** Iterate over pairs in mapping section recording their values in an array
 *
 * This array is the list of attributes we retrieve from LDAP, and is NULL
 * terminated.
 *
 * If we hit a CONF_SECTION we recurse and process its CONF_PAIRS too.
 *
 * @param[out] values array of char pointers.
 * @param[in,out] idx records current array offset.
 * @param[in] cs to iterate over.
 * @return 0 on success else -1 on error.
 */
static int rlm_ldap_client_get_attrs(char const **values, int *idx, CONF_SECTION const *cs)
{
	CONF_ITEM const *ci;

	for (ci = cf_item_find_next(cs, NULL);
	     ci != NULL;
	     ci = cf_item_find_next(cs, ci)) {
	     	char const *value;

		if (cf_item_is_section(ci)) {
			if (rlm_ldap_client_get_attrs(values, idx, cf_itemtosection(ci)) < 0) return -1;
			continue;
		}

		value = cf_pair_value(cf_itemtopair(ci));
		if (!value) return -1;

		values[(*idx)++] = value;
	}

	values[*idx] = NULL;

	return 0;
}
コード例 #26
0
ファイル: rlm_ldap.c プロジェクト: masuz/freeradius-server
/** Modify user's object in LDAP
 *
 * Process a modifcation map to update a user object in the LDAP directory.
 *
 * @param inst rlm_ldap instance.
 * @param request Current request.
 * @param section that holds the map to process.
 * @return one of the RLM_MODULE_* values.
 */
static rlm_rcode_t user_modify(ldap_instance_t *inst, REQUEST *request, ldap_acct_section_t *section)
{
	rlm_rcode_t	rcode = RLM_MODULE_OK;
	ldap_rcode_t	status;

	ldap_handle_t	*conn = NULL;

	LDAPMod		*mod_p[LDAP_MAX_ATTRMAP + 1], mod_s[LDAP_MAX_ATTRMAP];
	LDAPMod		**modify = mod_p;

	char		*passed[LDAP_MAX_ATTRMAP * 2];
	int		i, total = 0, last_pass = 0;

	char 		*expanded[LDAP_MAX_ATTRMAP];
	int		last_exp = 0;

	char const	*attr;
	char const	*value;

	char const	*dn;
	/*
	 *	Build our set of modifications using the update sections in
	 *	the config.
	 */
	CONF_ITEM  	*ci;
	CONF_PAIR	*cp;
	CONF_SECTION 	*cs;
	FR_TOKEN	op;
	char		path[MAX_STRING_LEN];

	char		*p = path;

	rad_assert(section);

	/*
	 *	Locate the update section were going to be using
	 */
	if (section->reference[0] != '.') {
		*p++ = '.';
	}

	if (radius_xlat(p, (sizeof(path) - (p - path)) - 1, request, section->reference, NULL, NULL) < 0) {
		goto error;
	}

	ci = cf_reference_item(NULL, section->cs, path);
	if (!ci) {
		goto error;
	}

	if (!cf_item_is_section(ci)){
		REDEBUG("Reference must resolve to a section");

		goto error;
	}

	cs = cf_section_sub_find(cf_itemtosection(ci), "update");
	if (!cs) {
		REDEBUG("Section must contain 'update' subsection");

		goto error;
	}

	/*
	 *	Iterate over all the pairs, building our mods array
	 */
	for (ci = cf_item_find_next(cs, NULL); ci != NULL; ci = cf_item_find_next(cs, ci)) {
		bool do_xlat = false;

		if (total == LDAP_MAX_ATTRMAP) {
			REDEBUG("Modify map size exceeded");

			goto error;
		}

		if (!cf_item_is_pair(ci)) {
			REDEBUG("Entry is not in \"ldap-attribute = value\" format");

			goto error;
		}

		/*
		 *	Retrieve all the information we need about the pair
		 */
		cp = cf_itemtopair(ci);
		value = cf_pair_value(cp);
		attr = cf_pair_attr(cp);
		op = cf_pair_operator(cp);

		if (!value || (*value == '\0')) {
			RDEBUG("Empty value string, skipping attribute \"%s\"", attr);

			continue;
		}

		switch (cf_pair_value_type(cp)) {
		case T_BARE_WORD:
		case T_SINGLE_QUOTED_STRING:
			break;

		case T_BACK_QUOTED_STRING:
		case T_DOUBLE_QUOTED_STRING:
			do_xlat = true;
			break;

		default:
			rad_assert(0);
			goto error;
		}

		if (op == T_OP_CMP_FALSE) {
			passed[last_pass] = NULL;
		} else if (do_xlat) {
			char *exp = NULL;

			if (radius_axlat(&exp, request, value, NULL, NULL) <= 0) {
				RDEBUG("Skipping attribute \"%s\"", attr);

				talloc_free(exp);

				continue;
			}

			expanded[last_exp++] = exp;
			passed[last_pass] = exp;
		/*
		 *	Static strings
		 */
		} else {
			memcpy(&(passed[last_pass]), &value, sizeof(passed[last_pass]));
		}

		passed[last_pass + 1] = NULL;

		mod_s[total].mod_values = &(passed[last_pass]);

		last_pass += 2;

		switch (op) {
		/*
		 *  T_OP_EQ is *NOT* supported, it is impossible to
		 *  support because of the lack of transactions in LDAP
		 */
		case T_OP_ADD:
			mod_s[total].mod_op = LDAP_MOD_ADD;
			break;

		case T_OP_SET:
			mod_s[total].mod_op = LDAP_MOD_REPLACE;
			break;

		case T_OP_SUB:
		case T_OP_CMP_FALSE:
			mod_s[total].mod_op = LDAP_MOD_DELETE;
			break;

#ifdef LDAP_MOD_INCREMENT
		case T_OP_INCRM:
			mod_s[total].mod_op = LDAP_MOD_INCREMENT;
			break;
#endif
		default:
			REDEBUG("Operator '%s' is not supported for LDAP modify operations",
				fr_int2str(fr_tokens, op, "<INVALID>"));

			goto error;
		}

		/*
		 *	Now we know the value is ok, copy the pointers into
		 *	the ldapmod struct.
		 */
		memcpy(&(mod_s[total].mod_type), &attr, sizeof(mod_s[total].mod_type));

		mod_p[total] = &(mod_s[total]);
		total++;
	}

	if (total == 0) {
		rcode = RLM_MODULE_NOOP;
		goto release;
	}

	mod_p[total] = NULL;

	conn = mod_conn_get(inst, request);
	if (!conn) return RLM_MODULE_FAIL;


	dn = rlm_ldap_find_user(inst, request, &conn, NULL, false, NULL, &rcode);
	if (!dn || (rcode != RLM_MODULE_OK)) {
		goto error;
	}

	status = rlm_ldap_modify(inst, request, &conn, dn, modify);
	switch (status) {
	case LDAP_PROC_SUCCESS:
		break;

	case LDAP_PROC_REJECT:
	case LDAP_PROC_BAD_DN:
		rcode = RLM_MODULE_INVALID;
		break;

	default:
		rcode = RLM_MODULE_FAIL;
		break;
	};

	release:
	error:
	/*
	 *	Free up any buffers we allocated for xlat expansion
	 */
	for (i = 0; i < last_exp; i++) {
		talloc_free(expanded[i]);
	}

	mod_conn_release(inst, conn);

	return rcode;
}
コード例 #27
0
ファイル: eap_tls.c プロジェクト: roocell/freeradius-server
/*
 *	Parse TLS configuration
 *
 *	If the option given by 'attr' is set, we find the config section
 *	of that name and use that for the TLS configuration. If not, we
 *	fall back to compatibility mode and read the TLS options from
 *	the 'tls' section.
 */
fr_tls_server_conf_t *eaptls_conf_parse(CONF_SECTION *cs, char const *attr)
{
	char const 		*tls_conf_name;
	CONF_PAIR		*cp;
	CONF_SECTION		*parent;
	CONF_SECTION		*tls_cs;
	fr_tls_server_conf_t	*tls_conf;

	if (!cs)
		return NULL;

	rad_assert(attr != NULL);

	parent = cf_item_parent(cf_section_to_item(cs));

	cp = cf_pair_find(cs, attr);
	if (cp) {
		tls_conf_name = cf_pair_value(cp);

		tls_cs = cf_section_sub_find_name2(parent, TLS_CONFIG_SECTION, tls_conf_name);

		if (!tls_cs) {
			ERROR("Cannot find tls config \"%s\"", tls_conf_name);
			return NULL;
		}
	} else {
		/*
		 *	If we can't find the section given by the 'attr', we
		 *	fall-back to looking for the "tls" section, as in
		 *	previous versions.
		 *
		 *	We don't fall back if the 'attr' is specified, but we can't
		 *	find the section - that is just a config error.
		 */
		INFO("TLS section \"%s\" missing, trying to use legacy configuration", attr);
		tls_cs = cf_section_sub_find(parent, "tls");
	}

	if (!tls_cs)
		return NULL;

	tls_conf = tls_server_conf_parse(tls_cs);

	if (!tls_conf)
		return NULL;

	/*
	 *	The EAP RFC's say 1020, but we're less picky.
	 */
	if (tls_conf->fragment_size < 100) {
		ERROR("Configured fragment size is too small, must be >= 100");
		return NULL;
	}

	/*
	 *	The maximum size for a RADIUS packet is 4096,
	 *	minus the header (20), Message-Authenticator (18),
	 *	and State (18), etc. results in about 4000 bytes of data
	 *	that can be devoted *solely* to EAP.
	 */
	if (tls_conf->fragment_size > 4000) {
		ERROR("Configured fragment size is too large, must be <= 4000");
		return NULL;
	}

	/*
	 *	Account for the EAP header (4), and the EAP-TLS header
	 *	(6), as per Section 4.2 of RFC 2716.  What's left is
	 *	the maximum amount of data we read from a TLS buffer.
	 */
	tls_conf->fragment_size -= 10;

	return tls_conf;
}
コード例 #28
0
ファイル: mainconfig.c プロジェクト: Gejove/freeradius-server
/*
 *	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;
}
コード例 #29
0
ファイル: rlm_sql.c プロジェクト: nvdnkpr/freeradius-server
/*
 *	Generic function for failing between a bunch of queries.
 *
 *	Uses the same principle as rlm_linelog, expanding the 'reference' config
 *	item using xlat to figure out what query it should execute.
 *
 *	If the reference matches multiple config items, and a query fails or
 *	doesn't update any rows, the next matching config item is used.
 *
 */
static int acct_redundant(rlm_sql_t *inst, REQUEST *request, sql_acct_section_t *section)
{
	rlm_rcode_t		rcode = RLM_MODULE_OK;

	rlm_sql_handle_t	*handle = NULL;
	int			sql_ret;
	int			numaffected = 0;

	CONF_ITEM		*item;
	CONF_PAIR 		*pair;
	char const		*attr = NULL;
	char const		*value;

	char			path[MAX_STRING_LEN];
	char			*p = path;
	char			*expanded = NULL;

	rad_assert(section);

	if (section->reference[0] != '.') {
		*p++ = '.';
	}

	if (radius_xlat(p, sizeof(path) - (p - path), request, section->reference, NULL, NULL) < 0) {
		rcode = RLM_MODULE_FAIL;

		goto finish;
	}

	item = cf_reference_item(NULL, section->cs, path);
	if (!item) {
		rcode = RLM_MODULE_FAIL;

		goto finish;
	}

	if (cf_item_is_section(item)){
		REDEBUG("Sections are not supported as references");
		rcode = RLM_MODULE_FAIL;

		goto finish;
	}

	pair = cf_itemtopair(item);
	attr = cf_pair_attr(pair);

	RDEBUG2("Using query template '%s'", attr);

	handle = sql_get_socket(inst);
	if (!handle) {
		rcode = RLM_MODULE_FAIL;

		goto finish;
	}

	sql_set_user(inst, request, NULL);

	while (true) {
		value = cf_pair_value(pair);
		if (!value) {
			RDEBUG("Ignoring null query");
			rcode = RLM_MODULE_NOOP;

			goto finish;
		}

		if (radius_axlat(&expanded, request, value, sql_escape_func, inst) < 0) {
			rcode = RLM_MODULE_FAIL;

			goto finish;
		}

		if (!*expanded) {
			RDEBUG("Ignoring null query");
			rcode = RLM_MODULE_NOOP;
			talloc_free(expanded);

			goto finish;
		}

		rlm_sql_query_log(inst, request, section, expanded);

		/*
		 *  If rlm_sql_query cannot use the socket it'll try and
		 *  reconnect. Reconnecting will automatically release
		 *  the current socket, and try to select a new one.
		 *
		 *  If we get RLM_SQL_RECONNECT it means all connections in the pool
		 *  were exhausted, and we couldn't create a new connection,
		 *  so we do not need to call sql_release_socket.
		 */
		sql_ret = rlm_sql_query(&handle, inst, expanded);
		TALLOC_FREE(expanded);

		if (sql_ret == RLM_SQL_RECONNECT) {
			rcode = RLM_MODULE_FAIL;

			goto finish;
		}
		rad_assert(handle);

		/*
		 *  Assume all other errors are incidental, and just meant our
		 *  operation failed and its not a client or SQL syntax error.
		 *
		 *  @fixme We should actually be able to distinguish between key
		 *  constraint violations (which we expect) and other errors.
		 */
		if (sql_ret == RLM_SQL_OK) {
			numaffected = (inst->module->sql_affected_rows)(handle, inst->config);
			if (numaffected > 0) {
				break;	/* A query succeeded, were done! */
			}

			RDEBUG("No records updated");
		}

		(inst->module->sql_finish_query)(handle, inst->config);

		/*
		 *  We assume all entries with the same name form a redundant
		 *  set of queries.
		 */
		pair = cf_pair_find_next(section->cs, pair, attr);

		if (!pair) {
			RDEBUG("No additional queries configured");
			rcode = RLM_MODULE_NOOP;

			goto finish;
		}

		RDEBUG("Trying next query...");
	}

	(inst->module->sql_finish_query)(handle, inst->config);

	finish:
	talloc_free(expanded);
	sql_release_socket(inst, handle);

	return rcode;
}
コード例 #30
0
ファイル: radmin.c プロジェクト: masuz/freeradius-server
int main(int argc, char **argv)
{
	int		argval;
	bool		quiet = false;
	int		sockfd = -1;
	char		*line = NULL;
	ssize_t		len;
	char const	*file = NULL;
	char const	*name = "radiusd";
	char		*p, buffer[65536];
	char const	*input_file = NULL;
	FILE		*inputfp = stdin;
	char const	*output_file = NULL;
	char const	*server = NULL;

	char const	*radius_dir = RADIUS_DIR;
	char const	*dict_dir = DICTDIR;

	char *commands[MAX_COMMANDS];
	int num_commands = -1;

#ifndef NDEBUG
	if (fr_fault_setup(getenv("PANIC_ACTION"), argv[0]) < 0) {
		fr_perror("radmin");
		exit(EXIT_FAILURE);
	}
#endif

	talloc_set_log_stderr();

	outputfp = stdout;	/* stdout is not a constant value... */

	if ((progname = strrchr(argv[0], FR_DIR_SEP)) == NULL) {
		progname = argv[0];
	} else {
		progname++;
	}

	while ((argval = getopt(argc, argv, "d:D:hi:e:Ef:n:o:qs:S")) != EOF) {
		switch (argval) {
		case 'd':
			if (file) {
				fprintf(stderr, "%s: -d and -f cannot be used together.\n", progname);
				exit(1);
			}
			if (server) {
				fprintf(stderr, "%s: -d and -s cannot be used together.\n", progname);
				exit(1);
			}
			radius_dir = optarg;
			break;

		case 'D':
			dict_dir = optarg;
			break;

		case 'e':
			num_commands++; /* starts at -1 */
			if (num_commands >= MAX_COMMANDS) {
				fprintf(stderr, "%s: Too many '-e'\n",
					progname);
				exit(1);
			}
			commands[num_commands] = optarg;
			break;

		case 'E':
			echo = true;
			break;

		case 'f':
			radius_dir = NULL;
			file = optarg;
			break;

		default:
		case 'h':
			usage(0);
			break;

		case 'i':
			if (strcmp(optarg, "-") != 0) {
				input_file = optarg;
			}
			quiet = true;
			break;

		case 'n':
			name = optarg;
			break;

		case 'o':
			if (strcmp(optarg, "-") != 0) {
				output_file = optarg;
			}
			quiet = true;
			break;

		case 'q':
			quiet = true;
			break;

		case 's':
			if (file) {
				fprintf(stderr, "%s: -s and -f cannot be used together.\n", progname);
				usage(1);
			}
			radius_dir = NULL;
			server = optarg;
			break;

		case 'S':
			secret = NULL;
			break;
		}
	}

	/*
	 *	Mismatch between the binary and the libraries it depends on
	 */
	if (fr_check_lib_magic(RADIUSD_MAGIC_NUMBER) < 0) {
		fr_perror("radmin");
		exit(1);
	}

	if (radius_dir) {
		int rcode;
		CONF_SECTION *cs, *subcs;

		file = NULL;	/* MUST read it from the conffile now */

		snprintf(buffer, sizeof(buffer), "%s/%s.conf", radius_dir, name);

		/*
		 *	Need to read in the dictionaries, else we may get
		 *	validation errors when we try and parse the config.
		 */
		if (dict_init(dict_dir, RADIUS_DICTIONARY) < 0) {
			fr_perror("radmin");
			exit(64);
		}

		if (dict_read(radius_dir, RADIUS_DICTIONARY) == -1) {
			fr_perror("radmin");
			exit(64);
		}

		cs = cf_file_read(buffer);
		if (!cs) {
			fprintf(stderr, "%s: Errors reading or parsing %s\n", progname, buffer);
			usage(1);
		}

		subcs = NULL;
		while ((subcs = cf_subsection_find_next(cs, subcs, "listen")) != NULL) {
			char const *value;
			CONF_PAIR *cp = cf_pair_find(subcs, "type");

			if (!cp) continue;

			value = cf_pair_value(cp);
			if (!value) continue;

			if (strcmp(value, "control") != 0) continue;

			/*
			 *	Now find the socket name (sigh)
			 */
			rcode = cf_item_parse(subcs, "socket", FR_ITEM_POINTER(PW_TYPE_STRING, &file), NULL);
			if (rcode < 0) {
				fprintf(stderr, "%s: Failed parsing listen section\n", progname);
				exit(1);
			}

			if (!file) {
				fprintf(stderr, "%s: No path given for socket\n", progname);
				usage(1);
			}
			break;
		}

		if (!file) {
			fprintf(stderr, "%s: Could not find control socket in %s\n", progname, buffer);
			exit(1);
		}
	}

	if (input_file) {
		inputfp = fopen(input_file, "r");
		if (!inputfp) {
			fprintf(stderr, "%s: Failed opening %s: %s\n", progname, input_file, fr_syserror(errno));
			exit(1);
		}
	}

	if (output_file) {
		outputfp = fopen(output_file, "w");
		if (!outputfp) {
			fprintf(stderr, "%s: Failed creating %s: %s\n", progname, output_file, fr_syserror(errno));
			exit(1);
		}
	}

	if (!file && !server) {
		fprintf(stderr, "%s: Must use one of '-d' or '-f' or '-s'\n",
			progname);
		exit(1);
	}

	/*
	 *	Check if stdin is a TTY only if input is from stdin
	 */
	if (input_file && !quiet && !isatty(STDIN_FILENO)) quiet = true;

#ifdef USE_READLINE
	if (!quiet) {
#ifdef USE_READLINE_HISTORY
		using_history();
#endif
		rl_bind_key('\t', rl_insert);
	}
#endif

	/*
	 *	Prevent SIGPIPEs from terminating the process
	 */
	signal(SIGPIPE, SIG_IGN);

	if (do_connect(&sockfd, file, server) < 0) exit(1);

	/*
	 *	Run one command.
	 */
	if (num_commands >= 0) {
		int i;

		for (i = 0; i <= num_commands; i++) {
			len = run_command(sockfd, commands[i], buffer, sizeof(buffer));
			if (len < 0) exit(1);

			if (buffer[0]) {
				fputs(buffer, outputfp);
				fprintf(outputfp, "\n");
				fflush(outputfp);
			}
		}
		exit(0);
	}

	if (!quiet) {
		printf("%s - FreeRADIUS Server administration tool.\n", radmin_version);
		printf("Copyright (C) 2008-2014 The FreeRADIUS server project and contributors.\n");
		printf("There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n");
		printf("PARTICULAR PURPOSE.\n");
		printf("You may redistribute copies of FreeRADIUS under the terms of the\n");
		printf("GNU General Public License v2.\n");
	}

	/*
	 *	FIXME: Do login?
	 */

	while (1) {
#ifndef USE_READLINE
		if (!quiet) {
			printf("radmin> ");
			fflush(stdout);
		}
#else
		if (!quiet) {
			line = readline("radmin> ");

			if (!line) break;

			if (!*line) {
				free(line);
				continue;
			}

#ifdef USE_READLINE_HISTORY
			add_history(line);
#endif
		} else		/* quiet, or no readline */
#endif
		{
			line = fgets(buffer, sizeof(buffer), inputfp);
			if (!line) break;

			p = strchr(buffer, '\n');
			if (!p) {
				fprintf(stderr, "%s: Input line too long\n",
					progname);
				exit(1);
			}

			*p = '\0';

			/*
			 *	Strip off leading spaces.
			 */
			for (p = line; *p != '\0'; p++) {
				if ((p[0] == ' ') ||
				    (p[0] == '\t')) {
					line = p + 1;
					continue;
				}

				if (p[0] == '#') {
					line = NULL;
					break;
				}

				break;
			}

			/*
			 *	Comments: keep going.
			 */
			if (!line) continue;

			/*
			 *	Strip off CR / LF
			 */
			for (p = line; *p != '\0'; p++) {
				if ((p[0] == '\r') ||
				    (p[0] == '\n')) {
					p[0] = '\0';
					break;
				}
			}
		}

		if (strcmp(line, "reconnect") == 0) {
			if (do_connect(&sockfd, file, server) < 0) exit(1);
			line = NULL;
			continue;
		}

		if (memcmp(line, "secret ", 7) == 0) {
			if (!secret) {
				secret = line + 7;
				do_challenge(sockfd);
			}
			line = NULL;
			continue;
		}

		/*
		 *	Exit, done, etc.
		 */
		if ((strcmp(line, "exit") == 0) ||
		    (strcmp(line, "quit") == 0)) {
			break;
		}

		if (server && !secret) {
			fprintf(stderr, "ERROR: You must enter 'secret <SECRET>' before running any commands\n");
			line = NULL;
			continue;
		}

		len = run_command(sockfd, line, buffer, sizeof(buffer));
		if ((len < 0) && (do_connect(&sockfd, file, server) < 0)) {
			fprintf(stderr, "Reconnecting...");
			exit(1);
		} else if (len == 0) break;
		else if (len == 1) continue; /* no output. */

		fputs(buffer, outputfp);
		fflush(outputfp);
		fprintf(outputfp, "\n");
	}

	fprintf(outputfp, "\n");

	return 0;
}