]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
allow raw.Vendor-Specific = 0xabcdef
authorAlan T. DeKok <aland@freeradius.org>
Thu, 14 Sep 2023 12:08:52 +0000 (08:08 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Thu, 14 Sep 2023 13:59:22 +0000 (09:59 -0400)
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"

src/lib/util/pair.c
src/lib/util/pair_legacy.c

index 7ea5247168d7992435ca9554559918ddf63b4c63..8b6b6d7731ccc6a0199fec1a035a069dd9b76f94 100644 (file)
@@ -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;
 }
 
index ee9a8cd15b3476beb482a2de53773d5c677fefdf..fe41cc1787afb4a971e33cf0c7fad339e75b8076 100644 (file)
@@ -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.
                 */