From: Alan T. DeKok Date: Wed, 7 Apr 2021 19:13:23 +0000 (-0400) Subject: decode RADIUS TLVs as nested pairs. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6aea55db373640a88a736a236c4c551aa1ff0a35;p=thirdparty%2Ffreeradius-server.git decode RADIUS TLVs as nested pairs. This means that the detail writer will no longer print foo.bar = 1 but instead will print foo = { bar = 1} Happily, the detail reader will still read the new format. For future reference, we should replace the detail writer/reader loop with an internal "serialize/unserialize" loop, for things such as fail-over when SQL is down. The existing detail writer can then be updated to print "flattened" attribute names. And, it will only be used by third-party tools. --- diff --git a/src/lib/util/pair_print.c b/src/lib/util/pair_print.c index 96a9caa783..7957ffad59 100644 --- a/src/lib/util/pair_print.c +++ b/src/lib/util/pair_print.c @@ -132,6 +132,10 @@ ssize_t fr_pair_print(fr_sbuff_t *out, fr_pair_t const *parent, fr_pair_t const * Complete string with '\\t' and '\\n' is written to buffer before printing to * avoid issues when running with multiple threads. * + * This function will print *flattened* lists, as is suitable for use + * with rlm_detail. In fact, the only user of this function is + * rlm_detail. + * * @param fp to output to. * @param vp to print. */ diff --git a/src/protocols/radius/decode.c b/src/protocols/radius/decode.c index 6992a733ba..3635ed3b67 100644 --- a/src/protocols/radius/decode.c +++ b/src/protocols/radius/decode.c @@ -419,6 +419,7 @@ ssize_t fr_radius_decode_tlv(TALLOC_CTX *ctx, fr_dcursor_t *cursor, fr_dict_t co fr_dict_attr_t const *child; fr_pair_list_t head; fr_dcursor_t tlv_cursor; + fr_pair_t *vp; fr_pair_list_init(&head); if (data_len < 3) return -1; /* type, length, value */ @@ -431,8 +432,12 @@ ssize_t fr_radius_decode_tlv(TALLOC_CTX *ctx, fr_dcursor_t *cursor, fr_dict_t co if (fr_radius_decode_tlv_ok(p, data_len, 1, 1) < 0) return -1; + vp = fr_pair_afrom_da(ctx, parent); + if (!vp) return PAIR_DECODE_OOM; + /* - * Record where we were in the list when this function was called + * Create a temporary sub-list, so decode errors don't + * affect the main list. */ fr_dcursor_init(&tlv_cursor, &head); while (p < end) { @@ -448,21 +453,21 @@ ssize_t fr_radius_decode_tlv(TALLOC_CTX *ctx, fr_dcursor_t *cursor, fr_dict_t co child = fr_dict_unknown_attr_afrom_num(packet_ctx->tmp_ctx, parent, p[0]); if (!child) { error: - fr_pair_list_free(&head); + talloc_free(vp); return -1; } } FR_PROTO_TRACE("decode context changed %s -> %s", parent->name, child->name); - tlv_len = fr_radius_decode_pair_value(ctx, &tlv_cursor, dict, + tlv_len = fr_radius_decode_pair_value(vp, &tlv_cursor, dict, child, p + 2, p[1] - 2, p[1] - 2, packet_ctx); if (tlv_len < 0) goto error; p += p[1]; } - fr_dcursor_head(&tlv_cursor); - fr_dcursor_tail(cursor); - fr_dcursor_merge(cursor, &tlv_cursor); /* Wind to the end of the new pairs */ + + fr_tmp_pair_list_move(&vp->vp_group, &head); + fr_dcursor_append(cursor, vp); return data_len; } diff --git a/src/tests/unit/protocols/radius/rfc8045.txt b/src/tests/unit/protocols/radius/rfc8045.txt index a9e3659e95..d9ad7eb47e 100644 --- a/src/tests/unit/protocols/radius/rfc8045.txt +++ b/src/tests/unit/protocols/radius/rfc8045.txt @@ -17,7 +17,7 @@ encode-pair Extended-Attribute-1.IP-Port-Limit-Info.Type = 1, Extended-Attribute match f1 0f 05 01 06 00 00 00 01 02 06 00 00 00 02 decode-pair - -match Extended-Attribute-1.IP-Port-Limit-Info.Type = 1, Extended-Attribute-1.IP-Port-Limit-Info.Limit = 2 +match Extended-Attribute-1.IP-Port-Limit-Info = { Type = 1, Limit = 2 } # # And for the other attributes @@ -26,7 +26,7 @@ encode-pair Extended-Attribute-1.IP-Port-Range.Type = 1, Extended-Attribute-1.IP match f1 0f 06 01 06 00 00 00 01 02 06 00 00 00 02 decode-pair - -match Extended-Attribute-1.IP-Port-Range.Type = 1, Extended-Attribute-1.IP-Port-Range.Limit = 2 +match Extended-Attribute-1.IP-Port-Range = { Type = 1, Limit = 2 } count match 14 diff --git a/src/tests/unit/protocols/radius/struct.txt b/src/tests/unit/protocols/radius/struct.txt index 5ecb6571fd..28f5086668 100644 --- a/src/tests/unit/protocols/radius/struct.txt +++ b/src/tests/unit/protocols/radius/struct.txt @@ -19,13 +19,13 @@ encode-pair Extended-Attribute-1.Unit-Ext-241-Struct2.Unit-Struct2-Int1 = 1, Ext match f1 1a f8 00 00 00 01 00 04 01 06 00 00 00 06 02 06 00 00 00 07 03 05 66 6f 6f decode-pair - -match Extended-Attribute-1.Unit-Ext-241-Struct2.Unit-Struct2-Int1 = 1, Extended-Attribute-1.Unit-Ext-241-Struct2.Unit-Struct2-Short = 4, Extended-Attribute-1.Unit-Ext-241-Struct2.Unit-Struct2-TLV.Unit-Struct2-TLV-Int1 = 6, Extended-Attribute-1.Unit-Ext-241-Struct2.Unit-Struct2-TLV.Unit-Struct2-TLV-Int2 = 7, Extended-Attribute-1.Unit-Ext-241-Struct2.Unit-Struct2-TLV.Unit-Struct2-TLV-String = "foo" +match Extended-Attribute-1.Unit-Ext-241-Struct2.Unit-Struct2-Int1 = 1, Extended-Attribute-1.Unit-Ext-241-Struct2.Unit-Struct2-Short = 4, Extended-Attribute-1.Unit-Ext-241-Struct2.Unit-Struct2-TLV = { Unit-Struct2-TLV-Int1 = 6, Unit-Struct2-TLV-Int2 = 7, Unit-Struct2-TLV-String = "foo" } encode-pair Extended-Attribute-1.Unit-Ext-241-Struct3.Unit-Struct3-Int = 1, Extended-Attribute-1.Unit-Ext-241-Struct3.Unit-Struct3-TLV.Unit-Struct3a.Unit-Struct3a-Ipaddr1 = 127.0.0.1, Extended-Attribute-1.Unit-Ext-241-Struct3.Unit-Struct3-TLV.Unit-Struct3a.Unit-Struct3a-Ipaddr2 = 8.8.8.8 match f1 11 f9 00 00 00 01 01 0a 7f 00 00 01 08 08 08 08 decode-pair - -match Extended-Attribute-1.Unit-Ext-241-Struct3.Unit-Struct3-Int = 1, Extended-Attribute-1.Unit-Ext-241-Struct3.Unit-Struct3-TLV.Unit-Struct3a.Unit-Struct3a-Ipaddr1 = 127.0.0.1, Extended-Attribute-1.Unit-Ext-241-Struct3.Unit-Struct3-TLV.Unit-Struct3a.Unit-Struct3a-Ipaddr2 = 8.8.8.8 +match Extended-Attribute-1.Unit-Ext-241-Struct3.Unit-Struct3-Int = 1, Extended-Attribute-1.Unit-Ext-241-Struct3.Unit-Struct3-TLV = { Unit-Struct3a.Unit-Struct3a-Ipaddr1 = 127.0.0.1, Unit-Struct3a.Unit-Struct3a-Ipaddr2 = 8.8.8.8 } # # Fixed size struct diff --git a/src/tests/unit/protocols/radius/unit.txt b/src/tests/unit/protocols/radius/unit.txt index dde21f5bd6..ecdaffbf8b 100644 --- a/src/tests/unit/protocols/radius/unit.txt +++ b/src/tests/unit/protocols/radius/unit.txt @@ -42,7 +42,7 @@ encode-pair Extended-Attribute-1.Unit-Ext-241-TLV.Unit-TLV-Integer = 1, Extended match f1 0f f3 01 06 00 00 00 01 01 06 00 00 00 02 decode-pair - -match Extended-Attribute-1.Unit-Ext-241-TLV.Unit-TLV-Integer = 1, Extended-Attribute-1.Unit-Ext-241-TLV.Unit-TLV-Integer = 2 +match Extended-Attribute-1.Unit-Ext-241-TLV = { Unit-TLV-Integer = 1, Unit-TLV-Integer = 2 } # # And "long extended" EVS @@ -77,8 +77,11 @@ encode-pair - match fe 08 02 06 00 00 00 05 decode-pair - -match Unit-TLV.Delta-MSec = 5 +match Unit-TLV = { Delta-MSec = 5 } +# +# @todo - not yet converted to make nested TLVs! +# attribute Unit-TLV.Delta-Sec = 10 match Unit-TLV.Delta-Sec = 10 @@ -86,7 +89,7 @@ encode-pair - match fe 08 03 06 00 00 00 0a decode-pair - -match Unit-TLV.Delta-Sec = 10 +match Unit-TLV = { Delta-Sec = 10 } # # Allow encoding as nested VPs diff --git a/src/tests/unit/protocols/radius/wimax.txt b/src/tests/unit/protocols/radius/wimax.txt index dda3763681..0b7e37903b 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", Vendor-Specific.WiMAX.Capability.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,16 +87,19 @@ 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, Vendor-Specific.WiMAX.Packet-Flow-Descriptor-v2.Classifier.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 # 26.24757.84.9.4 has the correct length. # 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.Vendor-Specific.WiMAX.Packet-Flow-Descriptor-v2.Classifier.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 @@ -173,34 +176,34 @@ 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, Vendor-Specific.WiMAX.Packet-Flow-Descriptor-v2.Classifier.Classifier-Eth-Option.Eth-Priority-Range.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, Vendor-Specific.WiMAX.Packet-Flow-Descriptor-v2.Classifier.Classifier-Eth-Option.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 raw.Vendor-Specific.WiMAX.Packet-Flow-Descriptor-v2.Classifier.Classifier-Eth-Option.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 raw.Vendor-Specific.WiMAX.Packet-Flow-Descriptor-v2.Classifier.Classifier-Eth-Option.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.Vendor-Specific.WiMAX.Packet-Flow-Descriptor-v2.Classifier.Classifier-Eth-Option.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 raw.Vendor-Specific.WiMAX.Packet-Flow-Descriptor-v2.Classifier.Classifier-Eth-Option.Eth-Priority-Range = 0x010237, Vendor-Specific.WiMAX.Packet-Flow-Descriptor-v2.Classifier.Classifier-Eth-Option.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", Vendor-Specific.WiMAX.Capability.Accounting-Capabilities = No-Accounting +match Vendor-Specific.WiMAX.Capability = { Release = "1.0", Accounting-Capabilities = No-Accounting } # # See if encoding multiple attributes works @@ -241,7 +244,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, Vendor-Specific.WiMAX.Packet-Flow-Descriptor.Classifier.Src-Spec.Port = 2112, Vendor-Specific.WiMAX.Packet-Flow-Descriptor.Classifier.Src-Spec.Port-Range.Start = 2112, Vendor-Specific.WiMAX.Packet-Flow-Descriptor.Classifier.Src-Spec.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 @@ -250,4 +253,4 @@ 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 count -match 116 +match 118