2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-22 01:59:26 +00:00
bind/tests/dns/sigs_test.c
Ondřej Surý ef7aba7072
Remove OpenSSL Engine support
The OpenSSL 1.x Engines support has been deprecated in the OpenSSL 3.x
and is going to be removed.  Remove the OpenSSL Engine support in favor
of OpenSSL Providers.
2024-08-06 15:17:48 +02:00

444 lines
12 KiB
C

/*
* 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 <inttypes.h>
#include <sched.h> /* IWYU pragma: keep */
#include <setjmp.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define UNIT_TESTING
#include <cmocka.h>
#include <isc/buffer.h>
#include <isc/list.h>
#include <isc/region.h>
#include <isc/result.h>
#include <isc/stdtime.h>
#include <isc/types.h>
#include <isc/util.h>
#include <dns/db.h>
#include <dns/diff.h>
#include <dns/dnssec.h>
#include <dns/fixedname.h>
#include <dns/name.h>
#include <dns/rdata.h>
#include <dns/rdatastruct.h>
#include <dns/rdatatype.h>
#include <dns/types.h>
#include <dns/zone.h>
#include <dst/dst.h>
#include "zone_p.h"
#include <tests/dns.h>
/*%
* Structure characterizing a single diff tuple in the dns_diff_t structure
* prepared by dns__zone_updatesigs().
*/
typedef struct {
dns_diffop_t op;
const char *owner;
dns_ttl_t ttl;
const char *type;
} zonediff_t;
#define ZONEDIFF_SENTINEL { 0, NULL, 0, NULL }
/*%
* Structure defining a dns__zone_updatesigs() test.
*/
typedef struct {
const char *description; /* test description */
const zonechange_t *changes; /* array of "raw" zone changes */
const zonediff_t *zonediff; /* array of "processed" zone changes
* */
} updatesigs_test_params_t;
static int
setup_test(void **state) {
isc_result_t result;
UNUSED(state);
result = dst_lib_init(mctx);
if (result != ISC_R_SUCCESS) {
return (1);
}
return (0);
}
static int
teardown_test(void **state) {
UNUSED(state);
dst_lib_destroy();
return (0);
}
/*%
* Check whether the 'found' tuple matches the 'expected' tuple. 'found' is
* the 'index'th tuple output by dns__zone_updatesigs() in test 'test'.
*/
static void
compare_tuples(const zonediff_t *expected, dns_difftuple_t *found,
size_t index) {
char found_covers[DNS_RDATATYPE_FORMATSIZE] = {};
char found_type[DNS_RDATATYPE_FORMATSIZE] = {};
char found_name[DNS_NAME_FORMATSIZE];
isc_consttextregion_t typeregion;
dns_fixedname_t expected_fname;
dns_rdatatype_t expected_type;
dns_name_t *expected_name;
dns_rdata_rrsig_t rrsig;
isc_buffer_t typebuf;
isc_result_t result;
REQUIRE(expected != NULL);
REQUIRE(found != NULL);
REQUIRE(index > 0);
/*
* Check operation.
*/
assert_int_equal(expected->op, found->op);
/*
* Check owner name.
*/
expected_name = dns_fixedname_initname(&expected_fname);
result = dns_name_fromstring(expected_name, expected->owner,
dns_rootname, 0, mctx);
assert_int_equal(result, ISC_R_SUCCESS);
dns_name_format(&found->name, found_name, sizeof(found_name));
assert_true(dns_name_equal(expected_name, &found->name));
/*
* Check TTL.
*/
assert_int_equal(expected->ttl, found->ttl);
/*
* Parse expected RR type.
*/
typeregion.base = expected->type;
typeregion.length = strlen(expected->type);
result = dns_rdatatype_fromtext(&expected_type,
(isc_textregion_t *)&typeregion);
assert_int_equal(result, ISC_R_SUCCESS);
/*
* Format found RR type for reporting purposes.
*/
isc_buffer_init(&typebuf, found_type, sizeof(found_type));
result = dns_rdatatype_totext(found->rdata.type, &typebuf);
assert_int_equal(result, ISC_R_SUCCESS);
/*
* Check RR type.
*/
switch (expected->op) {
case DNS_DIFFOP_ADDRESIGN:
case DNS_DIFFOP_DELRESIGN:
/*
* Found tuple must be of type RRSIG.
*/
assert_int_equal(found->rdata.type, dns_rdatatype_rrsig);
if (found->rdata.type != dns_rdatatype_rrsig) {
break;
}
/*
* The signature must cover an RRset of type 'expected->type'.
*/
result = dns_rdata_tostruct(&found->rdata, &rrsig, NULL);
assert_int_equal(result, ISC_R_SUCCESS);
isc_buffer_init(&typebuf, found_covers, sizeof(found_covers));
result = dns_rdatatype_totext(rrsig.covered, &typebuf);
assert_int_equal(result, ISC_R_SUCCESS);
assert_int_equal(expected_type, rrsig.covered);
break;
default:
/*
* Found tuple must be of type 'expected->type'.
*/
assert_int_equal(expected_type, found->rdata.type);
break;
}
}
/*%
* Perform a single dns__zone_updatesigs() test defined in 'test'. All other
* arguments are expected to remain constant between subsequent invocations of
* this function.
*/
static void
updatesigs_test(const updatesigs_test_params_t *test, dns_zone_t *zone,
dns_db_t *db, dst_key_t *zone_keys[], unsigned int nkeys,
isc_stdtime_t now) {
size_t tuples_expected, tuples_found, index;
dns_dbversion_t *version = NULL;
dns_diff_t raw_diff, zone_diff;
const zonediff_t *expected;
dns_difftuple_t *found;
isc_result_t result;
dns__zonediff_t zonediff = {
.diff = &zone_diff,
.offline = false,
};
REQUIRE(test != NULL);
REQUIRE(test->description != NULL);
REQUIRE(test->changes != NULL);
REQUIRE(zone != NULL);
REQUIRE(db != NULL);
REQUIRE(zone_keys != NULL);
/*
* Create a new version of the zone's database.
*/
result = dns_db_newversion(db, &version);
assert_int_equal(result, ISC_R_SUCCESS);
/*
* Create a diff representing the supplied changes.
*/
result = dns_test_difffromchanges(&raw_diff, test->changes, false);
assert_int_equal(result, ISC_R_SUCCESS);
/*
* Apply the "raw" diff to the new version of the zone's database as
* this is what dns__zone_updatesigs() expects to happen before it is
* called.
*/
dns_diff_apply(&raw_diff, db, version);
/*
* Initialize the structure dns__zone_updatesigs() will modify.
*/
dns_diff_init(mctx, &zone_diff);
/*
* Check whether dns__zone_updatesigs() behaves as expected.
*/
result = dns__zone_updatesigs(&raw_diff, db, version, zone_keys, nkeys,
zone, now - 3600, now + 3600, 0, now,
&zonediff);
assert_int_equal(result, ISC_R_SUCCESS);
assert_true(ISC_LIST_EMPTY(raw_diff.tuples));
assert_false(ISC_LIST_EMPTY(zone_diff.tuples));
/*
* Ensure that the number of tuples in the zone diff is as expected.
*/
tuples_expected = 0;
for (expected = test->zonediff; expected->owner != NULL; expected++) {
tuples_expected++;
}
tuples_found = 0;
for (found = ISC_LIST_HEAD(zone_diff.tuples); found != NULL;
found = ISC_LIST_NEXT(found, link))
{
tuples_found++;
}
assert_int_equal(tuples_expected, tuples_found);
/*
* Ensure that every tuple in the zone diff matches expectations.
*/
expected = test->zonediff;
index = 1;
for (found = ISC_LIST_HEAD(zone_diff.tuples); found != NULL;
found = ISC_LIST_NEXT(found, link))
{
compare_tuples(expected, found, index);
expected++;
index++;
}
/*
* Apply changes to zone database contents and clean up.
*/
dns_db_closeversion(db, &version, true);
dns_diff_clear(&zone_diff);
dns_diff_clear(&raw_diff);
}
/* dns__zone_updatesigs() tests */
ISC_RUN_TEST_IMPL(updatesigs_next) {
dst_key_t *zone_keys[DNS_MAXZONEKEYS];
dns_zone_t *zone = NULL;
dns_db_t *db = NULL;
isc_result_t result;
unsigned int nkeys;
isc_stdtime_t now = isc_stdtime_now();
size_t i;
UNUSED(state);
/*
* Prepare a zone along with its signing keys.
*/
result = dns_test_makezone("example", &zone, NULL, false);
assert_int_equal(result, ISC_R_SUCCESS);
result = dns_test_loaddb(&db, dns_dbtype_zone, "example",
"testdata/master/master18.data");
assert_int_equal(result, DNS_R_SEENINCLUDE);
result = dns_zone_setkeydirectory(zone, TESTS_DIR "/testkeys");
assert_int_equal(result, ISC_R_SUCCESS);
result = dns_zone_findkeys(zone, db, NULL, now, mctx, DNS_MAXZONEKEYS,
zone_keys, &nkeys);
assert_int_equal(result, ISC_R_SUCCESS);
assert_int_equal(nkeys, 2);
/*
* Define the tests to be run. Note that changes to zone database
* contents introduced by each test are preserved between tests.
*/
const zonechange_t changes_add[] = {
{ DNS_DIFFOP_ADD, "foo.example", 300, "TXT", "foo" },
{ DNS_DIFFOP_ADD, "bar.example", 600, "TXT", "bar" },
ZONECHANGE_SENTINEL,
};
const zonediff_t zonediff_add[] = {
{ DNS_DIFFOP_ADDRESIGN, "foo.example", 300, "TXT" },
{ DNS_DIFFOP_ADD, "foo.example", 300, "TXT" },
{ DNS_DIFFOP_ADDRESIGN, "bar.example", 600, "TXT" },
{ DNS_DIFFOP_ADD, "bar.example", 600, "TXT" },
ZONEDIFF_SENTINEL,
};
const updatesigs_test_params_t test_add = {
.description = "add new RRsets",
.changes = changes_add,
.zonediff = zonediff_add,
};
const zonechange_t changes_append[] = {
{ DNS_DIFFOP_ADD, "foo.example", 300, "TXT", "foo1" },
{ DNS_DIFFOP_ADD, "foo.example", 300, "TXT", "foo2" },
ZONECHANGE_SENTINEL,
};
const zonediff_t zonediff_append[] = {
{ DNS_DIFFOP_DELRESIGN, "foo.example", 300, "TXT" },
{ DNS_DIFFOP_ADDRESIGN, "foo.example", 300, "TXT" },
{ DNS_DIFFOP_ADD, "foo.example", 300, "TXT" },
{ DNS_DIFFOP_ADD, "foo.example", 300, "TXT" },
ZONEDIFF_SENTINEL,
};
const updatesigs_test_params_t test_append = {
.description = "append multiple RRs to an existing RRset",
.changes = changes_append,
.zonediff = zonediff_append,
};
const zonechange_t changes_replace[] = {
{ DNS_DIFFOP_DEL, "bar.example", 600, "TXT", "bar" },
{ DNS_DIFFOP_ADD, "bar.example", 600, "TXT", "rab" },
ZONECHANGE_SENTINEL,
};
const zonediff_t zonediff_replace[] = {
{ DNS_DIFFOP_DELRESIGN, "bar.example", 600, "TXT" },
{ DNS_DIFFOP_ADDRESIGN, "bar.example", 600, "TXT" },
{ DNS_DIFFOP_DEL, "bar.example", 600, "TXT" },
{ DNS_DIFFOP_ADD, "bar.example", 600, "TXT" },
ZONEDIFF_SENTINEL,
};
const updatesigs_test_params_t test_replace = {
.description = "replace an existing RRset",
.changes = changes_replace,
.zonediff = zonediff_replace,
};
const zonechange_t changes_delete[] = {
{ DNS_DIFFOP_DEL, "bar.example", 600, "TXT", "rab" },
ZONECHANGE_SENTINEL,
};
const zonediff_t zonediff_delete[] = {
{ DNS_DIFFOP_DELRESIGN, "bar.example", 600, "TXT" },
{ DNS_DIFFOP_DEL, "bar.example", 600, "TXT" },
ZONEDIFF_SENTINEL,
};
const updatesigs_test_params_t test_delete = {
.description = "delete an existing RRset",
.changes = changes_delete,
.zonediff = zonediff_delete,
};
const zonechange_t changes_mixed[] = {
{ DNS_DIFFOP_ADD, "baz.example", 900, "TXT", "baz1" },
{ DNS_DIFFOP_ADD, "baz.example", 900, "A", "127.0.0.1" },
{ DNS_DIFFOP_ADD, "baz.example", 900, "TXT", "baz2" },
{ DNS_DIFFOP_ADD, "baz.example", 900, "AAAA", "::1" },
ZONECHANGE_SENTINEL,
};
const zonediff_t zonediff_mixed[] = {
{ DNS_DIFFOP_ADDRESIGN, "baz.example", 900, "TXT" },
{ DNS_DIFFOP_ADD, "baz.example", 900, "TXT" },
{ DNS_DIFFOP_ADD, "baz.example", 900, "TXT" },
{ DNS_DIFFOP_ADDRESIGN, "baz.example", 900, "A" },
{ DNS_DIFFOP_ADD, "baz.example", 900, "A" },
{ DNS_DIFFOP_ADDRESIGN, "baz.example", 900, "AAAA" },
{ DNS_DIFFOP_ADD, "baz.example", 900, "AAAA" },
ZONEDIFF_SENTINEL,
};
const updatesigs_test_params_t test_mixed = {
.description = "add different RRsets with common owner name",
.changes = changes_mixed,
.zonediff = zonediff_mixed,
};
const updatesigs_test_params_t *tests[] = {
&test_add, &test_append, &test_replace,
&test_delete, &test_mixed,
};
/*
* Run tests.
*/
for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
updatesigs_test(tests[i], zone, db, zone_keys, nkeys, now);
}
/*
* Clean up.
*/
for (i = 0; i < nkeys; i++) {
dst_key_free(&zone_keys[i]);
}
dns_db_detach(&db);
dns_zone_detach(&zone);
}
ISC_TEST_LIST_START
ISC_TEST_ENTRY_CUSTOM(updatesigs_next, setup_test, teardown_test)
ISC_TEST_LIST_END
ISC_TEST_MAIN