1 /*
2 * Copyright (C) 2008, 2009, 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: nsec3param_51.c,v 1.7 2009/12/04 21:09:34 marka Exp $ */
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_NSEC3PARAM_51_C
38 #define RDATA_GENERIC_NSEC3PARAM_51_C
39
40 #include <isc/iterated_hash.h>
41 #include <isc/base32.h>
42
43 #define RRTYPE_NSEC3PARAM_ATTRIBUTES (DNS_RDATATYPEATTR_DNSSEC)
44
45 static inline isc_result_t
fromtext_nsec3param(ARGS_FROMTEXT)46 fromtext_nsec3param(ARGS_FROMTEXT) {
47 isc_token_t token;
48 unsigned int flags = 0;
49 unsigned char hashalg;
50
51 REQUIRE(type == dns_rdatatype_nsec3param);
52
53 UNUSED(type);
54 UNUSED(rdclass);
55 UNUSED(callbacks);
56 UNUSED(origin);
57 UNUSED(options);
58
59 /* Hash. */
60 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
61 ISC_FALSE));
62 RETTOK(dns_hashalg_fromtext(&hashalg, &token.value.as_textregion));
63 RETERR(uint8_tobuffer(hashalg, target));
64
65 /* Flags. */
66 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
67 ISC_FALSE));
68 flags = token.value.as_ulong;
69 if (flags > 255U)
70 RETTOK(ISC_R_RANGE);
71 RETERR(uint8_tobuffer(flags, target));
72
73 /* Iterations. */
74 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
75 ISC_FALSE));
76 if (token.value.as_ulong > 0xffffU)
77 RETTOK(ISC_R_RANGE);
78 RETERR(uint16_tobuffer(token.value.as_ulong, target));
79
80 /* Salt. */
81 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
82 ISC_FALSE));
83 if (token.value.as_textregion.length > (255*2))
84 RETTOK(DNS_R_TEXTTOOLONG);
85 if (strcmp(DNS_AS_STR(token), "-") == 0) {
86 RETERR(uint8_tobuffer(0, target));
87 } else {
88 RETERR(uint8_tobuffer(strlen(DNS_AS_STR(token)) / 2, target));
89 RETERR(isc_hex_decodestring(DNS_AS_STR(token), target));
90 }
91
92 return (ISC_R_SUCCESS);
93 }
94
95 static inline isc_result_t
totext_nsec3param(ARGS_TOTEXT)96 totext_nsec3param(ARGS_TOTEXT) {
97 isc_region_t sr;
98 unsigned int i, j;
99 unsigned char hash;
100 unsigned char flags;
101 char buf[sizeof("65535 ")];
102 isc_uint32_t iterations;
103
104 REQUIRE(rdata->type == dns_rdatatype_nsec3param);
105 REQUIRE(rdata->length != 0);
106
107 UNUSED(tctx);
108
109 dns_rdata_toregion(rdata, &sr);
110
111 hash = uint8_fromregion(&sr);
112 isc_region_consume(&sr, 1);
113
114 flags = uint8_fromregion(&sr);
115 isc_region_consume(&sr, 1);
116
117 iterations = uint16_fromregion(&sr);
118 isc_region_consume(&sr, 2);
119
120 sprintf(buf, "%u ", hash);
121 RETERR(str_totext(buf, target));
122
123 sprintf(buf, "%u ", flags);
124 RETERR(str_totext(buf, target));
125
126 sprintf(buf, "%u ", iterations);
127 RETERR(str_totext(buf, target));
128
129 j = uint8_fromregion(&sr);
130 isc_region_consume(&sr, 1);
131 INSIST(j <= sr.length);
132
133 if (j != 0) {
134 i = sr.length;
135 sr.length = j;
136 RETERR(isc_hex_totext(&sr, 1, "", target));
137 sr.length = i - j;
138 } else
139 RETERR(str_totext("-", target));
140
141 return (ISC_R_SUCCESS);
142 }
143
144 static inline isc_result_t
fromwire_nsec3param(ARGS_FROMWIRE)145 fromwire_nsec3param(ARGS_FROMWIRE) {
146 isc_region_t sr, rr;
147 unsigned int saltlen;
148
149 REQUIRE(type == dns_rdatatype_nsec3param);
150
151 UNUSED(type);
152 UNUSED(rdclass);
153 UNUSED(options);
154 UNUSED(dctx);
155
156 isc_buffer_activeregion(source, &sr);
157 rr = sr;
158
159 /* hash(1), flags(1), iterations(2), saltlen(1) */
160 if (sr.length < 5U)
161 RETERR(DNS_R_FORMERR);
162 saltlen = sr.base[4];
163 isc_region_consume(&sr, 5);
164
165 if (sr.length < saltlen)
166 RETERR(DNS_R_FORMERR);
167 isc_region_consume(&sr, saltlen);
168 RETERR(mem_tobuffer(target, rr.base, rr.length));
169 isc_buffer_forward(source, rr.length);
170 return (ISC_R_SUCCESS);
171 }
172
173 static inline isc_result_t
towire_nsec3param(ARGS_TOWIRE)174 towire_nsec3param(ARGS_TOWIRE) {
175 isc_region_t sr;
176
177 REQUIRE(rdata->type == dns_rdatatype_nsec3param);
178 REQUIRE(rdata->length != 0);
179
180 UNUSED(cctx);
181
182 dns_rdata_toregion(rdata, &sr);
183 return (mem_tobuffer(target, sr.base, sr.length));
184 }
185
186 static inline int
compare_nsec3param(ARGS_COMPARE)187 compare_nsec3param(ARGS_COMPARE) {
188 isc_region_t r1;
189 isc_region_t r2;
190
191 REQUIRE(rdata1->type == rdata2->type);
192 REQUIRE(rdata1->rdclass == rdata2->rdclass);
193 REQUIRE(rdata1->type == dns_rdatatype_nsec3param);
194 REQUIRE(rdata1->length != 0);
195 REQUIRE(rdata2->length != 0);
196
197 dns_rdata_toregion(rdata1, &r1);
198 dns_rdata_toregion(rdata2, &r2);
199 return (isc_region_compare(&r1, &r2));
200 }
201
202 static inline isc_result_t
fromstruct_nsec3param(ARGS_FROMSTRUCT)203 fromstruct_nsec3param(ARGS_FROMSTRUCT) {
204 dns_rdata_nsec3param_t *nsec3param = source;
205
206 REQUIRE(type == dns_rdatatype_nsec3param);
207 REQUIRE(source != NULL);
208 REQUIRE(nsec3param->common.rdtype == type);
209 REQUIRE(nsec3param->common.rdclass == rdclass);
210
211 UNUSED(type);
212 UNUSED(rdclass);
213
214 RETERR(uint8_tobuffer(nsec3param->hash, target));
215 RETERR(uint8_tobuffer(nsec3param->flags, target));
216 RETERR(uint16_tobuffer(nsec3param->iterations, target));
217 RETERR(uint8_tobuffer(nsec3param->salt_length, target));
218 RETERR(mem_tobuffer(target, nsec3param->salt,
219 nsec3param->salt_length));
220 return (ISC_R_SUCCESS);
221 }
222
223 static inline isc_result_t
tostruct_nsec3param(ARGS_TOSTRUCT)224 tostruct_nsec3param(ARGS_TOSTRUCT) {
225 isc_region_t region;
226 dns_rdata_nsec3param_t *nsec3param = target;
227
228 REQUIRE(rdata->type == dns_rdatatype_nsec3param);
229 REQUIRE(target != NULL);
230 REQUIRE(rdata->length != 0);
231
232 nsec3param->common.rdclass = rdata->rdclass;
233 nsec3param->common.rdtype = rdata->type;
234 ISC_LINK_INIT(&nsec3param->common, link);
235
236 region.base = rdata->data;
237 region.length = rdata->length;
238 nsec3param->hash = uint8_consume_fromregion(®ion);
239 nsec3param->flags = uint8_consume_fromregion(®ion);
240 nsec3param->iterations = uint16_consume_fromregion(®ion);
241
242 nsec3param->salt_length = uint8_consume_fromregion(®ion);
243 nsec3param->salt = mem_maybedup(mctx, region.base,
244 nsec3param->salt_length);
245 if (nsec3param->salt == NULL)
246 return (ISC_R_NOMEMORY);
247 isc_region_consume(®ion, nsec3param->salt_length);
248
249 nsec3param->mctx = mctx;
250 return (ISC_R_SUCCESS);
251 }
252
253 static inline void
freestruct_nsec3param(ARGS_FREESTRUCT)254 freestruct_nsec3param(ARGS_FREESTRUCT) {
255 dns_rdata_nsec3param_t *nsec3param = source;
256
257 REQUIRE(source != NULL);
258 REQUIRE(nsec3param->common.rdtype == dns_rdatatype_nsec3param);
259
260 if (nsec3param->mctx == NULL)
261 return;
262
263 if (nsec3param->salt != NULL)
264 isc_mem_free(nsec3param->mctx, nsec3param->salt);
265 nsec3param->mctx = NULL;
266 }
267
268 static inline isc_result_t
additionaldata_nsec3param(ARGS_ADDLDATA)269 additionaldata_nsec3param(ARGS_ADDLDATA) {
270 REQUIRE(rdata->type == dns_rdatatype_nsec3param);
271
272 UNUSED(rdata);
273 UNUSED(add);
274 UNUSED(arg);
275
276 return (ISC_R_SUCCESS);
277 }
278
279 static inline isc_result_t
digest_nsec3param(ARGS_DIGEST)280 digest_nsec3param(ARGS_DIGEST) {
281 isc_region_t r;
282
283 REQUIRE(rdata->type == dns_rdatatype_nsec3param);
284
285 dns_rdata_toregion(rdata, &r);
286 return ((digest)(arg, &r));
287 }
288
289 static inline isc_boolean_t
checkowner_nsec3param(ARGS_CHECKOWNER)290 checkowner_nsec3param(ARGS_CHECKOWNER) {
291
292 REQUIRE(type == dns_rdatatype_nsec3param);
293
294 UNUSED(name);
295 UNUSED(type);
296 UNUSED(rdclass);
297 UNUSED(wildcard);
298
299 return (ISC_TRUE);
300 }
301
302 static inline isc_boolean_t
checknames_nsec3param(ARGS_CHECKNAMES)303 checknames_nsec3param(ARGS_CHECKNAMES) {
304
305 REQUIRE(rdata->type == dns_rdatatype_nsec3param);
306
307 UNUSED(rdata);
308 UNUSED(owner);
309 UNUSED(bad);
310
311 return (ISC_TRUE);
312 }
313
314 static inline int
casecompare_nsec3param(ARGS_COMPARE)315 casecompare_nsec3param(ARGS_COMPARE) {
316 return (compare_nsec3param(rdata1, rdata2));
317 }
318
319 #endif /* RDATA_GENERIC_NSEC3PARAM_51_C */
320