Пример #1
0
/** 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;
}
Пример #2
0
/** Convert strings to value_pair_map_e
 *
 * Treatment of operands depends on quotation, barewords are treated
 * as attribute references, double quoted values are treated as
 * expandable strings, single quoted values are treated as literal
 * strings.
 *
 * Return must be freed with talloc_free
 *
 * @param[in] ctx for talloc
 * @param[in] lhs of the operation
 * @param[in] lhs_type type of the LHS string
 * @param[in] op the operation to perform
 * @param[in] rhs of the operation
 * @param[in] rhs_type type of the RHS string
 * @param[in] dst_request_def The default request to insert unqualified
 *	attributes into.
 * @param[in] dst_list_def The default list to insert unqualified attributes
 *	into.
 * @param[in] src_request_def The default request to resolve attribute
 *	references in.
 * @param[in] src_list_def The default list to resolve unqualified attributes
 *	in.
 * @return value_pair_map_t if successful or NULL on error.
 */
value_pair_map_t *radius_str2map(TALLOC_CTX *ctx, char const *lhs, FR_TOKEN lhs_type,
				 FR_TOKEN op, char const *rhs, FR_TOKEN rhs_type,
				 request_refs_t dst_request_def,
				 pair_lists_t dst_list_def,
				 request_refs_t src_request_def,
				 pair_lists_t src_list_def)
{
	value_pair_map_t *map;

	map = talloc_zero(ctx, value_pair_map_t);

	if ((lhs_type == T_BARE_WORD) && (*lhs == '&')) {
		map->dst = radius_attr2tmpl(map, lhs + 1, dst_request_def, dst_list_def);
	} else {
		map->dst = radius_str2tmpl(map, lhs, lhs_type);
	}

	if (!map->dst) {
	error:
		talloc_free(map);
		return NULL;
	}

	map->op = op;

	/*
	 *	Ignore the RHS if it's a true / false comparison.
	 */
	if ((map->op == T_OP_CMP_TRUE) || (map->op == T_OP_CMP_FALSE)) {
		return map;
	}

	if ((rhs_type == T_BARE_WORD) && (*rhs == '&')) {
		map->src = radius_attr2tmpl(map, rhs + 1, src_request_def, src_list_def);
	} else {
		map->src = radius_str2tmpl(map, rhs, rhs_type);
	}

	if (!map->dst) goto error;

	return map;
}
Пример #3
0
/** Convert CONFIG_PAIR (which may contain refs) to value_pair_map_t.
 *
 * Treats the left operand as an attribute reference
 * @verbatim<request>.<list>.<attribute>@endverbatim
 *
 * Treatment of left operand depends on quotation, barewords are treated as
 * attribute references, double quoted values are treated as expandable strings,
 * single quoted values are treated as literal strings.
 *
 * Return must be freed with talloc_free
 *
 * @param[in] ctx for talloc
 * @param[in] cp to convert to map.
 * @param[in] dst_request_def The default request to insert unqualified
 *	attributes into.
 * @param[in] dst_list_def The default list to insert unqualified attributes
 *	into.
 * @param[in] src_request_def The default request to resolve attribute
 *	references in.
 * @param[in] src_list_def The default list to resolve unqualified attributes
 *	in.
 * @return value_pair_map_t if successful or NULL on error.
 */
value_pair_map_t *radius_cp2map(TALLOC_CTX *ctx, CONF_PAIR *cp,
				request_refs_t dst_request_def,
				pair_lists_t dst_list_def,
				request_refs_t src_request_def,
				pair_lists_t src_list_def)
{
	value_pair_map_t *map;
	char const *attr;
	char const *value;
	FR_TOKEN type;
	CONF_ITEM *ci = cf_pairtoitem(cp);

	if (!cp) return NULL;

	map = talloc_zero(ctx, value_pair_map_t);

	attr = cf_pair_attr(cp);
	value = cf_pair_value(cp);
	if (!value) {
		cf_log_err(ci, "Missing attribute value");
		goto error;
	}

	map->dst = radius_attr2tmpl(map, attr, dst_request_def, dst_list_def);
	if (!map->dst) {
		cf_log_err(ci, "Syntax error in attribute definition");
		goto error;
	}

	/*
	 *	Bare words always mean attribute references.
	 */
	type = cf_pair_value_type(cp);
	if (type == T_BARE_WORD) {
		if (*value == '&') {
			map->src = radius_attr2tmpl(map, value + 1, src_request_def, src_list_def);

		} else {
			if (!isdigit((int) *value) &&
			    ((strchr(value, ':') != NULL) ||
			     (dict_attrbyname(value) != NULL))) {
				map->src = radius_attr2tmpl(map, value, src_request_def, src_list_def);
			}
			if (map->src) {
				WDEBUG("%s[%d]: Please add '&' for attribute reference '%s = &%s'",
				       cf_pair_filename(cp), cf_pair_lineno(cp),
				       attr, value);
			} else {
				map->src = radius_str2tmpl(map, value, type);
			}
		}
	} else {
		map->src = radius_str2tmpl(map, value, type);
	}

	if (!map->src) {
		goto error;
	}

	map->op = cf_pair_operator(cp);
	map->ci = ci;

	/*
	 *	Lots of sanity checks for insane people...
	 */

	/*
	 *	We don't support implicit type conversion,
	 *	except for "octets"
	 */
	if (map->dst->da && map->src->da &&
	    (map->src->da->type != map->dst->da->type) &&
	    (map->src->da->type != PW_TYPE_OCTETS) &&
	    (map->dst->da->type != PW_TYPE_OCTETS)) {
		cf_log_err(ci, "Attribute type mismatch");
		goto error;
	}

	/*
	 *	What exactly where you expecting to happen here?
	 */
	if ((map->dst->type == VPT_TYPE_ATTR) &&
	    (map->src->type == VPT_TYPE_LIST)) {
		cf_log_err(ci, "Can't copy list into an attribute");
		goto error;
	}

	/*
	 *	Can't copy an xlat expansion or literal into a list,
	 *	we don't know what type of attribute we'd need
	 *	to create
	 */
	if ((map->dst->type == VPT_TYPE_LIST) &&
	    ((map->src->type == VPT_TYPE_XLAT) || (map->src->type == VPT_TYPE_LITERAL))) {
		cf_log_err(ci, "Can't copy value into list (we don't know which attribute to create)");
		goto error;
	}

	/*
	 *	Depending on the attribute type, some operators are
	 *	disallowed.
	 */
	if (map->dst->type == VPT_TYPE_ATTR) {
		if ((map->op != T_OP_EQ) &&
		    (map->op != T_OP_CMP_EQ) &&
		    (map->op != T_OP_ADD) &&
		    (map->op != T_OP_SUB) &&
		    (map->op != T_OP_LE) &&
		    (map->op != T_OP_GE) &&
		    (map->op != T_OP_CMP_FALSE) &&
		    (map->op != T_OP_SET)) {
			cf_log_err(ci, "Invalid operator for attribute");
			goto error;
		}
	}

	switch (map->src->type) {
		/*
		 *	Only += and -= operators are supported for list copy.
		 */
		case VPT_TYPE_LIST:
			switch (map->op) {
			case T_OP_SUB:
			case T_OP_ADD:
				break;

			default:
				cf_log_err(ci, "Operator \"%s\" not allowed "
					   "for list copy",
					   fr_int2str(fr_tokens, map->op, "<INVALID>"));
				goto error;
			}
		break;

		default:
			break;
	}

	return map;

error:
	talloc_free(map);
	return NULL;
}
Пример #4
0
/** Convert CONFIG_PAIR (which may contain refs) to value_pair_map_t.
 *
 * Treats the left operand as an attribute reference
 * @verbatim<request>.<list>.<attribute>@endverbatim 
 *
 * Treatment of left operand depends on quotation, barewords are treated as
 * attribute references, double quoted values are treated as expandable strings,
 * single quoted values are treated as literal strings.
 *
 * Return must be freed with radius_mapfree.
 *
 * @param[in] cp to convert to map.
 * @param[in] dst_request_def The default request to insert unqualified
 *	attributes into.
 * @param[in] dst_list_def The default list to insert unqualified attributes
 *	into.
 * @param[in] src_request_def The default request to resolve attribute
 *	references in.
 * @param[in] src_list_def The default list to resolve unqualified attributes
 *	in.
 * @return value_pair_map_t if successful or NULL on error.
 */
value_pair_map_t *radius_cp2map(CONF_PAIR *cp,
				request_refs_t dst_request_def,
				pair_lists_t dst_list_def,
				request_refs_t src_request_def,
				pair_lists_t src_list_def)
{
	value_pair_map_t *map;
	const char *attr;
	const char *value;
	FR_TOKEN type;
	CONF_ITEM *ci = cf_pairtoitem(cp); 
	
	if (!cp) return NULL;
	
	map = rad_calloc(sizeof(value_pair_map_t));

	attr = cf_pair_attr(cp);
	value = cf_pair_value(cp);
	if (!value) {
		cf_log_err(ci, "Missing attribute value");
		
		goto error;
	}
	
	map->dst = radius_attr2tmpl(attr, dst_request_def, dst_list_def);
	if (!map->dst){
		goto error;
	}

	/*
	 *	Bare words always mean attribute references.
	 */
	type = cf_pair_value_type(cp);
	map->src = type == T_BARE_WORD ?
		   radius_attr2tmpl(value, src_request_def, src_list_def) :
		   radius_str2tmpl(value, type);

	if (!map->src) {
		goto error;
	}

	map->op = cf_pair_operator(cp);
	map->ci = ci;
	
	/*
	 *	Lots of sanity checks for insane people...
	 */
	 
	/*
	 *	We don't support implicit type conversion
	 */
	if (map->dst->da && map->src->da &&
	    (map->src->da->type != map->dst->da->type)) {
		cf_log_err(ci, "Attribute type mismatch");
		
		goto error;
	}
	
	/*
	 *	What exactly where you expecting to happen here?
	 */
	if ((map->dst->type == VPT_TYPE_ATTR) &&
	    (map->src->type == VPT_TYPE_LIST)) {
		cf_log_err(ci, "Can't copy list into an attribute");
		
		goto error;
	}

	switch (map->src->type) 
	{
	
		/*
		 *	Only += and -= operators are supported for list copy.
		 */
		case VPT_TYPE_LIST:
			switch (map->op) {
			case T_OP_SUB:
			case T_OP_ADD:
				break;
			
			default:
				cf_log_err(ci, "Operator \"%s\" not allowed "
					   "for list copy",
					   fr_int2str(fr_tokens, map->op,
						      "¿unknown?"));
				goto error;
			}
		break;
		/*
		 *	@todo add support for exec expansion.
		 */
		case VPT_TYPE_EXEC:
			cf_log_err(ci, "Exec values are not allowed");
			break;
		default:
			break;
	}
	
	return map;
	
	error:
		radius_mapfree(&map);
		return NULL;
}
Пример #5
0
/** Convert CONFIG_PAIR (which may contain refs) to value_pair_map_t.
 *
 * Treats the left operand as an attribute reference
 * @verbatim<request>.<list>.<attribute>@endverbatim
 *
 * Treatment of left operand depends on quotation, barewords are treated as
 * attribute references, double quoted values are treated as expandable strings,
 * single quoted values are treated as literal strings.
 *
 * Return must be freed with talloc_free
 *
 * @param[in] ctx for talloc
 * @param[in] cp to convert to map.
 * @param[in] dst_request_def The default request to insert unqualified
 *	attributes into.
 * @param[in] dst_list_def The default list to insert unqualified attributes
 *	into.
 * @param[in] src_request_def The default request to resolve attribute
 *	references in.
 * @param[in] src_list_def The default list to resolve unqualified attributes
 *	in.
 * @return value_pair_map_t if successful or NULL on error.
 */
value_pair_map_t *radius_cp2map(TALLOC_CTX *ctx, CONF_PAIR *cp,
				request_refs_t dst_request_def,
				pair_lists_t dst_list_def,
				request_refs_t src_request_def,
				pair_lists_t src_list_def)
{
	value_pair_map_t *map;
	char const *attr;
	char const *value;
	FR_TOKEN type;
	CONF_ITEM *ci = cf_pairtoitem(cp);

	if (!cp) return NULL;

	map = talloc_zero(ctx, value_pair_map_t);
	map->op = cf_pair_operator(cp);
	map->ci = ci;

	attr = cf_pair_attr(cp);
	value = cf_pair_value(cp);
	if (!value) {
		cf_log_err(ci, "Missing attribute value");
		goto error;
	}

	/*
	 *	LHS must always be an attribute reference.
	 */
	map->dst = radius_attr2tmpl(map, attr, dst_request_def, dst_list_def);
	if (!map->dst) {
		cf_log_err(ci, "Syntax error in attribute definition");
		goto error;
	}

	/*
	 *	RHS might be an attribute reference.
	 */
	type = cf_pair_value_type(cp);
	map->src = radius_str2tmpl(map, value, type, src_request_def, src_list_def);
	if (!map->src) {
		goto error;
	}

	/*
	 *	Anal-retentive checks.
	 */
	if (debug_flag > 2) {
		if ((map->dst->type == VPT_TYPE_ATTR) && (*attr != '&')) {
			WARN("%s[%d]: Please change attribute reference to '&%s %s ...'",
			       cf_pair_filename(cp), cf_pair_lineno(cp),
			       attr, fr_int2str(fr_tokens, map->op, "<INVALID>"));
		}

		if ((map->src->type == VPT_TYPE_ATTR) && (*value != '&')) {
			WARN("%s[%d]: Please change attribute reference to '... %s &%s'",
			       cf_pair_filename(cp), cf_pair_lineno(cp),
			       fr_int2str(fr_tokens, map->op, "<INVALID>"), value);
		}
	}

	/*
	 *	Lots of sanity checks for insane people...
	 */

	/*
	 *	We don't support implicit type conversion,
	 *	except for "octets"
	 */
	if (map->dst->vpt_da && map->src->vpt_da &&
	    (map->src->vpt_da->type != map->dst->vpt_da->type) &&
	    (map->src->vpt_da->type != PW_TYPE_OCTETS) &&
	    (map->dst->vpt_da->type != PW_TYPE_OCTETS)) {
		cf_log_err(ci, "Attribute type mismatch");
		goto error;
	}

	/*
	 *	What exactly where you expecting to happen here?
	 */
	if ((map->dst->type == VPT_TYPE_ATTR) &&
	    (map->src->type == VPT_TYPE_LIST)) {
		cf_log_err(ci, "Can't copy list into an attribute");
		goto error;
	}

	/*
	 *	Depending on the attribute type, some operators are
	 *	disallowed.
	 */
	if (map->dst->type == VPT_TYPE_ATTR) {
		if ((map->op != T_OP_EQ) &&
		    (map->op != T_OP_CMP_EQ) &&
		    (map->op != T_OP_ADD) &&
		    (map->op != T_OP_SUB) &&
		    (map->op != T_OP_LE) &&
		    (map->op != T_OP_GE) &&
		    (map->op != T_OP_CMP_FALSE) &&
		    (map->op != T_OP_SET)) {
			cf_log_err(ci, "Invalid operator for attribute");
			goto error;
		}

		/*
		 *	This will be an error in future versions of
		 *	the server.
		 */
		if ((map->op == T_OP_CMP_FALSE) &&
		    ((map->src->type != VPT_TYPE_LITERAL) ||
		     (strcmp(map->src->name, "ANY") != 0))) {
			WARN("%s[%d] Attribute deletion MUST use '!* ANY'",
			       cf_pair_filename(cp), cf_pair_lineno(cp));
		}
	}

	if (map->dst->type == VPT_TYPE_LIST) {
		/*
		 *	Only += and :=, and !* operators are supported
		 *	for lists.
		 */
		switch (map->op) {
		case T_OP_CMP_FALSE:
			if ((map->src->type != VPT_TYPE_LITERAL) ||
			    (strcmp(map->src->name, "ANY") != 0)) {
				cf_log_err(ci, "List deletion MUST use '!* ANY'");
				goto error;
			}
			break;

		case T_OP_ADD:
			if ((map->src->type != VPT_TYPE_LIST) &&
			    (map->src->type != VPT_TYPE_EXEC)) {
				cf_log_err(ci, "Invalid source for list '+='");
				goto error;
			}
			break;

		case T_OP_SET:
			if (map->src->type == VPT_TYPE_EXEC) {
				WARN("%s[%d] Please change ':=' to '=' for list assignment",
				       cf_pair_filename(cp), cf_pair_lineno(cp));
				break;
			}

			if (map->src->type != VPT_TYPE_LIST) {
				cf_log_err(ci, "Invalid source for ':=' operator");
				goto error;
			}
			break;

		case T_OP_EQ:
			if (map->src->type != VPT_TYPE_EXEC) {
				cf_log_err(ci, "Invalid source for '=' operator");
				goto error;
			}
			break;

		default:
			cf_log_err(ci, "Operator \"%s\" not allowed for list assignment",
				   fr_int2str(fr_tokens, map->op, "<INVALID>"));
			goto error;
		}
	}

	return map;

error:
	talloc_free(map);
	return NULL;
}