Home | History | Annotate | Line # | Download | only in dns
nsec3param_test.c revision 1.2.4.2
      1 /*	$NetBSD: nsec3param_test.c,v 1.2.4.2 2024/02/29 12:35:39 martin Exp $	*/
      2 
      3 /*
      4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      5  *
      6  * SPDX-License-Identifier: MPL-2.0
      7  *
      8  * This Source Code Form is subject to the terms of the Mozilla Public
      9  * License, v. 2.0. If a copy of the MPL was not distributed with this
     10  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
     11  *
     12  * See the COPYRIGHT file distributed with this work for additional
     13  * information regarding copyright ownership.
     14  */
     15 
     16 #include <inttypes.h>
     17 #include <sched.h> /* IWYU pragma: keep */
     18 #include <setjmp.h>
     19 #include <stdarg.h>
     20 #include <stddef.h>
     21 #include <stdlib.h>
     22 #include <string.h>
     23 #include <unistd.h>
     24 
     25 #define UNIT_TESTING
     26 #include <cmocka.h>
     27 
     28 #include <isc/hex.h>
     29 #include <isc/result.h>
     30 #include <isc/string.h>
     31 #include <isc/util.h>
     32 
     33 #include <dns/db.h>
     34 #include <dns/nsec3.h>
     35 
     36 #include "zone_p.h"
     37 
     38 #include <tests/dns.h>
     39 
     40 #define HASH	1
     41 #define FLAGS	0
     42 #define ITER	5
     43 #define SALTLEN 4
     44 #define SALT	"FEDCBA98"
     45 
     46 /*%
     47  * Structures containing parameters for nsec3param_salttotext_test().
     48  */
     49 typedef struct {
     50 	dns_hash_t hash;
     51 	unsigned char flags;
     52 	dns_iterations_t iterations;
     53 	unsigned char salt_length;
     54 	const char *salt;
     55 } nsec3param_rdata_test_params_t;
     56 
     57 typedef struct {
     58 	nsec3param_rdata_test_params_t lookup;
     59 	nsec3param_rdata_test_params_t expect;
     60 	bool resalt;
     61 	isc_result_t expected_result;
     62 } nsec3param_change_test_params_t;
     63 
     64 static void
     65 decode_salt(const char *string, unsigned char *salt, size_t saltlen) {
     66 	isc_buffer_t buf;
     67 	isc_result_t result;
     68 
     69 	isc_buffer_init(&buf, salt, saltlen);
     70 	result = isc_hex_decodestring(string, &buf);
     71 	assert_int_equal(result, ISC_R_SUCCESS);
     72 }
     73 
     74 static void
     75 copy_params(nsec3param_rdata_test_params_t from, dns_rdata_nsec3param_t *to,
     76 	    unsigned char *saltbuf, size_t saltlen) {
     77 	to->hash = from.hash;
     78 	to->flags = from.flags;
     79 	to->iterations = from.iterations;
     80 	to->salt_length = from.salt_length;
     81 	if (from.salt == NULL) {
     82 		to->salt = NULL;
     83 	} else if (strcmp(from.salt, "-") == 0) {
     84 		DE_CONST("-", to->salt);
     85 	} else {
     86 		decode_salt(from.salt, saltbuf, saltlen);
     87 		to->salt = saltbuf;
     88 	}
     89 }
     90 
     91 static nsec3param_rdata_test_params_t
     92 rdata_fromparams(uint8_t hash, uint8_t flags, uint16_t iter, uint8_t saltlen,
     93 		 const char *salt) {
     94 	nsec3param_rdata_test_params_t nsec3param;
     95 	nsec3param.hash = hash;
     96 	nsec3param.flags = flags;
     97 	nsec3param.iterations = iter;
     98 	nsec3param.salt_length = saltlen;
     99 	nsec3param.salt = salt;
    100 	return (nsec3param);
    101 }
    102 
    103 /*%
    104  * Check whether zone_lookup_nsec3param() finds the correct NSEC3PARAM
    105  * and sets the correct parameters to use in dns_zone_setnsec3param().
    106  */
    107 static void
    108 nsec3param_change_test(const nsec3param_change_test_params_t *test) {
    109 	dns_zone_t *zone = NULL;
    110 	dns_rdata_nsec3param_t param, lookup, expect;
    111 	isc_result_t result;
    112 	unsigned char lookupsalt[255];
    113 	unsigned char expectsalt[255];
    114 	unsigned char saltbuf[255];
    115 
    116 	/*
    117 	 * Prepare a zone along with its signing keys.
    118 	 */
    119 	result = dns_test_makezone("nsec3", &zone, NULL, false);
    120 	assert_int_equal(result, ISC_R_SUCCESS);
    121 
    122 	result = dns_zone_setfile(
    123 		zone, TESTS_DIR "/testdata/nsec3param/nsec3.db.signed",
    124 		dns_masterformat_text, &dns_master_style_default);
    125 	assert_int_equal(result, ISC_R_SUCCESS);
    126 
    127 	result = dns_zone_load(zone, false);
    128 	assert_int_equal(result, ISC_R_SUCCESS);
    129 
    130 	/*
    131 	 * Copy parameters.
    132 	 */
    133 	copy_params(test->lookup, &lookup, lookupsalt, sizeof(lookupsalt));
    134 	copy_params(test->expect, &expect, expectsalt, sizeof(expectsalt));
    135 
    136 	/*
    137 	 * Test dns__zone_lookup_nsec3param().
    138 	 */
    139 	result = dns__zone_lookup_nsec3param(zone, &lookup, &param, saltbuf,
    140 					     test->resalt);
    141 	assert_int_equal(result, test->expected_result);
    142 	assert_int_equal(param.hash, expect.hash);
    143 	assert_int_equal(param.flags, expect.flags);
    144 	assert_int_equal(param.iterations, expect.iterations);
    145 	assert_int_equal(param.salt_length, expect.salt_length);
    146 	assert_non_null(param.salt);
    147 	if (expect.salt != NULL) {
    148 		int ret = memcmp(param.salt, expect.salt, expect.salt_length);
    149 		assert_true(ret == 0);
    150 	} else {
    151 		/*
    152 		 * We don't know what the new salt is, but we can compare it
    153 		 * to the previous salt and test that it has changed.
    154 		 */
    155 		unsigned char salt[SALTLEN];
    156 		int ret;
    157 		decode_salt(SALT, salt, SALTLEN);
    158 		ret = memcmp(param.salt, salt, SALTLEN);
    159 		assert_false(ret == 0);
    160 	}
    161 
    162 	/*
    163 	 * Detach.
    164 	 */
    165 	dns_zone_detach(&zone);
    166 }
    167 
    168 ISC_RUN_TEST_IMPL(nsec3param_change) {
    169 	size_t i;
    170 
    171 	/*
    172 	 * Define tests.
    173 	 */
    174 	const nsec3param_change_test_params_t tests[] = {
    175 		/*
    176 		 * 1. Change nothing (don't care about salt).
    177 		 * This should return ISC_R_SUCCESS because we are already
    178 		 * using these NSEC3 parameters.
    179 		 */
    180 		{ rdata_fromparams(HASH, FLAGS, ITER, SALTLEN, NULL),
    181 		  rdata_fromparams(HASH, FLAGS, ITER, SALTLEN, SALT), false,
    182 		  ISC_R_SUCCESS },
    183 		/*
    184 		 * 2. Change nothing, but force a resalt.
    185 		 * This should change the salt. Set 'expect.salt' to NULL to
    186 		 * test a new salt has been generated.
    187 		 */
    188 		{ rdata_fromparams(HASH, FLAGS, ITER, SALTLEN, NULL),
    189 		  rdata_fromparams(HASH, FLAGS, ITER, SALTLEN, NULL), true,
    190 		  DNS_R_NSEC3RESALT },
    191 		/*
    192 		 * 3. Change iterations.
    193 		 * The NSEC3 paarameters are not found, and there is no
    194 		 * need to resalt because an explicit salt has been set,
    195 		 * and resalt is not enforced.
    196 		 */
    197 		{ rdata_fromparams(HASH, FLAGS, 10, SALTLEN, SALT),
    198 		  rdata_fromparams(HASH, FLAGS, 10, SALTLEN, SALT), false,
    199 		  ISC_R_NOTFOUND },
    200 		/*
    201 		 * 4. Change iterations, don't care about the salt.
    202 		 * We don't care about the salt. Since we need to change the
    203 		 * NSEC3 parameters, we will also resalt.
    204 		 */
    205 		{ rdata_fromparams(HASH, FLAGS, 10, SALTLEN, NULL),
    206 		  rdata_fromparams(HASH, FLAGS, 10, SALTLEN, NULL), false,
    207 		  DNS_R_NSEC3RESALT },
    208 		/*
    209 		 * 5. Change salt length.
    210 		 * Changing salt length means we need to resalt.
    211 		 */
    212 		{ rdata_fromparams(HASH, FLAGS, ITER, 16, NULL),
    213 		  rdata_fromparams(HASH, FLAGS, ITER, 16, NULL), false,
    214 		  DNS_R_NSEC3RESALT },
    215 		/*
    216 		 * 6. Set explicit salt.
    217 		 * A different salt, so the NSEC3 parameters are not found.
    218 		 * No need to resalt because an explicit salt is available.
    219 		 */
    220 		{ rdata_fromparams(HASH, FLAGS, ITER, 4, "12345678"),
    221 		  rdata_fromparams(HASH, FLAGS, ITER, 4, "12345678"), false,
    222 		  ISC_R_NOTFOUND },
    223 		/*
    224 		 * 7. Same salt.
    225 		 * Nothing changed, so expect ISC_R_SUCCESS as a result.
    226 		 */
    227 		{ rdata_fromparams(HASH, FLAGS, ITER, SALTLEN, SALT),
    228 		  rdata_fromparams(HASH, FLAGS, ITER, SALTLEN, SALT), false,
    229 		  ISC_R_SUCCESS },
    230 		/*
    231 		 * 8. Same salt, and force resalt.
    232 		 * Nothing changed, but a resalt is enforced.
    233 		 */
    234 		{ rdata_fromparams(HASH, FLAGS, ITER, SALTLEN, SALT),
    235 		  rdata_fromparams(HASH, FLAGS, ITER, SALTLEN, NULL), true,
    236 		  DNS_R_NSEC3RESALT },
    237 		/*
    238 		 * 9. No salt.
    239 		 * Change parameters to use no salt. These parameters are
    240 		 * not found, and no new salt needs to be generated.
    241 		 */
    242 		{ rdata_fromparams(HASH, FLAGS, ITER, 0, NULL),
    243 		  rdata_fromparams(HASH, FLAGS, ITER, 0, "-"), true,
    244 		  ISC_R_NOTFOUND },
    245 		/*
    246 		 * 10. No salt, explicit.
    247 		 * Same as above, but set no salt explicitly.
    248 		 */
    249 		{ rdata_fromparams(HASH, FLAGS, ITER, 0, "-"),
    250 		  rdata_fromparams(HASH, FLAGS, ITER, 0, "-"), true,
    251 		  ISC_R_NOTFOUND },
    252 	};
    253 
    254 	UNUSED(state);
    255 
    256 	/*
    257 	 * Run tests.
    258 	 */
    259 	for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
    260 		nsec3param_change_test(&tests[i]);
    261 	}
    262 }
    263 
    264 ISC_TEST_LIST_START
    265 ISC_TEST_ENTRY(nsec3param_change)
    266 ISC_TEST_LIST_END
    267 
    268 ISC_TEST_MAIN
    269