Home | History | Annotate | Line # | Download | only in dns
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], &param->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