From: Arran Cudbard-Bell Date: Thu, 4 Nov 2021 03:20:35 +0000 (-0400) Subject: Copy all of the server_id and client_id attributes X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b3ff46ea9b0c5e57520438b6ac6d477c68aacbcd;p=thirdparty%2Ffreeradius-server.git Copy all of the server_id and client_id attributes --- diff --git a/src/lib/eap_aka_sim/encode.c b/src/lib/eap_aka_sim/encode.c index 79f25e7decc..056657f66c2 100644 --- a/src/lib/eap_aka_sim/encode.c +++ b/src/lib/eap_aka_sim/encode.c @@ -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 diff --git a/src/lib/util/pair.c b/src/lib/util/pair.c index 9f8f36feebd..15fbec3089a 100644 --- a/src/lib/util/pair.c +++ b/src/lib/util/pair.c @@ -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 diff --git a/src/lib/util/pair.h b/src/lib/util/pair.h index e477f135729..c3f86554e87 100644 --- a/src/lib/util/pair.h +++ b/src/lib/util/pair.h @@ -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); diff --git a/src/lib/util/pair_tests.c b/src/lib/util/pair_tests.c index 072773ca0e0..60953ef8c9c 100644 --- a/src/lib/util/pair_tests.c +++ b/src/lib/util/pair_tests.c @@ -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); diff --git a/src/process/dhcpv6/base.c b/src/process/dhcpv6/base.c index 6e0776798ea..07685dbdc6e 100644 --- a/src/process/dhcpv6/base.c +++ b/src/process/dhcpv6/base.c @@ -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); }