コード例 #1
0
ファイル: pair.c プロジェクト: bgmilne/freeradius-server
/** Copy matching pairs
 *
 * Copy pairs of a matching attribute number, vendor number and tag from the
 * the input list to a new list, and returns the head of this list.
 *
 * @param[in] ctx for talloc
 * @param[in] from whence to copy VALUE_PAIRs.
 * @param[in] attr to match, if 0 input list will not be filtered by attr.
 * @param[in] vendor to match.
 * @param[in] tag to match, TAG_ANY matches any tag, TAG_NONE matches tagless VPs.
 * @return the head of the new VALUE_PAIR list or NULL on error.
 */
VALUE_PAIR *paircopy_by_num(TALLOC_CTX *ctx, VALUE_PAIR *from, unsigned int attr, unsigned int vendor, int8_t tag)
{
	vp_cursor_t src, dst;

	VALUE_PAIR *out = NULL, *vp;

	fr_cursor_init(&dst, &out);
	for (vp = fr_cursor_init(&src, &from);
	     vp;
	     vp = fr_cursor_next(&src)) {
		VERIFY_VP(vp);

		if ((vp->da->attr != attr) || (vp->da->vendor != vendor)) {
			continue;
		}

		if (vp->da->flags.has_tag && !TAG_EQ(tag, vp->tag)) {
			continue;
		}

		vp = paircopyvp(ctx, vp);
		if (!vp) {
			pairfree(&out);
			return NULL;
		}
		fr_cursor_insert(&dst, vp);
	}

	return out;
}
コード例 #2
0
ファイル: pair.c プロジェクト: bgmilne/freeradius-server
/** Uses paircmp to verify all VALUE_PAIRs in list match the filter defined by check
 *
 * @note will sort both filter and list in place.
 *
 * @param failed pointer to an array to write the pointers of the filter/list attributes that didn't match.
 *	  May be NULL.
 * @param filter attributes to check list against.
 * @param list attributes, probably a request or reply
 */
bool pairvalidate(VALUE_PAIR const *failed[2], VALUE_PAIR *filter, VALUE_PAIR *list)
{
	vp_cursor_t filter_cursor;
	vp_cursor_t list_cursor;

	VALUE_PAIR *check, *match;

	if (!filter && !list) {
		return true;
	}

	/*
	 *	This allows us to verify the sets of validate and reply are equal
	 *	i.e. we have a validate rule which matches every reply attribute.
	 *
	 *	@todo this should be removed one we have sets and lists
	 */
	pairsort(&filter, attrtagcmp);
	pairsort(&list, attrtagcmp);

	check = fr_cursor_init(&filter_cursor, &filter);
	match = fr_cursor_init(&list_cursor, &list);
	while (match || check) {
		/*
		 *	Lists are of different lengths
		 */
		if (!match || !check) goto mismatch;

		/*
		 *	The lists are sorted, so if the first
		 *	attributes aren't of the same type, then we're
		 *	done.
		 */
		if (!ATTRIBUTE_EQ(check, match)) goto mismatch;

		/*
		 *	They're of the same type, but don't have the
		 *	same values.  This is a problem.
		 *
		 *	Note that the RFCs say that for attributes of
		 *	the same type, order is important.
		 */
		if (paircmp(check, match) != 1) goto mismatch;

		check = fr_cursor_next(&filter_cursor);
		match = fr_cursor_next(&list_cursor);
	}

	return true;

mismatch:
	if (failed) {
		failed[0] = check;
		failed[1] = match;
	}
	return false;
}
コード例 #3
0
ファイル: groups.c プロジェクト: WilliamRen/freeradius-server
/** Check group membership attributes to see if a user is a member.
 *
 * @param[in] inst rlm_ldap configuration.
 * @param[in] request Current request.
 * @param[in] check vp containing the group value (name or dn).
 *
 * @return One of the RLM_MODULE_* values.
 */
rlm_rcode_t rlm_ldap_check_cached(ldap_instance_t const *inst, REQUEST *request, VALUE_PAIR *check)
{
	VALUE_PAIR	*vp;
	int		ret;
	vp_cursor_t	cursor;

	fr_cursor_init(&cursor, &request->config_items);

	/*
	 *	We return RLM_MODULE_INVALID here as an indication
	 *	the caller should try a dynamic group lookup instead.
	 */
	vp = fr_cursor_next_by_num(&cursor, inst->cache_da->attr, inst->cache_da->vendor, TAG_ANY);
	if (!vp) return RLM_MODULE_INVALID;
	fr_cursor_first(&cursor);

	while ((vp = fr_cursor_next_by_num(&cursor, inst->cache_da->attr, inst->cache_da->vendor, TAG_ANY))) {
		ret = paircmp_op(T_OP_CMP_EQ, vp, check);
		if (ret == 1) {
			RDEBUG2("User found. Matched cached membership");
			return RLM_MODULE_OK;
		}

		if (ret < -1) {
			return RLM_MODULE_FAIL;
		}
	}

	RDEBUG2("Cached membership not found");
	return RLM_MODULE_NOTFOUND;
}
コード例 #4
0
ファイル: cf_util.c プロジェクト: zi0r/freeradius-server
/** Add a child
 *
 * @param[in] parent	to add child to.
 * @param[in] child	to add.
 */
void _cf_item_add(CONF_ITEM *parent, CONF_ITEM *child)
{
	fr_cursor_t	to_merge;
	CONF_ITEM	*ci;

	rad_assert(parent != child);

	if (!parent || !child) return;

	/*
	 *	New child, add child trees.
	 */
	if (!parent->ident1) parent->ident1 = rbtree_create(parent, _cf_ident1_cmp, NULL, RBTREE_FLAG_NONE);
	if (!parent->ident2) parent->ident2 = rbtree_create(parent, _cf_ident2_cmp, NULL, RBTREE_FLAG_NONE);

	fr_cursor_init(&to_merge, &child);

	for (ci = fr_cursor_head(&to_merge);
	     ci;
	     ci = fr_cursor_next(&to_merge)) {
		rbtree_insert(parent->ident1, ci);
		rbtree_insert(parent->ident2, ci);	/* NULL ident2 is still a value */
	 	fr_cursor_append(&parent->cursor, ci);	/* Append to the list of children */
	}
}
コード例 #5
0
/*
 *	Don't even ask what this is doing...
 */
static void alvarion_vsa_hack(VALUE_PAIR *vp)
{
	int number = 1;
	vp_cursor_t cursor;

	for (vp = fr_cursor_init(&cursor, &vp);
	     vp;
	     vp = fr_cursor_next(&cursor)) {
		DICT_ATTR const *da;

		if (vp->da->vendor != 12394) {
			continue;
		}

		if (vp->da->type != PW_TYPE_STRING) {
			continue;
		}

		da = dict_attrbyvalue(number, 12394);
		if (!da) {
			continue;
		}

		vp->da = da;

		number++;
	}
}
コード例 #6
0
ファイル: rlm_dhcp.c プロジェクト: roocell/freeradius-server
static ssize_t dhcp_xlat(UNUSED void *instance, REQUEST *request, char const *fmt, char **out, size_t freespace)
{
	vp_cursor_t cursor;
	VALUE_PAIR *vp;
	uint8_t binbuf[255];
	ssize_t len;

	while (isspace((int) *fmt)) fmt++;

	if ((radius_copy_vp(request, &vp, request, fmt) < 0) || !vp) return 0;
	fr_cursor_init(&cursor, &vp);

	len = fr_dhcp_encode_option(request, binbuf, sizeof(binbuf), &cursor);
	talloc_free(vp);
	if (len <= 0) {
		REDEBUG("DHCP option encoding failed: %s", fr_strerror());

		return -1;
	}

	if ((size_t)((len * 2) + 1) > freespace) {
		REDEBUG("DHCP option encoding failed: Output buffer exhausted, needed %zd bytes, have %zd bytes",
			(len * 2) + 1, freespace);

		return -1;
	}

	return fr_bin2hex(*out, binbuf, len);
}
コード例 #7
0
ファイル: proto_arp.c プロジェクト: zi0r/freeradius-server
static int arp_socket_decode(UNUSED rad_listen_t *listener, REQUEST *request)
{
	int			i;
	uint8_t	const		*p = request->packet->data, *end = p + request->packet->data_len;
	fr_cursor_t		cursor;

	fr_cursor_init(&cursor, &request->packet->vps);

	for (i = 0; header_names[i].name != NULL; i++) {
		ssize_t			ret;
		size_t			len;
		fr_dict_attr_t const	*da;
		VALUE_PAIR		*vp = NULL;

		len = header_names[i].len;

		if (!fr_cond_assert((size_t)(end - p) < len)) return -1; /* Should have been detected in socket_recv */

		da = fr_dict_attr_by_name(dict_arp, header_names[i].name);
		if (!da) return 0;

		MEM(vp = fr_pair_afrom_da(request->packet, da));
		ret = fr_value_box_from_network(vp, &vp->data, da->type, da, p, len, true);
		if (ret <= 0) {
			fr_pair_to_unknown(vp);
			fr_pair_value_memcpy(vp, p, len);
		}

		DEBUG2("&%pP", vp);
		fr_cursor_insert(&cursor, vp);
	}

	return 0;
}
コード例 #8
0
ファイル: groups.c プロジェクト: Tarouk17/freeradius-server
/** Check group membership attributes to see if a user is a member.
 *
 * @param[in] inst rlm_ldap configuration.
 * @param[in] request Current request.
 * @param[in] check vp containing the group value (name or dn).
 *
 * @return One of the RLM_MODULE_* values.
 */
rlm_rcode_t rlm_ldap_check_cached(ldap_instance_t const *inst, REQUEST *request, VALUE_PAIR *check)
{
	VALUE_PAIR	*vp;
	int		ret;
	vp_cursor_t	cursor;

	fr_cursor_init(&cursor, &request->config_items);
	vp = fr_cursor_next_by_num(&cursor, inst->cache_da->attr, inst->cache_da->vendor, TAG_ANY);
	if (!vp) {
		return RLM_MODULE_INVALID;
	}

	for (; vp; vp = fr_cursor_next_by_num(&cursor, inst->cache_da->attr, inst->cache_da->vendor, TAG_ANY)) {
		ret = radius_compare_vps(request, check, vp);
		if (ret == 0) {
			RDEBUG2("User found. Matched cached membership");
			return RLM_MODULE_OK;
		}

		if (ret < -1) {
			return RLM_MODULE_FAIL;
		}
	}

	RDEBUG2("Membership not found");
	return RLM_MODULE_NOTFOUND;
}
コード例 #9
0
/** Print a list of valuepairs to the request list.
 *
 * @param[in] level Debug level (1-4).
 * @param[in] request to read logging params from.
 * @param[in] vp to print.
 */
void rdebug_pair_list(int level, REQUEST *request, VALUE_PAIR *vp)
{
	vp_cursor_t cursor;
	char buffer[256];
	if (!vp || !request || !request->log.func) return;

	if (!radlog_debug_enabled(L_DBG, level, request)) return;

	for (vp = fr_cursor_init(&cursor, &vp);
	     vp;
	     vp = fr_cursor_next(&cursor)) {
		/*
		 *	Take this opportunity to verify all the VALUE_PAIRs are still valid.
		 */
		if (!talloc_get_type(vp, VALUE_PAIR)) {
			REDEBUG("Expected VALUE_PAIR pointer got \"%s\"", talloc_get_name(vp));

			fr_log_talloc_report(vp);
			rad_assert(0);
		}

		vp_prints(buffer, sizeof(buffer), vp);
		RDEBUGX(level, "\t%s", buffer);
	}
}
コード例 #10
0
static void print_packet(FILE *fp, RADIUS_PACKET *packet)
{
	VALUE_PAIR *vp;
	vp_cursor_t cursor;

	if (!packet) {
		fprintf(fp, "\n");
		return;
	}

	fprintf(fp, "%s\n", fr_packet_codes[packet->code]);

	for (vp = fr_cursor_init(&cursor, &packet->vps);
	     vp;
	     vp = fr_cursor_next(&cursor)) {
		/*
		 *	Take this opportunity to verify all the VALUE_PAIRs are still valid.
		 */
		if (!talloc_get_type(vp, VALUE_PAIR)) {
			ERROR("Expected VALUE_PAIR pointer got \"%s\"", talloc_get_name(vp));

			fr_log_talloc_report(vp);
			rad_assert(0);
		}

		vp_print(fp, vp);
	}
	fflush(fp);
}
コード例 #11
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;
}
コード例 #12
0
ファイル: rlm_dhcp.c プロジェクト: roocell/freeradius-server
/*
 *	Allow single attribute values to be retrieved from the dhcp.
 */
static ssize_t dhcp_options_xlat(UNUSED void *instance, REQUEST *request,
				 char const *fmt, char **out, size_t freespace)
{
	vp_cursor_t	cursor, src_cursor;
	vp_tmpl_t	src;
	VALUE_PAIR	*vp, *head = NULL;
	int		decoded = 0;
	ssize_t		slen;

	while (isspace((int) *fmt)) fmt++;

	slen = tmpl_from_attr_str(&src, fmt, REQUEST_CURRENT, PAIR_LIST_REQUEST, false, false);
	if (slen <= 0) {
		REMARKER(fmt, slen, fr_strerror());
	error:
		return -1;
	}

	if (src.type != TMPL_TYPE_ATTR) {
		REDEBUG("dhcp_options cannot operate on a %s", fr_int2str(tmpl_names, src.type, "<INVALID>"));
		goto error;
	}

	if (src.tmpl_da->type != PW_TYPE_OCTETS) {
		REDEBUG("dhcp_options got a %s attribute needed octets",
			fr_int2str(dict_attr_types, src.tmpl_da->type, "<INVALID>"));
		goto error;
	}

	for (vp = tmpl_cursor_init(NULL, &src_cursor, request, &src);
	     vp;
	     vp = tmpl_cursor_next(&src_cursor, &src)) {
		/*
		 *	@fixme: we should pass in a cursor, then decoding multiple
		 *	source attributes can be made atomic.
		 */
		if ((fr_dhcp_decode_options(request->packet, &head, vp->vp_octets, vp->vp_length) < 0) || (!head)) {
			RWDEBUG("DHCP option decoding failed: %s", fr_strerror());
			goto error;
		}

		for (vp = fr_cursor_init(&cursor, &head);
		     vp;
		     vp = fr_cursor_next(&cursor)) {
			rdebug_pair(L_DBG_LVL_2, request, vp, "dhcp_options: ");
			decoded++;
		}

		fr_pair_list_move(request->packet, &(request->packet->vps), &head);

		/* Free any unmoved pairs */
		fr_pair_list_free(&head);
	}

	snprintf(*out, freespace, "%i", decoded);

	return strlen(*out);
}
コード例 #13
0
/** Send a failure message
 *
 */
static int eap_sim_send_eap_failure_notification(eap_session_t *eap_session)
{
	REQUEST			*request = eap_session->request;
	RADIUS_PACKET		*packet = eap_session->request->reply;
	fr_cursor_t		cursor;
	VALUE_PAIR		*vp;
	eap_sim_session_t	*eap_sim_session = talloc_get_type_abort(eap_session->opaque, eap_sim_session_t);

	fr_cursor_init(&cursor, &packet->vps);

	vp = fr_pair_find_by_da(packet->vps, attr_eap_sim_notification, TAG_ANY);
	if (!vp) {
		vp = fr_pair_afrom_da(packet, attr_eap_sim_notification);
		vp->vp_uint16 = FR_EAP_SIM_NOTIFICATION_VALUE_GENERAL_FAILURE;
		fr_cursor_append(&cursor, vp);
	}

	/*
	 *	Change the failure notification depending where
	 *	we are in the state machine.
	 */
	if (eap_sim_session->challenge_success) {
		vp->vp_uint16 &= ~0x4000;	/* Unset phase bit */
	} else {
		vp->vp_uint16 |= 0x4000;	/* Set phase bit */
	}
	vp->vp_uint16 &= ~0x8000;               /* In both cases success bit should be low */

	RDEBUG2("Sending SIM-Notification (%pV)", &vp->data);
	eap_session->this_round->request->code = FR_EAP_CODE_REQUEST;

	/*
	 *	Set the subtype to notification
	 */
	vp = fr_pair_afrom_da(packet, attr_eap_sim_subtype);
	vp->vp_uint16 = FR_EAP_SIM_SUBTYPE_VALUE_SIM_NOTIFICATION;
	fr_cursor_append(&cursor, vp);

	/*
	 *	If we're after the challenge phase
	 *	then we need to include a MAC to
	 *	protect notifications.
	 */
	if (eap_sim_session->challenge_success) {
		vp = fr_pair_afrom_da(packet, attr_eap_sim_mac);
		fr_pair_replace(&packet->vps, vp);
	}

	/*
	 *	Encode the packet
	 */
	if (eap_sim_compose(eap_session, NULL, 0) < 0) {
		fr_pair_list_free(&packet->vps);
		return -1;
	}

	return 0;
}
コード例 #14
0
/*
 *	This hack strips out Cisco's VSA duplicities in lines
 *	(Cisco not implemented VSA's in standard way.
 *
 *	Cisco sends it's VSA attributes with the attribute name *again*
 *	in the string, like:  H323-Attribute = "h323-attribute=value".
 *	This sort of behaviour is nonsense.
 */
static void cisco_vsa_hack(REQUEST *request)
{
	int		vendorcode;
	char		*ptr;
	char		newattr[MAX_STRING_LEN];
	VALUE_PAIR	*vp;
	vp_cursor_t	cursor;
	for (vp = fr_cursor_init(&cursor, &request->packet->vps);
	     vp;
	     vp = fr_cursor_next(&cursor)) {
		vendorcode = vp->da->vendor;
		if (!((vendorcode == 9) || (vendorcode == 6618))) {
			continue; /* not a Cisco or Quintum VSA, continue */
		}

		if (vp->da->type != PW_TYPE_STRING) {
			continue;
		}

		/*
		 *  No weird packing.  Ignore it.
		 */
		ptr = strchr(vp->vp_strvalue, '='); /* find an '=' */
		if (!ptr) {
			continue;
		}

		/*
		 *	Cisco-AVPair's get packed as:
		 *
		 *	Cisco-AVPair = "h323-foo-bar = baz"
		 *	Cisco-AVPair = "h323-foo-bar=baz"
		 *
		 *	which makes sense only if you're a lunatic.
		 *	This code looks for the attribute named inside
		 *	of the string, and if it exists, adds it as a new
		 *	attribute.
		 */
		if (vp->da->attr == 1) {
			char const *p;

			p = vp->vp_strvalue;
			gettoken(&p, newattr, sizeof(newattr), false);

			if (dict_attrbyname(newattr) != NULL) {
				pairmake_packet(newattr, ptr + 1, T_OP_EQ);
			}
		} else {	/* h322-foo-bar = "h323-foo-bar = baz" */
			/*
			 *	We strip out the duplicity from the
			 *	value field, we use only the value on
			 *	the right side of the '=' character.
			 */
			pairstrcpy(vp, ptr + 1);
		}
	}
}
コード例 #15
0
ファイル: dhcpclient.c プロジェクト: geaaru/freeradius-server
static void dhcp_packet_debug(RADIUS_PACKET *packet, bool received)
{
	fr_cursor_t	cursor;
	char		buffer[256];

	char		src_ipaddr[INET6_ADDRSTRLEN];
	char		dst_ipaddr[INET6_ADDRSTRLEN];
#if defined(WITH_UDPFROMTO) && defined(WITH_IFINDEX_NAME_RESOLUTION)
	char		if_name[IFNAMSIZ];
#endif
	VALUE_PAIR	*vp;

	if (!packet) return;

	/*
	 *	Client-specific debugging re-prints the input
	 *	packet into the client log.
	 *
	 *	This really belongs in a utility library
	 */
	printf("%s %s Id %08x from %s%s%s:%i to %s%s%s:%i "
#if defined(WITH_UDPFROMTO) && defined(WITH_IFINDEX_NAME_RESOLUTION)
	       "%s%s%s"
#endif
	       "length %zu\n",
	       received ? "Received" : "Sending",
	       dhcp_message_types[packet->code],
	       packet->id,
	       packet->src_ipaddr.af == AF_INET6 ? "[" : "",
	       inet_ntop(packet->src_ipaddr.af,
			 &packet->src_ipaddr.addr,
			 src_ipaddr, sizeof(src_ipaddr)),
	       packet->src_ipaddr.af == AF_INET6 ? "]" : "",
	       packet->src_port,
	       packet->dst_ipaddr.af == AF_INET6 ? "[" : "",
	       inet_ntop(packet->dst_ipaddr.af,
			 &packet->dst_ipaddr.addr,
			 dst_ipaddr, sizeof(dst_ipaddr)),
	       packet->dst_ipaddr.af == AF_INET6 ? "]" : "",
	       packet->dst_port,
#if defined(WITH_UDPFROMTO) && defined(WITH_IFINDEX_NAME_RESOLUTION)
	       packet->if_index ? "via " : "",
	       packet->if_index ? fr_ifname_from_ifindex(if_name, packet->if_index) : "",
	       packet->if_index ? " " : "",
#endif
	       packet->data_len);

	for (vp = fr_cursor_init(&cursor, &packet->vps);
	     vp;
	     vp = fr_cursor_next(&cursor)) {
		VP_VERIFY(vp);

		fr_pair_snprint(buffer, sizeof(buffer), vp);
		printf("\t%s\n", buffer);
	}
}
コード例 #16
0
ファイル: print.c プロジェクト: k-paulius/freeradius-server
/** Print a list of attributes and enumv
 *
 * @param fp to output to.
 * @param const_vp to print.
 */
void vp_printlist(FILE *fp, VALUE_PAIR const *const_vp)
{
	VALUE_PAIR *vp;
	vp_cursor_t cursor;

	memcpy(&vp, &const_vp, sizeof(vp)); /* const work-arounds */

	for (vp = fr_cursor_init(&cursor, &vp); vp; vp = fr_cursor_next(&cursor)) {
		vp_print(fp, vp);
	}
}
コード例 #17
0
ファイル: tmpl.c プロジェクト: whyname/freeradius-server
/** Return a VP from a value_pair_tmpl_t
 *
 * @param out where to write the retrieved vp.
 * @param request current request.
 * @param vpt the value pair template
 * @return -1 if VP could not be found, -2 if list could not be found, -3 if context could not be found.
 */
int tmpl_find_vp(VALUE_PAIR **out, REQUEST *request, value_pair_tmpl_t const *vpt)
{
	VALUE_PAIR **vps, *vp;

	rad_assert((vpt->type == TMPL_TYPE_ATTR) || (vpt->type == TMPL_TYPE_LIST));

	if (out) *out = NULL;

	if (radius_request(&request, vpt->tmpl_request) < 0) {
		return -3;
	}

	vps = radius_list(request, vpt->tmpl_list);
	if (!vps) {
		return -2;
	}

	switch (vpt->type) {
	/*
	 *	May not may not be found, but it *is* a known name.
	 */
	case TMPL_TYPE_ATTR:
	{
		int num;
		vp_cursor_t cursor;

		if (vpt->tmpl_num == NUM_ANY) {
			vp = pairfind(*vps, vpt->tmpl_da->attr, vpt->tmpl_da->vendor, vpt->tmpl_tag);
			if (!vp) return -1;
			break;
		}

		(void) fr_cursor_init(&cursor, vps);
		num = vpt->tmpl_num;
		while ((vp = fr_cursor_next_by_da(&cursor, vpt->tmpl_da, vpt->tmpl_tag))) {
			VERIFY_VP(vp);
			if (num-- <= 0) goto finish;
		}
		return -1;
	}

	case TMPL_TYPE_LIST:
		vp = *vps;
		break;

	default:
		rad_assert(0);
	}

finish:
	if (out) *out = vp;

	return 0;
}
コード例 #18
0
ファイル: log.c プロジェクト: AlainRomeyer/freeradius-server
/*
 *      Dump a whole list of attributes to DEBUG2
 */
void vp_listdebug(VALUE_PAIR *vp)
{
	vp_cursor_t cursor;
	char tmpPair[70];
	for (vp = fr_cursor_init(&cursor, &vp);
	     vp;
	     vp = fr_cursor_next(&cursor)) {
		vp_prints(tmpPair, sizeof(tmpPair), vp);
		DEBUG2("     %s", tmpPair);
	}
}
コード例 #19
0
/** Merges two sets of VPs
 *
 * The list represented by cursor will hold the union of cursor and
 * add lists.
 *
 * @param cursor to insert VALUE_PAIRs with
 * @param add one or more VALUE_PAIRs.
 */
void fr_cursor_merge(vp_cursor_t *cursor, VALUE_PAIR *add)
{
	vp_cursor_t from;
	VALUE_PAIR *vp;

	for (vp = fr_cursor_init(&from, &add);
	     vp;
	     vp = fr_cursor_next(&from)) {
	 	fr_cursor_insert(cursor, vp);
	}
}
コード例 #20
0
ファイル: pair.c プロジェクト: bgmilne/freeradius-server
/** Find the pair with the matching DAs
 *
 */
VALUE_PAIR *pair_find_by_da(VALUE_PAIR *vp, DICT_ATTR const *da, int8_t tag)
{
	vp_cursor_t 	cursor;

	if(!fr_assert(da)) {
		 return NULL;
	}

	(void) fr_cursor_init(&cursor, &vp);
	return fr_cursor_next_by_da(&cursor, da, tag);
}
コード例 #21
0
ファイル: pair.c プロジェクト: bgmilne/freeradius-server
/** Copy a pairlist.
 *
 * Copy all pairs from 'from' regardless of tag, attribute or vendor.
 *
 * @param[in] ctx for new VALUE_PAIRs to be allocated in.
 * @param[in] from whence to copy VALUE_PAIRs.
 * @return the head of the new VALUE_PAIR list or NULL on error.
 */
VALUE_PAIR *paircopy(TALLOC_CTX *ctx, VALUE_PAIR *from)
{
	vp_cursor_t src, dst;

	VALUE_PAIR *out = NULL, *vp;

	fr_cursor_init(&dst, &out);
	for (vp = fr_cursor_init(&src, &from);
	     vp;
	     vp = fr_cursor_next(&src)) {
		VERIFY_VP(vp);
		vp = paircopyvp(ctx, vp);
		if (!vp) {
			pairfree(&out);
			return NULL;
		}
		fr_cursor_insert(&dst, vp); /* paircopy sets next pointer to NULL */
	}

	return out;
}
コード例 #22
0
ファイル: pair.c プロジェクト: bgmilne/freeradius-server
/** Find the pair with the matching attribute
 *
 * @todo should take DAs and do a pointer comparison.
 */
VALUE_PAIR *pairfind(VALUE_PAIR *vp, unsigned int attr, unsigned int vendor, int8_t tag)
{
	vp_cursor_t 	cursor;

	/* List head may be NULL if it contains no VPs */
	if (!vp) return NULL;

	VERIFY_LIST(vp);

	(void) fr_cursor_init(&cursor, &vp);
	return fr_cursor_next_by_num(&cursor, attr, vendor, tag);
}
コード例 #23
0
/*
 *	Convert field X to a VP.
 */
static int csv_map_getvalue(TALLOC_CTX *ctx, VALUE_PAIR **out, REQUEST *request, vp_map_t const *map, void *uctx)
{
	char const *str = uctx;
	VALUE_PAIR *head = NULL, *vp;
	vp_cursor_t cursor;
	DICT_ATTR const *da;

	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 = dict_attrbyname(attr);
		if (!da) {
			RWDEBUG("No such attribute '%s'", attr);
			return -1;
		}

		talloc_free(attr);
	}

	vp = pairalloc(ctx, da);
	rad_assert(vp);

	if (pairparsevalue(vp, str, talloc_array_length(str) - 1) < 0) {
		char *escaped;

		escaped = fr_aprints(vp, str, talloc_array_length(str) - 1, '\'');
		RWDEBUG("Failed parsing value \"%s\" for attribute %s: %s", escaped,
			map->lhs->tmpl_da->name, fr_strerror());

		talloc_free(vp); /* also frees escaped */
		return -1;
	}

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

	*out = head;
	return 0;
}
コード例 #24
0
ファイル: valuepair.c プロジェクト: kcnwogu/freeradius-server
/** Print a list of valuepairs to stderr or error log.
 *
 * @param[in] vp to print.
 */
void debug_pair_list(VALUE_PAIR *vp)
{
	vp_cursor_t cursor;
	if (!vp || !debug_flag || !fr_log_fp) return;

	for (vp = fr_cursor_init(&cursor, &vp);
	     vp;
	     vp = fr_cursor_next(&cursor)) {
		vp_print(fr_log_fp, vp);
	}
	fflush(fr_log_fp);
}
コード例 #25
0
ファイル: rlm_csv.c プロジェクト: mcnewton/freeradius-server
/*
 *	Convert field X to a VP.
 */
static int csv_map_getvalue(TALLOC_CTX *ctx, VALUE_PAIR **out, REQUEST *request, vp_map_t const *map, void *uctx)
{
	char const		*str = uctx;
	VALUE_PAIR		*head = NULL, *vp;
	fr_cursor_t		cursor;
	fr_dict_attr_t		const *da;

	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);
	}

	vp = fr_pair_afrom_da(ctx, da);
	rad_assert(vp);

	if (fr_pair_value_from_str(vp, str, talloc_array_length(str) - 1, '\0', true) < 0) {
		RWDEBUG("Failed parsing value \"%pV\" for attribute %s: %s", fr_box_strvalue_buffer(str),
			map->lhs->tmpl_da->name, fr_strerror());
		talloc_free(vp);

		return -1;
	}

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

	*out = head;
	return 0;
}
コード例 #26
0
/** Merges multiple VALUE_PAIR into the cursor
 *
 * Add multiple VALUE_PAIR from add to cursor.
 *
 * @addtogroup module_safe
 *
 * @param cursor to insert VALUE_PAIRs with
 * @param add one or more VALUE_PAIRs (may be NULL, which results in noop).
 */
void fr_cursor_merge(vp_cursor_t *cursor, VALUE_PAIR *add)
{
	vp_cursor_t from;
	VALUE_PAIR *vp;

	if (!add) return;

	if (!fr_assert(cursor->first)) return;	/* cursor must have been initialised */

	for (vp = fr_cursor_init(&from, &add);
	     vp;
	     vp = fr_cursor_next(&from)) {
	 	fr_cursor_insert(cursor, vp);
	}
}
コード例 #27
0
ファイル: pair.c プロジェクト: bgmilne/freeradius-server
/** Free memory used by a valuepair list.
 *
 * @todo TLV: needs to free all dependents of each VP freed.
 */
void pairfree(VALUE_PAIR **vps)
{
	VALUE_PAIR	*vp;
	vp_cursor_t	cursor;

	if (!vps || !*vps) {
		return;
	}

	for (vp = fr_cursor_init(&cursor, vps);
	     vp;
	     vp = fr_cursor_next(&cursor)) {
		VERIFY_VP(vp);
		talloc_free(vp);
	}

	*vps = NULL;
}
コード例 #28
0
ファイル: log.c プロジェクト: mcnewton/freeradius-server
/** Print a list of VALUE_PAIRs.
 *
 * @param[in] lvl	Debug lvl (1-4).
 * @param[in] request	to read logging params from.
 * @param[in] vp	to print.
 * @param[in] prefix	(optional).
 */
void log_request_pair_list(fr_log_lvl_t lvl, REQUEST *request, VALUE_PAIR *vp, char const *prefix)
{
	fr_cursor_t cursor;

	if (!vp || !request || !request->log.dst) return;

	if (!log_debug_enabled(L_DBG, lvl, request)) return;

	RINDENT();
	for (vp = fr_cursor_init(&cursor, &vp);
	     vp;
	     vp = fr_cursor_next(&cursor)) {
		VP_VERIFY(vp);

		RDEBUGX(lvl, "%s%pP", prefix ? prefix : "&", vp);
	}
	REXDENT();
}
コード例 #29
0
static int attr_filter_getfile(TALLOC_CTX *ctx, char const *filename, PAIR_LIST **pair_list)
{
	vp_cursor_t cursor;
	int rcode;
	PAIR_LIST *attrs = NULL;
	PAIR_LIST *entry;
	VALUE_PAIR *vp;

	rcode = pairlist_read(ctx, filename, &attrs, 1);
	if (rcode < 0) {
		return -1;
	}

	/*
	 * Walk through the 'attrs' file list.
	 */

	entry = attrs;
	while (entry) {
		entry->check = entry->reply;
		entry->reply = NULL;

		for (vp = fr_cursor_init(&cursor, &entry->check);
		     vp;
		     vp = fr_cursor_next(&cursor)) {
		    /*
		     * If it's NOT a vendor attribute,
		     * and it's NOT a wire protocol
		     * and we ignore Fall-Through,
		     * then bitch about it, giving a good warning message.
		     */
		     if ((vp->da->vendor == 0) &&
			 (vp->da->attr > 1000)) {
			WARN("[%s]:%d Check item \"%s\"\n\tfound in filter list for realm \"%s\".\n",
			       filename, entry->lineno, vp->da->name, entry->name);
		    }
		}

		entry = entry->next;
	}

	*pair_list = attrs;
	return 0;
}
コード例 #30
0
/** Send a success notification
 *
 */
static int eap_sim_send_eap_success_notification(eap_session_t *eap_session)
{
	REQUEST			*request = eap_session->request;
	RADIUS_PACKET		*packet = eap_session->request->reply;
	eap_sim_session_t	*eap_sim_session = talloc_get_type_abort(eap_session->opaque, eap_sim_session_t);
	fr_cursor_t		cursor;
	VALUE_PAIR		*vp;

	RDEBUG2("Sending SIM-Notification (Success)");
	eap_session->this_round->request->code = FR_EAP_CODE_REQUEST;

	if (!fr_cond_assert(eap_sim_session->challenge_success)) return -1;

	fr_cursor_init(&cursor, &packet->vps);

	/*
	 *	Set the subtype to notification
	 */
	vp = fr_pair_afrom_da(packet, attr_eap_sim_subtype);
	vp->vp_uint16 = FR_EAP_SIM_SUBTYPE_VALUE_SIM_NOTIFICATION;
	fr_cursor_append(&cursor, vp);

	vp = fr_pair_afrom_da(packet, attr_eap_sim_notification);
	vp->vp_uint16 = FR_EAP_SIM_NOTIFICATION_VALUE_SUCCESS;
	fr_cursor_append(&cursor, vp);

	/*
	 *	Need to include an AT_MAC attribute so that it will get
	 *	calculated.
	 */
	vp = fr_pair_afrom_da(packet, attr_eap_sim_mac);
	fr_pair_replace(&packet->vps, vp);

	/*
	 *	Encode the packet
	 */
	if (eap_sim_compose(eap_session, NULL, 0) < 0) {
		fr_pair_list_free(&packet->vps);
		return -1;
	}

	return 0;
}