nsec3_50.c revision 1.1.1.1 1 /* $NetBSD: nsec3_50.c,v 1.1.1.1 2018/08/12 12:08:17 christos Exp $ */
2
3 /*
4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5 *
6 * This Source Code Form is subject to the terms of the Mozilla Public
7 * License, v. 2.0. If a copy of the MPL was not distributed with this
8 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 *
10 * See the COPYRIGHT file distributed with this work for additional
11 * information regarding copyright ownership.
12 */
13
14
15 /*
16 * Copyright (C) 2004 Nominet, Ltd.
17 *
18 * Permission to use, copy, modify, and distribute this software for any
19 * purpose with or without fee is hereby granted, provided that the above
20 * copyright notice and this permission notice appear in all copies.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS" AND NOMINET DISCLAIMS ALL WARRANTIES WITH
23 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
24 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
25 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
26 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
27 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28 * PERFORMANCE OF THIS SOFTWARE.
29 */
30
31 /* RFC 5155 */
32
33 #ifndef RDATA_GENERIC_NSEC3_50_C
34 #define RDATA_GENERIC_NSEC3_50_C
35
36 #include <isc/iterated_hash.h>
37 #include <isc/base32.h>
38
39 #define RRTYPE_NSEC3_ATTRIBUTES DNS_RDATATYPEATTR_DNSSEC
40
41 static inline isc_result_t
42 fromtext_nsec3(ARGS_FROMTEXT) {
43 isc_token_t token;
44 unsigned int flags;
45 unsigned char hashalg;
46 isc_buffer_t b;
47 unsigned char buf[256];
48
49 REQUIRE(type == dns_rdatatype_nsec3);
50
51 UNUSED(type);
52 UNUSED(rdclass);
53 UNUSED(callbacks);
54 UNUSED(origin);
55 UNUSED(options);
56
57 /* Hash. */
58 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
59 ISC_FALSE));
60 RETTOK(dns_hashalg_fromtext(&hashalg, &token.value.as_textregion));
61 RETERR(uint8_tobuffer(hashalg, target));
62
63 /* Flags. */
64 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
65 ISC_FALSE));
66 flags = token.value.as_ulong;
67 if (flags > 255U)
68 RETTOK(ISC_R_RANGE);
69 RETERR(uint8_tobuffer(flags, target));
70
71 /* Iterations. */
72 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
73 ISC_FALSE));
74 if (token.value.as_ulong > 0xffffU)
75 RETTOK(ISC_R_RANGE);
76 RETERR(uint16_tobuffer(token.value.as_ulong, target));
77
78 /* salt */
79 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
80 ISC_FALSE));
81 if (token.value.as_textregion.length > (255*2))
82 RETTOK(DNS_R_TEXTTOOLONG);
83 if (strcmp(DNS_AS_STR(token), "-") == 0) {
84 RETERR(uint8_tobuffer(0, target));
85 } else {
86 RETERR(uint8_tobuffer(strlen(DNS_AS_STR(token)) / 2, target));
87 RETERR(isc_hex_decodestring(DNS_AS_STR(token), target));
88 }
89
90 /*
91 * Next hash a single base32hex word.
92 */
93 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
94 ISC_FALSE));
95 isc_buffer_init(&b, buf, sizeof(buf));
96 RETTOK(isc_base32hexnp_decodestring(DNS_AS_STR(token), &b));
97 if (isc_buffer_usedlength(&b) > 0xffU)
98 RETTOK(ISC_R_RANGE);
99 RETERR(uint8_tobuffer(isc_buffer_usedlength(&b), target));
100 RETERR(mem_tobuffer(target, &buf, isc_buffer_usedlength(&b)));
101
102 return (typemap_fromtext(lexer, target, ISC_TRUE));
103 }
104
105 static inline isc_result_t
106 totext_nsec3(ARGS_TOTEXT) {
107 isc_region_t sr;
108 unsigned int i, j;
109 unsigned char hash;
110 unsigned char flags;
111 char buf[sizeof("TYPE65535")];
112 isc_uint32_t iterations;
113
114 REQUIRE(rdata->type == dns_rdatatype_nsec3);
115 REQUIRE(rdata->length != 0);
116
117 dns_rdata_toregion(rdata, &sr);
118
119 /* Hash */
120 hash = uint8_fromregion(&sr);
121 isc_region_consume(&sr, 1);
122 snprintf(buf, sizeof(buf), "%u ", hash);
123 RETERR(str_totext(buf, target));
124
125 /* Flags */
126 flags = uint8_fromregion(&sr);
127 isc_region_consume(&sr, 1);
128 snprintf(buf, sizeof(buf), "%u ", flags);
129 RETERR(str_totext(buf, target));
130
131 /* Iterations */
132 iterations = uint16_fromregion(&sr);
133 isc_region_consume(&sr, 2);
134 snprintf(buf, sizeof(buf), "%u ", iterations);
135 RETERR(str_totext(buf, target));
136
137 /* Salt */
138 j = uint8_fromregion(&sr);
139 isc_region_consume(&sr, 1);
140 INSIST(j <= sr.length);
141
142 if (j != 0) {
143 i = sr.length;
144 sr.length = j;
145 RETERR(isc_hex_totext(&sr, 1, "", target));
146 sr.length = i - j;
147 } else
148 RETERR(str_totext("-", target));
149
150 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
151 RETERR(str_totext(" (", target));
152 RETERR(str_totext(tctx->linebreak, target));
153
154 /* Next hash */
155 j = uint8_fromregion(&sr);
156 isc_region_consume(&sr, 1);
157 INSIST(j <= sr.length);
158
159 i = sr.length;
160 sr.length = j;
161 RETERR(isc_base32hexnp_totext(&sr, 1, "", target));
162 sr.length = i - j;
163
164 /*
165 * Don't leave a trailing space when there's no typemap present.
166 */
167 if (((tctx->flags & DNS_STYLEFLAG_MULTILINE) == 0) && (sr.length > 0)) {
168 RETERR(str_totext(" ", target));
169 }
170 RETERR(typemap_totext(&sr, tctx, target));
171
172 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
173 RETERR(str_totext(" )", target));
174
175 return (ISC_R_SUCCESS);
176 }
177
178 static inline isc_result_t
179 fromwire_nsec3(ARGS_FROMWIRE) {
180 isc_region_t sr, rr;
181 unsigned int saltlen, hashlen;
182
183 REQUIRE(type == dns_rdatatype_nsec3);
184
185 UNUSED(type);
186 UNUSED(rdclass);
187 UNUSED(options);
188 UNUSED(dctx);
189
190 isc_buffer_activeregion(source, &sr);
191 rr = sr;
192
193 /* hash(1), flags(1), iteration(2), saltlen(1) */
194 if (sr.length < 5U)
195 RETERR(DNS_R_FORMERR);
196 saltlen = sr.base[4];
197 isc_region_consume(&sr, 5);
198
199 if (sr.length < saltlen)
200 RETERR(DNS_R_FORMERR);
201 isc_region_consume(&sr, saltlen);
202
203 if (sr.length < 1U)
204 RETERR(DNS_R_FORMERR);
205 hashlen = sr.base[0];
206 isc_region_consume(&sr, 1);
207
208 if (sr.length < hashlen)
209 RETERR(DNS_R_FORMERR);
210 isc_region_consume(&sr, hashlen);
211
212 RETERR(typemap_test(&sr, ISC_TRUE));
213
214 RETERR(mem_tobuffer(target, rr.base, rr.length));
215 isc_buffer_forward(source, rr.length);
216 return (ISC_R_SUCCESS);
217 }
218
219 static inline isc_result_t
220 towire_nsec3(ARGS_TOWIRE) {
221 isc_region_t sr;
222
223 REQUIRE(rdata->type == dns_rdatatype_nsec3);
224 REQUIRE(rdata->length != 0);
225
226 UNUSED(cctx);
227
228 dns_rdata_toregion(rdata, &sr);
229 return (mem_tobuffer(target, sr.base, sr.length));
230 }
231
232 static inline int
233 compare_nsec3(ARGS_COMPARE) {
234 isc_region_t r1;
235 isc_region_t r2;
236
237 REQUIRE(rdata1->type == rdata2->type);
238 REQUIRE(rdata1->rdclass == rdata2->rdclass);
239 REQUIRE(rdata1->type == dns_rdatatype_nsec3);
240 REQUIRE(rdata1->length != 0);
241 REQUIRE(rdata2->length != 0);
242
243 dns_rdata_toregion(rdata1, &r1);
244 dns_rdata_toregion(rdata2, &r2);
245 return (isc_region_compare(&r1, &r2));
246 }
247
248 static inline isc_result_t
249 fromstruct_nsec3(ARGS_FROMSTRUCT) {
250 dns_rdata_nsec3_t *nsec3 = source;
251 isc_region_t region;
252
253 REQUIRE(type == dns_rdatatype_nsec3);
254 REQUIRE(source != NULL);
255 REQUIRE(nsec3->common.rdtype == type);
256 REQUIRE(nsec3->common.rdclass == rdclass);
257 REQUIRE(nsec3->typebits != NULL || nsec3->len == 0);
258 REQUIRE(nsec3->hash == dns_hash_sha1);
259
260 UNUSED(type);
261 UNUSED(rdclass);
262
263 RETERR(uint8_tobuffer(nsec3->hash, target));
264 RETERR(uint8_tobuffer(nsec3->flags, target));
265 RETERR(uint16_tobuffer(nsec3->iterations, target));
266 RETERR(uint8_tobuffer(nsec3->salt_length, target));
267 RETERR(mem_tobuffer(target, nsec3->salt, nsec3->salt_length));
268 RETERR(uint8_tobuffer(nsec3->next_length, target));
269 RETERR(mem_tobuffer(target, nsec3->next, nsec3->next_length));
270
271 region.base = nsec3->typebits;
272 region.length = nsec3->len;
273 RETERR(typemap_test(®ion, ISC_TRUE));
274 return (mem_tobuffer(target, nsec3->typebits, nsec3->len));
275 }
276
277 static inline isc_result_t
278 tostruct_nsec3(ARGS_TOSTRUCT) {
279 isc_region_t region;
280 dns_rdata_nsec3_t *nsec3 = target;
281
282 REQUIRE(rdata->type == dns_rdatatype_nsec3);
283 REQUIRE(target != NULL);
284 REQUIRE(rdata->length != 0);
285
286 nsec3->common.rdclass = rdata->rdclass;
287 nsec3->common.rdtype = rdata->type;
288 ISC_LINK_INIT(&nsec3->common, link);
289
290 region.base = rdata->data;
291 region.length = rdata->length;
292 nsec3->hash = uint8_consume_fromregion(®ion);
293 nsec3->flags = uint8_consume_fromregion(®ion);
294 nsec3->iterations = uint16_consume_fromregion(®ion);
295
296 nsec3->salt_length = uint8_consume_fromregion(®ion);
297 nsec3->salt = mem_maybedup(mctx, region.base, nsec3->salt_length);
298 if (nsec3->salt == NULL)
299 return (ISC_R_NOMEMORY);
300 isc_region_consume(®ion, nsec3->salt_length);
301
302 nsec3->next_length = uint8_consume_fromregion(®ion);
303 nsec3->next = mem_maybedup(mctx, region.base, nsec3->next_length);
304 if (nsec3->next == NULL)
305 goto cleanup;
306 isc_region_consume(®ion, nsec3->next_length);
307
308 nsec3->len = region.length;
309 nsec3->typebits = mem_maybedup(mctx, region.base, region.length);
310 if (nsec3->typebits == NULL)
311 goto cleanup;
312
313 nsec3->mctx = mctx;
314 return (ISC_R_SUCCESS);
315
316 cleanup:
317 if (nsec3->next != NULL)
318 isc_mem_free(mctx, nsec3->next);
319 isc_mem_free(mctx, nsec3->salt);
320 return (ISC_R_NOMEMORY);
321 }
322
323 static inline void
324 freestruct_nsec3(ARGS_FREESTRUCT) {
325 dns_rdata_nsec3_t *nsec3 = source;
326
327 REQUIRE(source != NULL);
328 REQUIRE(nsec3->common.rdtype == dns_rdatatype_nsec3);
329
330 if (nsec3->mctx == NULL)
331 return;
332
333 if (nsec3->salt != NULL)
334 isc_mem_free(nsec3->mctx, nsec3->salt);
335 if (nsec3->next != NULL)
336 isc_mem_free(nsec3->mctx, nsec3->next);
337 if (nsec3->typebits != NULL)
338 isc_mem_free(nsec3->mctx, nsec3->typebits);
339 nsec3->mctx = NULL;
340 }
341
342 static inline isc_result_t
343 additionaldata_nsec3(ARGS_ADDLDATA) {
344 REQUIRE(rdata->type == dns_rdatatype_nsec3);
345
346 UNUSED(rdata);
347 UNUSED(add);
348 UNUSED(arg);
349
350 return (ISC_R_SUCCESS);
351 }
352
353 static inline isc_result_t
354 digest_nsec3(ARGS_DIGEST) {
355 isc_region_t r;
356
357 REQUIRE(rdata->type == dns_rdatatype_nsec3);
358
359 dns_rdata_toregion(rdata, &r);
360 return ((digest)(arg, &r));
361 }
362
363 static inline isc_boolean_t
364 checkowner_nsec3(ARGS_CHECKOWNER) {
365 unsigned char owner[NSEC3_MAX_HASH_LENGTH];
366 isc_buffer_t buffer;
367 dns_label_t label;
368
369 REQUIRE(type == dns_rdatatype_nsec3);
370
371 UNUSED(type);
372 UNUSED(rdclass);
373 UNUSED(wildcard);
374
375 /*
376 * First label is a base32hex string without padding.
377 */
378 dns_name_getlabel(name, 0, &label);
379 isc_region_consume(&label, 1);
380 isc_buffer_init(&buffer, owner, sizeof(owner));
381 if (isc_base32hexnp_decoderegion(&label, &buffer) == ISC_R_SUCCESS)
382 return (ISC_TRUE);
383
384 return (ISC_FALSE);
385 }
386
387 static inline isc_boolean_t
388 checknames_nsec3(ARGS_CHECKNAMES) {
389
390 REQUIRE(rdata->type == dns_rdatatype_nsec3);
391
392 UNUSED(rdata);
393 UNUSED(owner);
394 UNUSED(bad);
395
396 return (ISC_TRUE);
397 }
398
399 static inline int
400 casecompare_nsec3(ARGS_COMPARE) {
401 return (compare_nsec3(rdata1, rdata2));
402 }
403
404 #endif /* RDATA_GENERIC_NSEC3_50_C */
405