1 /*
2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3 *
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 *
8 * See the COPYRIGHT file distributed with this work for additional
9 * information regarding copyright ownership.
10 */
11
12 #if HAVE_CMOCKA
13
14 #include <sched.h> /* IWYU pragma: keep */
15 #include <setjmp.h>
16 #include <stdarg.h>
17 #include <stddef.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <unistd.h>
21
22 #define UNIT_TESTING
23 #include <cmocka.h>
24
25 #include <isc/string.h>
26 #include <isc/util.h>
27
28 #include <dns/db.h>
29 #include <dns/nsec3.h>
30
31 #include "dnstest.h"
32
33 static int
_setup(void ** state)34 _setup(void **state) {
35 isc_result_t result;
36
37 UNUSED(state);
38
39 result = dns_test_begin(NULL, false);
40 assert_int_equal(result, ISC_R_SUCCESS);
41
42 return (0);
43 }
44
45 static int
_teardown(void ** state)46 _teardown(void **state) {
47 UNUSED(state);
48
49 dns_test_end();
50
51 return (0);
52 }
53
54 static void
iteration_test(const char * file,unsigned int expected)55 iteration_test(const char *file, unsigned int expected) {
56 isc_result_t result;
57 dns_db_t *db = NULL;
58 unsigned int iterations;
59
60 result = dns_test_loaddb(&db, dns_dbtype_zone, "test", file);
61 assert_int_equal(result, ISC_R_SUCCESS);
62
63 result = dns_nsec3_maxiterations(db, NULL, dt_mctx, &iterations);
64 assert_int_equal(result, ISC_R_SUCCESS);
65
66 assert_int_equal(iterations, expected);
67
68 dns_db_detach(&db);
69 }
70
71 /*%
72 * Structure containing parameters for nsec3param_salttotext_test().
73 */
74 typedef struct {
75 const char *nsec3param_text; /* NSEC3PARAM RDATA in text form */
76 const char *expected_salt; /* string expected in target buffer */
77 } nsec3param_salttotext_test_params_t;
78
79 /*%
80 * Check whether dns_nsec3param_salttotext() handles supplied text form
81 * NSEC3PARAM RDATA correctly: test whether the result of calling the former is
82 * as expected and whether it properly checks available buffer space.
83 *
84 * Assumes supplied text form NSEC3PARAM RDATA is valid as testing handling of
85 * invalid NSEC3PARAM RDATA is out of scope of this unit test.
86 */
87 static void
nsec3param_salttotext_test(const nsec3param_salttotext_test_params_t * params)88 nsec3param_salttotext_test(const nsec3param_salttotext_test_params_t *params) {
89 dns_rdata_t rdata = DNS_RDATA_INIT;
90 dns_rdata_nsec3param_t nsec3param;
91 unsigned char buf[1024];
92 isc_result_t result;
93 char salt[64];
94 size_t length;
95
96 /*
97 * Prepare a dns_rdata_nsec3param_t structure for testing.
98 */
99 result = dns_test_rdatafromstring(
100 &rdata, dns_rdataclass_in, dns_rdatatype_nsec3param, buf,
101 sizeof(buf), params->nsec3param_text, false);
102 assert_int_equal(result, ISC_R_SUCCESS);
103 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
104 assert_int_equal(result, ISC_R_SUCCESS);
105
106 /*
107 * Check typical use.
108 */
109 result = dns_nsec3param_salttotext(&nsec3param, salt, sizeof(salt));
110 assert_int_equal(result, ISC_R_SUCCESS);
111 assert_string_equal(salt, params->expected_salt);
112
113 /*
114 * Ensure available space in the buffer is checked before the salt is
115 * printed to it and that the amount of space checked for includes the
116 * terminating NULL byte.
117 */
118 length = strlen(params->expected_salt);
119 assert_true(length < sizeof(salt) - 1); /* prevent buffer overwrite */
120 assert_true(length > 0U); /* prevent length underflow */
121
122 result = dns_nsec3param_salttotext(&nsec3param, salt, length - 1);
123 assert_int_equal(result, ISC_R_NOSPACE);
124
125 result = dns_nsec3param_salttotext(&nsec3param, salt, length);
126 assert_int_equal(result, ISC_R_NOSPACE);
127
128 result = dns_nsec3param_salttotext(&nsec3param, salt, length + 1);
129 assert_int_equal(result, ISC_R_SUCCESS);
130 }
131
132 /*
133 * check that appropriate max iterations is returned for different
134 * key size mixes
135 */
136 static void
max_iterations(void ** state)137 max_iterations(void **state) {
138 UNUSED(state);
139
140 iteration_test("testdata/nsec3/1024.db", 150);
141 iteration_test("testdata/nsec3/2048.db", 500);
142 iteration_test("testdata/nsec3/4096.db", 2500);
143 iteration_test("testdata/nsec3/min-1024.db", 150);
144 iteration_test("testdata/nsec3/min-2048.db", 500);
145 }
146
147 /* check dns_nsec3param_salttotext() */
148 static void
nsec3param_salttotext(void ** state)149 nsec3param_salttotext(void **state) {
150 size_t i;
151
152 const nsec3param_salttotext_test_params_t tests[] = {
153 /*
154 * Tests with non-empty salts.
155 */
156 { "0 0 10 0123456789abcdef", "0123456789ABCDEF" },
157 { "0 1 11 0123456789abcdef", "0123456789ABCDEF" },
158 { "1 0 12 42", "42" },
159 { "1 1 13 42", "42" },
160 /*
161 * Test with empty salt.
162 */
163 { "0 0 0 -", "-" },
164 };
165
166 UNUSED(state);
167
168 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
169 nsec3param_salttotext_test(&tests[i]);
170 }
171 }
172
173 int
main(void)174 main(void) {
175 const struct CMUnitTest tests[] = {
176 cmocka_unit_test_setup_teardown(max_iterations, _setup,
177 _teardown),
178 cmocka_unit_test_setup_teardown(nsec3param_salttotext, _setup,
179 _teardown),
180 };
181
182 return (cmocka_run_group_tests(tests, NULL, NULL));
183 }
184
185 #else /* HAVE_CMOCKA */
186
187 #include <stdio.h>
188
189 int
main(void)190 main(void) {
191 printf("1..0 # Skipped: cmocka not available\n");
192 return (0);
193 }
194
195 #endif /* if HAVE_CMOCKA */
196