PageRenderTime 60ms CodeModel.GetById 14ms app.highlight 41ms RepoModel.GetById 1ms app.codeStats 0ms

/contrib/bind9/lib/dns/private.c

https://bitbucket.org/freebsd/freebsd-head/
C | 295 lines | 189 code | 32 blank | 74 comment | 92 complexity | 1eb2efb3e45608e069ccaeab41d192ef MD5 | raw file
  1/*
  2 * Copyright (C) 2009, 2012  Internet Systems Consortium, Inc. ("ISC")
  3 *
  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.
  7 *
  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.
 15 */
 16
 17/* $Id$ */
 18
 19#include "config.h"
 20
 21#include <isc/result.h>
 22#include <isc/string.h>
 23#include <isc/types.h>
 24#include <isc/base64.h>
 25
 26#include <dns/nsec3.h>
 27#include <dns/private.h>
 28
 29/*
 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.
 32 *
 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.
 36 *
 37 * If the NSEC set exist then check to see if there is a request to create
 38 * a NSEC3 chain.
 39 *
 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.
 43 */
 44
 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)
 48
 49#define CHECK(x) do {					\
 50			 result = (x);			\
 51			 if (result != ISC_R_SUCCESS)	\
 52				goto failure;		\
 53		 } while (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
 63static isc_boolean_t
 64ignore(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 (ISC_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], &param->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 (ISC_FALSE);
 97		return (ISC_TRUE);
 98	}
 99	return (ISC_FALSE);
100}
101
102isc_result_t
103dns_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)
106{
107	dns_dbnode_t *node;
108	dns_rdataset_t nsecset, nsec3paramset, privateset;
109	isc_boolean_t nsec3chain;
110	isc_boolean_t 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 = ISC_TRUE;
138		if (build_nsec3 != NULL)
139			*build_nsec3 = ISC_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 chains.
153	 */
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))
160			goto success;
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;
167
168			dns_rdataset_current(&privateset, &private);
169			if (!dns_nsec3param_fromprivate(&private, &rdata,
170							buf, sizeof(buf)))
171				continue;
172			if (REMOVE(rdata.data[1]))
173				continue;
174			if (build_nsec3 != NULL)
175				*build_nsec3 = ISC_TRUE;
176			break;
177		}
178		goto success;
179	}
180
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))
187			goto success;
188		/*
189		 * If we are in the process of building a new NSEC3 chain
190		 * then we don't need to build a NSEC chain.
191		 */
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;
197
198			dns_rdataset_current(&privateset, &private);
199			if (!dns_nsec3param_fromprivate(&private, &rdata,
200							buf, sizeof(buf)))
201				continue;
202			if (CREATE(rdata.data[1]))
203				goto success;
204		}
205
206		/*
207		 * Check to see if there will be a active NSEC3CHAIN once
208		 * the changes queued complete.
209		 */
210		count = 0;
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;
215
216			/*
217			 * If there is more that one NSEC3 chain present then
218			 * we don't need to construct a NSEC chain.
219			 */
220			if (++count > 1)
221				goto success;
222			dns_rdataset_current(&nsec3paramset, &rdata);
223			if (ignore(&rdata, &privateset))
224				continue;
225			/*
226			 * We still have a good NSEC3 chain or we are
227			 * not creating a NSEC chain as NONSEC is set.
228			 */
229			goto success;
230		}
231
232		/*
233		 * The last NSEC3 chain is being removed and does not have
234		 * have NONSEC set.
235		 */
236		if (build_nsec != NULL)
237			*build_nsec = ISC_TRUE;
238		goto success;
239	}
240
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))
246		goto success;
247
248	signing = ISC_FALSE;
249	nsec3chain = ISC_FALSE;
250
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;
256
257		dns_rdataset_current(&privateset, &private);
258		if (!dns_nsec3param_fromprivate(&private, &rdata,
259						buf, sizeof(buf))) {
260			/*
261			 * Look for record that says we are signing the
262			 * zone with a key.
263			 */
264			if (private.length == 5 && private.data[0] != 0 &&
265			    private.data[3] == 0 && private.data[4] == 0)
266				signing = ISC_TRUE;
267		} else {
268			if (CREATE(rdata.data[1]))
269				nsec3chain = ISC_TRUE;
270		}
271	}
272
273	if (signing) {
274		if (nsec3chain) {
275			if (build_nsec3 != NULL)
276				*build_nsec3 = ISC_TRUE;
277		} else {
278			if (build_nsec != NULL)
279				*build_nsec = ISC_TRUE;
280		}
281	}
282
283 success:
284	result = ISC_R_SUCCESS;
285 failure:
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);
292	if (node != NULL)
293		dns_db_detachnode(db, &node);
294	return (result);
295}