1 /*
2 * Copyright (C) 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: nsec3_50.c,v 1.13 2020/09/14 08:40:43 florian 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_NSEC3_50_C
38 #define RDATA_GENERIC_NSEC3_50_C
39
40 #include <isc/base32.h>
41
42 static inline isc_result_t
totext_nsec3(ARGS_TOTEXT)43 totext_nsec3(ARGS_TOTEXT) {
44 isc_region_t sr;
45 unsigned int i, j;
46 unsigned char hash;
47 unsigned char flags;
48 char buf[sizeof("TYPE65535")];
49 uint32_t iterations;
50
51 REQUIRE(rdata->type == dns_rdatatype_nsec3);
52 REQUIRE(rdata->length != 0);
53
54 dns_rdata_toregion(rdata, &sr);
55
56 /* Hash */
57 hash = uint8_fromregion(&sr);
58 isc_region_consume(&sr, 1);
59 snprintf(buf, sizeof(buf), "%u ", hash);
60 RETERR(isc_str_tobuffer(buf, target));
61
62 /* Flags */
63 flags = uint8_fromregion(&sr);
64 isc_region_consume(&sr, 1);
65 snprintf(buf, sizeof(buf), "%u ", flags);
66 RETERR(isc_str_tobuffer(buf, target));
67
68 /* Iterations */
69 iterations = uint16_fromregion(&sr);
70 isc_region_consume(&sr, 2);
71 snprintf(buf, sizeof(buf), "%u ", iterations);
72 RETERR(isc_str_tobuffer(buf, target));
73
74 /* Salt */
75 j = uint8_fromregion(&sr);
76 isc_region_consume(&sr, 1);
77 INSIST(j <= sr.length);
78
79 if (j != 0) {
80 i = sr.length;
81 sr.length = j;
82 RETERR(isc_hex_totext(&sr, 1, "", target));
83 sr.length = i - j;
84 } else
85 RETERR(isc_str_tobuffer("-", target));
86
87 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
88 RETERR(isc_str_tobuffer(" (", target));
89 RETERR(isc_str_tobuffer(tctx->linebreak, target));
90
91 /* Next hash */
92 j = uint8_fromregion(&sr);
93 isc_region_consume(&sr, 1);
94 INSIST(j <= sr.length);
95
96 i = sr.length;
97 sr.length = j;
98 RETERR(isc_base32hexnp_totext(&sr, 1, "", target));
99 sr.length = i - j;
100
101 /*
102 * Don't leave a trailing space when there's no typemap present.
103 */
104 if (((tctx->flags & DNS_STYLEFLAG_MULTILINE) == 0) && (sr.length > 0)) {
105 RETERR(isc_str_tobuffer(" ", target));
106 }
107 RETERR(typemap_totext(&sr, tctx, target));
108
109 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
110 RETERR(isc_str_tobuffer(" )", target));
111
112 return (ISC_R_SUCCESS);
113 }
114
115 static inline isc_result_t
fromwire_nsec3(ARGS_FROMWIRE)116 fromwire_nsec3(ARGS_FROMWIRE) {
117 isc_region_t sr, rr;
118 unsigned int saltlen, hashlen;
119
120 REQUIRE(type == dns_rdatatype_nsec3);
121
122 UNUSED(type);
123 UNUSED(rdclass);
124 UNUSED(options);
125 UNUSED(dctx);
126
127 isc_buffer_activeregion(source, &sr);
128 rr = sr;
129
130 /* hash(1), flags(1), iteration(2), saltlen(1) */
131 if (sr.length < 5U)
132 return (DNS_R_FORMERR);
133 saltlen = sr.base[4];
134 isc_region_consume(&sr, 5);
135
136 if (sr.length < saltlen)
137 return (DNS_R_FORMERR);
138 isc_region_consume(&sr, saltlen);
139
140 if (sr.length < 1U)
141 return (DNS_R_FORMERR);
142 hashlen = sr.base[0];
143 isc_region_consume(&sr, 1);
144
145 if (sr.length < hashlen)
146 return (DNS_R_FORMERR);
147 isc_region_consume(&sr, hashlen);
148
149 RETERR(typemap_test(&sr, 1));
150
151 RETERR(isc_mem_tobuffer(target, rr.base, rr.length));
152 isc_buffer_forward(source, rr.length);
153 return (ISC_R_SUCCESS);
154 }
155
156 static inline isc_result_t
towire_nsec3(ARGS_TOWIRE)157 towire_nsec3(ARGS_TOWIRE) {
158 isc_region_t sr;
159
160 REQUIRE(rdata->type == dns_rdatatype_nsec3);
161 REQUIRE(rdata->length != 0);
162
163 UNUSED(cctx);
164
165 dns_rdata_toregion(rdata, &sr);
166 return (isc_mem_tobuffer(target, sr.base, sr.length));
167 }
168
169 #define NSEC3_MAX_HASH_LENGTH 155
170 static inline int
checkowner_nsec3(ARGS_CHECKOWNER)171 checkowner_nsec3(ARGS_CHECKOWNER) {
172 unsigned char owner[NSEC3_MAX_HASH_LENGTH];
173 isc_buffer_t buffer;
174 dns_label_t label;
175
176 REQUIRE(type == dns_rdatatype_nsec3);
177
178 UNUSED(type);
179 UNUSED(rdclass);
180 UNUSED(wildcard);
181
182 /*
183 * First label is a base32hex string without padding.
184 */
185 dns_name_getlabel(name, 0, &label);
186 isc_region_consume(&label, 1);
187 isc_buffer_init(&buffer, owner, sizeof(owner));
188 if (isc_base32hexnp_decoderegion(&label, &buffer) == ISC_R_SUCCESS)
189 return (1);
190
191 return (0);
192 }
193
194 #endif /* RDATA_GENERIC_NSEC3_50_C */
195