]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Copy all of the server_id and client_id attributes
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Thu, 4 Nov 2021 03:20:35 +0000 (23:20 -0400)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Thu, 4 Nov 2021 03:20:35 +0000 (23:20 -0400)
src/lib/eap_aka_sim/encode.c
src/lib/util/pair.c
src/lib/util/pair.h
src/lib/util/pair_tests.c
src/process/dhcpv6/base.c

index 79f25e7decc90bafd2983dcd1b0cd11fc2d25fbf..056657f66c28e61ad25412c3babab1185cb360cb 100644 (file)
@@ -882,7 +882,7 @@ ssize_t fr_aka_sim_encode(request_t *request, fr_pair_list_t *to_encode, void *e
         *      It might be too big for putting into an
         *      EAP packet.
         */
-       vp = fr_pair_find_by_child_num(to_encode, fr_dict_root(dict_eap_aka_sim), FR_SUBTYPE);
+       vp = fr_pair_find_by_child_num(to_encode, fr_dict_root(dict_eap_aka_sim), FR_SUBTYPE, 0);
        if (!vp) {
                REDEBUG("Missing subtype attribute");
                return PAIR_ENCODE_FATAL_ERROR;
@@ -900,7 +900,7 @@ ssize_t fr_aka_sim_encode(request_t *request, fr_pair_list_t *to_encode, void *e
        /*
         *      Will we need to generate a HMAC?
         */
-       if (fr_pair_find_by_child_num(to_encode, fr_dict_root(dict_eap_aka_sim), FR_MAC)) do_hmac = true;
+       if (fr_pair_find_by_child_num(to_encode, fr_dict_root(dict_eap_aka_sim), FR_MAC, 0)) do_hmac = true;
 
        /*
         *      Fast path, we just need to encode a subtype
index 9f8f36feebde899288ba5e83fd74a7b2cada5648..15fbec3089a29f2d1e6fe7b82bf6e562e27660b0 100644 (file)
@@ -658,6 +658,7 @@ fr_pair_t *fr_pair_find_by_da(fr_pair_list_t const *list, fr_dict_attr_t const *
 /** Find a pair which has the specified ancestor
  *
  * @param[in] list     to search in.
+ * @param[in] prev     where to start the search from.
  * @param[in] ancestor to look for in the list.
  * @return
  *     - first matching fr_pair_t.
@@ -665,9 +666,10 @@ fr_pair_t *fr_pair_find_by_da(fr_pair_list_t const *list, fr_dict_attr_t const *
  *
  * @hidecallergraph
  */
-fr_pair_t *fr_pair_find_by_ancestor(fr_pair_list_t const *list, fr_dict_attr_t const *ancestor)
+fr_pair_t *fr_pair_find_by_ancestor(fr_pair_list_t const *list,
+                                   fr_pair_t const *prev, fr_dict_attr_t const *ancestor)
 {
-       fr_pair_t       *vp = NULL;
+       fr_pair_t       *vp = UNCONST(fr_pair_t *, prev);
 
        while ((vp = fr_pair_list_next(list, vp))) {
                if (!fr_dict_attr_common_parent(ancestor, vp->da, true)) continue;
@@ -683,14 +685,15 @@ fr_pair_t *fr_pair_find_by_ancestor(fr_pair_list_t const *list, fr_dict_attr_t c
  * @param[in] list     in which to search.
  * @param[in] parent   attribute in which to lookup child.
  * @param[in] attr     id of child.
+ * @param[in] n                Instance of the attribute to return.
  * @return
  *     - first matching value pair.
  *     - NULL if no pair found.
  */
-fr_pair_t *fr_pair_find_by_child_num(fr_pair_list_t *list, fr_dict_attr_t const *parent, unsigned int attr)
+fr_pair_t *fr_pair_find_by_child_num(fr_pair_list_t *list,
+                                    fr_dict_attr_t const *parent, unsigned int attr, unsigned int n)
 {
        fr_dict_attr_t const    *da;
-       fr_pair_t               *vp;
 
        /* List head may be NULL if it contains no VPs */
        if (fr_dlist_empty(&list->order)) return NULL;
@@ -700,9 +703,7 @@ fr_pair_t *fr_pair_find_by_child_num(fr_pair_list_t *list, fr_dict_attr_t const
        da = fr_dict_attr_child_by_num(parent, attr);
        if (!da) return NULL;
 
-       for (vp = fr_pair_list_head(list); vp != NULL; vp = fr_pair_list_next(list, vp)) if (da == vp->da) return vp;
-
-       return NULL;
+       return fr_pair_find_by_da(list, da, n);
 }
 
 /** Return a pointer to the pair list
index e477f135729eb6e0de888a115a315d8b1cabab5e..c3f86554e87eb18ab0582916fc82c8ee4939f516 100644 (file)
@@ -265,11 +265,12 @@ unsigned int      fr_pair_count_by_da(fr_pair_list_t const *list, fr_dict_attr_t cons
 fr_pair_t      *fr_pair_find_by_da(fr_pair_list_t const *list,
                                    fr_dict_attr_t const *da, unsigned int n) CC_HINT(nonnull);
 
-fr_pair_t      *fr_pair_find_by_ancestor(fr_pair_list_t const *list,
-                                         fr_dict_attr_t const *ancestor) CC_HINT(nonnull);
+fr_pair_t      *fr_pair_find_by_ancestor(fr_pair_list_t const *list, fr_pair_t const *prev,
+                                         fr_dict_attr_t const *ancestor) CC_HINT(nonnull(1,3));
 
 fr_pair_t      *fr_pair_find_by_child_num(fr_pair_list_t *list,
-                                          fr_dict_attr_t const *parent, unsigned int attr) CC_HINT(nonnull);
+                                          fr_dict_attr_t const *parent, unsigned int attr,
+                                          unsigned int n) CC_HINT(nonnull);
 
 int            fr_pair_append(fr_pair_list_t *list, fr_pair_t *vp) CC_HINT(nonnull);
 
index 072773ca0e0bd8f46b35ec71b683d00318a1dd94..60953ef8c9cc19761ce80ae56ffe9f17f0d65e8c 100644 (file)
@@ -249,7 +249,7 @@ static void test_fr_pair_find_by_child_num(void)
        fr_pair_t *vp;
 
        TEST_CASE("Search for FR_TEST_ATTR_STRING using fr_pair_find_by_child_num()");
-       TEST_CHECK((vp = fr_pair_find_by_child_num(&test_pairs, fr_dict_root(test_dict), FR_TEST_ATTR_STRING)) != NULL);
+       TEST_CHECK((vp = fr_pair_find_by_child_num(&test_pairs, fr_dict_root(test_dict), FR_TEST_ATTR_STRING, 0)) != NULL);
 
        TEST_CASE("Validating PAIR_VERIFY()");
        PAIR_VERIFY(vp);
@@ -290,7 +290,7 @@ static void test_fr_pair_delete_by_child_num(void)
        fr_pair_delete_by_child_num(&test_pairs, fr_dict_root(test_dict), FR_TEST_ATTR_STRING);
 
        TEST_CASE("The fr_dict_attr_test_string shouldn't exist in 'test_pairs'");
-       TEST_CHECK(fr_pair_find_by_child_num(&test_pairs, fr_dict_root(test_dict), FR_TEST_ATTR_STRING) == NULL);
+       TEST_CHECK(fr_pair_find_by_child_num(&test_pairs, fr_dict_root(test_dict), FR_TEST_ATTR_STRING, 0) == NULL);
 
        TEST_CASE("Add fr_dict_attr_test_string back into 'test_pairs'");
        TEST_CHECK(fr_pair_prepend_by_da(autofree, NULL, &test_pairs, fr_dict_attr_test_string) == 0);
@@ -354,11 +354,11 @@ static void test_fr_pair_delete(void)
        fr_pair_t *vp;
 
        TEST_CASE("Delete fr_dict_attr_test_string using fr_pair_delete()");
-       TEST_CHECK((vp = fr_pair_find_by_child_num(&test_pairs, fr_dict_root(test_dict), FR_TEST_ATTR_STRING)) != NULL);
+       TEST_CHECK((vp = fr_pair_find_by_child_num(&test_pairs, fr_dict_root(test_dict), FR_TEST_ATTR_STRING, 0)) != NULL);
        fr_pair_delete(&test_pairs, vp);
 
        TEST_CASE("The fr_dict_attr_test_string shouldn't exist in 'test_pairs'");
-       TEST_CHECK((vp = fr_pair_find_by_child_num(&test_pairs, fr_dict_root(test_dict), FR_TEST_ATTR_STRING)) == NULL);
+       TEST_CHECK((vp = fr_pair_find_by_child_num(&test_pairs, fr_dict_root(test_dict), FR_TEST_ATTR_STRING, 0)) == NULL);
 
        TEST_CASE("Add fr_dict_attr_test_string back into 'test_pairs'");
        TEST_CHECK(fr_pair_prepend_by_da(autofree, NULL, &test_pairs, fr_dict_attr_test_string) == 0);
index 6e0776798ea057434827e38f37979f5c12532736..07685dbdc6e3213ab999baf74576bc8e7d5e2e03 100644 (file)
@@ -118,8 +118,8 @@ typedef struct {
  */
 typedef struct {
        fr_pair_t       *transaction_id;
-       fr_pair_t       *client_id;
-       fr_pair_t       *server_id;
+       fr_pair_list_t  client_id;
+       fr_pair_list_t  server_id;
 } process_dhcpv6_client_fields_t;
 
 /** Records fields from the original relay-request so we have a known good copy
@@ -207,13 +207,13 @@ process_dhcpv6_client_fields_t *dhcpv6_client_fields_store(request_t *request, b
                return NULL;
        }
 
-       client_id = fr_pair_find_by_ancestor(&request->request_pairs, attr_client_id);
+       client_id = fr_pair_find_by_ancestor(&request->request_pairs, NULL, attr_client_id);
        if (!client_id) {
                REDEBUG("Missing Client-ID");
                return NULL;
        }
 
-       server_id = fr_pair_find_by_da(&request->request_pairs, attr_server_id, 0);
+       server_id = fr_pair_find_by_ancestor(&request->request_pairs, NULL, attr_server_id);
        if (!server_id && expect_server_id) {
                REDEBUG("Missing Server-ID");
                return NULL;
@@ -224,8 +224,26 @@ process_dhcpv6_client_fields_t *dhcpv6_client_fields_store(request_t *request, b
 
        MEM(rctx = talloc_zero(unlang_interpret_frame_talloc_ctx(request), process_dhcpv6_client_fields_t));
        rctx->transaction_id = fr_pair_copy(rctx, transaction_id);
-       rctx->client_id = fr_pair_copy(rctx, client_id);
-       if (expect_server_id) rctx->server_id = fr_pair_copy(rctx, server_id);
+
+       /*
+        *      These should just become straight copies
+        *      when the structure pairs are nested.
+        */
+       if (fr_pair_list_copy_by_ancestor(rctx, &rctx->client_id,
+                                         &request->request_pairs, attr_client_id, 0) < 0) {
+               REDEBUG("Error copying Client-ID");
+       error:
+               talloc_free(rctx);
+               return NULL;
+       }
+
+       if (expect_server_id) {
+               if (fr_pair_list_copy_by_ancestor(rctx, &rctx->server_id,
+                                                 &request->request_pairs, attr_server_id, 0) < 0) {
+                       REDEBUG("Error copying Server-ID");
+                       goto error;
+               }
+       }
 
        return rctx;
 }
@@ -296,7 +314,8 @@ RECV(for_this_server)
 static inline CC_HINT(always_inline)
 int restore_field(request_t *request, fr_pair_t **to_restore)
 {
-       fr_pair_t                       *vp;
+       fr_pair_t       *vp;
+       int             ret = 0;
 
        PAIR_VERIFY(*to_restore);
 
@@ -304,17 +323,35 @@ int restore_field(request_t *request, fr_pair_t **to_restore)
        if (vp) {
                if (fr_pair_cmp(vp, *to_restore) != 0) {
                        RWDEBUG("&reply.%pP does not match &request.%pP", vp, *to_restore);
-                       return 0;
+               free:
+                       talloc_free(*to_restore);
+                       *to_restore = NULL;
+                       return ret;
                }
        } else if (fr_pair_steal_append(request->reply_ctx, &request->reply_pairs, *to_restore) < 0) {
                RPERROR("Failed adding %s", (*to_restore)->da->name);
-               return -1;
+               ret = -1;
+               goto free;
        }
        *to_restore = NULL;
 
        return 0;
 }
 
+static inline CC_HINT(always_inline)
+int restore_field_list(request_t *request, fr_pair_list_t *to_restore)
+{
+       fr_pair_t *vp;
+
+       while ((vp = fr_pair_list_head(to_restore))) {
+               fr_pair_remove(to_restore, vp);
+               if (restore_field(request, &vp) < 0) return -1;
+       }
+
+       return 0;
+}
+
+
 /** Add a status code if one doesn't already exist
  *
  */
@@ -364,8 +401,10 @@ RESUME(send_to_client)
                *p_result = RLM_MODULE_FAIL;
                return CALL_RESUME(send_generic);
        }
-       if (unlikely(restore_field(request, &fields->client_id) < 0)) goto fail;
-       if (fields->server_id && unlikely(restore_field(request, &fields->server_id) < 0)) goto fail;
+       if (unlikely(restore_field_list(request, &fields->client_id) < 0)) goto fail;
+       if (unlikely(restore_field_list(request, &fields->server_id) < 0)) goto fail;
+
+       dhcpv6_packet_debug(request, request->reply, &request->reply_pairs, false);
 
        return CALL_RESUME(send_generic);
 }
@@ -454,6 +493,8 @@ RESUME(send_to_relay)
        if (unlikely(restore_field(request, &fields->link_address) < 0)) goto fail;
        if (unlikely(restore_field(request, &fields->peer_address) < 0)) goto fail;
 
+       dhcpv6_packet_debug(request, request->reply, &request->reply_pairs, false);
+
        return CALL_RESUME(send_generic);
 }