示例#1
0
/** Setup a cursor to iterate over attribute pairs
 *
 * @param cursor Where to initialise the cursor (uses existing structure).
 * @param const_vp to start from.
 * @return the attribute pointed to by vp.
 */
VALUE_PAIR *fr_pair_cursor_init(vp_cursor_t *cursor, VALUE_PAIR * const *const_vp)
{
	VALUE_PAIR **vp;

	if (!const_vp || !cursor) {
		return NULL;
	}

	memset(cursor, 0, sizeof(*cursor));

	memcpy(&vp, &const_vp, sizeof(vp)); /* stupid const hacks */

	/*
	 *  Useful check to see if uninitialised memory is pointed
	 *  to by vp
	 */
#ifndef NDEBUG
	if (*vp) VP_VERIFY(*vp);
#endif
	memcpy(&cursor->first, &vp, sizeof(cursor->first));
	cursor->current = *cursor->first;

	if (cursor->current) {
		VP_VERIFY(cursor->current);
		cursor->next = cursor->current->next;
	}

	return cursor->current;
}
示例#2
0
/** Iterate over a collection of VALUE_PAIRs of a given type in the pairlist
 *
 * Find the next attribute of a given type. If no fr_pair_cursor_next_by_* function
 * has been called on a cursor before, or the previous call returned
 * NULL, the search will start with the current attribute. Subsequent calls to
 * fr_pair_cursor_next_by_* functions will start the search from the previously
 * matched attribute.
 *
 * @param cursor to operate on.
 * @param attr number to match.
 * @param vendor number to match (0 for none vendor attribute).
 * @param tag to match. Either a tag number or TAG_ANY to match any tagged or
 *	  untagged attribute, TAG_NONE to match attributes without tags.
 * @return
 *	- The next matching #VALUE_PAIR.
 *	- NULL if no #VALUE_PAIR (s) match.
 */
VALUE_PAIR *fr_pair_cursor_next_by_num(vp_cursor_t *cursor, unsigned int vendor, unsigned int attr, int8_t tag)
{
	VALUE_PAIR *i;

	if (!cursor->first) return NULL;

	if (!vendor) {
		/*
		 *	Find top-level attributes.
		 */
		for (i = cursor->found ? cursor->found->next : cursor->current;
		     i != NULL;
		     i = i->next) {
			VP_VERIFY(i);
			if (fr_dict_attr_is_top_level(i->da) && (i->da->attr == attr) && ATTR_TAG_MATCH(i, tag)) {
				break;
			}
		}
	} else {
		for (i = cursor->found ? cursor->found->next : cursor->current;
		     i != NULL;
		     i = i->next) {
			VP_VERIFY(i);
			if ((i->da->parent->type == FR_TYPE_VENDOR) &&
			    (i->da->attr == attr) && (fr_dict_vendor_num_by_da(i->da) == vendor) &&
			    ATTR_TAG_MATCH(i, tag)) {
				break;
			}
		}
	}

	return fr_pair_cursor_update(cursor, i);
}
示例#3
0
/** Rewind cursor to the start of the list
 *
 * @param cursor to operate on.
 * @return #VALUE_PAIR at the start of the list.
 */
VALUE_PAIR *fr_pair_cursor_head(vp_cursor_t *cursor)
{
	if (!cursor->first) return NULL;

	cursor->current = *cursor->first;

	if (cursor->current) {
		VP_VERIFY(cursor->current);
		cursor->next = cursor->current->next;
		if (cursor->next) VP_VERIFY(cursor->next);
		cursor->found = NULL;
	}

	return cursor->current;
}
示例#4
0
/** Compare check and vp. May call the attribute comparison function.
 *
 * Unlike paircmp_pairs() this function will call any attribute-specific
 * comparison functions registered.
 *
 * @param[in] request		Current request.
 * @param[in] request_list	list pairs.
 * @param[in] check		item to compare.
 * @param[in] check_list	list.
 * @param[in] reply_list	list.
 * @return
 *	- 0 if check and vp are equal.
 *	- -1 if vp value is less than check value.
 *	- 1 is vp value is more than check value.
 */
static int paircmp_func(REQUEST *request,
			VALUE_PAIR *request_list,
			VALUE_PAIR *check,
			VALUE_PAIR *check_list,
			VALUE_PAIR **reply_list)
{
	paircmp_t *c;

	VP_VERIFY(check);

	/*
	 *      Check for =* and !* and return appropriately
	 */
	if (check->op == T_OP_CMP_TRUE)  return 0;
	if (check->op == T_OP_CMP_FALSE) return 1;

	/*
	 *	See if there is a special compare function.
	 *
	 *	FIXME: use new RB-Tree code.
	 */
	for (c = cmp; c; c = c->next) {
		if (c->da == check->da) {
			return (c->compare)(c->instance, request, request_list, check, check_list, reply_list);
		}
	}

	if (!request) return -1; /* doesn't exist, don't compare it */

	return paircmp_pairs(request, check, request_list);
}
示例#5
0
/*
 *	Compare prefix/suffix.
 *
 *	If they compare:
 *	- if FR_STRIP_USER_NAME is present in check_list,
 *	  strip the username of prefix/suffix.
 *	- if FR_STRIP_USER_NAME is not present in check_list,
 *	  add a FR_STRIPPED_USER_NAME to the request.
 */
static int prefix_suffix_cmp(UNUSED void *instance,
			     REQUEST *request,
			     VALUE_PAIR *req,
			     VALUE_PAIR *check,
			     VALUE_PAIR *check_list,
			     UNUSED VALUE_PAIR **reply_list)
{
	VALUE_PAIR	*vp;
	char const	*name;
	char		rest[FR_MAX_STRING_LEN];
	int		len, namelen;
	int		ret = -1;

	if (!request || !request->username) return -1;

	VP_VERIFY(check);

	name = request->username->vp_strvalue;

	RDEBUG3("Comparing name \"%s\" and check value \"%s\"", name, check->vp_strvalue);

	len = strlen(check->vp_strvalue);

	if (check->da == attr_prefix) {
		ret = strncmp(name, check->vp_strvalue, len);
		if (ret == 0)
			strlcpy(rest, name + len, sizeof(rest));
	} else if (check->da == attr_suffix) {
		namelen = strlen(name);
		if (namelen >= len) {
			ret = strcmp(name + namelen - len, check->vp_strvalue);
			if (ret == 0) strlcpy(rest, name, namelen - len + 1);
		}
	}

	if (ret != 0) return ret;

	/*
	 *	If Strip-User-Name == No, then don't do any more.
	 */
	vp = fr_pair_find_by_da(check_list, attr_strip_user_name, TAG_ANY);
	if (vp && !vp->vp_uint32) return ret;

	/*
	 *	See where to put the stripped user name.
	 */
	vp = fr_pair_find_by_da(check_list, attr_stripped_user_name, TAG_ANY);
	if (!vp) {
		/*
		 *	If "request" is NULL, then the memory will be
		 *	lost!
		 */
		MEM(vp = fr_pair_afrom_da(request->packet, attr_stripped_user_name));
		fr_pair_add(&req, vp);
		request->username = vp;
	}
	fr_pair_value_strcpy(vp, rest);

	return ret;
}
示例#6
0
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);
	}
}
示例#7
0
/*
 *	Generic comparisons, via xlat.
 */
static int generic_cmp(UNUSED void *instance,
		       REQUEST *request,
		       VALUE_PAIR *req,
		       VALUE_PAIR *check,
		       UNUSED VALUE_PAIR *check_list,
		       UNUSED VALUE_PAIR **reply_list)
{
	VP_VERIFY(check);

	if ((check->op != T_OP_REG_EQ) && (check->op != T_OP_REG_NE)) {
		int rcode;
		char name[1024];
		char value[1024];
		VALUE_PAIR *vp;

		snprintf(name, sizeof(name), "%%{%s}", check->da->name);

		if (xlat_eval(value, sizeof(value), request, name, NULL, NULL) < 0) return 0;

		vp = fr_pair_afrom_da(req, check->da);
		vp->op = check->op;
		fr_pair_value_from_str(vp, value, -1, '"', false);

		/*
		 *	Paircmp returns 0 for failed comparison, 1 for succeeded -1 for error.
		 */
		rcode = fr_pair_cmp(check, vp);

		/*
		 *	We're being called from paircmp_func,
		 *	which wants 0 for success, and 1 for fail (sigh)
		 *
		 *	We should really fix the API so that it is
		 *	consistent.  i.e. the comparison callbacks should
		 *	return ONLY the resut of comparing A to B.
		 *	The radius_callback_cmp function should then
		 *	take care of using the operator to see if the
		 *	condition (A OP B) is true or not.
		 *
		 *	This would also allow "<", etc. to work in the
		 *	callback functions...
		 *
		 *	See rlm_ldap, ...groupcmp() for something that
		 *	returns 0 for matched, and 1 for didn't match.
		 */
		rcode = !rcode;
		fr_pair_list_free(&vp);

		return rcode;
	}

	/*
	 *	Will do the xlat for us
	 */
	return paircmp_pairs(request, check, NULL);
}
示例#8
0
/*
 *	Compare the request packet type.
 */
static int packet_cmp(UNUSED void *instance,
		      REQUEST *request,
		      UNUSED VALUE_PAIR *req,
		      VALUE_PAIR *check,
		      UNUSED VALUE_PAIR *check_list,
		      UNUSED VALUE_PAIR **reply_list)
{
	VP_VERIFY(check);

	if (request->packet->code == check->vp_uint32) return 0;

	return 1;
}
示例#9
0
int8_t fr_dhcpv4_attr_cmp(void const *a, void const *b)
{
	VALUE_PAIR const *my_a = a, *my_b = b;
	fr_dict_attr_t const *a_82, *b_82;

	VP_VERIFY(my_a);
	VP_VERIFY(my_b);

	/*
	 *	We can only use attribute numbers if we know they're
	 *	not nested attributes.
	 *
	 *	@fixme We should be able to use my_a->da->parent->flags.is_root,
	 *	but the DHCP attributes are hacked into the server under a vendor
	 *	dictionary, so we can't.
	 */

	/*
	 *	DHCP-Message-Type is first, for simplicity.
	 */
	if (((my_a->da->parent->type != FR_TYPE_TLV) && (my_a->da == attr_dhcp_message_type)) &&
	    ((my_b->da->parent->type == FR_TYPE_TLV) || (my_b->da != attr_dhcp_message_type))) return -1;
	if (((my_a->da->parent->type == FR_TYPE_TLV) || (my_a->da != attr_dhcp_message_type)) &&
	    ((my_b->da->parent->type != FR_TYPE_TLV) && (my_b->da == attr_dhcp_message_type))) return +1;

	/*
	 *	Relay-Agent is last.
	 *
	 *	Check if either of the options are descended from option 82.
	 */
	a_82 = fr_dict_parent_common(dhcp_option_82, my_a->da, true);
	b_82 = fr_dict_parent_common(dhcp_option_82, my_b->da, true);
	if (a_82 && !b_82) return +1;
	if (!a_82 && !b_82) return -1;

	return fr_pair_cmp_by_parent_num_tag(my_a, my_b);
}
示例#10
0
/** Insert a single VALUE_PAIR at the start of the list
 *
 * @note Will not advance cursor position to new attribute, but will set cursor
 *	 to this attribute, if it's the first one in the list.
 *
 * Insert a VALUE_PAIR at the start of the list.
 *
 * @param cursor to operate on.
 * @param vp to insert.
 */
void fr_pair_cursor_prepend(vp_cursor_t *cursor, VALUE_PAIR *vp)
{
	if (!fr_cond_assert(cursor->first)) return;	/* cursor must have been initialised */

	if (!vp) return;

	VP_VERIFY(vp);
	LIST_VERIFY(*(cursor->first));

	/*
	 *	Only allow one VP to by inserted at a time
	 */
	vp->next = NULL;

	/*
	 *	Cursor was initialised with a pointer to a NULL value_pair
	 */
	if (!*(cursor->first)) {
		*cursor->first = vp;
		cursor->current = vp;

		return;
	}

	/*
	 *	Append to the head of the list
	 */
	vp->next = *cursor->first;
	*cursor->first = vp;

	/*
	 *	Either current was never set, or something iterated to the
	 *	end of the attribute list. In both cases the newly inserted
	 *	VALUE_PAIR should be set as the current VALUE_PAIR.
	 */
	if (!cursor->current) cursor->current = vp;

	/*
	 *	If the next pointer was NULL, and the VALUE_PAIR
	 *	just added has a next pointer value, set the cursor's next
	 *	pointer to the VALUE_PAIR's next pointer.
	 */
	if (!cursor->next) cursor->next = cursor->current->next;

	LIST_VERIFY(*(cursor->first));
}
示例#11
0
/** Iterate over attributes of a given DA in the pairlist
 *
 * Find the next attribute of a given type. If no fr_pair_cursor_next_by_* function
 * has been called on a cursor before, or the previous call returned
 * NULL, the search will start with the current attribute. Subsequent calls to
 * fr_pair_cursor_next_by_* functions will start the search from the previously
 * matched attribute.
 *
 * @note fr_dict_attr_t pointers are compared, not the attribute numbers and vendors.
 *
 * @param cursor to operate on.
 * @param da to match.
 * @param tag to match. Either a tag number or TAG_ANY to match any tagged or
 *	  untagged attribute, TAG_NONE to match attributes without tags.
 * @return
 *	- Next matching #VALUE_PAIR.
 *	- NULL if no #VALUE_PAIR (s) match.
 */
VALUE_PAIR *fr_pair_cursor_next_by_da(vp_cursor_t *cursor, fr_dict_attr_t const *da, int8_t tag)
{
	VALUE_PAIR *i;

	if (!cursor->first) return NULL;

	for (i = cursor->found ? cursor->found->next : cursor->current;
	     i != NULL;
	     i = i->next) {
		VP_VERIFY(i);
		if ((i->da == da) && ATTR_TAG_MATCH(i, tag)) {
			break;
		}
	}

	return fr_pair_cursor_update(cursor, i);
}
示例#12
0
/** 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();
}
示例#13
0
/** Iterate over a collection of VALUE_PAIRs of a given type in the pairlist
 *
 * Find the next attribute of a given type. If no fr_pair_cursor_next_by_* function
 * has been called on a cursor before, or the previous call returned
 * NULL, the search will start with the current attribute. Subsequent calls to
 * fr_pair_cursor_next_by_* functions will start the search from the previously
 * matched attribute.
 *
 * @note If the attribute specified by attr is not a child of the parent, NULL will be returned.
 *
 * @param cursor	to operate on.
 * @param parent	to search for attr in.
 * @param attr		number to match.
 * @param tag		to match. Either a tag number or TAG_ANY to match any tagged or
 *	  		untagged attribute, TAG_NONE to match attributes without tags.
 * @return
 *	- The next matching #VALUE_PAIR.
	- NULL if no #VALUE_PAIR (s) match (or attr doesn't exist).
 */
VALUE_PAIR *fr_pair_cursor_next_by_child_num(vp_cursor_t *cursor,
					fr_dict_attr_t const *parent, unsigned int attr, int8_t tag)
{
	fr_dict_attr_t const *da;
	VALUE_PAIR *i;

	if (!cursor->first) return NULL;

	da = fr_dict_attr_child_by_num(parent, attr);
	if (!da) return NULL;

	for (i = cursor->found ? cursor->found->next : cursor->current;
	     i != NULL;
	     i = i->next) {
		VP_VERIFY(i);
		if ((i->da == da) && ATTR_TAG_MATCH(i, tag)) {
			break;
		}
	}

	return fr_pair_cursor_update(cursor, i);
}
示例#14
0
/** Advanced the cursor to the next VALUE_PAIR
 *
 * @param cursor to operate on.
 * @return
 *	- Next #VALUE_PAIR.
 *	- NULL if no more #VALUE_PAIR in the collection.
 */
VALUE_PAIR *fr_pair_cursor_next(vp_cursor_t *cursor)
{
	if (!cursor->first) return NULL;

	cursor->current = cursor->next;
	if (cursor->current) {
		VP_VERIFY(cursor->current);

		/*
		 *	Set this now in case 'current' gets freed before
		 *	fr_pair_cursor_next is called again.
		 */
		cursor->next = cursor->current->next;

		/*
		 *	Next call to fr_pair_cursor_next_by_num will start from the current
		 *	position in the list, not the last found instance.
		 */
		cursor->found = NULL;
	}

	return cursor->current;
}
示例#15
0
/*
 *
 *     Verify that a Perl SV is a string and save it in FreeRadius
 *     Value Pair Format
 *
 */
static int pairadd_sv(TALLOC_CTX *ctx, REQUEST *request, VALUE_PAIR **vps, char *key, SV *sv, FR_TOKEN op,
		      const char *hash_name, const char *list_name)
{
	char		*val;
	VALUE_PAIR      *vp;
	STRLEN		len;

	if (!SvOK(sv)) return -1;

	val = SvPV(sv, len);
	vp = fr_pair_make(ctx, request->dict, vps, key, NULL, op);
	if (!vp) {
	fail:
		REDEBUG("Failed to create pair %s:%s %s %s", list_name, key,
			fr_int2str(fr_tokens_table, op, "<INVALID>"), val);
		return -1;
	}

	switch (vp->vp_type) {
	case FR_TYPE_STRING:
		fr_pair_value_bstrncpy(vp, val, len);
		break;

	case FR_TYPE_OCTETS:
		fr_pair_value_memcpy(vp, (uint8_t const *)val, len);
		break;

	default:
		if (fr_pair_value_from_str(vp, val, len, '\0', false) < 0) goto fail;
	}

	VP_VERIFY(vp);

	RDEBUG2("&%s:%s %s $%s{'%s'} -> '%s'", list_name, key, fr_int2str(fr_tokens_table, op, "<INVALID>"),
	        hash_name, key, val);
	return 0;
}
示例#16
0
/** Insert a single VALUE_PAIR at the end of the list
 *
 * @note Will not advance cursor position to new attribute, but will set cursor
 *	 to this attribute, if it's the first one in the list.
 *
 * Insert a VALUE_PAIR at the end of the list.
 *
 * @param cursor to operate on.
 * @param vp to insert.
 */
void fr_pair_cursor_append(vp_cursor_t *cursor, VALUE_PAIR *vp)
{
	VALUE_PAIR *i;

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

	if (!vp) return;

	VP_VERIFY(vp);
	LIST_VERIFY(*(cursor->first));

	/*
	 *	Only allow one VP to by inserted at a time
	 */
	vp->next = NULL;

	/*
	 *	Cursor was initialised with a pointer to a NULL value_pair
	 */
	if (!*(cursor->first)) {
		*cursor->first = vp;
		cursor->current = vp;

		return;
	}

	/*
	 *	We don't yet know where the last VALUE_PAIR is
	 *
	 *	Assume current is closer to the end of the list and
	 *	use that if available.
	 */
	if (!cursor->last) cursor->last = cursor->current ? cursor->current : *cursor->first;

	VP_VERIFY(cursor->last);

	/*
	 *	Wind last to the end of the list.
	 */
	if (cursor->last->next) {
		for (i = cursor->last; i; i = i->next) {
			VP_VERIFY(i);
			cursor->last = i;
		}
	}

	/*
	 *	Either current was never set, or something iterated to the
	 *	end of the attribute list. In both cases the newly inserted
	 *	VALUE_PAIR should be set as the current VALUE_PAIR.
	 */
	if (!cursor->current) cursor->current = vp;

	/*
	 *	Add the VALUE_PAIR to the end of the list
	 */
	cursor->last->next = vp;
	cursor->last = vp;	/* Wind it forward a little more */

	/*
	 *	If the next pointer was NULL, and the VALUE_PAIR
	 *	just added has a next pointer value, set the cursor's next
	 *	pointer to the VALUE_PAIR's next pointer.
	 */
	if (!cursor->next) cursor->next = cursor->current->next;

	LIST_VERIFY(*(cursor->first));
}
示例#17
0
/** Return the VALUE_PAIR the cursor current points to
 *
 * @param cursor to operate on.
 * @return the #VALUE_PAIR the cursor currently points to.
 */
VALUE_PAIR *fr_pair_cursor_current(vp_cursor_t *cursor)
{
	if (cursor->current) VP_VERIFY(cursor->current);

	return cursor->current;
}