2 * Copyright (C) 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
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.
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.
21 #include <isc/result.h>
22 #include <isc/string.h>
23 #include <isc/types.h>
24 #include <isc/base64.h>
26 #include <dns/nsec3.h>
27 #include <dns/private.h>
30 * We need to build the relevant chain if there exists a NSEC/NSEC3PARAM
31 * at the apex; normally only one or the other of NSEC/NSEC3PARAM will exist.
33 * If a NSEC3PARAM RRset exists then we will need to build a NSEC chain
34 * if all the NSEC3PARAM records (and associated chains) are slated for
35 * destruction and we have not been told to NOT build the NSEC chain.
37 * If the NSEC set exist then check to see if there is a request to create
40 * If neither NSEC/NSEC3PARAM RRsets exist at the origin and the private
41 * type exists then we need to examine it to determine if NSEC3 chain has
42 * been requested to be built otherwise a NSEC chain needs to be built.
45 #define REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
46 #define CREATE(x) (((x) & DNS_NSEC3FLAG_CREATE) != 0)
47 #define INITIAL(x) (((x) & DNS_NSEC3FLAG_INITIAL) != 0)
48 #define NONSEC(x) (((x) & DNS_NSEC3FLAG_NONSEC) != 0)
50 #define CHECK(x) do { \
52 if (result != ISC_R_SUCCESS) \
57 * Work out if 'param' should be ignored or not (i.e. it is in the process
60 * Note: we 'belt-and-braces' here by also checking for a CREATE private
61 * record and keep the param record in this case.
65 ignore(dns_rdata_t *param, dns_rdataset_t *privateset) {
68 for (result = dns_rdataset_first(privateset);
69 result == ISC_R_SUCCESS;
70 result = dns_rdataset_next(privateset)) {
71 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
72 dns_rdata_t private = DNS_RDATA_INIT;
73 dns_rdata_t rdata = DNS_RDATA_INIT;
75 dns_rdataset_current(privateset, &private);
76 if (!dns_nsec3param_fromprivate(&private, &rdata,
80 * We are going to create a new NSEC3 chain so it
81 * doesn't matter if we are removing this one.
83 if (CREATE(rdata.data[1]))
85 if (rdata.data[0] != param->data[0] ||
86 rdata.data[2] != param->data[2] ||
87 rdata.data[3] != param->data[3] ||
88 rdata.data[4] != param->data[4] ||
89 memcmp(&rdata.data[5], ¶m->data[5], param->data[4]))
92 * The removal of this NSEC3 chain does NOT cause a
93 * NSEC chain to be created so we don't need to tell
94 * the caller that it will be removed.
96 if (NONSEC(rdata.data[1]))
104 dns_private_chains(dns_db_t *db, dns_dbversion_t *ver,
105 dns_rdatatype_t privatetype,
106 isc_boolean_t *build_nsec, isc_boolean_t *build_nsec3)
109 dns_rdataset_t nsecset, nsec3paramset, privateset;
110 isc_boolean_t nsec3chain;
111 isc_boolean_t signing;
113 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
117 dns_rdataset_init(&nsecset);
118 dns_rdataset_init(&nsec3paramset);
119 dns_rdataset_init(&privateset);
121 CHECK(dns_db_getoriginnode(db, &node));
123 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
124 0, (isc_stdtime_t) 0, &nsecset, NULL);
126 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
129 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
130 0, (isc_stdtime_t) 0, &nsec3paramset,
132 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
135 if (dns_rdataset_isassociated(&nsecset) &&
136 dns_rdataset_isassociated(&nsec3paramset)) {
137 if (build_nsec != NULL)
138 *build_nsec = ISC_TRUE;
139 if (build_nsec3 != NULL)
140 *build_nsec3 = ISC_TRUE;
144 if (privatetype != (dns_rdatatype_t)0) {
145 result = dns_db_findrdataset(db, node, ver, privatetype,
146 0, (isc_stdtime_t) 0,
148 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
153 * Look to see if we also need to be creating a NSEC3 chain.
155 if (dns_rdataset_isassociated(&nsecset)) {
156 if (build_nsec != NULL)
157 *build_nsec = ISC_TRUE;
158 if (build_nsec3 != NULL)
159 *build_nsec3 = ISC_FALSE;
160 if (!dns_rdataset_isassociated(&privateset))
162 for (result = dns_rdataset_first(&privateset);
163 result == ISC_R_SUCCESS;
164 result = dns_rdataset_next(&privateset)) {
165 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
166 dns_rdata_t private = DNS_RDATA_INIT;
167 dns_rdata_t rdata = DNS_RDATA_INIT;
169 dns_rdataset_current(&privateset, &private);
170 if (!dns_nsec3param_fromprivate(&private, &rdata,
173 if (REMOVE(rdata.data[1]))
175 if (build_nsec3 != NULL)
176 *build_nsec3 = ISC_TRUE;
182 if (dns_rdataset_isassociated(&nsec3paramset)) {
183 if (build_nsec3 != NULL)
184 *build_nsec3 = ISC_TRUE;
185 if (build_nsec != NULL)
186 *build_nsec = ISC_FALSE;
187 if (!dns_rdataset_isassociated(&privateset))
190 * If we are in the process of building a new NSEC3 chain
191 * then we don't need to build a NSEC chain.
193 for (result = dns_rdataset_first(&privateset);
194 result == ISC_R_SUCCESS;
195 result = dns_rdataset_next(&privateset)) {
196 dns_rdata_t private = DNS_RDATA_INIT;
197 dns_rdata_t rdata = DNS_RDATA_INIT;
199 dns_rdataset_current(&privateset, &private);
200 if (!dns_nsec3param_fromprivate(&private, &rdata,
203 if (CREATE(rdata.data[1]))
208 * Check to see if there will be a active NSEC3CHAIN once
209 * the changes queued complete.
212 for (result = dns_rdataset_first(&nsec3paramset);
213 result == ISC_R_SUCCESS;
214 result = dns_rdataset_next(&nsec3paramset)) {
215 dns_rdata_t rdata = DNS_RDATA_INIT;
218 * If there is more that one NSEC3 chain present then
219 * we don't need to construct a NSEC chain.
223 dns_rdataset_current(&nsec3paramset, &rdata);
224 if (ignore(&rdata, &privateset))
227 * We still have a good NSEC3 chain or we are
228 * not creating a NSEC chain as NONSEC is set.
234 * The last NSEC3 chain is being removed and does not have
237 if (build_nsec != NULL)
238 *build_nsec = ISC_TRUE;
242 if (build_nsec != NULL)
243 *build_nsec = ISC_FALSE;
244 if (build_nsec3 != NULL)
245 *build_nsec3 = ISC_FALSE;
246 if (!dns_rdataset_isassociated(&privateset))
250 nsec3chain = ISC_FALSE;
252 for (result = dns_rdataset_first(&privateset);
253 result == ISC_R_SUCCESS;
254 result = dns_rdataset_next(&privateset)) {
255 dns_rdata_t rdata = DNS_RDATA_INIT;
256 dns_rdata_t private = DNS_RDATA_INIT;
258 dns_rdataset_current(&privateset, &private);
259 if (!dns_nsec3param_fromprivate(&private, &rdata,
262 * Look for record that says we are signing the
265 if (private.length == 5 && private.data[0] != 0 &&
266 private.data[3] == 0 && private.data[4] == 0)
269 if (CREATE(rdata.data[1]))
270 nsec3chain = ISC_TRUE;
276 if (build_nsec3 != NULL)
277 *build_nsec3 = ISC_TRUE;
279 if (build_nsec != NULL)
280 *build_nsec = ISC_TRUE;
285 result = ISC_R_SUCCESS;
287 if (dns_rdataset_isassociated(&nsecset))
288 dns_rdataset_disassociate(&nsecset);
289 if (dns_rdataset_isassociated(&nsec3paramset))
290 dns_rdataset_disassociate(&nsec3paramset);
291 if (dns_rdataset_isassociated(&privateset))
292 dns_rdataset_disassociate(&privateset);
294 dns_db_detachnode(db, &node);
299 dns_private_totext(dns_rdata_t *private, isc_buffer_t *buf) {
302 if (private->length < 5)
303 return (ISC_R_NOTFOUND);
305 if (private->data[0] == 0) {
306 unsigned char nsec3buf[DNS_NSEC3PARAM_BUFFERSIZE];
307 unsigned char newbuf[DNS_NSEC3PARAM_BUFFERSIZE];
308 dns_rdata_t rdata = DNS_RDATA_INIT;
309 dns_rdata_nsec3param_t nsec3param;
310 isc_boolean_t remove, init, nonsec;
313 if (!dns_nsec3param_fromprivate(private, &rdata, nsec3buf,
315 CHECK(ISC_R_FAILURE);
317 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
319 remove = ISC_TF((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0);
320 init = ISC_TF((nsec3param.flags & DNS_NSEC3FLAG_INITIAL) != 0);
321 nonsec = ISC_TF((nsec3param.flags & DNS_NSEC3FLAG_NONSEC) != 0);
323 nsec3param.flags &= ~(DNS_NSEC3FLAG_CREATE|
324 DNS_NSEC3FLAG_REMOVE|
325 DNS_NSEC3FLAG_INITIAL|
326 DNS_NSEC3FLAG_NONSEC);
329 isc_buffer_putstr(buf, "Pending NSEC3 chain ");
331 isc_buffer_putstr(buf, "Removing NSEC3 chain ");
333 isc_buffer_putstr(buf, "Creating NSEC3 chain ");
335 dns_rdata_reset(&rdata);
336 isc_buffer_init(&b, newbuf, sizeof(newbuf));
337 CHECK(dns_rdata_fromstruct(&rdata, dns_rdataclass_in,
338 dns_rdatatype_nsec3param,
341 CHECK(dns_rdata_totext(&rdata, NULL, buf));
343 if (remove && !nonsec)
344 isc_buffer_putstr(buf, " / creating NSEC chain");
345 } else if (private->length == 5) {
346 unsigned char alg = private->data[0];
347 dns_keytag_t keyid = (private->data[2] | private->data[1] << 8);
348 char keybuf[BUFSIZ], algbuf[DNS_SECALG_FORMATSIZE];
349 isc_boolean_t remove = ISC_TF(private->data[3] != 0);
350 isc_boolean_t complete = ISC_TF(private->data[4] != 0);
352 if (remove && complete)
353 isc_buffer_putstr(buf, "Done removing signatures for ");
355 isc_buffer_putstr(buf, "Removing signatures for ");
357 isc_buffer_putstr(buf, "Done signing with ");
359 isc_buffer_putstr(buf, "Signing with ");
361 dns_secalg_format(alg, algbuf, sizeof(algbuf));
362 sprintf(keybuf, "key %d/%s", keyid, algbuf);
363 isc_buffer_putstr(buf, keybuf);
365 return (ISC_R_NOTFOUND);
367 isc_buffer_putuint8(buf, 0);
368 result = ISC_R_SUCCESS;