4 * Copyright (C) 2009 Internet Systems Consortium, Inc. ("ISC")
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
19 /* Id: private.c,v 1.3 2009/10/09 23:48:09 tbox Exp */
23 #include <isc/result.h>
24 #include <isc/string.h>
25 #include <isc/types.h>
26 #include <isc/base64.h>
28 #include <dns/nsec3.h>
29 #include <dns/private.h>
32 * We need to build the relevant chain if there exists a NSEC/NSEC3PARAM
33 * at the apex; normally only one or the other of NSEC/NSEC3PARAM will exist.
35 * If a NSEC3PARAM RRset exists then we will need to build a NSEC chain
36 * if all the NSEC3PARAM records (and associated chains) are slated for
37 * destruction and we have not been told to NOT build the NSEC chain.
39 * If the NSEC set exist then check to see if there is a request to create
42 * If neither NSEC/NSEC3PARAM RRsets exist at the origin and the private
43 * type exists then we need to examine it to determine if NSEC3 chain has
44 * been requested to be built otherwise a NSEC chain needs to be built.
47 #define REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
48 #define CREATE(x) (((x) & DNS_NSEC3FLAG_CREATE) != 0)
49 #define NONSEC(x) (((x) & DNS_NSEC3FLAG_NONSEC) != 0)
51 #define CHECK(x) do { \
53 if (result != ISC_R_SUCCESS) \
58 * Work out if 'param' should be ignored or not (i.e. it is in the process
61 * Note: we 'belt-and-braces' here by also checking for a CREATE private
62 * record and keep the param record in this case.
66 ignore(dns_rdata_t
*param
, dns_rdataset_t
*privateset
) {
69 for (result
= dns_rdataset_first(privateset
);
70 result
== ISC_R_SUCCESS
;
71 result
= dns_rdataset_next(privateset
)) {
72 unsigned char buf
[DNS_NSEC3PARAM_BUFFERSIZE
];
73 dns_rdata_t
private = DNS_RDATA_INIT
;
74 dns_rdata_t rdata
= DNS_RDATA_INIT
;
76 dns_rdataset_current(privateset
, &private);
77 if (!dns_nsec3param_fromprivate(&private, &rdata
,
81 * We are going to create a new NSEC3 chain so it
82 * doesn't matter if we are removing this one.
84 if (CREATE(rdata
.data
[1]))
86 if (rdata
.data
[0] != param
->data
[0] ||
87 rdata
.data
[2] != param
->data
[2] ||
88 rdata
.data
[3] != param
->data
[3] ||
89 rdata
.data
[4] != param
->data
[4] ||
90 memcmp(&rdata
.data
[5], ¶m
->data
[5], param
->data
[4]))
93 * The removal of this NSEC3 chain does NOT cause a
94 * NSEC chain to be created so we don't need to tell
95 * the caller that it will be removed.
97 if (NONSEC(rdata
.data
[1]))
105 dns_private_chains(dns_db_t
*db
, dns_dbversion_t
*ver
,
106 dns_rdatatype_t privatetype
,
107 isc_boolean_t
*build_nsec
, isc_boolean_t
*build_nsec3
)
110 dns_rdataset_t nsecset
, nsec3paramset
, privateset
;
111 isc_boolean_t nsec3chain
;
112 isc_boolean_t signing
;
114 unsigned char buf
[DNS_NSEC3PARAM_BUFFERSIZE
];
118 dns_rdataset_init(&nsecset
);
119 dns_rdataset_init(&nsec3paramset
);
120 dns_rdataset_init(&privateset
);
122 CHECK(dns_db_getoriginnode(db
, &node
));
124 result
= dns_db_findrdataset(db
, node
, ver
, dns_rdatatype_nsec
,
125 0, (isc_stdtime_t
) 0, &nsecset
, NULL
);
127 if (result
!= ISC_R_SUCCESS
&& result
!= ISC_R_NOTFOUND
)
130 result
= dns_db_findrdataset(db
, node
, ver
, dns_rdatatype_nsec3param
,
131 0, (isc_stdtime_t
) 0, &nsec3paramset
,
133 if (result
!= ISC_R_SUCCESS
&& result
!= ISC_R_NOTFOUND
)
136 if (dns_rdataset_isassociated(&nsecset
) &&
137 dns_rdataset_isassociated(&nsec3paramset
)) {
138 if (build_nsec
!= NULL
)
139 *build_nsec
= ISC_TRUE
;
140 if (build_nsec3
!= NULL
)
141 *build_nsec3
= ISC_TRUE
;
145 if (privatetype
!= (dns_rdatatype_t
)0) {
146 result
= dns_db_findrdataset(db
, node
, ver
, privatetype
,
147 0, (isc_stdtime_t
) 0,
149 if (result
!= ISC_R_SUCCESS
&& result
!= ISC_R_NOTFOUND
)
154 * Look to see if we also need to be creating a NSEC3 chains.
156 if (dns_rdataset_isassociated(&nsecset
)) {
157 if (build_nsec
!= NULL
)
158 *build_nsec
= ISC_TRUE
;
159 if (build_nsec3
!= NULL
)
160 *build_nsec3
= ISC_FALSE
;
161 if (!dns_rdataset_isassociated(&privateset
))
163 for (result
= dns_rdataset_first(&privateset
);
164 result
== ISC_R_SUCCESS
;
165 result
= dns_rdataset_next(&privateset
)) {
166 unsigned char buf
[DNS_NSEC3PARAM_BUFFERSIZE
];
167 dns_rdata_t
private = DNS_RDATA_INIT
;
168 dns_rdata_t rdata
= DNS_RDATA_INIT
;
170 dns_rdataset_current(&privateset
, &private);
171 if (!dns_nsec3param_fromprivate(&private, &rdata
,
174 if (REMOVE(rdata
.data
[1]))
176 if (build_nsec3
!= NULL
)
177 *build_nsec3
= ISC_TRUE
;
183 if (dns_rdataset_isassociated(&nsec3paramset
)) {
184 if (build_nsec3
!= NULL
)
185 *build_nsec3
= ISC_TRUE
;
186 if (build_nsec
!= NULL
)
187 *build_nsec
= ISC_FALSE
;
188 if (!dns_rdataset_isassociated(&privateset
))
191 * If we are in the process of building a new NSEC3 chain
192 * then we don't need to build a NSEC chain.
194 for (result
= dns_rdataset_first(&privateset
);
195 result
== ISC_R_SUCCESS
;
196 result
= dns_rdataset_next(&privateset
)) {
197 dns_rdata_t
private = DNS_RDATA_INIT
;
198 dns_rdata_t rdata
= DNS_RDATA_INIT
;
200 dns_rdataset_current(&privateset
, &private);
201 if (!dns_nsec3param_fromprivate(&private, &rdata
,
204 if (CREATE(rdata
.data
[1]))
209 * Check to see if there will be a active NSEC3CHAIN once
210 * the changes queued complete.
213 for (result
= dns_rdataset_first(&nsec3paramset
);
214 result
== ISC_R_SUCCESS
;
215 result
= dns_rdataset_next(&nsec3paramset
)) {
216 dns_rdata_t rdata
= DNS_RDATA_INIT
;
219 * If there is more that one NSEC3 chain present then
220 * we don't need to construct a NSEC chain.
224 dns_rdataset_current(&nsec3paramset
, &rdata
);
225 if (ignore(&rdata
, &privateset
))
228 * We still have a good NSEC3 chain or we are
229 * not creating a NSEC chain as NONSEC is set.
235 * The last NSEC3 chain is being removed and does not have
238 if (build_nsec
!= NULL
)
239 *build_nsec
= ISC_TRUE
;
243 if (build_nsec
!= NULL
)
244 *build_nsec
= ISC_FALSE
;
245 if (build_nsec3
!= NULL
)
246 *build_nsec3
= ISC_FALSE
;
247 if (!dns_rdataset_isassociated(&privateset
))
251 nsec3chain
= ISC_FALSE
;
253 for (result
= dns_rdataset_first(&privateset
);
254 result
== ISC_R_SUCCESS
;
255 result
= dns_rdataset_next(&privateset
)) {
256 dns_rdata_t rdata
= DNS_RDATA_INIT
;
257 dns_rdata_t
private = DNS_RDATA_INIT
;
259 dns_rdataset_current(&privateset
, &private);
260 if (!dns_nsec3param_fromprivate(&private, &rdata
,
263 * Look for record that says we are signing the
266 if (private.length
== 5 && private.data
[0] != 0 &&
267 private.data
[3] == 0 && private.data
[4] == 0)
270 if (CREATE(rdata
.data
[1]))
271 nsec3chain
= ISC_TRUE
;
277 if (build_nsec3
!= NULL
)
278 *build_nsec3
= ISC_TRUE
;
280 if (build_nsec
!= NULL
)
281 *build_nsec
= ISC_TRUE
;
286 result
= ISC_R_SUCCESS
;
288 if (dns_rdataset_isassociated(&nsecset
))
289 dns_rdataset_disassociate(&nsecset
);
290 if (dns_rdataset_isassociated(&nsec3paramset
))
291 dns_rdataset_disassociate(&nsec3paramset
);
292 if (dns_rdataset_isassociated(&privateset
))
293 dns_rdataset_disassociate(&privateset
);
295 dns_db_detachnode(db
, &node
);