1 /* $NetBSD: private.c,v 1.7 2015/07/08 17:28:59 christos Exp $ */ 2 3 /* 4 * Copyright (C) 2009, 2011, 2012, 2015 Internet Systems Consortium, Inc. ("ISC") 5 * 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. 9 * 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. 17 */ 18 19 /* Id */ 20 21 #include "config.h" 22 23 #include <isc/result.h> 24 #include <isc/string.h> 25 #include <isc/types.h> 26 #include <isc/base64.h> 27 28 #include <dns/nsec3.h> 29 #include <dns/private.h> 30 31 /* 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. 34 * 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. 38 * 39 * If the NSEC set exist then check to see if there is a request to create 40 * a NSEC3 chain. 41 * 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. 45 */ 46 47 #define REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0) 48 #define CREATE(x) (((x) & DNS_NSEC3FLAG_CREATE) != 0) 49 #define INITIAL(x) (((x) & DNS_NSEC3FLAG_INITIAL) != 0) 50 #define NONSEC(x) (((x) & DNS_NSEC3FLAG_NONSEC) != 0) 51 52 #define CHECK(x) do { \ 53 result = (x); \ 54 if (result != ISC_R_SUCCESS) \ 55 goto failure; \ 56 } while (/*CONSTCOND*/0) 57 58 /* 59 * Work out if 'param' should be ignored or not (i.e. it is in the process 60 * of being removed). 61 * 62 * Note: we 'belt-and-braces' here by also checking for a CREATE private 63 * record and keep the param record in this case. 64 */ 65 66 static isc_boolean_t 67 ignore(dns_rdata_t *param, dns_rdataset_t *privateset) { 68 isc_result_t result; 69 70 for (result = dns_rdataset_first(privateset); 71 result == ISC_R_SUCCESS; 72 result = dns_rdataset_next(privateset)) { 73 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE]; 74 dns_rdata_t private = DNS_RDATA_INIT; 75 dns_rdata_t rdata = DNS_RDATA_INIT; 76 77 dns_rdataset_current(privateset, &private); 78 if (!dns_nsec3param_fromprivate(&private, &rdata, 79 buf, sizeof(buf))) 80 continue; 81 /* 82 * We are going to create a new NSEC3 chain so it 83 * doesn't matter if we are removing this one. 84 */ 85 if (CREATE(rdata.data[1])) 86 return (ISC_FALSE); 87 if (rdata.data[0] != param->data[0] || 88 rdata.data[2] != param->data[2] || 89 rdata.data[3] != param->data[3] || 90 rdata.data[4] != param->data[4] || 91 memcmp(&rdata.data[5], ¶m->data[5], param->data[4])) 92 continue; 93 /* 94 * The removal of this NSEC3 chain does NOT cause a 95 * NSEC chain to be created so we don't need to tell 96 * the caller that it will be removed. 97 */ 98 if (NONSEC(rdata.data[1])) 99 return (ISC_FALSE); 100 return (ISC_TRUE); 101 } 102 return (ISC_FALSE); 103 } 104 105 isc_result_t 106 dns_private_chains(dns_db_t *db, dns_dbversion_t *ver, 107 dns_rdatatype_t privatetype, 108 isc_boolean_t *build_nsec, isc_boolean_t *build_nsec3) 109 { 110 dns_dbnode_t *node; 111 dns_rdataset_t nsecset, nsec3paramset, privateset; 112 isc_boolean_t nsec3chain; 113 isc_boolean_t signing; 114 isc_result_t result; 115 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE]; 116 unsigned int count; 117 118 node = NULL; 119 dns_rdataset_init(&nsecset); 120 dns_rdataset_init(&nsec3paramset); 121 dns_rdataset_init(&privateset); 122 123 CHECK(dns_db_getoriginnode(db, &node)); 124 125 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec, 126 0, (isc_stdtime_t) 0, &nsecset, NULL); 127 128 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) 129 goto failure; 130 131 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param, 132 0, (isc_stdtime_t) 0, &nsec3paramset, 133 NULL); 134 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) 135 goto failure; 136 137 if (dns_rdataset_isassociated(&nsecset) && 138 dns_rdataset_isassociated(&nsec3paramset)) { 139 if (build_nsec != NULL) 140 *build_nsec = ISC_TRUE; 141 if (build_nsec3 != NULL) 142 *build_nsec3 = ISC_TRUE; 143 goto success; 144 } 145 146 if (privatetype != (dns_rdatatype_t)0) { 147 result = dns_db_findrdataset(db, node, ver, privatetype, 148 0, (isc_stdtime_t) 0, 149 &privateset, NULL); 150 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) 151 goto failure; 152 } 153 154 /* 155 * Look to see if we also need to be creating a NSEC3 chain. 156 */ 157 if (dns_rdataset_isassociated(&nsecset)) { 158 if (build_nsec != NULL) 159 *build_nsec = ISC_TRUE; 160 if (build_nsec3 != NULL) 161 *build_nsec3 = ISC_FALSE; 162 if (!dns_rdataset_isassociated(&privateset)) 163 goto success; 164 for (result = dns_rdataset_first(&privateset); 165 result == ISC_R_SUCCESS; 166 result = dns_rdataset_next(&privateset)) { 167 dns_rdata_t private = DNS_RDATA_INIT; 168 dns_rdata_t rdata = DNS_RDATA_INIT; 169 170 dns_rdataset_current(&privateset, &private); 171 if (!dns_nsec3param_fromprivate(&private, &rdata, 172 buf, sizeof(buf))) 173 continue; 174 if (REMOVE(rdata.data[1])) 175 continue; 176 if (build_nsec3 != NULL) 177 *build_nsec3 = ISC_TRUE; 178 break; 179 } 180 goto success; 181 } 182 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)) 189 goto success; 190 /* 191 * If we are in the process of building a new NSEC3 chain 192 * then we don't need to build a NSEC chain. 193 */ 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; 199 200 dns_rdataset_current(&privateset, &private); 201 if (!dns_nsec3param_fromprivate(&private, &rdata, 202 buf, sizeof(buf))) 203 continue; 204 if (CREATE(rdata.data[1])) 205 goto success; 206 } 207 208 /* 209 * Check to see if there will be a active NSEC3CHAIN once 210 * the changes queued complete. 211 */ 212 count = 0; 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; 217 218 /* 219 * If there is more that one NSEC3 chain present then 220 * we don't need to construct a NSEC chain. 221 */ 222 if (++count > 1) 223 goto success; 224 dns_rdataset_current(&nsec3paramset, &rdata); 225 if (ignore(&rdata, &privateset)) 226 continue; 227 /* 228 * We still have a good NSEC3 chain or we are 229 * not creating a NSEC chain as NONSEC is set. 230 */ 231 goto success; 232 } 233 234 /* 235 * The last NSEC3 chain is being removed and does not have 236 * have NONSEC set. 237 */ 238 if (build_nsec != NULL) 239 *build_nsec = ISC_TRUE; 240 goto success; 241 } 242 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)) 248 goto success; 249 250 signing = ISC_FALSE; 251 nsec3chain = ISC_FALSE; 252 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; 258 259 dns_rdataset_current(&privateset, &private); 260 if (!dns_nsec3param_fromprivate(&private, &rdata, 261 buf, sizeof(buf))) { 262 /* 263 * Look for record that says we are signing the 264 * zone with a key. 265 */ 266 if (private.length == 5 && private.data[0] != 0 && 267 private.data[3] == 0 && private.data[4] == 0) 268 signing = ISC_TRUE; 269 } else { 270 if (CREATE(rdata.data[1])) 271 nsec3chain = ISC_TRUE; 272 } 273 } 274 275 if (signing) { 276 if (nsec3chain) { 277 if (build_nsec3 != NULL) 278 *build_nsec3 = ISC_TRUE; 279 } else { 280 if (build_nsec != NULL) 281 *build_nsec = ISC_TRUE; 282 } 283 } 284 285 success: 286 result = ISC_R_SUCCESS; 287 failure: 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); 294 if (node != NULL) 295 dns_db_detachnode(db, &node); 296 return (result); 297 } 298 299 isc_result_t 300 dns_private_totext(dns_rdata_t *private, isc_buffer_t *buf) { 301 isc_result_t result; 302 303 if (private->length < 5) 304 return (ISC_R_NOTFOUND); 305 306 if (private->data[0] == 0) { 307 unsigned char nsec3buf[DNS_NSEC3PARAM_BUFFERSIZE]; 308 unsigned char newbuf[DNS_NSEC3PARAM_BUFFERSIZE]; 309 dns_rdata_t rdata = DNS_RDATA_INIT; 310 dns_rdata_nsec3param_t nsec3param; 311 isc_boolean_t remove, init, nonsec; 312 isc_buffer_t b; 313 314 if (!dns_nsec3param_fromprivate(private, &rdata, nsec3buf, 315 sizeof(nsec3buf))) 316 CHECK(ISC_R_FAILURE); 317 318 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL)); 319 320 remove = ISC_TF((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0); 321 init = ISC_TF((nsec3param.flags & DNS_NSEC3FLAG_INITIAL) != 0); 322 nonsec = ISC_TF((nsec3param.flags & DNS_NSEC3FLAG_NONSEC) != 0); 323 324 nsec3param.flags &= ~(DNS_NSEC3FLAG_CREATE| 325 DNS_NSEC3FLAG_REMOVE| 326 DNS_NSEC3FLAG_INITIAL| 327 DNS_NSEC3FLAG_NONSEC); 328 329 if (init) 330 isc_buffer_putstr(buf, "Pending NSEC3 chain "); 331 else if (remove) 332 isc_buffer_putstr(buf, "Removing NSEC3 chain "); 333 else 334 isc_buffer_putstr(buf, "Creating NSEC3 chain "); 335 336 dns_rdata_reset(&rdata); 337 isc_buffer_init(&b, newbuf, sizeof(newbuf)); 338 CHECK(dns_rdata_fromstruct(&rdata, dns_rdataclass_in, 339 dns_rdatatype_nsec3param, 340 &nsec3param, &b)); 341 342 CHECK(dns_rdata_totext(&rdata, NULL, buf)); 343 344 if (remove && !nonsec) 345 isc_buffer_putstr(buf, " / creating NSEC chain"); 346 } else if (private->length == 5) { 347 unsigned char alg = private->data[0]; 348 dns_keytag_t keyid = (private->data[2] | private->data[1] << 8); 349 char keybuf[BUFSIZ], algbuf[DNS_SECALG_FORMATSIZE]; 350 isc_boolean_t remove = ISC_TF(private->data[3] != 0); 351 isc_boolean_t complete = ISC_TF(private->data[4] != 0); 352 353 if (remove && complete) 354 isc_buffer_putstr(buf, "Done removing signatures for "); 355 else if (remove) 356 isc_buffer_putstr(buf, "Removing signatures for "); 357 else if (complete) 358 isc_buffer_putstr(buf, "Done signing with "); 359 else 360 isc_buffer_putstr(buf, "Signing with "); 361 362 dns_secalg_format(alg, algbuf, sizeof(algbuf)); 363 sprintf(keybuf, "key %d/%s", keyid, algbuf); 364 isc_buffer_putstr(buf, keybuf); 365 } else 366 return (ISC_R_NOTFOUND); 367 368 isc_buffer_putuint8(buf, 0); 369 result = ISC_R_SUCCESS; 370 failure: 371 return (result); 372 } 373