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