From f71c032c8a509fa2a23340ffebc08d6196b54127 Mon Sep 17 00:00:00 2001 From: Colin Vidal Date: Tue, 21 Jan 2025 14:05:22 +0100 Subject: [PATCH] add support for dynamic PTR record --- bin/plugins/Makefile.am | 3 + bin/plugins/dynptrr.c | 167 +++++++++++++++++++ bin/tests/system/dynptrr/.gitignore | 3 + bin/tests/system/dynptrr/ns1/example.db | 25 +++ bin/tests/system/dynptrr/ns1/named.conf.in | 37 ++++ bin/tests/system/dynptrr/ns1/root.db | 23 +++ bin/tests/system/dynptrr/setup.sh | 16 ++ bin/tests/system/dynptrr/tests.sh | 49 ++++++ bin/tests/system/dynptrr/tests_sh_dynptrr.py | 23 +++ 9 files changed, 346 insertions(+) create mode 100644 bin/plugins/dynptrr.c create mode 100644 bin/tests/system/dynptrr/.gitignore create mode 100644 bin/tests/system/dynptrr/ns1/example.db create mode 100644 bin/tests/system/dynptrr/ns1/named.conf.in create mode 100644 bin/tests/system/dynptrr/ns1/root.db create mode 100644 bin/tests/system/dynptrr/setup.sh create mode 100644 bin/tests/system/dynptrr/tests.sh create mode 100644 bin/tests/system/dynptrr/tests_sh_dynptrr.py diff --git a/bin/plugins/Makefile.am b/bin/plugins/Makefile.am index 611dd1b1e0..2c3f2d54ba 100644 --- a/bin/plugins/Makefile.am +++ b/bin/plugins/Makefile.am @@ -8,8 +8,11 @@ AM_CPPFLAGS += \ pkglib_LTLIBRARIES = filter-aaaa.la pkglib_LTLIBRARIES += filter-a.la +pkglib_LTLIBRARIES += dynptrr.la filter_aaaa_la_SOURCES = filter-aaaa.c filter_a_la_SOURCES = filter-a.c filter_aaaa_la_LDFLAGS = -avoid-version -module -shared -export-dynamic filter_a_la_LDFLAGS = -avoid-version -module -shared -export-dynamic +dynptrr_la_SOURCES = dynptrr.c +dynptrr_la_LDFLAGS = -avoid-version -module -shared -export-dynamic diff --git a/bin/plugins/dynptrr.c b/bin/plugins/dynptrr.c new file mode 100644 index 0000000000..9da8e6ab71 --- /dev/null +++ b/bin/plugins/dynptrr.c @@ -0,0 +1,167 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include +#include +#include +#include + +typedef struct dynptrr dynptrr_t; +struct dynptrr { + isc_mem_t *mctx; +}; + +static ns_hookresult_t +dynptrr_nxdomain_begin(void *arg, void *cbdata, isc_result_t *resp) { + query_ctx_t *qctx = (query_ctx_t *)arg; + isc_mem_t *mctx = qctx->client->view->mctx; + dynptrr_t *inst = (dynptrr_t *)cbdata; + UNUSED(inst); + + *resp = ISC_R_UNSET; + if (qctx->type != dns_rdatatype_ptr) { + return NS_HOOK_CONTINUE; + } + isc_log_write(NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_HOOKS, + ISC_LOG_DEBUG(1), "dynptrr nxdomain begin"); + + dns_message_t *message = qctx->client->message; + + dns_name_t *name = isc_mem_get(mctx, sizeof(*name)); + dns_rdataset_t *synth = NULL; + dns_rdatalist_t *synthlist = NULL; + dns_rdata_t *synthdata = NULL; + + dns_name_init(name); + dns_name_dup(qctx->client->query.qname, mctx, name); + char n[512]; + dns_name_format(name, n, 512); + isc_log_write(NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_HOOKS, + ISC_LOG_DEBUG(1), "dynptrr %s", n); + + dns_message_gettemprdataset(message, &synth); + dns_rdataset_init(synth); + synth->ttl = 60; + synth->rdclass = dns_rdataclass_in; + synth->type = dns_rdatatype_ptr; + + dns_message_gettemprdatalist(message, &synthlist); + dns_rdatalist_init(synthlist); + synthlist->ttl = 60; + synthlist->rdclass = dns_rdataclass_in; + synthlist->type = dns_rdatatype_ptr; + + dns_message_gettemprdata(message, &synthdata); + dns_rdata_init(synthdata); + synthdata->rdclass = dns_rdataclass_in; + synthdata->type = dns_rdatatype_ptr; + + /* + * It seems that for a ptr type, the data must be the ndata pointer of a + * dns_name_t. (I attempted putting a raw string instead, and it was a + * crash) + */ + synthdata->data = name->ndata; + synthdata->length = name->length; + + ISC_LIST_APPEND(synthlist->rdata, synthdata, link); + + dns_rdatalist_tordataset(synthlist, synth); + dns_rdataset_setownercase(synth, name); + dns_message_addname(message, name, DNS_SECTION_ANSWER); + ISC_LIST_APPEND(name->list, synth, link); + + isc_result_t result = ns_query_done(qctx); + *resp = result; + + /* ------------------------------------------------- */ + +// isc_netaddr_t peeraddr; +// isc_netaddr_fromsockaddr(&peeraddr, &qctx->client->peeraddr); +// +// char createdptrnamed[512]; +// isc_buffer_t createdptrnameb; +// isc_buffer_init(&createdptrnameb, createdptrnamed, 512); +// +// dns_name_t *createdptrname = isc_mem_get(mctx, sizeof(*createdptrname)); +// dns_name_init(createdptrname); +// dns_name_setbuffer(createdptrname, &createdptrnameb); +// isc_result_t r = dns_byaddr_createptrname(&peeraddr, createdptrname); +// isc_log_write(NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_HOOKS, +// ISC_LOG_DEBUG(1), "dynptrr %s", isc_result_totext(r)); +// dns_name_format(createdptrname, n, 512); +// isc_log_write(NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_HOOKS, +// ISC_LOG_DEBUG(1), "dynptrr ptr %s", n); +// isc_mem_put(mctx, createdptrname, sizeof(*createdptrname)); +// + /* ------------------------------------------------- */ + + return NS_HOOK_RETURN; +} + + +void +plugin_destroy(void **instp) { + REQUIRE(instp && *instp); + + dynptrr_t *inst = *instp; + isc_mem_t *mctx = inst->mctx; + isc_mem_put(mctx, inst, sizeof(*inst)); + *instp = NULL; + + printf("dynptrr plugin_destroy\n"); +} + +int +plugin_version(void) { + printf("dynptrr plugin_version\n"); + return NS_PLUGIN_VERSION; +} + +isc_result_t +plugin_register(const char *parameters, const void *cfg, const char *cfg_file, + unsigned long cfg_line, isc_mem_t *mctx, void *actx, + ns_hooktable_t *hooktable, void **instp) { + REQUIRE(cfg); + REQUIRE(mctx); + REQUIRE(actx); + REQUIRE(hooktable); + REQUIRE(instp && *instp == NULL); + + printf("dynptrr plugin_register %s %s %ld\n", parameters, cfg_file, + cfg_line); + + dynptrr_t *inst = isc_mem_get(mctx, sizeof(*inst)); + *inst = (dynptrr_t){ .mctx = mctx }; + *instp = inst; + + const ns_hook_t testhook = { + .action = dynptrr_nxdomain_begin, + .action_data = inst + }; + ns_hook_add(hooktable, mctx, NS_QUERY_NXDOMAIN_BEGIN, &testhook); + + return ISC_R_SUCCESS; +} + +isc_result_t +plugin_check(const char *parameters, const void *cfg, const char *cfg_file, + unsigned long cfg_line, isc_mem_t *mctx, void *actx) { + REQUIRE(cfg); + REQUIRE(mctx); + REQUIRE(actx); + + printf("dynptrr plugin_check %s %s %ld\n", parameters, cfg_file, + cfg_line); + return ISC_R_SUCCESS; +} diff --git a/bin/tests/system/dynptrr/.gitignore b/bin/tests/system/dynptrr/.gitignore new file mode 100644 index 0000000000..75f7b7c462 --- /dev/null +++ b/bin/tests/system/dynptrr/.gitignore @@ -0,0 +1,3 @@ +named.conf +named.memstats +named.run diff --git a/bin/tests/system/dynptrr/ns1/example.db b/bin/tests/system/dynptrr/ns1/example.db new file mode 100644 index 0000000000..a5a7343754 --- /dev/null +++ b/bin/tests/system/dynptrr/ns1/example.db @@ -0,0 +1,25 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, you can obtain one at https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 120 +@ SOA ns.example. hostmaster.ns.example. ( 1 3600 1200 604800 60 ) +@ NS ns +@ MX 10 mx + +ns A 10.53.0.1 + AAAA fd92:7065:b8e:ffff::1 + +a-only NS 1.0.0.4 +aaaa-only AAAA 2001:db8::5 +dual A 1.0.0.6 +dual AAAA 2001:db8::6 +mx A 1.0.0.3 +mx AAAA 2001:db8::3 diff --git a/bin/tests/system/dynptrr/ns1/named.conf.in b/bin/tests/system/dynptrr/ns1/named.conf.in new file mode 100644 index 0000000000..45e26f0d01 --- /dev/null +++ b/bin/tests/system/dynptrr/ns1/named.conf.in @@ -0,0 +1,37 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +options { + query-source address 10.53.0.1; + port @PORT@; + pid-file "named.pid"; + listen-on { 10.53.0.1; }; + listen-on-v6 { fd92:7065:b8e:ffff::1; }; + recursion no; +}; + +plugin query "../../../../plugins/.libs/dynptrr.so" { +}; + +key rndc_key { + secret "1234abcd8765"; + algorithm @DEFAULT_HMAC@; +}; + +controls { + inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; }; +}; + + +zone "." { type primary; file "root.db"; }; +zone "example" { type primary; file "example.db"; }; diff --git a/bin/tests/system/dynptrr/ns1/root.db b/bin/tests/system/dynptrr/ns1/root.db new file mode 100644 index 0000000000..aae7f3d414 --- /dev/null +++ b/bin/tests/system/dynptrr/ns1/root.db @@ -0,0 +1,23 @@ +; Copyright (C) Internet Systems Consortium, Inc. ("ISC") +; +; SPDX-License-Identifier: MPL-2.0 +; +; This Source Code Form is subject to the terms of the Mozilla Public +; License, v. 2.0. If a copy of the MPL was not distributed with this +; file, you can obtain one at https://mozilla.org/MPL/2.0/. +; +; See the COPYRIGHT file distributed with this work for additional +; information regarding copyright ownership. + +$TTL 120 +@ SOA ns.utld hostmaster.ns.utld ( 1 3600 1200 604800 60 ) +@ NS ns.utld +ns.utld A 10.53.0.1 +ns.utld AAAA fd92:7065:b8e:ffff::1 +; + +example NS ns.example +ns.example A 10.53.0.1 +ns.example AAAA fd92:7065:b8e:ffff::1 + +10.53.0.1 PTR ns.example diff --git a/bin/tests/system/dynptrr/setup.sh b/bin/tests/system/dynptrr/setup.sh new file mode 100644 index 0000000000..82240a7c1b --- /dev/null +++ b/bin/tests/system/dynptrr/setup.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, you can obtain one at https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +. ../conf.sh + +copy_setports ns1/named.conf.in ns1/named.conf diff --git a/bin/tests/system/dynptrr/tests.sh b/bin/tests/system/dynptrr/tests.sh new file mode 100644 index 0000000000..d2b5980258 --- /dev/null +++ b/bin/tests/system/dynptrr/tests.sh @@ -0,0 +1,49 @@ +#!/bin/sh + +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, you can obtain one at https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +set -e + +. ../conf.sh + +status=0 +n=0 + +rm -f dig.out.* + +dig_with_opts() { + "${DIG}" -p "${PORT}" "${@}" +} + + +n=$((n + 1)) +echo_i "PTR exists, dynptrr hook is not run ($n)" +ret=0 +dig_with_opts ptr 10.53.0.1 @10.53.0.1 >dig.out.ns1.test$n || ret=1 +grep "status: NOERROR" dig.out.ns1.test${n} >/dev/null || ret=1 +grep "ns.example" dig.out.ns1.test$n >/dev/null || ret=1 +grep "dynptrr nxdomain begin" ns1/named.run && ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +n=$((n + 1)) +echo_i "PTR does not exists, dynptrr hook is run ($n)" +ret=0 +dig_with_opts ptr 10.53.0.2 @10.53.0.1 >dig.out.ns1.test$n || ret=1 +grep "status: NXDOMAIN" dig.out.ns1.test${n} >/dev/null || ret=1 +grep "dynptrr nxdomain begin" ns1/named.run || ret=1 +if [ $ret != 0 ]; then echo_i "failed"; fi +status=$((status + ret)) + +exit 1 +echo_i "exit status: $status" +[ $status -eq 0 ] || exit 1 diff --git a/bin/tests/system/dynptrr/tests_sh_dynptrr.py b/bin/tests/system/dynptrr/tests_sh_dynptrr.py new file mode 100644 index 0000000000..0143945c29 --- /dev/null +++ b/bin/tests/system/dynptrr/tests_sh_dynptrr.py @@ -0,0 +1,23 @@ +# Copyright (C) Internet Systems Consortium, Inc. ("ISC") +# +# SPDX-License-Identifier: MPL-2.0 +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, you can obtain one at https://mozilla.org/MPL/2.0/. +# +# See the COPYRIGHT file distributed with this work for additional +# information regarding copyright ownership. + +import pytest + +pytestmark = pytest.mark.extra_artifacts( + [ + "managed-keys.bind.jnl", + "dig.out.*", + ] +) + + +def test_dynptrr(run_tests_sh): + run_tests_sh()