From: Alan T. DeKok Date: Thu, 14 Sep 2023 12:08:52 +0000 (-0400) Subject: allow raw.Vendor-Specific = 0xabcdef X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5359d0e9812111972d8ae47e9940f6129ceebad9;p=thirdparty%2Ffreeradius-server.git allow raw.Vendor-Specific = 0xabcdef which parses it as a Vendor-Specific, then sees the 0x..., and converts it to type 'octets'. Note that the attribute MUST already be marked up as "raw" --- diff --git a/src/lib/util/pair.c b/src/lib/util/pair.c index 7ea5247168d..8b6b6d7731c 100644 --- a/src/lib/util/pair.c +++ b/src/lib/util/pair.c @@ -305,25 +305,28 @@ int fr_pair_reinit_from_da(fr_pair_list_t *list, fr_pair_t *vp, fr_dict_attr_t c { fr_dict_attr_t const *to_free; - /* - * This only works for leaf nodes. - */ - if (!fr_type_is_leaf(da->type)) return -1; - /* * vp may be created from fr_pair_alloc_null(), in which case it has no da. */ - if (vp->da) { + if (vp->da && !vp->da->flags.is_raw) { if (vp->da == da) return 0; if (!fr_type_is_leaf(vp->vp_type)) return -1; if ((da->type != vp->vp_type) && (fr_value_box_cast_in_place(vp, &vp->data, da->type, da) < 0)) return -1; } else { + fr_assert(fr_type_is_leaf(vp->vp_type) || (fr_pair_list_num_elements(&vp->vp_group) == 0)); + fr_value_box_init(&vp->data, da->type, da, false); } to_free = vp->da; + vp->da = da; + + /* + * Only frees unknown fr_dict_attr_t's + */ + fr_dict_unknown_free(&to_free); /* * Ensure we update the attribute index in the parent. @@ -331,18 +334,9 @@ int fr_pair_reinit_from_da(fr_pair_list_t *list, fr_pair_t *vp, fr_dict_attr_t c if (list) { fr_pair_remove(list, vp); - vp->da = da; - fr_pair_append(list, vp); - } else { - vp->da = da; } - /* - * Only frees unknown fr_dict_attr_t's - */ - fr_dict_unknown_free(&to_free); - return 0; } diff --git a/src/lib/util/pair_legacy.c b/src/lib/util/pair_legacy.c index ee9a8cd15b3..fe41cc1787a 100644 --- a/src/lib/util/pair_legacy.c +++ b/src/lib/util/pair_legacy.c @@ -233,7 +233,7 @@ static ssize_t fr_pair_list_afrom_substr(TALLOC_CTX *ctx, fr_dict_attr_t const * * If we force it to be raw, then only do that if it's not already unknown. */ if (is_raw && !da_unknown) { - da_unknown = fr_dict_unknown_attr_afrom_da(ctx, da); + da_unknown = fr_dict_unknown_afrom_da(ctx, da); if (!da_unknown) goto error; da = da_unknown; } @@ -290,6 +290,24 @@ static ssize_t fr_pair_list_afrom_substr(TALLOC_CTX *ctx, fr_dict_attr_t const * vp->op = op; + /* + * Peek ahead for structural elements which are raw. If the caller wants to parse them + * as a set of raw octets, then swap the data type to be octets. + */ + if (is_raw && (p[0] == '0') && (p[1] == 'x') && (da->type != FR_TYPE_OCTETS)) { + fr_dict_unknown_free(&da_unknown); + + da_unknown = fr_dict_unknown_attr_afrom_da(vp, vp->da); + if (!da_unknown) goto error; + + fr_assert(da_unknown->type == FR_TYPE_OCTETS); + + if (fr_pair_reinit_from_da(NULL, vp, da_unknown) < 0) goto error; + + da = vp->da; + da_unknown = NULL; /* already parented from vp */ + } + /* * Allow grouping attributes. */