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