Skip to content

Commit

Permalink
make decode_struct use standard functions
Browse files Browse the repository at this point in the history
and not RADIUS ones.  Struct entries aren't encrypted, they
shouldn't really use RADIUS-specific data types, etc.
  • Loading branch information
alandekok committed Oct 11, 2018
1 parent 1a93638 commit 318f72f
Showing 1 changed file with 47 additions and 15 deletions.
62 changes: 47 additions & 15 deletions src/protocols/radius/decode.c
Expand Up @@ -454,7 +454,7 @@ ssize_t fr_radius_decode_tlv(TALLOC_CTX *ctx, fr_cursor_t *cursor,
*/
static ssize_t fr_radius_decode_struct(TALLOC_CTX *ctx, fr_cursor_t *cursor,
fr_dict_attr_t const *parent, uint8_t const *data, size_t data_len,
void *decoder_ctx)
UNUSED void *decoder_ctx)
{
unsigned int child_num;
uint8_t const *p = data, *end = data + data_len;
Expand All @@ -466,16 +466,20 @@ static ssize_t fr_radius_decode_struct(TALLOC_CTX *ctx, fr_cursor_t *cursor,

FR_PROTO_HEX_DUMP("struct", p, data_len);

/*
* Data is too small for the structure, ignore it.
*/
if (data_len < parent->flags.length) goto raw;

/*
* Record where we were in the list when this function was called
*/
fr_cursor_init(&child_cursor, &head);

child_num = 1;
while (p < end) {
ssize_t decoded_len;
size_t child_length;
VALUE_PAIR *vp;

/*
* Go to the next child. If it doesn't exist, we're done.
Expand All @@ -488,18 +492,36 @@ static ssize_t fr_radius_decode_struct(TALLOC_CTX *ctx, fr_cursor_t *cursor,
child_length = child->flags.length;
if (!child_length) child_length = (end - p);

vp = fr_pair_afrom_da(ctx, child);
if (!vp) return -1;

/*
* Decode the next field based on the length of the child.
* dict.c enforces that child->flags.length is non-zero.
* We only allow a limited number of data types
* inside of a struct.
*/
decoded_len = fr_radius_decode_pair_value(ctx, &child_cursor, child, p,
child_length, child_length,
decoder_ctx);
if (decoded_len < 0) {
switch (child->type) {
default:
fr_strerror_printf("Invalid data type passed to encode_struct");
return -1;

case FR_TYPE_VALUES:
case FR_TYPE_STRUCT:
break;
}

/*
* No protocol-specific magic here.
*
* @todo - allow it, if necessary
*/
if (fr_value_box_from_network(vp, &vp->data, vp->da->type, vp->da, p, child_length, true) < 0) {
TALLOC_FREE(vp);

FR_PROTO_TRACE("Failed to decode child %u of STRUCT %s", child_num, parent->name);

raw:
fr_pair_list_free(&head);

raw:
fr_cursor_init(&child_cursor, &head);

/*
Expand All @@ -509,15 +531,24 @@ static ssize_t fr_radius_decode_struct(TALLOC_CTX *ctx, fr_cursor_t *cursor,
fr_dict_vendor_num_by_da(parent), parent->attr);
if (!child) return -1;

/*
* Decode the whole STRUCT as an unknown attribute
*/
decoded_len = fr_radius_decode_pair_value(ctx, &child_cursor, child,
data, data_len, data_len, decoder_ctx);
if (decoded_len < 0) return decoded_len;
vp = fr_pair_afrom_da(ctx, child);
if (!vp) return -1;

if (fr_value_box_from_network(vp, &vp->data, vp->da->type, vp->da, data, data_len, true) < 0) {
TALLOC_FREE(vp);
return -1;
}

vp->type = VT_DATA;
vp->vp_tainted = true;
fr_cursor_append(&child_cursor, vp);
break;
}

vp->type = VT_DATA;
vp->vp_tainted = true;
fr_cursor_append(&child_cursor, vp);

/*
* Note that we're decoding fixed fields here.
* So we skip the input based on the *known*
Expand All @@ -526,6 +557,7 @@ static ssize_t fr_radius_decode_struct(TALLOC_CTX *ctx, fr_cursor_t *cursor,
p += child_length;
child_num++; /* go to the next child */
}

fr_cursor_head(&child_cursor);
fr_cursor_tail(cursor);
fr_cursor_merge(cursor, &child_cursor); /* Wind to the end of the new pairs */
Expand Down

0 comments on commit 318f72f

Please sign in to comment.