29 RCSID(
"$Id: 33d6ad0bddff18c91ba33aeed0d47395a46bf03b $")
31 #include <freeradius-devel/radiusd.h>
32 #include <freeradius-devel/rad_assert.h>
39 RDEBUG(
">>> MAP TYPES LHS: %s, RHS: %s",
91 if ((rhs[0] !=
'0') || (tolower((
int)rhs[1]) !=
'x'))
return false;
92 if (!rhs[2])
return false;
94 len = strlen(rhs + 2);
96 ptr = talloc_array(map, uint8_t, len >> 1);
97 if (!ptr)
return false;
109 if (rlen < 0)
return false;
111 if ((
size_t) rlen < len) {
127 if (!map->
rhs)
goto free_vp;
129 map->
rhs->tmpl_data_type = da->
type;
130 map->
rhs->tmpl_data_length = vp->vp_length;
136 map->
rhs->tmpl_data_value.ptr = talloc_memdup(map->
rhs, vp->
data.ptr, vp->vp_length);
140 memcpy(&map->
rhs->tmpl_data_value, &vp->
data,
sizeof(map->
rhs->tmpl_data_value));
150 memcpy(&vpt->
data.attribute, &map->
lhs->
data.attribute,
sizeof(vpt->
data.attribute));
165 vpt->
name = talloc_asprintf(vpt,
"%.*s:%s",
171 talloc_free(map->
lhs);
212 char const *attr, *value;
240 type, dst_request_def, dst_list_def,
true);
277 if ((type ==
T_BARE_WORD) && (value[0] ==
'0') && (tolower((
int)value[1]) ==
'x') &&
281 slen =
tmpl_afrom_str(map, &map->
rhs, value, strlen(value), type, src_request_def, src_list_def,
true);
282 if (slen < 0)
goto marker;
336 char const *cs_list, *p;
343 unsigned int total = 0;
365 cf_log_err(ci,
"Default request specified in mapping section is invalid");
371 cf_log_err(ci,
"Default list \"%s\" specified "
372 "in mapping section is invalid", p);
380 if (total++ == max) {
388 cf_log_err(ci,
"Entry is not in \"attribute = value\" format");
402 if (validate && (validate(map, ctx) < 0))
goto error;
404 parent = *tail =
map;
446 slen =
tmpl_afrom_str(map, &map->
lhs, lhs, strlen(lhs), lhs_type, dst_request_def, dst_list_def,
true);
456 map->
lhs->tmpl_da->flags.is_unknown &&
461 slen =
tmpl_afrom_str(map, &map->
rhs, rhs, strlen(rhs), rhs_type, src_request_def, src_list_def,
true);
462 if (slen < 0)
goto error;
491 char const *p = vp_str;
522 dst_request_def, dst_list_def, src_request_def, src_list_def) < 0) {
557 if (cmp != 0)
return cmp;
559 if (my_a->tmpl_tag < my_b->tmpl_tag)
return -1;
561 if (my_a->tmpl_tag > my_b->tmpl_tag)
return 1;
563 if (my_a->tmpl_num < my_b->tmpl_num)
return -1;
565 if (my_a->tmpl_num > my_b->tmpl_num)
return 1;
578 if (!source || !source->
next) {
615 if (
cmp(a, b) <= 0) {
640 if (!head || !head->
next) {
671 char *expanded = NULL;
696 request, map->
rhs->
name, input_pairs ? *input_pairs : NULL,
698 talloc_free(expanded);
700 talloc_free(output_pairs);
707 REDEBUG(
"No valid attributes received from program");
720 vp->
tag = map->
lhs->tmpl_tag;
788 if (!found)
return 0;
835 new->tag = map->
lhs->tmpl_tag;
860 new->tag = map->
lhs->tmpl_tag;
876 new->tag = map->
lhs->tmpl_tag;
922 new->tag = map->
lhs->tmpl_tag;
933 vp->
da = map->
lhs->tmpl_da;
935 vp->
tag = map->
lhs->tmpl_tag;
948 if (map->
lhs->tmpl_da->
type == map->
rhs->tmpl_data_type) {
949 if (
value_data_copy(
new, &new->data, new->da->type, &map->
rhs->tmpl_data_value) < 0) {
954 if (
value_data_cast(
new, &new->data, new->da->type, new->da, map->
rhs->tmpl_data_type,
955 NULL, &map->
rhs->tmpl_data_value) < 0) {
962 new->tag = map->
lhs->tmpl_tag;
989 #define DEBUG_OVERWRITE(_old, _new) \
991 if (RDEBUG_ENABLED3) {\
992 char *old = fr_pair_value_asprint(request, _old, '"');\
993 char *new = fr_pair_value_asprint(request, _new, '"');\
995 RDEBUG3("--> overwriting '%s' with '%s'", old, new);\
1067 REDEBUG(
"Left side \"%.*s\" expansion not an attribute reference: %s",
1074 memcpy(&exp_map, map,
sizeof(exp_map));
1075 exp_map.
lhs = &exp_lhs;
1092 REDEBUG(
"Left side \"%.*s\" of map should be an attr or list but is an %s",
1100 REDEBUG(
"Mapping \"%.*s\" -> \"%.*s\" invalid in this context",
1112 REDEBUG(
"Failed to create a CoA/Disconnect Request message");
1122 REDEBUG(
"Mapping \"%.*s\" -> \"%.*s\" invalid in this context",
1138 rcode = func(parent, &head, request, map, ctx);
1205 num = map->
lhs->tmpl_num;
1209 if (num-- == 0)
break;
1236 map->
lhs->tmpl_tag);
1285 if (!found)
return 0;
1308 if (!found)
return 0;
1319 vp->
tag = map->
lhs->tmpl_tag;
1329 RDEBUG3(
"Refusing to overwrite (use :=)");
1376 RDEBUG3(
"No existing attribute to filter, adding instead");
1396 if (rcode == 0)
continue;
1406 if (rcode <= 0)
continue;
1410 if (rcode >= 0)
continue;
1419 if (!found)
return 0;
1451 if (vp->
da->
attr == PW_STRIPPED_USER_NAME) {
1456 if (vp->
da->
attr == PW_USER_PASSWORD) {
1499 char *end = out + outlen;
1517 len =
strlcpy(p,
"ANY", (end - p));
1590 memcpy(&vpt, map->
rhs,
sizeof(vpt));
1591 vpt.tmpl_da = vp->
da;
1592 vpt.tmpl_tag = vp->
tag;
1601 vp->vp_length) ?
'\'' :
'"';
1618 vp->vp_length) ?
'\'' :
'"';
1625 strcpy(buffer,
"ANY");
1645 if (value != buffer) talloc_free(value);
void fr_pair_list_free(VALUE_PAIR **)
Free memory used by a valuepair list.
int8_t(* fr_cmp_t)(void const *a, void const *b)
ssize_t ssize_t ssize_t radius_axlat(char **out, REQUEST *request, char const *fmt, xlat_escape_t escape, void *escape_ctx) CC_HINT(nonnull(1
int(* radius_map_getvalue_t)(TALLOC_CTX *ctx, VALUE_PAIR **out, REQUEST *request, vp_map_t const *map, void *uctx)
int radius_exec_program(TALLOC_CTX *ctx, char *out, size_t outlen, VALUE_PAIR **output_pairs, REQUEST *request, char const *cmd, VALUE_PAIR *input_pairs, bool exec_wait, bool shell_escape, int timeout) CC_HINT(nonnull(5
FR_TOKEN getop(char const **ptr)
const char fr_token_quote[]
Convert tokens back to a quoting character.
VALUE_PAIR * fr_cursor_first(vp_cursor_t *cursor)
Rewind cursor to the start of the list.
FR_TOKEN cf_pair_value_type(CONF_PAIR const *pair)
Return the value (rhs) type.
ssize_t tmpl_afrom_str(TALLOC_CTX *ctx, vp_tmpl_t **out, char const *name, size_t inlen, FR_TOKEN type, request_refs_t request_def, pair_lists_t list_def, bool do_escape)
Convert an arbitrary string into a vp_tmpl_t.
ssize_t ssize_t ssize_t ssize_t radius_axlat_struct(char **out, REQUEST *request, xlat_exp_t const *xlat, xlat_escape_t escape, void *ctx) CC_HINT(nonnull(1
static int map_exec_to_vp(TALLOC_CTX *ctx, VALUE_PAIR **out, REQUEST *request, vp_map_t const *map)
Process map which has exec as a src.
VALUE_PAIR * fr_cursor_last(vp_cursor_t *cursor)
Wind cursor to the last pair in the list.
int8_t fr_pointer_cmp(void const *a, void const *b)
Compares two pointers.
char const * name
Raw string used to create the template.
char const * fr_token_name(int)
int map_afrom_cp(TALLOC_CTX *ctx, vp_map_t **out, 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)
Convert CONFIG_PAIR (which may contain refs) to vp_map_t.
vp_tmpl_t * lhs
Typically describes the attribute to add, modify or compare.
CONF_ITEM * cf_pair_to_item(CONF_PAIR const *cp)
Cast a CONF_PAIR to a CONF_ITEM.
TALLOC_CTX * radius_list_ctx(REQUEST *request, pair_lists_t list_name)
Return the correct TALLOC_CTX to alloc VALUE_PAIR in, for a list.
VALUE_PAIR ** radius_list(REQUEST *request, pair_lists_t list)
Resolve attribute pair_lists_t value to an attribute list.
vp_tmpl_t * rhs
Typically describes a literal value or a src attribute to copy or compare.
Pre-parsed XLAT expansion.
static vp_map_t * map_sort_merge(vp_map_t *a, vp_map_t *b, fr_cmp_t cmp)
int map_to_request(REQUEST *request, vp_map_t const *map, radius_map_getvalue_t func, void *ctx)
Convert vp_map_t to VALUE_PAIR (s) and add them to a REQUEST.
VALUE_PAIR * username
Cached username VALUE_PAIR from request RADIUS_PACKET.
Attributes to send in a forked CoA-Request.
ssize_t tmpl_afrom_attr_str(TALLOC_CTX *ctx, vp_tmpl_t **out, char const *name, request_refs_t request_def, pair_lists_t list_def, bool allow_unknown, bool allow_undefined)
Parse a string into a TMPL_TYPE_ATTR_* or TMPL_TYPE_LIST type vp_tmpl_t.
int8_t map_cmp_by_lhs_attr(void const *a, void const *b)
Compare map where LHS is TMPL_TYPE_ATTR.
int8_t tag
Tag value used to group valuepairs.
void size_t fr_pair_value_snprint(char *out, size_t outlen, VALUE_PAIR const *vp, char quote)
Print the value of an attribute to a string.
const FR_NAME_NUMBER fr_tokens_table[]
bool map_cast_from_hex(vp_map_t *map, FR_TOKEN rhs_type, char const *rhs)
re-parse a map where the lhs is an unknown attribute.
unsigned int is_pointer
data is a pointer
VALUE_PAIR * fr_cursor_init(vp_cursor_t *cursor, VALUE_PAIR *const *node)
Setup a cursor to iterate over attribute pairs.
void void void cf_log_err_cp(CONF_PAIR const *cp, char const *fmt,...) CC_HINT(format(printf
VALUE_PAIR * password
Cached password VALUE_PAIR from request RADIUS_PACKET.
REQUEST * request_alloc_coa(REQUEST *request)
int map_afrom_fields(TALLOC_CTX *ctx, vp_map_t **out, 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)
Convert strings to vp_map_t.
static void map_sort_split(vp_map_t *source, vp_map_t **front, vp_map_t **back)
size_t map_snprint(char *out, size_t outlen, vp_map_t const *map)
Print a map to a string.
int map_afrom_attr_str(TALLOC_CTX *ctx, vp_map_t **out, char const *vp_str, request_refs_t dst_request_def, pair_lists_t dst_list_def, request_refs_t src_request_def, pair_lists_t src_list_def)
Convert a value pair string to valuepair map.
Abstraction to allow iterating over different configurations of VALUE_PAIRs.
fr_dict_attr_flags_t flags
Flags.
char const * cf_pair_value(CONF_PAIR const *pair)
struct vp_map * next
The next valuepair map.
bool map_dst_valid(REQUEST *request, vp_map_t const *map)
Check whether the destination of a map is currently valid.
char * fr_pair_value_asprint(TALLOC_CTX *ctx, VALUE_PAIR const *vp, char quote)
Print one attribute value to a string.
RADIUS_PACKET * proxy
Outgoing request to proxy server.
Attributes to send in a forked Disconnect-Request.
int fr_str2int(FR_NAME_NUMBER const *table, char const *name, int def)
int tmpl_define_unknown_attr(vp_tmpl_t *vpt)
Add an unknown fr_dict_attr_t specified by a vp_tmpl_t to the main dictionary.
ssize_t fr_radius_decode_pair_value(TALLOC_CTX *ctx, vp_cursor_t *cursor, fr_dict_attr_t const *parent, uint8_t const *data, size_t const attr_len, size_t const packet_len, void *decoder_ctx)
Create any kind of VP from the attribute contents.
VALUE_PAIR * fr_pair_list_copy(TALLOC_CTX *ctx, VALUE_PAIR *from)
Copy a pairlist.
char r_opand[1024]
Right hand side of the pair.
unsigned int is_unknown
Attribute number or vendor is unknown.
bool is_printable(void const *value, size_t len)
Check whether the string is made up of printable UTF8 chars.
int value_data_cast(TALLOC_CTX *ctx, value_data_t *dst, PW_TYPE dst_type, fr_dict_attr_t const *dst_enumv, PW_TYPE src_type, fr_dict_attr_t const *src_enumv, value_data_t const *src)
Convert one type of value_data_t to another.
int map_to_vp(TALLOC_CTX *ctx, VALUE_PAIR **out, REQUEST *request, vp_map_t const *map, UNUSED void *uctx)
Convert a map to a VALUE_PAIR.
char const * cf_pair_attr(CONF_PAIR const *pair)
void fr_cursor_merge(vp_cursor_t *cursor, VALUE_PAIR *vp)
Merges multiple VALUE_PAIR into the cursor.
ssize_t tmpl_from_attr_str(vp_tmpl_t *vpt, char const *name, request_refs_t request_def, pair_lists_t list_def, bool allow_unknown, bool allow_undefined)
Parse a string into a TMPL_TYPE_ATTR_* or TMPL_TYPE_LIST type vp_tmpl_t.
void fr_cursor_insert(vp_cursor_t *cursor, VALUE_PAIR *vp)
Insert a single VALUE_PAIR at the end of the list.
void fr_pair_add(VALUE_PAIR **head, VALUE_PAIR *vp)
Add a VP to the end of the list.
size_t fr_hex2bin(uint8_t *bin, size_t outlen, char const *hex, size_t inlen)
Convert hex strings to binary data.
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *item)
Cast a CONF_ITEM to a CONF_PAIR.
unsigned int attr
Attribute number.
REQUEST * coa
CoA request originated by this request.
Attributes in incoming or internally proxied request.
int radius_request(REQUEST **request, request_refs_t name)
Resolve a request_refs_t to a REQUEST.
unsigned int code
Packet code (type).
A VALUE_PAIR in string format.
CONF_ITEM * cf_section_to_item(CONF_SECTION const *cs)
Cast a CONF_SECTION to a CONF_ITEM.
unsigned int vendor
Vendor that defines this attribute.
Stores an attribute, a value and various bits of other data.
void rad_const_free(void const *ptr)
ssize_t tmpl_aexpand(TALLOC_CTX *ctx, char **out, REQUEST *request, vp_tmpl_t const *vpt, xlat_escape_t escape, void *escape_ctx)
Expand a template to a string, allocing a new buffer to hold the string.
VALUE_PAIR * fr_cursor_current(vp_cursor_t *cursor)
Return the VALUE_PAIR the cursor current points to.
char * talloc_typed_asprintf(void const *t, char const *fmt,...)
Call talloc vasprintf, setting the type on the new chunk correctly.
bool cf_item_is_pair(CONF_ITEM const *item)
Configuration AVP similar to a VALUE_PAIR.
FR_TOKEN op
Operator to use when moving or inserting valuepair into a list.
int fr_pair_value_from_str(VALUE_PAIR *vp, char const *value, size_t len)
Convert string value to native attribute value.
tmpl_type_t type
What type of value tmpl refers to.
RFC3575/RFC5176 - CoA-Request.
char const * fr_strerror(void)
Get the last library error.
size_t len
Length of the raw string used to create the template.
#define RETURN_IF_TRUNCATED(_p, _ret, _max)
Boilerplate for checking truncation.
int tmpl_copy_vps(TALLOC_CTX *ctx, VALUE_PAIR **out, REQUEST *request, vp_tmpl_t const *vpt)
Copy pairs matching a vp_tmpl_t in the current REQUEST.
int value_data_copy(TALLOC_CTX *ctx, value_data_t *dst, PW_TYPE type, const value_data_t *src)
Copy value data verbatim duplicating any buffers.
void fr_pair_delete_by_num(VALUE_PAIR **head, unsigned int vendor, unsigned int attr, int8_t tag)
Delete matching pairs.
char const * cf_section_name1(CONF_SECTION const *cs)
Callout to an external script or program.
int(* map_validate_t)(vp_map_t *map, void *ctx)
void fr_pair_list_move(TALLOC_CTX *ctx, VALUE_PAIR **to, VALUE_PAIR **from)
Move pairs from source list to destination list respecting operator.
char name[1]
Attribute name.
char * talloc_bstrndup(void const *t, char const *in, size_t inlen)
Binary safe strndup function.
VALUE_PAIR * fr_cursor_replace(vp_cursor_t *cursor, VALUE_PAIR *new)
Replace the current pair.
void cf_log_err(CONF_ITEM const *ci, char const *fmt,...) CC_HINT(format(printf
FR_TOKEN op
The operator that controls insertion of the dst attribute.
log_lvl_t rad_debug_lvl
Global debugging level.
FR_TOKEN gettoken(char const **ptr, char *buf, int buflen, bool unescape)
VALUE_PAIR * fr_cursor_next(vp_cursor_t *cursor)
Advanced the cursor to the next VALUE_PAIR.
size_t radius_list_name(pair_lists_t *out, char const *name, pair_lists_t default_list)
Resolve attribute name to a pair_lists_t value.
size_t tmpl_snprint(char *buffer, size_t bufsize, vp_tmpl_t const *vpt, fr_dict_attr_t const *values)
Print a vp_tmpl_t to a string.
int map_afrom_cs(vp_map_t **out, CONF_SECTION *cs, pair_lists_t dst_list_def, pair_lists_t src_list_def, map_validate_t validate, void *ctx, unsigned int max)
Convert an 'update' config section into an attribute map.
void void void fr_canonicalize_error(TALLOC_CTX *ctx, char **spaces, char **text, ssize_t slen, char const *msg)
Canonicalize error strings, removing tabs, and generate spaces for error marker.
enum pair_lists pair_lists_t
void fr_strerror_printf(char const *,...) CC_HINT(format(printf
unsigned int has_tag
Tagged attribute.
CONF_ITEM * cf_item_find_next(CONF_SECTION const *section, CONF_ITEM const *item)
Return the next item after a CONF_ITEM.
#define DEBUG_OVERWRITE(_old, _new)
VALUE_PAIR * fr_cursor_remove(vp_cursor_t *cursor)
Remove the current pair.
size_t radius_request_name(request_refs_t *out, char const *name, request_refs_t unknown)
Resolve attribute name to a request_refs_t value.
size_t strlcpy(char *dst, char const *src, size_t siz)
VALUE_PAIR * fr_pair_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Dynamically allocate a new attribute.
FR_TOKEN cf_pair_attr_type(CONF_PAIR const *pair)
Return the value (lhs) type.
char const * fr_int2str(FR_NAME_NUMBER const *table, int number, char const *def)
fr_dict_attr_t const * da
Dictionary attribute defines the attribute.
char l_opand[256]
Left hand side of the pair.
fr_dict_attr_t const * fr_dict_attr_by_num(fr_dict_t *dict, unsigned int vendor, unsigned int attr)
Lookup a fr_dict_attr_t by its vendor and attribute numbers.
String of printable characters.
FR_TOKEN quote
What type of quoting was around the raw string.
FR_TOKEN quote
Type of quoting around the r_opand.
VALUE_PAIR * fr_cursor_next_by_da(vp_cursor_t *cursor, fr_dict_attr_t const *da, int8_t tag) CC_HINT(nonnull)
Iterate over attributes of a given DA in the pairlist.
FR_TOKEN cf_pair_operator(CONF_PAIR const *pair)
int radius_compare_vps(REQUEST *request, VALUE_PAIR *check, VALUE_PAIR *vp)
union vp_tmpl_t::@11 data
A source or sink of value data.
enum requests request_refs_t
const FR_NAME_NUMBER tmpl_names[]
Map tmpl_type_t values to descriptive strings.
vp_tmpl_t * tmpl_alloc(TALLOC_CTX *ctx, tmpl_type_t type, char const *name, ssize_t len, FR_TOKEN quote)
Create a new heap allocated vp_tmpl_t.
CONF_ITEM * ci
Config item that the map was created from.
char const * cf_section_name2(CONF_SECTION const *cs)
void map_sort(vp_map_t **maps, fr_cmp_t cmp)
Sort a linked list of vp_map_t using merge sort.
void map_debug_log(REQUEST *request, vp_map_t const *map, VALUE_PAIR const *vp)
RFC3575/RFC5176 - Disconnect-Request.