]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
allow EAP-AKA-SIM to encode nested pairs.
authorAlan T. DeKok <aland@freeradius.org>
Tue, 12 Sep 2023 20:57:48 +0000 (16:57 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Tue, 12 Sep 2023 20:57:48 +0000 (16:57 -0400)
The decoder is still not done.  That's next.

src/lib/eap_aka_sim/encode.c
src/tests/unit/protocols/eap/sim/encode.txt
src/tests/unit/protocols/eap/sim/encrypted.txt

index ab495b03884d12843b37f26a9d5e5601d78bd4a6..084ef1dbab8618c6e3d242bbbda7950c6c036849 100644 (file)
@@ -57,9 +57,9 @@ RCSID("$Id$")
  * of 32 bits, and includes the Type/Length fields.
  */
 
-static ssize_t encode_tlv_hdr(fr_dbuff_t *dbuff,
-                             fr_da_stack_t *da_stack, unsigned int depth,
-                             fr_dcursor_t *cursor, void *encode_ctx);
+static ssize_t encode_tlv(fr_dbuff_t *dbuff,
+                         fr_da_stack_t *da_stack, unsigned int depth,
+                         fr_dcursor_t *cursor, void *encode_ctx);
 
 /** Evaluation function for EAP-AKA-encodability
  *
@@ -584,7 +584,7 @@ static ssize_t encode_array(fr_dbuff_t *dbuff,
  * If it's a standard attribute, then vp->da->attr == attribute.
  * Otherwise, attribute may be something else.
  */
-static ssize_t encode_rfc_hdr(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, unsigned int depth,
+static ssize_t encode_rfc(fr_dbuff_t *dbuff, fr_da_stack_t *da_stack, unsigned int depth,
                              fr_dcursor_t *cursor, void *encode_ctx)
 {
        size_t                  pad_len;
@@ -677,9 +677,9 @@ static inline ssize_t encode_tlv_internal(fr_dbuff_t *dbuff,
                 *      Determine the nested type and call the appropriate encoder
                 */
                if (da_stack->da[depth + 1]->type == FR_TYPE_TLV) {
-                       slen = encode_tlv_hdr(&work_dbuff, da_stack, depth + 1, cursor, encode_ctx);
+                       slen = encode_tlv(&work_dbuff, da_stack, depth + 1, cursor, encode_ctx);
                } else {
-                       slen = encode_rfc_hdr(&work_dbuff, da_stack, depth + 1, cursor, encode_ctx);
+                       slen = encode_rfc(&work_dbuff, da_stack, depth + 1, cursor, encode_ctx);
                }
 
                if (slen <= 0) {
@@ -724,7 +724,7 @@ static inline ssize_t encode_tlv_internal(fr_dbuff_t *dbuff,
        return fr_dbuff_set(dbuff, &work_dbuff);
 }
 
-static ssize_t encode_tlv_hdr(fr_dbuff_t *dbuff,
+static ssize_t encode_tlv(fr_dbuff_t *dbuff,
                              fr_da_stack_t *da_stack, unsigned int depth,
                              fr_dcursor_t *cursor, void *encode_ctx)
 {
@@ -733,6 +733,8 @@ static ssize_t encode_tlv_hdr(fr_dbuff_t *dbuff,
        fr_dict_attr_t const    *da;
        fr_dbuff_t              tl_dbuff;
        fr_dbuff_t              work_dbuff = FR_DBUFF(dbuff);
+       fr_dcursor_t            *my_cursor = cursor;
+       fr_dcursor_t            child_cursor;
 
        PAIR_VERIFY(fr_dcursor_current(cursor));
        FR_PROTO_STACK_PRINT(da_stack, depth);
@@ -744,8 +746,20 @@ static ssize_t encode_tlv_hdr(fr_dbuff_t *dbuff,
        }
 
        if (!da_stack->da[depth + 1]) {
-               fr_strerror_printf("%s: Can't encode empty TLV", __FUNCTION__);
-               return PAIR_ENCODE_FATAL_ERROR;
+               fr_pair_t *vp;
+
+               vp = fr_dcursor_current(cursor);
+               if ((vp->vp_type != FR_TYPE_TLV) || (fr_pair_list_num_elements(&vp->vp_group) == 0)) {
+                       fr_strerror_printf("%s: Can't encode empty TLV", __FUNCTION__);
+                       return PAIR_ENCODE_FATAL_ERROR;
+               }
+
+               fr_assert(vp->da == da_stack->da[depth]);
+
+               vp = fr_pair_dcursor_child_iter_init(&child_cursor, &vp->vp_group, cursor);
+               my_cursor = &child_cursor;
+
+               fr_proto_da_stack_build(da_stack, vp->da);
        }
 
        /*
@@ -764,9 +778,11 @@ static ssize_t encode_tlv_hdr(fr_dbuff_t *dbuff,
 
        da = da_stack->da[depth];
        len = encode_tlv_internal(&FR_DBUFF_MAX_BIND_CURRENT(&work_dbuff, SIM_MAX_ATTRIBUTE_VALUE_LEN - 2),
-                                 da_stack, depth, cursor, encode_ctx);
+                                 da_stack, depth, my_cursor, encode_ctx);
        if (len <= 0) return len;
 
+       if (my_cursor != cursor) fr_dcursor_next(cursor);
+
        /*
         *      Round attr + len + data length out to a multiple
         *      of four, and setup the attribute header and
@@ -788,7 +804,6 @@ ssize_t fr_aka_sim_encode_pair(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, void *en
        ssize_t                 slen;
 
        fr_da_stack_t           da_stack;
-       fr_dict_attr_t const    *da = NULL;
 
        fr_dbuff_marker(&m, &work_dbuff);
        if (!cursor) return PAIR_ENCODE_FATAL_ERROR;
@@ -814,42 +829,20 @@ ssize_t fr_aka_sim_encode_pair(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, void *en
         *      only use 4 * 255 bytes of buffer space at a time.
         */
 
-       /*
-        *      Fast path for the common case.
-        */
-       if ((vp->da->parent == fr_dict_root(dict_eap_aka_sim)) && (vp->vp_type != FR_TYPE_TLV)) {
-               da_stack.da[0] = vp->da;
-               da_stack.da[1] = NULL;
-               da_stack.depth = 1;
-               FR_PROTO_STACK_PRINT(&da_stack, 0);
-               return encode_rfc_hdr(&FR_DBUFF_MAX_BIND_CURRENT(dbuff, SIM_MAX_ATTRIBUTE_VALUE_LEN + 2),
-                                     &da_stack, 0, cursor, encode_ctx);
-       }
-
        /*
         *      Do more work to set up the stack for the complex case.
         */
        fr_proto_da_stack_build(&da_stack, vp->da);
        FR_PROTO_STACK_PRINT(&da_stack, 0);
 
-       da = da_stack.da[0];
-
-       switch (da->type) {
-       /*
-        *      Supported types
-        */
-       default:
-               slen = encode_rfc_hdr(&FR_DBUFF_MAX_BIND_CURRENT(&work_dbuff, SIM_MAX_ATTRIBUTE_VALUE_LEN + 2),
-                                     &da_stack, 0, cursor, encode_ctx);
-               if (slen < 0) return slen;
-               break;
-
-       case FR_TYPE_TLV:
-               slen = encode_tlv_hdr(&FR_DBUFF_MAX_BIND_CURRENT(&work_dbuff, SIM_MAX_ATTRIBUTE_VALUE_LEN + 2),
-                                     &da_stack, 0, cursor, encode_ctx);
-               if (slen < 0) return slen;
-               break;
+       if (da_stack.da[0]->type == FR_TYPE_TLV) {
+               slen = encode_tlv(&FR_DBUFF_MAX_BIND_CURRENT(&work_dbuff, SIM_MAX_ATTRIBUTE_VALUE_LEN + 2),
+                                 &da_stack, 0, cursor, encode_ctx);
+       } else {
+               slen = encode_rfc(&FR_DBUFF_MAX_BIND_CURRENT(&work_dbuff, SIM_MAX_ATTRIBUTE_VALUE_LEN + 2),
+                                 &da_stack, 0, cursor, encode_ctx);
        }
+       if (slen < 0) return slen;
 
        /*
         *      We couldn't do it, so we didn't do anything.
index 18bf19a5dc5703ec97916fbf6a667d7365f1c8c8..45e1534391add58d29935a9b290bd49ed2e6901c 100644 (file)
@@ -8,8 +8,6 @@ need-feature tls
 proto eap-aka-sim
 proto-dictionary eap-aka-sim eap/aka-sim
 
-migrate pair_legacy_nested = false
-
 # Boolean attribute
 encode-pair.sim_tp_encode Any-ID-Req = yes
 match 0d 01 00 00
@@ -86,12 +84,20 @@ match 82 09 00 00 3f b8 34 1f f8 26 e0 4d 4a f3 f9 61 3c a9 84 26 0f 4a 53 ce 33
 decode-pair.sim_tp_decode -
 match Encr-Data.Next-Pseudonym = "testing123", Encr-Data.Counter-Too-Small = yes
 
+pair Encr-Data.Next-Pseudonym = "testing123", Any-ID-Req = yes, Encr-Data.Counter-Too-Small = yes
+match Encr-Data = { Next-Pseudonym = "testing123", Counter-Too-Small = yes }, Any-ID-Req = yes
+
 # Plaintext and encrypted attributes interleaved (this shouldn't happen usually, due to sorting)
 encode-pair.sim_tp_encode Encr-Data.Next-Pseudonym = "testing123", Any-ID-Req = yes, Encr-Data.Counter-Too-Small = yes
-match 82 05 00 00 3f b8 34 1f f8 26 e0 4d 4a f3 f9 61 3c a9 84 26 0d 01 00 00 82 05 00 00 5a f8 99 3c 02 f5 6c 04 b8 6e bb 54 3a af 74 32
+match 82 09 00 00 3f b8 34 1f f8 26 e0 4d 4a f3 f9 61 3c a9 84 26 0f 4a 53 ce 33 99 9e 4f 29 df a4 79 18 a9 57 dd 0d 01 00 00
+
+#
+#  Old style: NOT nested.  So we put the children of the TLV 82 into different top-level TLVs.
+#
+#match 82 05 00 00 3f b8 34 1f f8 26 e0 4d 4a f3 f9 61 3c a9 84 26 0d 01 00 00 82 05 00 00 5a f8 99 3c 02 f5 6c 04 b8 6e bb 54 3a af 74 32
 
 decode-pair.sim_tp_decode -
-match Encr-Data.Next-Pseudonym = "testing123", Any-ID-Req = yes, Encr-Data.Counter-Too-Small = yes
+match Encr-Data.Next-Pseudonym = "testing123", Encr-Data.Counter-Too-Small = yes, Any-ID-Req = yes
 
 # Array (one element)
 encode-pair.sim_tp_encode Version-List = 1
@@ -126,4 +132,4 @@ encode-pair.sim_tp_encode_rfc4186 IV = 0xcdf7ffa65de04c026b56c86b76b102ea, Encr-
 match 81 05 00 00 cd f7 ff a6 5d e0 4c 02 6b 56 c8 6b 76 b1 02 ea 82 05 00 00 b6 ed d3 82 79 e2 a1 42 3c 1a fc 5c 45 5c 7d 56
 
 count
-match 63
+match 64
index 63dc0fe7f6effb724c8efc4e831a22258da1ed9d..350ccf2a261d96a92c9453a870cea6f8d75ee896 100644 (file)
@@ -9,8 +9,6 @@ need-feature tls
 proto eap-aka-sim
 proto-dictionary eap-aka-sim eap/aka-sim
 
-migrate pair_legacy_nested = false
-
 # Encr-Data attributes should not be split between multiple outer TLVs (regression test)
 encode-pair.sim_tp_encode_rfc4186 IV = 0xd585ac7786b90336657c77b46575b9c4, Encr-Data.Next-Reauth-ID = "8osafwilQBCdof4", Encr-Data.Next-Pseudonym = "7QSzGAfgFKU8De9", Encr-Data.Nonce-S = 0xd61d1c6124106953f6f7283ae680a5ed, Encr-Data.Counter = 1
 match 81 05 00 00 d5 85 ac 77 86 b9 03 36 65 7c 77 b4 65 75 b9 c4 82 11 00 00 6e a1 2b 5c d1 57 fa fc be a9 c9 7c ad 30 07 ff 72 dc cb c8 a9 96 b3 33 1f 71 aa 06 bb f0 1d 04 6b 51 9e fa 83 31 11 67 c6 93 1e 9c 06 5c 1f 2c 62 0d 1d 6d b0 b1 59 2f 91 f1 56 98 a9 e2 dc 3c