Home | History | Annotate | Line # | Download | only in dns
private.c revision 1.3
      1 /*	$NetBSD: private.c,v 1.3 2019/01/09 16:55:11 christos 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 <stdbool.h>
     17 
     18 #include <isc/base64.h>
     19 #include <isc/print.h>
     20 #include <isc/result.h>
     21 #include <isc/string.h>
     22 #include <isc/types.h>
     23 #include <isc/util.h>
     24 
     25 #include <dns/nsec3.h>
     26 #include <dns/private.h>
     27 
     28 /*
     29  * We need to build the relevant chain if there exists a NSEC/NSEC3PARAM
     30  * at the apex; normally only one or the other of NSEC/NSEC3PARAM will exist.
     31  *
     32  * If a NSEC3PARAM RRset exists then we will need to build a NSEC chain
     33  * if all the NSEC3PARAM records (and associated chains) are slated for
     34  * destruction and we have not been told to NOT build the NSEC chain.
     35  *
     36  * If the NSEC set exist then check to see if there is a request to create
     37  * a NSEC3 chain.
     38  *
     39  * If neither NSEC/NSEC3PARAM RRsets exist at the origin and the private
     40  * type exists then we need to examine it to determine if NSEC3 chain has
     41  * been requested to be built otherwise a NSEC chain needs to be built.
     42  */
     43 
     44 #define REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
     45 #define CREATE(x) (((x) & DNS_NSEC3FLAG_CREATE) != 0)
     46 #define INITIAL(x) (((x) & DNS_NSEC3FLAG_INITIAL) != 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 (/*CONSTCOND*/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 
     63 static bool
     64 ignore(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 (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 (false);
     97 		return (true);
     98 	}
     99 	return (false);
    100 }
    101 
    102 isc_result_t
    103 dns_private_chains(dns_db_t *db, dns_dbversion_t *ver,
    104 		   dns_rdatatype_t privatetype,
    105 		   bool *build_nsec, bool *build_nsec3)
    106 {
    107 	dns_dbnode_t *node;
    108 	dns_rdataset_t nsecset, nsec3paramset, privateset;
    109 	bool nsec3chain;
    110 	bool 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 = true;
    138 		if (build_nsec3 != NULL)
    139 			*build_nsec3 = 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 chain.
    153 	 */
    154 	if (dns_rdataset_isassociated(&nsecset)) {
    155 		if (build_nsec != NULL)
    156 			*build_nsec = true;
    157 		if (build_nsec3 != NULL)
    158 			*build_nsec3 = 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 			dns_rdata_t private = DNS_RDATA_INIT;
    165 			dns_rdata_t rdata = DNS_RDATA_INIT;
    166 
    167 			dns_rdataset_current(&privateset, &private);
    168 			if (!dns_nsec3param_fromprivate(&private, &rdata,
    169 							buf, sizeof(buf)))
    170 				continue;
    171 			if (REMOVE(rdata.data[1]))
    172 				continue;
    173 			if (build_nsec3 != NULL)
    174 				*build_nsec3 = true;
    175 			break;
    176 		}
    177 		goto success;
    178 	}
    179 
    180 	if (dns_rdataset_isassociated(&nsec3paramset)) {
    181 		if (build_nsec3 != NULL)
    182 			*build_nsec3 = true;
    183 		if (build_nsec != NULL)
    184 			*build_nsec = false;
    185 		if (!dns_rdataset_isassociated(&privateset))
    186 			goto success;
    187 		/*
    188 		 * If we are in the process of building a new NSEC3 chain
    189 		 * then we don't need to build a NSEC chain.
    190 		 */
    191 		for (result = dns_rdataset_first(&privateset);
    192 		     result == ISC_R_SUCCESS;
    193 		     result = dns_rdataset_next(&privateset)) {
    194 			dns_rdata_t private = DNS_RDATA_INIT;
    195 			dns_rdata_t rdata = DNS_RDATA_INIT;
    196 
    197 			dns_rdataset_current(&privateset, &private);
    198 			if (!dns_nsec3param_fromprivate(&private, &rdata,
    199 							buf, sizeof(buf)))
    200 				continue;
    201 			if (CREATE(rdata.data[1]))
    202 				goto success;
    203 		}
    204 
    205 		/*
    206 		 * Check to see if there will be a active NSEC3CHAIN once
    207 		 * the changes queued complete.
    208 		 */
    209 		count = 0;
    210 		for (result = dns_rdataset_first(&nsec3paramset);
    211 		     result == ISC_R_SUCCESS;
    212 		     result = dns_rdataset_next(&nsec3paramset)) {
    213 			dns_rdata_t rdata = DNS_RDATA_INIT;
    214 
    215 			/*
    216 			 * If there is more that one NSEC3 chain present then
    217 			 * we don't need to construct a NSEC chain.
    218 			 */
    219 			if (++count > 1)
    220 				goto success;
    221 			dns_rdataset_current(&nsec3paramset, &rdata);
    222 			if (ignore(&rdata, &privateset))
    223 				continue;
    224 			/*
    225 			 * We still have a good NSEC3 chain or we are
    226 			 * not creating a NSEC chain as NONSEC is set.
    227 			 */
    228 			goto success;
    229 		}
    230 
    231 		/*
    232 		 * The last NSEC3 chain is being removed and does not have
    233 		 * have NONSEC set.
    234 		 */
    235 		if (build_nsec != NULL)
    236 			*build_nsec = true;
    237 		goto success;
    238 	}
    239 
    240 	if (build_nsec != NULL)
    241 		*build_nsec = false;
    242 	if (build_nsec3 != NULL)
    243 		*build_nsec3 = false;
    244 	if (!dns_rdataset_isassociated(&privateset))
    245 		goto success;
    246 
    247 	signing = false;
    248 	nsec3chain = false;
    249 
    250 	for (result = dns_rdataset_first(&privateset);
    251 	     result == ISC_R_SUCCESS;
    252 	     result = dns_rdataset_next(&privateset)) {
    253 		dns_rdata_t rdata = DNS_RDATA_INIT;
    254 		dns_rdata_t private = DNS_RDATA_INIT;
    255 
    256 		dns_rdataset_current(&privateset, &private);
    257 		if (!dns_nsec3param_fromprivate(&private, &rdata,
    258 						buf, sizeof(buf))) {
    259 			/*
    260 			 * Look for record that says we are signing the
    261 			 * zone with a key.
    262 			 */
    263 			if (private.length == 5 && private.data[0] != 0 &&
    264 			    private.data[3] == 0 && private.data[4] == 0)
    265 				signing = true;
    266 		} else {
    267 			if (CREATE(rdata.data[1]))
    268 				nsec3chain = true;
    269 		}
    270 	}
    271 
    272 	if (signing) {
    273 		if (nsec3chain) {
    274 			if (build_nsec3 != NULL)
    275 				*build_nsec3 = true;
    276 		} else {
    277 			if (build_nsec != NULL)
    278 				*build_nsec = true;
    279 		}
    280 	}
    281 
    282  success:
    283 	result = ISC_R_SUCCESS;
    284  failure:
    285 	if (dns_rdataset_isassociated(&nsecset))
    286 		dns_rdataset_disassociate(&nsecset);
    287 	if (dns_rdataset_isassociated(&nsec3paramset))
    288 		dns_rdataset_disassociate(&nsec3paramset);
    289 	if (dns_rdataset_isassociated(&privateset))
    290 		dns_rdataset_disassociate(&privateset);
    291 	if (node != NULL)
    292 		dns_db_detachnode(db, &node);
    293 	return (result);
    294 }
    295 
    296 isc_result_t
    297 dns_private_totext(dns_rdata_t *private, isc_buffer_t *buf) {
    298 	isc_result_t result;
    299 
    300 	if (private->length < 5)
    301 		return (ISC_R_NOTFOUND);
    302 
    303 	if (private->data[0] == 0) {
    304 		unsigned char nsec3buf[DNS_NSEC3PARAM_BUFFERSIZE];
    305 		unsigned char newbuf[DNS_NSEC3PARAM_BUFFERSIZE];
    306 		dns_rdata_t rdata = DNS_RDATA_INIT;
    307 		dns_rdata_nsec3param_t nsec3param;
    308 		bool del, init, nonsec;
    309 		isc_buffer_t b;
    310 
    311 		if (!dns_nsec3param_fromprivate(private, &rdata, nsec3buf,
    312 						sizeof(nsec3buf)))
    313 			CHECK(ISC_R_FAILURE);
    314 
    315 		CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
    316 
    317 		del = ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0);
    318 		init = ((nsec3param.flags & DNS_NSEC3FLAG_INITIAL) != 0);
    319 		nonsec = ((nsec3param.flags & DNS_NSEC3FLAG_NONSEC) != 0);
    320 
    321 		nsec3param.flags &= ~(DNS_NSEC3FLAG_CREATE|
    322 				      DNS_NSEC3FLAG_REMOVE|
    323 				      DNS_NSEC3FLAG_INITIAL|
    324 				      DNS_NSEC3FLAG_NONSEC);
    325 
    326 		if (init)
    327 			isc_buffer_putstr(buf, "Pending NSEC3 chain ");
    328 		else if (del)
    329 			isc_buffer_putstr(buf, "Removing NSEC3 chain ");
    330 		else
    331 			isc_buffer_putstr(buf, "Creating NSEC3 chain ");
    332 
    333 		dns_rdata_reset(&rdata);
    334 		isc_buffer_init(&b, newbuf, sizeof(newbuf));
    335 		CHECK(dns_rdata_fromstruct(&rdata, dns_rdataclass_in,
    336 					   dns_rdatatype_nsec3param,
    337 					   &nsec3param, &b));
    338 
    339 		CHECK(dns_rdata_totext(&rdata, NULL, buf));
    340 
    341 		if (del && !nonsec)
    342 			isc_buffer_putstr(buf, " / creating NSEC chain");
    343 	} else if (private->length == 5) {
    344 		unsigned char alg = private->data[0];
    345 		dns_keytag_t keyid = (private->data[2] | private->data[1] << 8);
    346 		char keybuf[BUFSIZ], algbuf[DNS_SECALG_FORMATSIZE];
    347 		bool del = private->data[3];
    348 		bool complete = private->data[4];
    349 
    350 		if (del && complete)
    351 			isc_buffer_putstr(buf, "Done removing signatures for ");
    352 		else if (del)
    353 			isc_buffer_putstr(buf, "Removing signatures for ");
    354 		else if (complete)
    355 			isc_buffer_putstr(buf, "Done signing with ");
    356 		else
    357 			isc_buffer_putstr(buf, "Signing with ");
    358 
    359 		dns_secalg_format(alg, algbuf, sizeof(algbuf));
    360 		snprintf(keybuf, sizeof(keybuf), "key %d/%s", keyid, algbuf);
    361 		isc_buffer_putstr(buf, keybuf);
    362 	} else
    363 		return (ISC_R_NOTFOUND);
    364 
    365 	isc_buffer_putuint8(buf, 0);
    366 	result = ISC_R_SUCCESS;
    367  failure:
    368 	return (result);
    369 }
    370