private.c revision 1.3 1 /* $NetBSD: private.c,v 1.3 2019/01/09 16:55:11 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 #include <config.h>
15
16 #include <stdbool.h>
17
18 #include <isc/base64.h>
19 #include <isc/print.h>
20 #include <isc/result.h>
21 #include <isc/string.h>
22 #include <isc/types.h>
23 #include <isc/util.h>
24
25 #include <dns/nsec3.h>
26 #include <dns/private.h>
27
28 /*
29 * We need to build the relevant chain if there exists a NSEC/NSEC3PARAM
30 * at the apex; normally only one or the other of NSEC/NSEC3PARAM will exist.
31 *
32 * If a NSEC3PARAM RRset exists then we will need to build a NSEC chain
33 * if all the NSEC3PARAM records (and associated chains) are slated for
34 * destruction and we have not been told to NOT build the NSEC chain.
35 *
36 * If the NSEC set exist then check to see if there is a request to create
37 * a NSEC3 chain.
38 *
39 * If neither NSEC/NSEC3PARAM RRsets exist at the origin and the private
40 * type exists then we need to examine it to determine if NSEC3 chain has
41 * been requested to be built otherwise a NSEC chain needs to be built.
42 */
43
44 #define REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
45 #define CREATE(x) (((x) & DNS_NSEC3FLAG_CREATE) != 0)
46 #define INITIAL(x) (((x) & DNS_NSEC3FLAG_INITIAL) != 0)
47 #define NONSEC(x) (((x) & DNS_NSEC3FLAG_NONSEC) != 0)
48
49 #define CHECK(x) do { \
50 result = (x); \
51 if (result != ISC_R_SUCCESS) \
52 goto failure; \
53 } while (/*CONSTCOND*/0)
54
55 /*
56 * Work out if 'param' should be ignored or not (i.e. it is in the process
57 * of being removed).
58 *
59 * Note: we 'belt-and-braces' here by also checking for a CREATE private
60 * record and keep the param record in this case.
61 */
62
63 static bool
64 ignore(dns_rdata_t *param, dns_rdataset_t *privateset) {
65 isc_result_t result;
66
67 for (result = dns_rdataset_first(privateset);
68 result == ISC_R_SUCCESS;
69 result = dns_rdataset_next(privateset)) {
70 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
71 dns_rdata_t private = DNS_RDATA_INIT;
72 dns_rdata_t rdata = DNS_RDATA_INIT;
73
74 dns_rdataset_current(privateset, &private);
75 if (!dns_nsec3param_fromprivate(&private, &rdata,
76 buf, sizeof(buf)))
77 continue;
78 /*
79 * We are going to create a new NSEC3 chain so it
80 * doesn't matter if we are removing this one.
81 */
82 if (CREATE(rdata.data[1]))
83 return (false);
84 if (rdata.data[0] != param->data[0] ||
85 rdata.data[2] != param->data[2] ||
86 rdata.data[3] != param->data[3] ||
87 rdata.data[4] != param->data[4] ||
88 memcmp(&rdata.data[5], ¶m->data[5], param->data[4]))
89 continue;
90 /*
91 * The removal of this NSEC3 chain does NOT cause a
92 * NSEC chain to be created so we don't need to tell
93 * the caller that it will be removed.
94 */
95 if (NONSEC(rdata.data[1]))
96 return (false);
97 return (true);
98 }
99 return (false);
100 }
101
102 isc_result_t
103 dns_private_chains(dns_db_t *db, dns_dbversion_t *ver,
104 dns_rdatatype_t privatetype,
105 bool *build_nsec, bool *build_nsec3)
106 {
107 dns_dbnode_t *node;
108 dns_rdataset_t nsecset, nsec3paramset, privateset;
109 bool nsec3chain;
110 bool signing;
111 isc_result_t result;
112 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
113 unsigned int count;
114
115 node = NULL;
116 dns_rdataset_init(&nsecset);
117 dns_rdataset_init(&nsec3paramset);
118 dns_rdataset_init(&privateset);
119
120 CHECK(dns_db_getoriginnode(db, &node));
121
122 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
123 0, (isc_stdtime_t) 0, &nsecset, NULL);
124
125 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
126 goto failure;
127
128 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
129 0, (isc_stdtime_t) 0, &nsec3paramset,
130 NULL);
131 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
132 goto failure;
133
134 if (dns_rdataset_isassociated(&nsecset) &&
135 dns_rdataset_isassociated(&nsec3paramset)) {
136 if (build_nsec != NULL)
137 *build_nsec = true;
138 if (build_nsec3 != NULL)
139 *build_nsec3 = true;
140 goto success;
141 }
142
143 if (privatetype != (dns_rdatatype_t)0) {
144 result = dns_db_findrdataset(db, node, ver, privatetype,
145 0, (isc_stdtime_t) 0,
146 &privateset, NULL);
147 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
148 goto failure;
149 }
150
151 /*
152 * Look to see if we also need to be creating a NSEC3 chain.
153 */
154 if (dns_rdataset_isassociated(&nsecset)) {
155 if (build_nsec != NULL)
156 *build_nsec = true;
157 if (build_nsec3 != NULL)
158 *build_nsec3 = false;
159 if (!dns_rdataset_isassociated(&privateset))
160 goto success;
161 for (result = dns_rdataset_first(&privateset);
162 result == ISC_R_SUCCESS;
163 result = dns_rdataset_next(&privateset)) {
164 dns_rdata_t private = DNS_RDATA_INIT;
165 dns_rdata_t rdata = DNS_RDATA_INIT;
166
167 dns_rdataset_current(&privateset, &private);
168 if (!dns_nsec3param_fromprivate(&private, &rdata,
169 buf, sizeof(buf)))
170 continue;
171 if (REMOVE(rdata.data[1]))
172 continue;
173 if (build_nsec3 != NULL)
174 *build_nsec3 = true;
175 break;
176 }
177 goto success;
178 }
179
180 if (dns_rdataset_isassociated(&nsec3paramset)) {
181 if (build_nsec3 != NULL)
182 *build_nsec3 = true;
183 if (build_nsec != NULL)
184 *build_nsec = false;
185 if (!dns_rdataset_isassociated(&privateset))
186 goto success;
187 /*
188 * If we are in the process of building a new NSEC3 chain
189 * then we don't need to build a NSEC chain.
190 */
191 for (result = dns_rdataset_first(&privateset);
192 result == ISC_R_SUCCESS;
193 result = dns_rdataset_next(&privateset)) {
194 dns_rdata_t private = DNS_RDATA_INIT;
195 dns_rdata_t rdata = DNS_RDATA_INIT;
196
197 dns_rdataset_current(&privateset, &private);
198 if (!dns_nsec3param_fromprivate(&private, &rdata,
199 buf, sizeof(buf)))
200 continue;
201 if (CREATE(rdata.data[1]))
202 goto success;
203 }
204
205 /*
206 * Check to see if there will be a active NSEC3CHAIN once
207 * the changes queued complete.
208 */
209 count = 0;
210 for (result = dns_rdataset_first(&nsec3paramset);
211 result == ISC_R_SUCCESS;
212 result = dns_rdataset_next(&nsec3paramset)) {
213 dns_rdata_t rdata = DNS_RDATA_INIT;
214
215 /*
216 * If there is more that one NSEC3 chain present then
217 * we don't need to construct a NSEC chain.
218 */
219 if (++count > 1)
220 goto success;
221 dns_rdataset_current(&nsec3paramset, &rdata);
222 if (ignore(&rdata, &privateset))
223 continue;
224 /*
225 * We still have a good NSEC3 chain or we are
226 * not creating a NSEC chain as NONSEC is set.
227 */
228 goto success;
229 }
230
231 /*
232 * The last NSEC3 chain is being removed and does not have
233 * have NONSEC set.
234 */
235 if (build_nsec != NULL)
236 *build_nsec = true;
237 goto success;
238 }
239
240 if (build_nsec != NULL)
241 *build_nsec = false;
242 if (build_nsec3 != NULL)
243 *build_nsec3 = false;
244 if (!dns_rdataset_isassociated(&privateset))
245 goto success;
246
247 signing = false;
248 nsec3chain = false;
249
250 for (result = dns_rdataset_first(&privateset);
251 result == ISC_R_SUCCESS;
252 result = dns_rdataset_next(&privateset)) {
253 dns_rdata_t rdata = DNS_RDATA_INIT;
254 dns_rdata_t private = DNS_RDATA_INIT;
255
256 dns_rdataset_current(&privateset, &private);
257 if (!dns_nsec3param_fromprivate(&private, &rdata,
258 buf, sizeof(buf))) {
259 /*
260 * Look for record that says we are signing the
261 * zone with a key.
262 */
263 if (private.length == 5 && private.data[0] != 0 &&
264 private.data[3] == 0 && private.data[4] == 0)
265 signing = true;
266 } else {
267 if (CREATE(rdata.data[1]))
268 nsec3chain = true;
269 }
270 }
271
272 if (signing) {
273 if (nsec3chain) {
274 if (build_nsec3 != NULL)
275 *build_nsec3 = true;
276 } else {
277 if (build_nsec != NULL)
278 *build_nsec = true;
279 }
280 }
281
282 success:
283 result = ISC_R_SUCCESS;
284 failure:
285 if (dns_rdataset_isassociated(&nsecset))
286 dns_rdataset_disassociate(&nsecset);
287 if (dns_rdataset_isassociated(&nsec3paramset))
288 dns_rdataset_disassociate(&nsec3paramset);
289 if (dns_rdataset_isassociated(&privateset))
290 dns_rdataset_disassociate(&privateset);
291 if (node != NULL)
292 dns_db_detachnode(db, &node);
293 return (result);
294 }
295
296 isc_result_t
297 dns_private_totext(dns_rdata_t *private, isc_buffer_t *buf) {
298 isc_result_t result;
299
300 if (private->length < 5)
301 return (ISC_R_NOTFOUND);
302
303 if (private->data[0] == 0) {
304 unsigned char nsec3buf[DNS_NSEC3PARAM_BUFFERSIZE];
305 unsigned char newbuf[DNS_NSEC3PARAM_BUFFERSIZE];
306 dns_rdata_t rdata = DNS_RDATA_INIT;
307 dns_rdata_nsec3param_t nsec3param;
308 bool del, init, nonsec;
309 isc_buffer_t b;
310
311 if (!dns_nsec3param_fromprivate(private, &rdata, nsec3buf,
312 sizeof(nsec3buf)))
313 CHECK(ISC_R_FAILURE);
314
315 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
316
317 del = ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0);
318 init = ((nsec3param.flags & DNS_NSEC3FLAG_INITIAL) != 0);
319 nonsec = ((nsec3param.flags & DNS_NSEC3FLAG_NONSEC) != 0);
320
321 nsec3param.flags &= ~(DNS_NSEC3FLAG_CREATE|
322 DNS_NSEC3FLAG_REMOVE|
323 DNS_NSEC3FLAG_INITIAL|
324 DNS_NSEC3FLAG_NONSEC);
325
326 if (init)
327 isc_buffer_putstr(buf, "Pending NSEC3 chain ");
328 else if (del)
329 isc_buffer_putstr(buf, "Removing NSEC3 chain ");
330 else
331 isc_buffer_putstr(buf, "Creating NSEC3 chain ");
332
333 dns_rdata_reset(&rdata);
334 isc_buffer_init(&b, newbuf, sizeof(newbuf));
335 CHECK(dns_rdata_fromstruct(&rdata, dns_rdataclass_in,
336 dns_rdatatype_nsec3param,
337 &nsec3param, &b));
338
339 CHECK(dns_rdata_totext(&rdata, NULL, buf));
340
341 if (del && !nonsec)
342 isc_buffer_putstr(buf, " / creating NSEC chain");
343 } else if (private->length == 5) {
344 unsigned char alg = private->data[0];
345 dns_keytag_t keyid = (private->data[2] | private->data[1] << 8);
346 char keybuf[BUFSIZ], algbuf[DNS_SECALG_FORMATSIZE];
347 bool del = private->data[3];
348 bool complete = private->data[4];
349
350 if (del && complete)
351 isc_buffer_putstr(buf, "Done removing signatures for ");
352 else if (del)
353 isc_buffer_putstr(buf, "Removing signatures for ");
354 else if (complete)
355 isc_buffer_putstr(buf, "Done signing with ");
356 else
357 isc_buffer_putstr(buf, "Signing with ");
358
359 dns_secalg_format(alg, algbuf, sizeof(algbuf));
360 snprintf(keybuf, sizeof(keybuf), "key %d/%s", keyid, algbuf);
361 isc_buffer_putstr(buf, keybuf);
362 } else
363 return (ISC_R_NOTFOUND);
364
365 isc_buffer_putuint8(buf, 0);
366 result = ISC_R_SUCCESS;
367 failure:
368 return (result);
369 }
370