2 * Copyright (C) 2009, 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 NONSEC(x) (((x) & DNS_NSEC3FLAG_NONSEC) != 0)
49 #define CHECK(x) do { \
51 if (result != ISC_R_SUCCESS) \
56 * Work out if 'param' should be ignored or not (i.e. it is in the process
59 * Note: we 'belt-and-braces' here by also checking for a CREATE private
60 * record and keep the param record in this case.
64 ignore(dns_rdata_t *param, dns_rdataset_t *privateset) {
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;
74 dns_rdataset_current(privateset, &private);
75 if (!dns_nsec3param_fromprivate(&private, &rdata,
79 * We are going to create a new NSEC3 chain so it
80 * doesn't matter if we are removing this one.
82 if (CREATE(rdata.data[1]))
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]))
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.
95 if (NONSEC(rdata.data[1]))
103 dns_private_chains(dns_db_t *db, dns_dbversion_t *ver,
104 dns_rdatatype_t privatetype,
105 isc_boolean_t *build_nsec, isc_boolean_t *build_nsec3)
108 dns_rdataset_t nsecset, nsec3paramset, privateset;
109 isc_boolean_t nsec3chain;
110 isc_boolean_t signing;
112 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
116 dns_rdataset_init(&nsecset);
117 dns_rdataset_init(&nsec3paramset);
118 dns_rdataset_init(&privateset);
120 CHECK(dns_db_getoriginnode(db, &node));
122 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
123 0, (isc_stdtime_t) 0, &nsecset, NULL);
125 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
128 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
129 0, (isc_stdtime_t) 0, &nsec3paramset,
131 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
134 if (dns_rdataset_isassociated(&nsecset) &&
135 dns_rdataset_isassociated(&nsec3paramset)) {
136 if (build_nsec != NULL)
137 *build_nsec = ISC_TRUE;
138 if (build_nsec3 != NULL)
139 *build_nsec3 = ISC_TRUE;
143 if (privatetype != (dns_rdatatype_t)0) {
144 result = dns_db_findrdataset(db, node, ver, privatetype,
145 0, (isc_stdtime_t) 0,
147 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
152 * Look to see if we also need to be creating a NSEC3 chains.
154 if (dns_rdataset_isassociated(&nsecset)) {
155 if (build_nsec != NULL)
156 *build_nsec = ISC_TRUE;
157 if (build_nsec3 != NULL)
158 *build_nsec3 = ISC_FALSE;
159 if (!dns_rdataset_isassociated(&privateset))
161 for (result = dns_rdataset_first(&privateset);
162 result == ISC_R_SUCCESS;
163 result = dns_rdataset_next(&privateset)) {
164 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
165 dns_rdata_t private = DNS_RDATA_INIT;
166 dns_rdata_t rdata = DNS_RDATA_INIT;
168 dns_rdataset_current(&privateset, &private);
169 if (!dns_nsec3param_fromprivate(&private, &rdata,
172 if (REMOVE(rdata.data[1]))
174 if (build_nsec3 != NULL)
175 *build_nsec3 = ISC_TRUE;
181 if (dns_rdataset_isassociated(&nsec3paramset)) {
182 if (build_nsec3 != NULL)
183 *build_nsec3 = ISC_TRUE;
184 if (build_nsec != NULL)
185 *build_nsec = ISC_FALSE;
186 if (!dns_rdataset_isassociated(&privateset))
189 * If we are in the process of building a new NSEC3 chain
190 * then we don't need to build a NSEC chain.
192 for (result = dns_rdataset_first(&privateset);
193 result == ISC_R_SUCCESS;
194 result = dns_rdataset_next(&privateset)) {
195 dns_rdata_t private = DNS_RDATA_INIT;
196 dns_rdata_t rdata = DNS_RDATA_INIT;
198 dns_rdataset_current(&privateset, &private);
199 if (!dns_nsec3param_fromprivate(&private, &rdata,
202 if (CREATE(rdata.data[1]))
207 * Check to see if there will be a active NSEC3CHAIN once
208 * the changes queued complete.
211 for (result = dns_rdataset_first(&nsec3paramset);
212 result == ISC_R_SUCCESS;
213 result = dns_rdataset_next(&nsec3paramset)) {
214 dns_rdata_t rdata = DNS_RDATA_INIT;
217 * If there is more that one NSEC3 chain present then
218 * we don't need to construct a NSEC chain.
222 dns_rdataset_current(&nsec3paramset, &rdata);
223 if (ignore(&rdata, &privateset))
226 * We still have a good NSEC3 chain or we are
227 * not creating a NSEC chain as NONSEC is set.
233 * The last NSEC3 chain is being removed and does not have
236 if (build_nsec != NULL)
237 *build_nsec = ISC_TRUE;
241 if (build_nsec != NULL)
242 *build_nsec = ISC_FALSE;
243 if (build_nsec3 != NULL)
244 *build_nsec3 = ISC_FALSE;
245 if (!dns_rdataset_isassociated(&privateset))
249 nsec3chain = ISC_FALSE;
251 for (result = dns_rdataset_first(&privateset);
252 result == ISC_R_SUCCESS;
253 result = dns_rdataset_next(&privateset)) {
254 dns_rdata_t rdata = DNS_RDATA_INIT;
255 dns_rdata_t private = DNS_RDATA_INIT;
257 dns_rdataset_current(&privateset, &private);
258 if (!dns_nsec3param_fromprivate(&private, &rdata,
261 * Look for record that says we are signing the
264 if (private.length == 5 && private.data[0] != 0 &&
265 private.data[3] == 0 && private.data[4] == 0)
268 if (CREATE(rdata.data[1]))
269 nsec3chain = ISC_TRUE;
275 if (build_nsec3 != NULL)
276 *build_nsec3 = ISC_TRUE;
278 if (build_nsec != NULL)
279 *build_nsec = ISC_TRUE;
284 result = ISC_R_SUCCESS;
286 if (dns_rdataset_isassociated(&nsecset))
287 dns_rdataset_disassociate(&nsecset);
288 if (dns_rdataset_isassociated(&nsec3paramset))
289 dns_rdataset_disassociate(&nsec3paramset);
290 if (dns_rdataset_isassociated(&privateset))
291 dns_rdataset_disassociate(&privateset);
293 dns_db_detachnode(db, &node);