Skip to content

Commit

Permalink
allow casts in RHS of raw attributes
Browse files Browse the repository at this point in the history
so that we can set the data type
  • Loading branch information
alandekok committed Nov 11, 2024
1 parent e487e0a commit aeae2ff
Showing 1 changed file with 71 additions and 9 deletions.
80 changes: 71 additions & 9 deletions src/lib/util/pair_legacy.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,11 @@ fr_slen_t fr_pair_list_afrom_substr(fr_pair_parse_t const *root, fr_pair_parse_t
fr_sbuff_t *in)
{
int i, components;
bool raw, raw_octets;
bool raw;
bool was_relative = false;
bool append;
bool keep_going;
fr_type_t raw_type;
fr_token_t op;
fr_slen_t slen;
fr_pair_t *vp;
Expand Down Expand Up @@ -184,8 +185,10 @@ fr_slen_t fr_pair_list_afrom_substr(fr_pair_parse_t const *root, fr_pair_parse_t

redo:
append = true;
raw = raw_octets = false;
raw = false;
raw_type = FR_TYPE_NULL;
relative->last_char = 0;
vp = NULL;

fr_sbuff_adv_past_whitespace(&our_in, SIZE_MAX, NULL);

Expand Down Expand Up @@ -270,10 +273,40 @@ fr_slen_t fr_pair_list_afrom_substr(fr_pair_parse_t const *root, fr_pair_parse_t
fr_sbuff_marker(&rhs_m, &our_in);

/*
* Peek ahead to see if the final element is defined to be structural, but the caller instead
* wants to parse it as raw octets.
* If the value of the attribute is 0x..., then we always force the raw type to be octets, even
* if the attribute is named and known. e.g. raw.Framed-IP-Address = 0x01
*
* OR if the attribute is entirely unknown (and not a raw version of a known one), then we allow a
* cast to set the data type.
*/
if (raw) raw_octets = fr_sbuff_is_str_literal(&our_in, "0x");
if (raw) {
if (fr_sbuff_is_str_literal(&our_in, "0x")) {
raw_type = FR_TYPE_OCTETS;

} else if (fr_sbuff_next_if_char(&our_in, '(')) {
fr_sbuff_marker_t m;

fr_sbuff_marker(&m, &our_in);

fr_sbuff_out_by_longest_prefix(&slen, &raw_type, fr_type_table, &our_in, FR_TYPE_NULL);
if ((raw_type == FR_TYPE_NULL) || !fr_type_is_leaf(raw_type)) {
fr_sbuff_set(&our_in, &rhs_m);
fr_strerror_const("Invalid data type in cast");
return fr_sbuff_error(&our_in);
}

if (!fr_sbuff_next_if_char(&our_in, ')')) {
fr_strerror_const("Missing ')' in cast");
return fr_sbuff_error(&our_in);
}

fr_sbuff_adv_past_whitespace(&our_in, SIZE_MAX, NULL);
fr_sbuff_marker(&rhs_m, &our_in);

} else if (fr_sbuff_is_char(&our_in, '{')) {
raw_type = FR_TYPE_TLV;
}
}

fr_sbuff_set(&our_in, &lhs_m);

Expand All @@ -294,7 +327,19 @@ fr_slen_t fr_pair_list_afrom_substr(fr_pair_parse_t const *root, fr_pair_parse_t
*/
if (!fr_sbuff_is_digit(&our_in)) goto notfound;

slen = fr_dict_attr_unknown_afrom_oid_substr(NULL, &da_unknown, relative->da, &our_in, FR_TYPE_OCTETS);
if (raw_type == FR_TYPE_NULL) {
raw_type = FR_TYPE_OCTETS;

} else if (raw_type == FR_TYPE_TLV) {
/*
* Reset the type based on the parent.
*/
if (relative->da->type == FR_TYPE_VSA) {
raw_type = FR_TYPE_VENDOR;
}
}

slen = fr_dict_attr_unknown_afrom_oid_substr(NULL, &da_unknown, relative->da, &our_in, raw_type);
if (slen < 0) return fr_sbuff_error(&our_in) + slen;

fr_assert(da_unknown);
Expand Down Expand Up @@ -388,8 +433,23 @@ fr_slen_t fr_pair_list_afrom_substr(fr_pair_parse_t const *root, fr_pair_parse_t
* its structural or anything else. Just
* create the raw attribute.
*/
} else if (raw_octets) {
if (!da_unknown) da_unknown = fr_dict_attr_unknown_raw_afrom_da(NULL, da);
} else if (raw_type != FR_TYPE_NULL) {
/*
* We have parsed the full OID tree, *and* found a known attribute. e.g. raw.Vendor-Specific = ...
*
* For some reason, we allow: raw.Vendor-Specific = { ... }
*
* But this is what we really want: raw.Vendor-Specific = 0xabcdef
*/
fr_assert(!da_unknown);

if ((raw_type != FR_TYPE_OCTETS) && (raw_type != da->type)) {
fr_strerror_printf("Cannot create raw attribute %s which changes data type from %s to %s",
da->name, fr_type_to_str(da->type), fr_type_to_str(raw_type));
return fr_sbuff_error(&our_in);
}

da_unknown = fr_dict_attr_unknown_raw_afrom_da(NULL, da);
if (!da_unknown) return fr_sbuff_error(&our_in);

fr_assert(da_unknown->type == FR_TYPE_OCTETS);
Expand All @@ -398,6 +458,7 @@ fr_slen_t fr_pair_list_afrom_substr(fr_pair_parse_t const *root, fr_pair_parse_t
fr_dict_attr_unknown_free(&da_unknown);
return fr_sbuff_error(&our_in);
}

fr_dict_attr_unknown_free(&da_unknown);
fr_assert(vp->vp_type == FR_TYPE_OCTETS);

Expand Down Expand Up @@ -513,7 +574,8 @@ fr_slen_t fr_pair_list_afrom_substr(fr_pair_parse_t const *root, fr_pair_parse_t
};

if (!fr_type_is_structural(vp->vp_type)) {
fr_strerror_const("Cannot assign list to leaf data type");
fr_strerror_printf("Cannot assign list to leaf data type %s for attribute %s",
fr_type_to_str(vp->vp_type), vp->da->name);
return fr_sbuff_error(&our_in);
}

Expand Down

0 comments on commit aeae2ff

Please sign in to comment.