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, ¶m, 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