From: Alan T. DeKok Date: Mon, 19 Apr 2021 11:17:23 +0000 (-0400) Subject: decode VSAs and vendors as nested attributes. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e906e3d73ff649d16916405165ed7736fb496372;p=thirdparty%2Ffreeradius-server.git decode VSAs and vendors as nested attributes. Update the tests accordingly. Note that WiMAX fails, as it does not correctly decode "continued" attributes. But it turns out that didn't work previously, either. --- diff --git a/src/protocols/radius/decode.c b/src/protocols/radius/decode.c index c0c4eb1181b..4bfbbdd1c66 100644 --- a/src/protocols/radius/decode.c +++ b/src/protocols/radius/decode.c @@ -490,14 +490,14 @@ ssize_t fr_radius_decode_tlv(TALLOC_CTX *ctx, fr_dcursor_t *cursor, fr_dict_t co return data_len; } -/** Convert a top-level VSA to a VP. +/** Convert one VSA to a VP. * * "length" can be LONGER than just this sub-vsa. */ -static ssize_t decode_vsa_internal(TALLOC_CTX *ctx, fr_dcursor_t *cursor, fr_dict_t const *dict, - fr_dict_attr_t const *parent, - uint8_t const *data, size_t data_len, - fr_radius_ctx_t *packet_ctx, fr_dict_vendor_t const *dv) +static ssize_t decode_vsa_single(TALLOC_CTX *ctx, fr_dcursor_t *cursor, fr_dict_t const *dict, + fr_dict_attr_t const *parent, + uint8_t const *data, size_t data_len, + fr_radius_ctx_t *packet_ctx, fr_dict_vendor_t const *dv) { unsigned int attribute; ssize_t attrlen, my_len; @@ -611,11 +611,10 @@ static ssize_t decode_extended(TALLOC_CTX *ctx, fr_dcursor_t *cursor, fr_dict_t /* * data = Ext-Attr Flag ... */ - if (attr_len < 3) return -1; /* - * No continuation, just decode the attributre in place. + * No continuation, just decode the attribute in place. */ if ((data[1] & 0x80) == 0) { ret = fr_radius_decode_pair_value(ctx, cursor, dict, @@ -687,50 +686,55 @@ static ssize_t decode_extended(TALLOC_CTX *ctx, fr_dcursor_t *cursor, fr_dict_t * * @note Called ONLY for Vendor-Specific */ -static ssize_t decode_wimax(TALLOC_CTX *ctx, fr_dcursor_t *cursor, fr_dict_t const *dict, - fr_dict_attr_t const *parent, +static ssize_t decode_wimax(fr_pair_t *parent, fr_dict_t const *dict, uint8_t const *data, size_t attr_len, size_t packet_len, fr_radius_ctx_t *packet_ctx) { ssize_t ret; size_t wimax_len; - bool more; uint8_t *head, *tail; uint8_t const *attr, *end; fr_dict_attr_t const *da; + fr_pair_list_t list; + fr_dcursor_t cursor; #ifdef __clang_analyzer__ if (!packet_ctx->tmp_ctx) return -1; #endif - /* - * data = VID VID VID VID WiMAX-Attr WiMAX-Len Continuation ... - */ - if (attr_len < 8) return -1; + fr_assert(parent->da->type == FR_TYPE_VENDOR); + fr_assert(parent->da->attr == VENDORPEC_WIMAX); /* - * WiMAX-Attr WiMAX-Len Continuation + * We're passed data = WiMAX-Attr WiMAX-Len Continuation ... */ - if (data[5] < 3) return -1; + fr_assert(attr_len > 3); + + da = fr_dict_attr_child_by_num(parent->da, data[0]); /* - * The WiMAX-Len + 4 VID must exactly fill the attribute. + * Unknown attribute, or the WiMAX length doesn't match + * the enclosing attribute length, it's an unknown + * attribute. */ - if (((size_t) (data[5] + 4)) != attr_len) return -1; - - da = fr_dict_attr_child_by_num(parent, data[4]); - if (!da) da = fr_dict_unknown_attr_afrom_num(packet_ctx->tmp_ctx, parent, data[4]); - if (!da) return -1; + if (!da || (data[1] != attr_len)) { + da = fr_dict_unknown_attr_afrom_num(packet_ctx->tmp_ctx, parent->da, data[0]); + if (!da) return -1; + } FR_PROTO_TRACE("decode context changed %s -> %s", da->parent->name, da->name); + fr_pair_list_init(&list); + fr_dcursor_init(&cursor, &list); + /* - * No continuation, just decode the attributre in place. + * No continuation, just decode the attribute in place. */ - if ((data[6] & 0x80) == 0) { - ret = fr_radius_decode_pair_value(ctx, cursor, dict, - da, data + 7, data[5] - 3, data[5] - 3, packet_ctx); + if ((data[2] & 0x80) == 0) { + ret = fr_radius_decode_pair_value(parent, &cursor, dict, + da, data + 3, data[1] - 3, data[1] - 3, packet_ctx); if (ret < 0) return ret; + fr_pair_list_append(&parent->vp_group, &list); return attr_len; } @@ -739,117 +743,117 @@ static ssize_t decode_wimax(TALLOC_CTX *ctx, fr_dcursor_t *cursor, fr_dict_t con * now, they MUST be contiguous in the packet, and they * MUST be all of the same VSA, WiMAX, and WiMAX-attr. * - * The first fragment doesn't have a RADIUS attribute - * header. + * The first fragment has already been checked, so we + * start off with that. */ - wimax_len = 0; - attr = data + 4; + wimax_len = attr_len - 3; + attr = data + attr_len; end = data + packet_len; + /* + * Loop over the entire packet. The base RFC format is + * valid, as the packet was already checked for sanity. + */ while (attr < end) { + uint32_t vendor; + uint8_t const *wimax; + /* - * Not enough room for Attribute + length + - * continuation, it's bad. + * This check shouldn't be necessary, but what + * the heck. */ - if ((end - attr) < 3) return -1; + if ((attr + 2) > end) break; /* - * Must have non-zero data in the attribute. + * This check shouldn't be necessary, either. */ - if (attr[1] <= 3) return -1; + if ((attr + attr[1]) > end) break; /* - * If the WiMAX attribute overflows the packet, - * it's bad. + * The attribute isn't a VSA, stop. */ - if ((attr + attr[1]) > end) return -1; + if (attr[0] != FR_VENDOR_SPECIFIC) break; /* - * Check the continuation flag. + * Not enough room for RFC header + Vendor-ID + + * WiMAX header + Continuation, stop. */ - more = ((attr[2] & 0x80) != 0); + if (attr[1] < 2 + 4 + 2 + 1) break; /* - * Or, there's no more data, in which case we - * shorten "end" to finish at this attribute. + * Not a WiMAX VSA, stop. */ - if (!more) end = attr + attr[1]; + vendor = fr_net_to_uint32(attr + 2); + if (vendor != VENDORPEC_WIMAX) break; + /* - * There's more data, but we're at the end of the - * packet. The attribute is malformed! + * Point to WiMAX-Attr */ - if (more && ((attr + attr[1]) == end)) return -1; + wimax = attr + 2 + 4; /* - * Add in the length of the data we need to - * concatenate together. + * Not the same WiMAX attribute. */ - wimax_len += attr[1] - 3; + if (data[0] != wimax[0]) break; /* - * Go to the next attribute, and stop if there's - * no more. + * WiMAX attribute does not fill the + * Vendor-Specific attribute, either + * overflow or underflow. */ - attr += attr[1]; - if (!more) break; + if (attr[1] != (wimax[1] + 6)) break; /* - * data = VID VID VID VID WiMAX-Attr WimAX-Len Continuation ... - * - * attr = Vendor-Specific VSA-Length VID VID VID VID WiMAX-Attr WimAX-Len Continuation ... - * + * Seems OK, add the length in. */ + wimax_len += wimax[1] - 3; /* - * No room for Vendor-Specific + length + - * Vendor(4) + attr + length + continuation + data + * We've successfully included this attribute, so + * point to the next one. */ - if ((end - attr) < 9) return -1; - - if (attr[0] != FR_VENDOR_SPECIFIC) return -1; - if (attr[1] < 9) return -1; - if ((attr + attr[1]) > end) return -1; - if (memcmp(data, attr + 2, 4) != 0) return -1; /* not WiMAX Vendor ID */ - - if (attr[1] != (attr[7] + 6)) return -1; /* WiMAX attr doesn't exactly fill the VSA */ - - if (data[4] != attr[6]) return -1; /* different WiMAX attribute */ + attr += attr[1]; /* - * Skip over the Vendor-Specific header, and - * continue with the WiMAX attributes. + * No more continuation, stop. */ - attr += 6; + if ((wimax[2] & 0x80) == 0) break; } /* - * No data in the WiMAX attribute, make a "raw" one. + * Remember where the continued WiMAX attributes ended. */ - if (!wimax_len) return -1; + end = attr; - head = tail = talloc_array(ctx, uint8_t, wimax_len); + head = tail = talloc_array(packet_ctx->tmp_ctx, uint8_t, wimax_len); if (!head) return -1; /* * Copy the data over, this time trusting the attribute - * contents. + * contents. When this function is called, 'data' is + * pointing to WiMAX-Attr. So we back up in order to be + * able to point to the Vendor-Specific byte, which + * treats all of the attributes the same. */ - attr = data; + attr = data - 6; while (attr < end) { - memcpy_bounded(tail, attr + 4 + 3, attr[4 + 1] - 3, end); - tail += attr[4 + 1] - 3; - attr += 4 + attr[4 + 1]; /* skip VID+WiMax header */ - attr += 2; /* skip Vendor-Specific header */ + uint8_t const *wimax = attr + 2 + 4; + + memcpy_bounded(tail, wimax + 3, wimax[1] - 3, end); + tail += wimax[1] - 3; + attr += attr[1]; } FR_PROTO_HEX_DUMP(head, wimax_len, "Wimax fragments"); - ret = fr_radius_decode_pair_value(ctx, cursor, dict, + ret = fr_radius_decode_pair_value(parent, &cursor, dict, da, head, wimax_len, wimax_len, packet_ctx); talloc_free(head); if (ret < 0) return ret; + fr_pair_list_append(&parent->vp_group, &list); + return end - data; } @@ -863,12 +867,12 @@ static ssize_t CC_HINT(nonnull) decode_vsa(TALLOC_CTX *ctx, fr_dcursor_t *curso fr_radius_ctx_t *packet_ctx) { size_t total; - ssize_t ret; uint32_t vendor; fr_dict_vendor_t const *dv; fr_pair_list_t head; fr_dict_vendor_t my_dv; fr_dict_attr_t const *vendor_da; + fr_pair_t *vp; fr_dcursor_t tlv_cursor; fr_pair_list_init(&head); @@ -883,8 +887,7 @@ static ssize_t CC_HINT(nonnull) decode_vsa(TALLOC_CTX *ctx, fr_dcursor_t *curso if (!fr_cond_assert(parent->type == FR_TYPE_VSA)) return -1; if (attr_len > packet_len) return -1; - if (attr_len < 5) return -1; /* vid, value */ - if (data[0] != 0) return -1; /* we require 24-bit VIDs */ + if (attr_len < 4) return -1; /* must have at least a 32-bit vendor ID */ FR_PROTO_TRACE("Decoding VSA"); @@ -893,30 +896,23 @@ static ssize_t CC_HINT(nonnull) decode_vsa(TALLOC_CTX *ctx, fr_dcursor_t *curso /* * Verify that the parent (which should be a VSA) - * contains a fake attribute representing the vendor. - * - * If it doesn't then this vendor is unknown, but - * (unlike DHCP) we know vendor attributes have a - * standard format, so we can decode the data anyway. + * contains a child which represents the vendor. */ vendor_da = fr_dict_attr_child_by_num(parent, vendor); if (!vendor_da) { fr_dict_attr_t *n; - /* - * RFC format is 1 octet type, 1 octet length - */ - if (fr_radius_decode_tlv_ok(data + 4, attr_len - 4, 1, 1) < 0) { - FR_PROTO_TRACE("Unknown TLVs not OK: %s", fr_strerror()); - return -1; - } n = fr_dict_unknown_vendor_afrom_num(packet_ctx->tmp_ctx, parent, vendor); if (!n) return -1; vendor_da = n; + } - /* - * Create an unknown DV too... - */ + /* + * Create an unknown DV if necessary. If the DV isn't + * known, we default to RFC format. + */ + dv = fr_dict_vendor_by_num(dict, vendor); + if (!dv) { memset(&my_dv, 0, sizeof(my_dv)); my_dv.pen = vendor; @@ -924,74 +920,107 @@ static ssize_t CC_HINT(nonnull) decode_vsa(TALLOC_CTX *ctx, fr_dcursor_t *curso my_dv.length = 1; dv = &my_dv; - - goto create_attrs; } /* - * We found an attribute representing the vendor - * so it *MUST* exist in the vendor tree. + * VSAs should be in a TLV format. */ - dv = fr_dict_vendor_by_num(dict, vendor); - if (!fr_cond_assert(dv)) return -1; - FR_PROTO_TRACE("decode context %s -> %s", parent->name, vendor_da->name); + if (fr_radius_decode_tlv_ok(data + 4, attr_len - 4, dv->type, dv->length) < 0) { + FR_PROTO_TRACE("TLVs not OK: %s", fr_strerror()); + return -1; + } /* - * WiMAX craziness + * Ensure that Vendor-Specific exists. If it doesn't + * exist, create it and add it to the parent list. + * + * Since fr_radius_decode_tlv_ok() has returned OK, we + * know that any malformed attributes will be created as + * "raw" attributes. The decode functions we call will + * return -1 only on OOM, or other unrecoverable error. */ - if ((vendor == VENDORPEC_WIMAX) && dv->flags) { - ret = decode_wimax(ctx, cursor, dict, vendor_da, data, attr_len, packet_len, packet_ctx); - return ret; + vp = packet_ctx->vendor_specific; + if (!vp) { + vp = fr_pair_afrom_da(ctx, parent); + if (!vp) return -1; + + packet_ctx->vendor_specific = vp; + fr_dcursor_append(cursor, vp); } /* - * VSAs should normally be in TLV format. + * Ensure that a child VP of this vendor exists. */ - if (fr_radius_decode_tlv_ok(data + 4, attr_len - 4, dv->type, dv->length) < 0) { - FR_PROTO_TRACE("TLVs not OK: %s", fr_strerror()); - return -1; + vp = fr_pair_find_by_da(&packet_ctx->vendor_specific->vp_group, vendor_da); + if (!vp) { + vp = fr_pair_afrom_da(packet_ctx->vendor_specific, vendor_da); + if (!vp) return -1; + + fr_pair_append(&packet_ctx->vendor_specific->vp_group, vp); } - /* - * There may be more than one VSA in the - * Vendor-Specific. If so, loop over them all. - */ -create_attrs: data += 4; attr_len -= 4; packet_len -= 4; total = 4; + /* + * WiMAX craziness. + */ + if (vendor == VENDORPEC_WIMAX) { + ssize_t slen; + + /* + * If there's only Vendor-Attr + Vendor-Length, + * then there's either continuation byte, or only + * a continuation byte. We return zero + * attributes. + * + * Note that we don't bother checking for the + * continuation flag. If it's set, then there's + * no reason to concatenate an empty attribute + * with the next one. + */ + if (attr_len <= 3) return total + attr_len; + + /* + * There's a continuation byte, and some data. + * Let's decode it. + */ + slen = decode_wimax(vp, dict, data, attr_len, packet_len, packet_ctx); + if (slen < 0) return slen; + return total + slen; + } + + FR_PROTO_TRACE("decode context %s -> %s", parent->name, vendor_da->name); + + /* + * There may be many TLVs in the attribute. Loop over + * them all. + */ fr_dcursor_init(&tlv_cursor, &head); while (attr_len > 0) { - ssize_t vsa_len; + ssize_t slen; /* - * Vendor attributes can have subattributes (if you hadn't guessed) + * Decode this one VSA, which itself might have + * child attributes. */ - vsa_len = decode_vsa_internal(ctx, &tlv_cursor, dict, - vendor_da, data, attr_len, packet_ctx, dv); - if (vsa_len < 0) { + slen = decode_vsa_single(vp, &tlv_cursor, dict, + vendor_da, data, attr_len, packet_ctx, dv); + if (slen < 0) { fr_strerror_printf("%s: Internal sanity check %d", __FUNCTION__, __LINE__); fr_pair_list_free(&head); return -1; } - data += vsa_len; - attr_len -= vsa_len; - packet_len -= vsa_len; - total += vsa_len; + data += slen; + attr_len -= slen; + packet_len -= slen; + total += slen; } - fr_dcursor_head(&tlv_cursor); - fr_dcursor_tail(cursor); - fr_dcursor_merge(cursor, &tlv_cursor); - /* - * When the unknown attributes were created by - * decode_vsa_internal, the hierachy between that unknown - * attribute and first known attribute was cloned - * meaning we can now free the unknown vendor. - */ + fr_pair_list_append(&vp->vp_group, &head); return total; } diff --git a/src/protocols/radius/radius.h b/src/protocols/radius/radius.h index 96f8b39975c..2d6a561f593 100644 --- a/src/protocols/radius/radius.h +++ b/src/protocols/radius/radius.h @@ -172,6 +172,7 @@ typedef struct { char const *secret; //!< shared secret. MUST be talloc'd fr_fast_rand_t rand_ctx; //!< for tunnel passwords int salt_offset; //!< for tunnel passwords + fr_pair_t *vendor_specific; //!< for decoding VSAs into nested sets bool tunnel_password_zeros; //!< check for trailing zeros on decode bool disallow_tunnel_passwords; //!< not all packets can have tunnel passwords diff --git a/src/tests/unit/protocols/radius/ascend.txt b/src/tests/unit/protocols/radius/ascend.txt index 97617f795a5..51866bc9a64 100644 --- a/src/tests/unit/protocols/radius/ascend.txt +++ b/src/tests/unit/protocols/radius/ascend.txt @@ -5,7 +5,7 @@ encode-pair Vendor-Specific.Ascend.Data-Filter = "ip in drop tcp dstport > 1023" match 1a 28 00 00 02 11 f2 22 01 00 01 00 00 00 00 00 00 00 00 00 00 00 06 00 00 00 03 ff 00 03 00 00 00 00 00 00 00 00 00 00 decode-pair - -match Vendor-Specific.Ascend.Data-Filter = "ip in drop tcp dstport > 1023" +match Vendor-Specific = { Ascend = { Data-Filter = "ip in drop tcp dstport > 1023" } } # # We no longer support setting Vendor-Specific.Ascend.Data-Filters as hex strings @@ -17,28 +17,28 @@ encode-pair Vendor-Specific.Ascend.Data-Filter = "ip in forward srcip 1.2.3.4/5 match 1a 28 00 00 02 11 f2 22 01 01 01 00 01 02 03 04 0a 0b 0c 0d 05 20 06 00 00 05 04 d2 02 02 00 00 00 00 00 00 00 00 00 00 decode-pair 1a2800000211f22201010100010203040a0b0c0d05200600000504d2020200000000000000000000 -match Vendor-Specific.Ascend.Data-Filter = "ip in forward srcip 1.2.3.4/5 dstip 10.11.12.13/32 tcp srcport = 5 dstport = 1234" +match Vendor-Specific = { Ascend = { Data-Filter = "ip in forward srcip 1.2.3.4/5 dstip 10.11.12.13/32 tcp srcport = 5 dstport = 1234" } } encode-pair Vendor-Specific.Ascend.Data-Filter = "ipv6 in forward srcip ::1 dstip ::1 tcp srcport = 5 dstport = 1234" match 1a 38 00 00 02 11 f2 32 03 01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 80 80 06 00 00 05 04 d2 02 02 00 00 decode-pair - -match Vendor-Specific.Ascend.Data-Filter = "ipv6 in forward srcip ::1/128 dstip ::1/128 tcp srcport = 5 dstport = 1234" +match Vendor-Specific = { Ascend = { Data-Filter = "ipv6 in forward srcip ::1/128 dstip ::1/128 tcp srcport = 5 dstport = 1234" } } # length < 16 gets padded with zeros encode-pair Vendor-Specific.Ascend.Send-Secret = "foo" match 1a 18 00 00 02 11 d6 12 ce 8d bb 09 a0 cd c2 9c ca f1 bd cb 25 41 f7 70 decode-pair - -match Vendor-Specific.Ascend.Send-Secret = "foo" +match Vendor-Specific = { Ascend = { Send-Secret = "foo" } } # length > 16 gets chopped encode-pair Vendor-Specific.Ascend.Send-Secret = "foo 56789abcdef012" match 1a 18 00 00 02 11 d6 12 ce 8d bb 29 95 fb f5 a4 f3 90 df a8 41 24 91 40 decode-pair - -match Vendor-Specific.Ascend.Send-Secret = "foo 56789abcdef0" +match Vendor-Specific = { Ascend = { Send-Secret = "foo 56789abcdef0" } } count match 22 diff --git a/src/tests/unit/protocols/radius/lucent.txt b/src/tests/unit/protocols/radius/lucent.txt index 0d17cfcdae2..5f350e6b553 100644 --- a/src/tests/unit/protocols/radius/lucent.txt +++ b/src/tests/unit/protocols/radius/lucent.txt @@ -5,10 +5,10 @@ encode-pair Vendor-Specific.Lucent.Max-Shared-Users = 1 match 1a 0d 00 00 12 ee 00 02 07 00 00 00 01 decode-pair - -match Vendor-Specific.Lucent.Max-Shared-Users = 1 +match Vendor-Specific = { Lucent = { Max-Shared-Users = 1 } } decode-pair 1a 0d 00 00 12 ee ff 02 07 00 00 00 01 -match Vendor-Specific.Lucent.65282 = 0x00000001 +match Vendor-Specific = { Lucent = { 65282 = 0x00000001 } } encode-pair Vendor-Specific.Lucent.65282 = 0x00000001 match 1a 0d 00 00 12 ee ff 02 07 00 00 00 01 diff --git a/src/tests/unit/protocols/radius/vendor.txt b/src/tests/unit/protocols/radius/vendor.txt index 25db8118669..2587d33ef04 100644 --- a/src/tests/unit/protocols/radius/vendor.txt +++ b/src/tests/unit/protocols/radius/vendor.txt @@ -1,38 +1,35 @@ proto radius proto-dictionary radius -encode-pair Vendor-Specific = { Starent = { VPN-Name = "foo" } } -match 1a 0d 00 00 1f e4 00 02 00 07 66 6f 6f - encode-pair Vendor-Specific.Starent.VPN-Name = "foo" match 1a 0d 00 00 1f e4 00 02 00 07 66 6f 6f decode-pair - -match Vendor-Specific.Starent.VPN-Name = "foo" +match Vendor-Specific = { Starent = { VPN-Name = "foo" } } encode-pair Vendor-Specific.USR.Event-Id = 1234 match 1a 0e 00 00 01 ad 00 00 bf be 00 00 04 d2 decode-pair - -match Vendor-Specific.USR.Event-Id = 1234 +match Vendor-Specific = { USR = { Event-Id = 1234 } } decode-pair 1a 15 00 00 4e 20 01 0f 6c 69 74 68 69 61 73 70 72 69 6e 67 73 -match Vendor-Specific.20000.1 = 0x6c6974686961737072696e6773 +match Vendor-Specific = { 20000 = { = 0x6c6974686961737072696e6773 } } encode-pair Vendor-Specific.3com.User-Access-Level = Visitor, Vendor-Specific.3com.Ip-Host-Addr = "155.4.12.100 00:00:00:00:00:00" match 1a 0c 00 00 00 2b 01 06 00 00 00 00 1a 26 00 00 00 2b 3c 20 31 35 35 2e 34 2e 31 32 2e 31 30 30 20 30 30 3a 30 30 3a 30 30 3a 30 30 3a 30 30 3a 30 30 decode-pair - -match Vendor-Specific.3com.User-Access-Level = Visitor, Vendor-Specific.3com.Ip-Host-Addr = "155.4.12.100 00:00:00:00:00:00" +match Vendor-Specific = { 3com = { User-Access-Level = Visitor, Ip-Host-Addr = "155.4.12.100 00:00:00:00:00:00" } } # # The VSAs could also be packet into one Vendor-Specific # decode-pair 1a 2e 00 00 00 2b 1c 02 01 06 00 00 00 00 3c 20 31 35 35 2e 34 2e 31 32 2e 31 30 30 20 30 30 3a 30 30 3a 30 30 3a 30 30 3a 30 30 3a 30 30 -match Vendor-Specific.3com.User-Access-Level = Visitor, Vendor-Specific.3com.Ip-Host-Addr = "155.4.12.100 00:00:00:00:00:00" +match Vendor-Specific = { 3com = { User-Access-Level = Visitor, Ip-Host-Addr = "155.4.12.100 00:00:00:00:00:00" } } decode-pair 1a 2c 00 00 00 2b 01 06 00 00 00 00 3c 20 31 35 35 2e 34 2e 31 32 2e 31 30 30 20 30 30 3a 30 30 3a 30 30 3a 30 30 3a 30 30 3a 30 30 -match Vendor-Specific.3com.User-Access-Level = Visitor, Vendor-Specific.3com.Ip-Host-Addr = "155.4.12.100 00:00:00:00:00:00" +match Vendor-Specific = { 3com = { User-Access-Level = Visitor, Ip-Host-Addr = "155.4.12.100 00:00:00:00:00:00" } } # # Vendor-Specific is of type "vsa", and therefore cannot be assigned values. @@ -57,7 +54,7 @@ encode-pair Vendor-Specific.Unisphere.ERX-LI-Action = off match 1a 1a 00 00 13 0a 3a 14 8d 31 89 6e 2e 8a f5 fa 78 fb d5 90 d8 1a 15 91 c1 f1 decode-pair - -match Vendor-Specific.Unisphere.ERX-LI-Action = off +match Vendor-Specific = { Unisphere = { ERX-LI-Action = off } } #packet coa_request #original null @@ -69,7 +66,7 @@ match Vendor-Specific.Unisphere.ERX-LI-Action = off # Unknown vendors get decoded as TLVs with type=1,length=1 # decode-pair 1a12000080000105abcdef02076161616161 -match Vendor-Specific.32768.1 = 0xabcdef, Vendor-Specific.32768.2 = 0x6161616161 +match Vendor-Specific = { 32768 = { = 0xabcdef, = 0x6161616161 } } # # This MUST be 50 octets of data @@ -78,14 +75,14 @@ encode-pair Vendor-Specific.Microsoft.CHAP-Response = "xxxxxxxxxxxxxxxxxxxxxxxxx match 1a 3a 00 00 01 37 01 34 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 58 decode-pair - -match Vendor-Specific.Microsoft.CHAP-Response = 0x7878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787858 +match Vendor-Specific = { Microsoft = { CHAP-Response = 0x7878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787858 } } # # And now something which *isn't* 50 octets, but instead 49. # Therefore it's an "invalid attribute", as defined in RFC 6929 Section 2.8. # decode-pair 1a 39 00 00 01 37 01 33 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 -match raw.Vendor-Specific.Microsoft.CHAP-Response = 0x78787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878 +match Vendor-Specific = { Microsoft = { raw.CHAP-Response = 0x78787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878 } } count -match 42 +match 40 diff --git a/src/tests/unit/protocols/radius/wimax.txt b/src/tests/unit/protocols/radius/wimax.txt index 0b7e37903b3..9e52e274389 100644 --- a/src/tests/unit/protocols/radius/wimax.txt +++ b/src/tests/unit/protocols/radius/wimax.txt @@ -8,19 +8,19 @@ encode-pair Vendor-Specific.WiMAX.Capability.Release = "1.0" match 1a 0e 00 00 60 b5 01 08 00 01 05 31 2e 30 decode-pair - -match Vendor-Specific.WiMAX.Capability = { Release = "1.0" } +match Vendor-Specific = { WiMAX = { Capability = { Release = "1.0" } } } encode-pair Vendor-Specific.WiMAX.Capability.Accounting-Capabilities = 1 match 1a 0c 00 00 60 b5 01 06 00 02 03 01 decode-pair - -match Vendor-Specific.WiMAX.Capability = { Accounting-Capabilities = IP-Session-Based } +match Vendor-Specific = { WiMAX = { Capability = { Accounting-Capabilities = IP-Session-Based } } } encode-pair Vendor-Specific.WiMAX.Capability.Release = "1.0", Vendor-Specific.WiMAX.Capability.Accounting-Capabilities = 1 match 1a 11 00 00 60 b5 01 0b 00 01 05 31 2e 30 02 03 01 decode-pair - -match Vendor-Specific.WiMAX.Capability = { Release = "1.0", Accounting-Capabilities = IP-Session-Based } +match Vendor-Specific = { WiMAX = { Capability = { Release = "1.0", Accounting-Capabilities = IP-Session-Based } } } encode-pair - match 1a 11 00 00 60 b5 01 0b 00 01 05 31 2e 30 02 03 01 @@ -87,10 +87,10 @@ encode-pair Vendor-Specific.WiMAX.Packet-Flow-Descriptor-v2.Classifier.Direction match 1a 14 00 00 60 b5 54 0e 00 09 0b 04 03 01 05 06 04 04 1a 99 decode-pair - -match Vendor-Specific.WiMAX.Packet-Flow-Descriptor-v2 = { Classifier = { Direction = 1, Src-Spec = { Port = 6809 } } } +match Vendor-Specific = { WiMAX = { Packet-Flow-Descriptor-v2 = { Classifier = { Direction = 1, Src-Spec = { Port = 6809 } } } } } decode-pair 1a 11 00 00 60 b5 54 0b 00 09 08 05 06 04 04 1a 99 -match Vendor-Specific.WiMAX.Packet-Flow-Descriptor-v2 = { Classifier = { Src-Spec = { Port = 6809 } } } +match Vendor-Specific = { WiMAX = { Packet-Flow-Descriptor-v2 = { Classifier = { Src-Spec = { Port = 6809 } } } } } encode-pair - match 1a 11 00 00 60 b5 54 0b 00 09 08 05 06 04 04 1a 99 @@ -99,7 +99,7 @@ match 1a 11 00 00 60 b5 54 0b 00 09 08 05 06 04 04 1a 99 # 26.24757.84.9.5 has the correct length. # 26.24757.84.9.5.4 has the wrong length. decode-pair 1a 14 00 00 60 b5 54 0e 00 09 0b 04 03 01 05 06 04 05 1a 99 -match Vendor-Specific.WiMAX.Packet-Flow-Descriptor-v2 = { Classifier = { Direction = 1, raw.Src-Spec = 0x04051a99 } } +match Vendor-Specific = { WiMAX = { Packet-Flow-Descriptor-v2 = { Classifier = { Direction = 1, raw.Src-Spec = 0x04051a99 } } } } # The 26.24757.1 has the wrong length decode-pair 1a 11 00 00 60 b5 01 0a 00 01 05 31 2e 30 02 03 01 @@ -116,10 +116,10 @@ match 1a 11 00 00 60 b5 01 0c 00 01 05 31 2e 30 02 03 01 # 26.24757.1.1 has the wrong length decode-pair 1a 11 00 00 60 b5 01 0b 00 01 04 31 2e 30 02 03 01 -match raw.Vendor-Specific.WiMAX.Capability = 0x0104312e30020301 +match Vendor-Specific = { WiMAX = { raw.Capability = 0x0104312e30020301 } } decode-pair 1a 11 00 00 60 b5 01 0b 00 01 06 31 2e 30 02 03 01 -match raw.Vendor-Specific.WiMAX.Capability = 0x0106312e30020301 +match Vendor-Specific = { WiMAX = { raw.Capability = 0x0106312e30020301 } } encode-pair - match 1a 11 00 00 60 b5 01 0b 00 01 06 31 2e 30 02 03 01 @@ -149,7 +149,7 @@ match 1a 11 00 00 60 b5 01 0b 00 01 06 31 2e 30 02 03 01 # 26.24757.1.2 has the wrong length decode-pair 1a 11 00 00 60 b5 01 0b 00 01 05 31 2e 30 02 02 01 -match raw.Vendor-Specific.WiMAX.Capability = 0x0105312e30020201 +match Vendor-Specific = { WiMAX = { raw.Capability = 0x0105312e30020201 } } encode-pair - match 1a 11 00 00 60 b5 01 0b 00 01 05 31 2e 30 02 02 01 @@ -161,7 +161,7 @@ match 1a 11 00 00 60 b5 01 0b 00 01 05 31 2e 30 02 02 01 # 26.24757.1.2 has the wrong length # This means that 26.24757.1 is invalid, and we create a raw attribute. decode-pair 1a 11 00 00 60 b5 01 0b 00 01 05 31 2e 30 02 04 01 -match raw.Vendor-Specific.WiMAX.Capability = 0x0105312e30020401 +match Vendor-Specific = { WiMAX = { raw.Capability = 0x0105312e30020401 } } encode-pair - match 1a 11 00 00 60 b5 01 0b 00 01 05 31 2e 30 02 04 01 @@ -176,34 +176,35 @@ encode-pair Vendor-Specific.WiMAX.Packet-Flow-Descriptor-v2.Classifier.Classifie match 1a 15 00 00 60 b5 54 0f 00 09 0c 09 0a 03 08 01 03 37 02 03 54 decode-pair - -match Vendor-Specific.WiMAX.Packet-Flow-Descriptor-v2 = { Classifier = { Classifier-Eth-Option = { Eth-Priority-Range = { Low = 55, High = 84 } } } } +match Vendor-Specific = { WiMAX = { Packet-Flow-Descriptor-v2 = { Classifier = { Classifier-Eth-Option = { Eth-Priority-Range = { Low = 55, High = 84 } } } } } } # A less efficient encoding of the above data decode-pair 1a 17 00 00 60 b5 54 11 00 09 0e 09 0c 03 05 01 03 37 03 05 02 03 54 -match Vendor-Specific.WiMAX.Packet-Flow-Descriptor-v2 = { Classifier = { Classifier-Eth-Option = { Eth-Priority-Range = { Low = 55 }, Eth-Priority-Range = { High = 84 } } } } +match Vendor-Specific = { WiMAX = { Packet-Flow-Descriptor-v2 = { Classifier = { Classifier-Eth-Option = { Eth-Priority-Range = { Low = 55 }, Eth-Priority-Range = { High = 84 } } } } } } + # 26.24757.84.9.9.3.1 has the wrong length decode-pair 1a 15 00 00 60 b5 54 0f 00 09 0c 09 0a 03 08 01 04 37 02 03 54 -match Vendor-Specific.WiMAX.Packet-Flow-Descriptor-v2 = { Classifier = { Classifier-Eth-Option = { raw.Eth-Priority-Range = 0x010437020354 } } } +match Vendor-Specific = { WiMAX = { Packet-Flow-Descriptor-v2 = { Classifier = { Classifier-Eth-Option = { raw.Eth-Priority-Range = 0x010437020354 } } } } } # 26.24757.84.9.9.3.2 has the wrong length decode-pair 1a 15 00 00 60 b5 54 0f 00 09 0c 09 0a 03 08 01 03 37 02 04 54 -match Vendor-Specific.WiMAX.Packet-Flow-Descriptor-v2 = { Classifier = { Classifier-Eth-Option = { raw.Eth-Priority-Range = 0x010337020454 } } } +match Vendor-Specific = { WiMAX = { Packet-Flow-Descriptor-v2 = { Classifier = { Classifier-Eth-Option = { raw.Eth-Priority-Range = 0x010337020454 } } } } } # 26.24757.84.9.9.3.2 has the wrong length # This means that the SECOND 26.24757.84.9.9.3 is invalid. decode-pair 1a 17 00 00 60 b5 54 11 00 09 0e 09 0c 03 05 01 03 37 03 05 02 04 54 -match Vendor-Specific.WiMAX.Packet-Flow-Descriptor-v2 = { Classifier = { Classifier-Eth-Option = { Eth-Priority-Range = { Low = 55 }, raw.Eth-Priority-Range = 0x020454 } } } +match Vendor-Specific = { WiMAX = { Packet-Flow-Descriptor-v2 = { Classifier = { Classifier-Eth-Option = { Eth-Priority-Range = { Low = 55 }, raw.Eth-Priority-Range = 0x020454 } } } } } # 26.24757.84.9.9.3.1 has the wrong length # This means that 26.24757.84.9.9.3 is invalid. decode-pair 1a 17 00 00 60 b5 54 11 00 09 0e 09 0c 03 05 01 02 37 03 05 02 03 54 -match Vendor-Specific.WiMAX.Packet-Flow-Descriptor-v2 = { Classifier = { Classifier-Eth-Option = { raw.Eth-Priority-Range = 0x010237, Eth-Priority-Range = { High = 84 } } } } +match Vendor-Specific = { WiMAX = { Packet-Flow-Descriptor-v2 = { Classifier = { Classifier-Eth-Option = { raw.Eth-Priority-Range = 0x010237, Eth-Priority-Range = { High = 84 } } } } } } # # Simple test for continued attributes # decode-pair 1a 0e 00 00 60 b5 01 08 80 01 05 31 2e 30 1a 0c 00 00 60 b5 01 06 00 02 03 00 -match Vendor-Specific.WiMAX.Capability = { Release = "1.0", Accounting-Capabilities = No-Accounting } +match Vendor-Specific = { WiMAX = { Capability = { Release = "1.0", Accounting-Capabilities = No-Accounting } } } # # See if encoding multiple attributes works @@ -244,7 +245,7 @@ match 1a 1d 00 00 60 b5 1c 17 00 0b 14 05 12 01 06 7f 00 00 01 04 04 08 40 05 06 # Structs not yet decoded into sub-groups # decode-pair - -match Vendor-Specific.WiMAX.Packet-Flow-Descriptor = { Classifier = { Src-Spec = { IP-Address = 127.0.0.1, Port = 2112, Port-Range.Start = 2112, Port-Range.End = 6809 } } } +match Vendor-Specific = { WiMAX = { Packet-Flow-Descriptor = { Classifier = { Src-Spec = { IP-Address = 127.0.0.1, Port = 2112, Port-Range.Start = 2112, Port-Range.End = 6809 } } } } } encode-pair Vendor-Specific.WiMAX.DNS-Server = ::1 match 1a 19 00 00 60 b5 34 13 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 @@ -252,5 +253,15 @@ match 1a 19 00 00 60 b5 34 13 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 encode-pair Vendor-Specific.WiMAX.DNS-Server = 127.0.0.1 match 1a 0d 00 00 60 b5 34 07 00 7f 00 00 01 +# +# Test for attribute overflow +# +encode-pair Vendor-Specific.WiMAX.Capability.Release = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +match 1a ff 00 00 60 b5 01 f9 80 01 fd 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 78 1a 09 00 00 02 78 78 7f 78 + +decode-pair - +match Vendor-Specific = { WiMAX = { Capability = { Release = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" } } } + + count match 118