xref: /netbsd/external/mpl/bind/dist/lib/dns/update.c (revision 4ac1c27e)
1 /*	$NetBSD: update.c,v 1.12 2023/01/25 21:43:30 christos Exp $	*/
2 
3 /*
4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5  *
6  * SPDX-License-Identifier: MPL-2.0
7  *
8  * This Source Code Form is subject to the terms of the Mozilla Public
9  * License, v. 2.0. If a copy of the MPL was not distributed with this
10  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11  *
12  * See the COPYRIGHT file distributed with this work for additional
13  * information regarding copyright ownership.
14  */
15 
16 #include <inttypes.h>
17 #include <stdbool.h>
18 #include <time.h>
19 
20 #include <isc/log.h>
21 #include <isc/magic.h>
22 #include <isc/mem.h>
23 #include <isc/netaddr.h>
24 #include <isc/platform.h>
25 #include <isc/print.h>
26 #include <isc/random.h>
27 #include <isc/serial.h>
28 #include <isc/stats.h>
29 #include <isc/stdtime.h>
30 #include <isc/string.h>
31 #include <isc/taskpool.h>
32 #include <isc/time.h>
33 #include <isc/util.h>
34 
35 #include <dns/db.h>
36 #include <dns/dbiterator.h>
37 #include <dns/diff.h>
38 #include <dns/dnssec.h>
39 #include <dns/events.h>
40 #include <dns/fixedname.h>
41 #include <dns/journal.h>
42 #include <dns/kasp.h>
43 #include <dns/keyvalues.h>
44 #include <dns/log.h>
45 #include <dns/message.h>
46 #include <dns/nsec.h>
47 #include <dns/nsec3.h>
48 #include <dns/private.h>
49 #include <dns/rdataclass.h>
50 #include <dns/rdataset.h>
51 #include <dns/rdatasetiter.h>
52 #include <dns/rdatastruct.h>
53 #include <dns/rdatatype.h>
54 #include <dns/result.h>
55 #include <dns/soa.h>
56 #include <dns/ssu.h>
57 #include <dns/stats.h>
58 #include <dns/tsig.h>
59 #include <dns/update.h>
60 #include <dns/view.h>
61 #include <dns/zone.h>
62 #include <dns/zt.h>
63 
64 /**************************************************************************/
65 
66 #define STATE_MAGIC	       ISC_MAGIC('S', 'T', 'T', 'E')
67 #define DNS_STATE_VALID(state) ISC_MAGIC_VALID(state, STATE_MAGIC)
68 
69 /*%
70  * Log level for tracing dynamic update protocol requests.
71  */
72 #define LOGLEVEL_PROTOCOL ISC_LOG_INFO
73 
74 /*%
75  * Log level for low-level debug tracing.
76  */
77 #define LOGLEVEL_DEBUG ISC_LOG_DEBUG(8)
78 
79 /*%
80  * Check an operation for failure.  These macros all assume that
81  * the function using them has a 'result' variable and a 'failure'
82  * label.
83  */
84 #define CHECK(op)                            \
85 	do {                                 \
86 		result = (op);               \
87 		if (result != ISC_R_SUCCESS) \
88 			goto failure;        \
89 	} while (0)
90 
91 /*%
92  * Fail unconditionally with result 'code', which must not
93  * be ISC_R_SUCCESS.  The reason for failure presumably has
94  * been logged already.
95  *
96  * The test against ISC_R_SUCCESS is there to keep the Solaris compiler
97  * from complaining about "end-of-loop code not reached".
98  */
99 
100 #define FAIL(code)                           \
101 	do {                                 \
102 		result = (code);             \
103 		if (result != ISC_R_SUCCESS) \
104 			goto failure;        \
105 	} while (0)
106 
107 /*%
108  * Fail unconditionally and log as a client error.
109  * The test against ISC_R_SUCCESS is there to keep the Solaris compiler
110  * from complaining about "end-of-loop code not reached".
111  */
112 #define FAILC(code, msg)                                                       \
113 	do {                                                                   \
114 		const char *_what = "failed";                                  \
115 		result = (code);                                               \
116 		switch (result) {                                              \
117 		case DNS_R_NXDOMAIN:                                           \
118 		case DNS_R_YXDOMAIN:                                           \
119 		case DNS_R_YXRRSET:                                            \
120 		case DNS_R_NXRRSET:                                            \
121 			_what = "unsuccessful";                                \
122 		}                                                              \
123 		update_log(log, zone, LOGLEVEL_PROTOCOL, "update %s: %s (%s)", \
124 			   _what, msg, isc_result_totext(result));             \
125 		if (result != ISC_R_SUCCESS)                                   \
126 			goto failure;                                          \
127 	} while (0)
128 
129 #define FAILN(code, name, msg)                                             \
130 	do {                                                               \
131 		const char *_what = "failed";                              \
132 		result = (code);                                           \
133 		switch (result) {                                          \
134 		case DNS_R_NXDOMAIN:                                       \
135 		case DNS_R_YXDOMAIN:                                       \
136 		case DNS_R_YXRRSET:                                        \
137 		case DNS_R_NXRRSET:                                        \
138 			_what = "unsuccessful";                            \
139 		}                                                          \
140 		if (isc_log_wouldlog(dns_lctx, LOGLEVEL_PROTOCOL)) {       \
141 			char _nbuf[DNS_NAME_FORMATSIZE];                   \
142 			dns_name_format(name, _nbuf, sizeof(_nbuf));       \
143 			update_log(log, zone, LOGLEVEL_PROTOCOL,           \
144 				   "update %s: %s: %s (%s)", _what, _nbuf, \
145 				   msg, isc_result_totext(result));        \
146 		}                                                          \
147 		if (result != ISC_R_SUCCESS)                               \
148 			goto failure;                                      \
149 	} while (0)
150 
151 #define FAILNT(code, name, type, msg)                                         \
152 	do {                                                                  \
153 		const char *_what = "failed";                                 \
154 		result = (code);                                              \
155 		switch (result) {                                             \
156 		case DNS_R_NXDOMAIN:                                          \
157 		case DNS_R_YXDOMAIN:                                          \
158 		case DNS_R_YXRRSET:                                           \
159 		case DNS_R_NXRRSET:                                           \
160 			_what = "unsuccessful";                               \
161 		}                                                             \
162 		if (isc_log_wouldlog(dns_lctx, LOGLEVEL_PROTOCOL)) {          \
163 			char _nbuf[DNS_NAME_FORMATSIZE];                      \
164 			char _tbuf[DNS_RDATATYPE_FORMATSIZE];                 \
165 			dns_name_format(name, _nbuf, sizeof(_nbuf));          \
166 			dns_rdatatype_format(type, _tbuf, sizeof(_tbuf));     \
167 			update_log(log, zone, LOGLEVEL_PROTOCOL,              \
168 				   "update %s: %s/%s: %s (%s)", _what, _nbuf, \
169 				   _tbuf, msg, isc_result_totext(result));    \
170 		}                                                             \
171 		if (result != ISC_R_SUCCESS)                                  \
172 			goto failure;                                         \
173 	} while (0)
174 
175 /*%
176  * Fail unconditionally and log as a server error.
177  * The test against ISC_R_SUCCESS is there to keep the Solaris compiler
178  * from complaining about "end-of-loop code not reached".
179  */
180 #define FAILS(code, msg)                                                       \
181 	do {                                                                   \
182 		result = (code);                                               \
183 		update_log(log, zone, LOGLEVEL_PROTOCOL, "error: %s: %s", msg, \
184 			   isc_result_totext(result));                         \
185 		if (result != ISC_R_SUCCESS)                                   \
186 			goto failure;                                          \
187 	} while (0)
188 
189 /**************************************************************************/
190 
191 typedef struct rr rr_t;
192 
193 struct rr {
194 	/* dns_name_t name; */
195 	uint32_t ttl;
196 	dns_rdata_t rdata;
197 };
198 
199 typedef struct update_event update_event_t;
200 
201 /**************************************************************************/
202 
203 static void
204 update_log(dns_update_log_t *callback, dns_zone_t *zone, int level,
205 	   const char *fmt, ...) ISC_FORMAT_PRINTF(4, 5);
206 
207 static void
update_log(dns_update_log_t * callback,dns_zone_t * zone,int level,const char * fmt,...)208 update_log(dns_update_log_t *callback, dns_zone_t *zone, int level,
209 	   const char *fmt, ...) {
210 	va_list ap;
211 	char message[4096];
212 
213 	if (callback == NULL) {
214 		return;
215 	}
216 
217 	if (!isc_log_wouldlog(dns_lctx, level)) {
218 		return;
219 	}
220 
221 	va_start(ap, fmt);
222 	vsnprintf(message, sizeof(message), fmt, ap);
223 	va_end(ap);
224 
225 	(callback->func)(callback->arg, zone, level, message);
226 }
227 
228 /*%
229  * Update a single RR in version 'ver' of 'db' and log the
230  * update in 'diff'.
231  *
232  * Ensures:
233  * \li	'*tuple' == NULL.  Either the tuple is freed, or its
234  *	ownership has been transferred to the diff.
235  */
236 static isc_result_t
do_one_tuple(dns_difftuple_t ** tuple,dns_db_t * db,dns_dbversion_t * ver,dns_diff_t * diff)237 do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
238 	     dns_diff_t *diff) {
239 	dns_diff_t temp_diff;
240 	isc_result_t result;
241 
242 	/*
243 	 * Create a singleton diff.
244 	 */
245 	dns_diff_init(diff->mctx, &temp_diff);
246 	ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
247 
248 	/*
249 	 * Apply it to the database.
250 	 */
251 	result = dns_diff_apply(&temp_diff, db, ver);
252 	ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
253 	if (result != ISC_R_SUCCESS) {
254 		dns_difftuple_free(tuple);
255 		return (result);
256 	}
257 
258 	/*
259 	 * Merge it into the current pending journal entry.
260 	 */
261 	dns_diff_appendminimal(diff, tuple);
262 
263 	/*
264 	 * Do not clear temp_diff.
265 	 */
266 	return (ISC_R_SUCCESS);
267 }
268 
269 static isc_result_t
update_one_rr(dns_db_t * db,dns_dbversion_t * ver,dns_diff_t * diff,dns_diffop_t op,dns_name_t * name,dns_ttl_t ttl,dns_rdata_t * rdata)270 update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
271 	      dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
272 	      dns_rdata_t *rdata) {
273 	dns_difftuple_t *tuple = NULL;
274 	isc_result_t result;
275 	result = dns_difftuple_create(diff->mctx, op, name, ttl, rdata, &tuple);
276 	if (result != ISC_R_SUCCESS) {
277 		return (result);
278 	}
279 	return (do_one_tuple(&tuple, db, ver, diff));
280 }
281 
282 /**************************************************************************/
283 /*
284  * Callback-style iteration over rdatasets and rdatas.
285  *
286  * foreach_rrset() can be used to iterate over the RRsets
287  * of a name and call a callback function with each
288  * one.  Similarly, foreach_rr() can be used to iterate
289  * over the individual RRs at name, optionally restricted
290  * to RRs of a given type.
291  *
292  * The callback functions are called "actions" and take
293  * two arguments: a void pointer for passing arbitrary
294  * context information, and a pointer to the current RRset
295  * or RR.  By convention, their names end in "_action".
296  */
297 
298 /*
299  * XXXRTH  We might want to make this public somewhere in libdns.
300  */
301 
302 /*%
303  * Function type for foreach_rrset() iterator actions.
304  */
305 typedef isc_result_t
306 rrset_func(void *data, dns_rdataset_t *rrset);
307 
308 /*%
309  * Function type for foreach_rr() iterator actions.
310  */
311 typedef isc_result_t
312 rr_func(void *data, rr_t *rr);
313 
314 /*%
315  * Internal context struct for foreach_node_rr().
316  */
317 typedef struct {
318 	rr_func *rr_action;
319 	void *rr_action_data;
320 } foreach_node_rr_ctx_t;
321 
322 /*%
323  * Internal helper function for foreach_node_rr().
324  */
325 static isc_result_t
foreach_node_rr_action(void * data,dns_rdataset_t * rdataset)326 foreach_node_rr_action(void *data, dns_rdataset_t *rdataset) {
327 	isc_result_t result;
328 	foreach_node_rr_ctx_t *ctx = data;
329 	for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
330 	     result = dns_rdataset_next(rdataset))
331 	{
332 		rr_t rr = { 0, DNS_RDATA_INIT };
333 
334 		dns_rdataset_current(rdataset, &rr.rdata);
335 		rr.ttl = rdataset->ttl;
336 		result = (*ctx->rr_action)(ctx->rr_action_data, &rr);
337 		if (result != ISC_R_SUCCESS) {
338 			return (result);
339 		}
340 	}
341 	if (result != ISC_R_NOMORE) {
342 		return (result);
343 	}
344 	return (ISC_R_SUCCESS);
345 }
346 
347 /*%
348  * For each rdataset of 'name' in 'ver' of 'db', call 'action'
349  * with the rdataset and 'action_data' as arguments.  If the name
350  * does not exist, do nothing.
351  *
352  * If 'action' returns an error, abort iteration and return the error.
353  */
354 static isc_result_t
foreach_rrset(dns_db_t * db,dns_dbversion_t * ver,dns_name_t * name,rrset_func * action,void * action_data)355 foreach_rrset(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
356 	      rrset_func *action, void *action_data) {
357 	isc_result_t result;
358 	dns_dbnode_t *node;
359 	dns_rdatasetiter_t *iter;
360 
361 	node = NULL;
362 	result = dns_db_findnode(db, name, false, &node);
363 	if (result == ISC_R_NOTFOUND) {
364 		return (ISC_R_SUCCESS);
365 	}
366 	if (result != ISC_R_SUCCESS) {
367 		return (result);
368 	}
369 
370 	iter = NULL;
371 	result = dns_db_allrdatasets(db, node, ver, 0, (isc_stdtime_t)0, &iter);
372 	if (result != ISC_R_SUCCESS) {
373 		goto cleanup_node;
374 	}
375 
376 	for (result = dns_rdatasetiter_first(iter); result == ISC_R_SUCCESS;
377 	     result = dns_rdatasetiter_next(iter))
378 	{
379 		dns_rdataset_t rdataset;
380 
381 		dns_rdataset_init(&rdataset);
382 		dns_rdatasetiter_current(iter, &rdataset);
383 
384 		result = (*action)(action_data, &rdataset);
385 
386 		dns_rdataset_disassociate(&rdataset);
387 		if (result != ISC_R_SUCCESS) {
388 			goto cleanup_iterator;
389 		}
390 	}
391 	if (result == ISC_R_NOMORE) {
392 		result = ISC_R_SUCCESS;
393 	}
394 
395 cleanup_iterator:
396 	dns_rdatasetiter_destroy(&iter);
397 
398 cleanup_node:
399 	dns_db_detachnode(db, &node);
400 
401 	return (result);
402 }
403 
404 /*%
405  * For each RR of 'name' in 'ver' of 'db', call 'action'
406  * with the RR and 'action_data' as arguments.  If the name
407  * does not exist, do nothing.
408  *
409  * If 'action' returns an error, abort iteration
410  * and return the error.
411  */
412 static isc_result_t
foreach_node_rr(dns_db_t * db,dns_dbversion_t * ver,dns_name_t * name,rr_func * rr_action,void * rr_action_data)413 foreach_node_rr(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
414 		rr_func *rr_action, void *rr_action_data) {
415 	foreach_node_rr_ctx_t ctx;
416 	ctx.rr_action = rr_action;
417 	ctx.rr_action_data = rr_action_data;
418 	return (foreach_rrset(db, ver, name, foreach_node_rr_action, &ctx));
419 }
420 
421 /*%
422  * For each of the RRs specified by 'db', 'ver', 'name', 'type',
423  * (which can be dns_rdatatype_any to match any type), and 'covers', call
424  * 'action' with the RR and 'action_data' as arguments. If the name
425  * does not exist, or if no RRset of the given type exists at the name,
426  * do nothing.
427  *
428  * If 'action' returns an error, abort iteration and return the error.
429  */
430 static isc_result_t
foreach_rr(dns_db_t * db,dns_dbversion_t * ver,dns_name_t * name,dns_rdatatype_t type,dns_rdatatype_t covers,rr_func * rr_action,void * rr_action_data)431 foreach_rr(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
432 	   dns_rdatatype_t type, dns_rdatatype_t covers, rr_func *rr_action,
433 	   void *rr_action_data) {
434 	isc_result_t result;
435 	dns_dbnode_t *node;
436 	dns_rdataset_t rdataset;
437 
438 	if (type == dns_rdatatype_any) {
439 		return (foreach_node_rr(db, ver, name, rr_action,
440 					rr_action_data));
441 	}
442 
443 	node = NULL;
444 	if (type == dns_rdatatype_nsec3 ||
445 	    (type == dns_rdatatype_rrsig && covers == dns_rdatatype_nsec3))
446 	{
447 		result = dns_db_findnsec3node(db, name, false, &node);
448 	} else {
449 		result = dns_db_findnode(db, name, false, &node);
450 	}
451 	if (result == ISC_R_NOTFOUND) {
452 		return (ISC_R_SUCCESS);
453 	}
454 	if (result != ISC_R_SUCCESS) {
455 		return (result);
456 	}
457 
458 	dns_rdataset_init(&rdataset);
459 	result = dns_db_findrdataset(db, node, ver, type, covers,
460 				     (isc_stdtime_t)0, &rdataset, NULL);
461 	if (result == ISC_R_NOTFOUND) {
462 		result = ISC_R_SUCCESS;
463 		goto cleanup_node;
464 	}
465 	if (result != ISC_R_SUCCESS) {
466 		goto cleanup_node;
467 	}
468 
469 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
470 	     result = dns_rdataset_next(&rdataset))
471 	{
472 		rr_t rr = { 0, DNS_RDATA_INIT };
473 		dns_rdataset_current(&rdataset, &rr.rdata);
474 		rr.ttl = rdataset.ttl;
475 		result = (*rr_action)(rr_action_data, &rr);
476 		if (result != ISC_R_SUCCESS) {
477 			goto cleanup_rdataset;
478 		}
479 	}
480 	if (result != ISC_R_NOMORE) {
481 		goto cleanup_rdataset;
482 	}
483 	result = ISC_R_SUCCESS;
484 
485 cleanup_rdataset:
486 	dns_rdataset_disassociate(&rdataset);
487 cleanup_node:
488 	dns_db_detachnode(db, &node);
489 
490 	return (result);
491 }
492 
493 /**************************************************************************/
494 /*
495  * Various tests on the database contents (for prerequisites, etc).
496  */
497 
498 /*%
499  * Function type for predicate functions that compare a database RR 'db_rr'
500  * against an update RR 'update_rr'.
501  */
502 typedef bool
503 rr_predicate(dns_rdata_t *update_rr, dns_rdata_t *db_rr);
504 
505 /*%
506  * Helper function for rrset_exists().
507  */
508 static isc_result_t
rrset_exists_action(void * data,rr_t * rr)509 rrset_exists_action(void *data, rr_t *rr) {
510 	UNUSED(data);
511 	UNUSED(rr);
512 	return (ISC_R_EXISTS);
513 }
514 
515 /*%
516  * Utility macro for RR existence checking functions.
517  *
518  * If the variable 'result' has the value ISC_R_EXISTS or
519  * ISC_R_SUCCESS, set *exists to true or false,
520  * respectively, and return success.
521  *
522  * If 'result' has any other value, there was a failure.
523  * Return the failure result code and do not set *exists.
524  *
525  * This would be more readable as "do { if ... } while(0)",
526  * but that form generates tons of warnings on Solaris 2.6.
527  */
528 #define RETURN_EXISTENCE_FLAG                                         \
529 	return ((result == ISC_R_EXISTS)                              \
530 			? (*exists = true, ISC_R_SUCCESS)             \
531 			: ((result == ISC_R_SUCCESS)                  \
532 				   ? (*exists = false, ISC_R_SUCCESS) \
533 				   : result))
534 
535 /*%
536  * Set '*exists' to true iff an rrset of the given type exists,
537  * to false otherwise.
538  */
539 static isc_result_t
rrset_exists(dns_db_t * db,dns_dbversion_t * ver,dns_name_t * name,dns_rdatatype_t type,dns_rdatatype_t covers,bool * exists)540 rrset_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
541 	     dns_rdatatype_t type, dns_rdatatype_t covers, bool *exists) {
542 	isc_result_t result;
543 	result = foreach_rr(db, ver, name, type, covers, rrset_exists_action,
544 			    NULL);
545 	RETURN_EXISTENCE_FLAG;
546 }
547 
548 /*%
549  * Set '*visible' to true if the RRset exists and is part of the
550  * visible zone.  Otherwise '*visible' is set to false unless a
551  * error occurs.
552  */
553 static isc_result_t
rrset_visible(dns_db_t * db,dns_dbversion_t * ver,dns_name_t * name,dns_rdatatype_t type,bool * visible)554 rrset_visible(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
555 	      dns_rdatatype_t type, bool *visible) {
556 	isc_result_t result;
557 	dns_fixedname_t fixed;
558 
559 	dns_fixedname_init(&fixed);
560 	result = dns_db_find(db, name, ver, type, DNS_DBFIND_NOWILD,
561 			     (isc_stdtime_t)0, NULL, dns_fixedname_name(&fixed),
562 			     NULL, NULL);
563 	switch (result) {
564 	case ISC_R_SUCCESS:
565 		*visible = true;
566 		break;
567 	/*
568 	 * Glue, obscured, deleted or replaced records.
569 	 */
570 	case DNS_R_DELEGATION:
571 	case DNS_R_DNAME:
572 	case DNS_R_CNAME:
573 	case DNS_R_NXDOMAIN:
574 	case DNS_R_NXRRSET:
575 	case DNS_R_EMPTYNAME:
576 	case DNS_R_COVERINGNSEC:
577 		*visible = false;
578 		result = ISC_R_SUCCESS;
579 		break;
580 	default:
581 		*visible = false; /* silence false compiler warning */
582 		break;
583 	}
584 	return (result);
585 }
586 
587 /*%
588  * Context struct and helper function for name_exists().
589  */
590 
591 static isc_result_t
name_exists_action(void * data,dns_rdataset_t * rrset)592 name_exists_action(void *data, dns_rdataset_t *rrset) {
593 	UNUSED(data);
594 	UNUSED(rrset);
595 	return (ISC_R_EXISTS);
596 }
597 
598 /*%
599  * Set '*exists' to true iff the given name exists, to false otherwise.
600  */
601 static isc_result_t
name_exists(dns_db_t * db,dns_dbversion_t * ver,dns_name_t * name,bool * exists)602 name_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
603 	    bool *exists) {
604 	isc_result_t result;
605 	result = foreach_rrset(db, ver, name, name_exists_action, NULL);
606 	RETURN_EXISTENCE_FLAG;
607 }
608 
609 /**************************************************************************/
610 /*
611  * Checking of "RRset exists (value dependent)" prerequisites.
612  *
613  * In the RFC2136 section 3.2.5, this is the pseudocode involving
614  * a variable called "temp", a mapping of <name, type> tuples to rrsets.
615  *
616  * Here, we represent the "temp" data structure as (non-minimal) "dns_diff_t"
617  * where each tuple has op==DNS_DIFFOP_EXISTS.
618  */
619 
620 /*%
621  * A comparison function defining the sorting order for the entries
622  * in the "temp" data structure.  The major sort key is the owner name,
623  * followed by the type and rdata.
624  */
625 static int
temp_order(const void * av,const void * bv)626 temp_order(const void *av, const void *bv) {
627 	dns_difftuple_t const *const *ap = av;
628 	dns_difftuple_t const *const *bp = bv;
629 	dns_difftuple_t const *a = *ap;
630 	dns_difftuple_t const *b = *bp;
631 	int r;
632 	r = dns_name_compare(&a->name, &b->name);
633 	if (r != 0) {
634 		return (r);
635 	}
636 	r = (b->rdata.type - a->rdata.type);
637 	if (r != 0) {
638 		return (r);
639 	}
640 	r = dns_rdata_casecompare(&a->rdata, &b->rdata);
641 	return (r);
642 }
643 
644 /**************************************************************************/
645 /*
646  * Conditional deletion of RRs.
647  */
648 
649 /*%
650  * Context structure for delete_if().
651  */
652 
653 typedef struct {
654 	rr_predicate *predicate;
655 	dns_db_t *db;
656 	dns_dbversion_t *ver;
657 	dns_diff_t *diff;
658 	dns_name_t *name;
659 	dns_rdata_t *update_rr;
660 } conditional_delete_ctx_t;
661 
662 /*%
663  * Predicate functions for delete_if().
664  */
665 
666 /*%
667  * Return true always.
668  */
669 static bool
true_p(dns_rdata_t * update_rr,dns_rdata_t * db_rr)670 true_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) {
671 	UNUSED(update_rr);
672 	UNUSED(db_rr);
673 	return (true);
674 }
675 
676 /*%
677  * Return true if the record is a RRSIG.
678  */
679 static bool
rrsig_p(dns_rdata_t * update_rr,dns_rdata_t * db_rr)680 rrsig_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) {
681 	UNUSED(update_rr);
682 	return ((db_rr->type == dns_rdatatype_rrsig) ? true : false);
683 }
684 
685 /*%
686  * Internal helper function for delete_if().
687  */
688 static isc_result_t
delete_if_action(void * data,rr_t * rr)689 delete_if_action(void *data, rr_t *rr) {
690 	conditional_delete_ctx_t *ctx = data;
691 	if ((*ctx->predicate)(ctx->update_rr, &rr->rdata)) {
692 		isc_result_t result;
693 		result = update_one_rr(ctx->db, ctx->ver, ctx->diff,
694 				       DNS_DIFFOP_DEL, ctx->name, rr->ttl,
695 				       &rr->rdata);
696 		return (result);
697 	} else {
698 		return (ISC_R_SUCCESS);
699 	}
700 }
701 
702 /*%
703  * Conditionally delete RRs.  Apply 'predicate' to the RRs
704  * specified by 'db', 'ver', 'name', and 'type' (which can
705  * be dns_rdatatype_any to match any type).  Delete those
706  * RRs for which the predicate returns true, and log the
707  * deletions in 'diff'.
708  */
709 static isc_result_t
delete_if(rr_predicate * predicate,dns_db_t * db,dns_dbversion_t * ver,dns_name_t * name,dns_rdatatype_t type,dns_rdatatype_t covers,dns_rdata_t * update_rr,dns_diff_t * diff)710 delete_if(rr_predicate *predicate, dns_db_t *db, dns_dbversion_t *ver,
711 	  dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers,
712 	  dns_rdata_t *update_rr, dns_diff_t *diff) {
713 	conditional_delete_ctx_t ctx;
714 	ctx.predicate = predicate;
715 	ctx.db = db;
716 	ctx.ver = ver;
717 	ctx.diff = diff;
718 	ctx.name = name;
719 	ctx.update_rr = update_rr;
720 	return (foreach_rr(db, ver, name, type, covers, delete_if_action,
721 			   &ctx));
722 }
723 
724 /**************************************************************************/
725 /*
726  * Incremental updating of NSECs and RRSIGs.
727  */
728 
729 /*%
730  * We abuse the dns_diff_t type to represent a set of domain names
731  * affected by the update.
732  */
733 static isc_result_t
namelist_append_name(dns_diff_t * list,dns_name_t * name)734 namelist_append_name(dns_diff_t *list, dns_name_t *name) {
735 	isc_result_t result;
736 	dns_difftuple_t *tuple = NULL;
737 	static dns_rdata_t dummy_rdata = DNS_RDATA_INIT;
738 
739 	CHECK(dns_difftuple_create(list->mctx, DNS_DIFFOP_EXISTS, name, 0,
740 				   &dummy_rdata, &tuple));
741 	dns_diff_append(list, &tuple);
742 failure:
743 	return (result);
744 }
745 
746 static isc_result_t
namelist_append_subdomain(dns_db_t * db,dns_name_t * name,dns_diff_t * affected)747 namelist_append_subdomain(dns_db_t *db, dns_name_t *name,
748 			  dns_diff_t *affected) {
749 	isc_result_t result;
750 	dns_fixedname_t fixedname;
751 	dns_name_t *child;
752 	dns_dbiterator_t *dbit = NULL;
753 
754 	child = dns_fixedname_initname(&fixedname);
755 
756 	CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit));
757 
758 	for (result = dns_dbiterator_seek(dbit, name); result == ISC_R_SUCCESS;
759 	     result = dns_dbiterator_next(dbit))
760 	{
761 		dns_dbnode_t *node = NULL;
762 		CHECK(dns_dbiterator_current(dbit, &node, child));
763 		dns_db_detachnode(db, &node);
764 		if (!dns_name_issubdomain(child, name)) {
765 			break;
766 		}
767 		CHECK(namelist_append_name(affected, child));
768 	}
769 	if (result == ISC_R_NOMORE) {
770 		result = ISC_R_SUCCESS;
771 	}
772 failure:
773 	if (dbit != NULL) {
774 		dns_dbiterator_destroy(&dbit);
775 	}
776 	return (result);
777 }
778 
779 /*%
780  * Helper function for non_nsec_rrset_exists().
781  */
782 static isc_result_t
is_non_nsec_action(void * data,dns_rdataset_t * rrset)783 is_non_nsec_action(void *data, dns_rdataset_t *rrset) {
784 	UNUSED(data);
785 	if (!(rrset->type == dns_rdatatype_nsec ||
786 	      rrset->type == dns_rdatatype_nsec3 ||
787 	      (rrset->type == dns_rdatatype_rrsig &&
788 	       (rrset->covers == dns_rdatatype_nsec ||
789 		rrset->covers == dns_rdatatype_nsec3))))
790 	{
791 		return (ISC_R_EXISTS);
792 	}
793 	return (ISC_R_SUCCESS);
794 }
795 
796 /*%
797  * Check whether there is an rrset other than a NSEC or RRSIG NSEC,
798  * i.e., anything that justifies the continued existence of a name
799  * after a secure update.
800  *
801  * If such an rrset exists, set '*exists' to true.
802  * Otherwise, set it to false.
803  */
804 static isc_result_t
non_nsec_rrset_exists(dns_db_t * db,dns_dbversion_t * ver,dns_name_t * name,bool * exists)805 non_nsec_rrset_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
806 		      bool *exists) {
807 	isc_result_t result;
808 	result = foreach_rrset(db, ver, name, is_non_nsec_action, NULL);
809 	RETURN_EXISTENCE_FLAG;
810 }
811 
812 /*%
813  * A comparison function for sorting dns_diff_t:s by name.
814  */
815 static int
name_order(const void * av,const void * bv)816 name_order(const void *av, const void *bv) {
817 	dns_difftuple_t const *const *ap = av;
818 	dns_difftuple_t const *const *bp = bv;
819 	dns_difftuple_t const *a = *ap;
820 	dns_difftuple_t const *b = *bp;
821 	return (dns_name_compare(&a->name, &b->name));
822 }
823 
824 static isc_result_t
uniqify_name_list(dns_diff_t * list)825 uniqify_name_list(dns_diff_t *list) {
826 	isc_result_t result;
827 	dns_difftuple_t *p, *q;
828 
829 	CHECK(dns_diff_sort(list, name_order));
830 
831 	p = ISC_LIST_HEAD(list->tuples);
832 	while (p != NULL) {
833 		do {
834 			q = ISC_LIST_NEXT(p, link);
835 			if (q == NULL || !dns_name_equal(&p->name, &q->name)) {
836 				break;
837 			}
838 			ISC_LIST_UNLINK(list->tuples, q, link);
839 			dns_difftuple_free(&q);
840 		} while (1);
841 		p = ISC_LIST_NEXT(p, link);
842 	}
843 failure:
844 	return (result);
845 }
846 
847 static isc_result_t
is_active(dns_db_t * db,dns_dbversion_t * ver,dns_name_t * name,bool * flag,bool * cut,bool * unsecure)848 is_active(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, bool *flag,
849 	  bool *cut, bool *unsecure) {
850 	isc_result_t result;
851 	dns_fixedname_t foundname;
852 	dns_fixedname_init(&foundname);
853 	result = dns_db_find(db, name, ver, dns_rdatatype_any,
854 			     DNS_DBFIND_GLUEOK | DNS_DBFIND_NOWILD,
855 			     (isc_stdtime_t)0, NULL,
856 			     dns_fixedname_name(&foundname), NULL, NULL);
857 	if (result == ISC_R_SUCCESS || result == DNS_R_EMPTYNAME) {
858 		*flag = true;
859 		*cut = false;
860 		if (unsecure != NULL) {
861 			*unsecure = false;
862 		}
863 		return (ISC_R_SUCCESS);
864 	} else if (result == DNS_R_ZONECUT) {
865 		*flag = true;
866 		*cut = true;
867 		if (unsecure != NULL) {
868 			/*
869 			 * We are at the zonecut.  Check to see if there
870 			 * is a DS RRset.
871 			 */
872 			if (dns_db_find(db, name, ver, dns_rdatatype_ds, 0,
873 					(isc_stdtime_t)0, NULL,
874 					dns_fixedname_name(&foundname), NULL,
875 					NULL) == DNS_R_NXRRSET)
876 			{
877 				*unsecure = true;
878 			} else {
879 				*unsecure = false;
880 			}
881 		}
882 		return (ISC_R_SUCCESS);
883 	} else if (result == DNS_R_GLUE || result == DNS_R_DNAME ||
884 		   result == DNS_R_DELEGATION || result == DNS_R_NXDOMAIN)
885 	{
886 		*flag = false;
887 		*cut = false;
888 		if (unsecure != NULL) {
889 			*unsecure = false;
890 		}
891 		return (ISC_R_SUCCESS);
892 	} else {
893 		/*
894 		 * Silence compiler.
895 		 */
896 		*flag = false;
897 		*cut = false;
898 		if (unsecure != NULL) {
899 			*unsecure = false;
900 		}
901 		return (result);
902 	}
903 }
904 
905 /*%
906  * Find the next/previous name that has a NSEC record.
907  * In other words, skip empty database nodes and names that
908  * have had their NSECs removed because they are obscured by
909  * a zone cut.
910  */
911 static isc_result_t
next_active(dns_update_log_t * log,dns_zone_t * zone,dns_db_t * db,dns_dbversion_t * ver,dns_name_t * oldname,dns_name_t * newname,bool forward)912 next_active(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
913 	    dns_dbversion_t *ver, dns_name_t *oldname, dns_name_t *newname,
914 	    bool forward) {
915 	isc_result_t result;
916 	dns_dbiterator_t *dbit = NULL;
917 	bool has_nsec = false;
918 	unsigned int wraps = 0;
919 	bool secure = dns_db_issecure(db);
920 
921 	CHECK(dns_db_createiterator(db, 0, &dbit));
922 
923 	CHECK(dns_dbiterator_seek(dbit, oldname));
924 	do {
925 		dns_dbnode_t *node = NULL;
926 
927 		if (forward) {
928 			result = dns_dbiterator_next(dbit);
929 		} else {
930 			result = dns_dbiterator_prev(dbit);
931 		}
932 		if (result == ISC_R_NOMORE) {
933 			/*
934 			 * Wrap around.
935 			 */
936 			if (forward) {
937 				CHECK(dns_dbiterator_first(dbit));
938 			} else {
939 				CHECK(dns_dbiterator_last(dbit));
940 			}
941 			wraps++;
942 			if (wraps == 2) {
943 				update_log(log, zone, ISC_LOG_ERROR,
944 					   "secure zone with no NSECs");
945 				result = DNS_R_BADZONE;
946 				goto failure;
947 			}
948 		}
949 		CHECK(dns_dbiterator_current(dbit, &node, newname));
950 		dns_db_detachnode(db, &node);
951 
952 		/*
953 		 * The iterator may hold the tree lock, and
954 		 * rrset_exists() calls dns_db_findnode() which
955 		 * may try to reacquire it.  To avoid deadlock
956 		 * we must pause the iterator first.
957 		 */
958 		CHECK(dns_dbiterator_pause(dbit));
959 		if (secure) {
960 			CHECK(rrset_exists(db, ver, newname, dns_rdatatype_nsec,
961 					   0, &has_nsec));
962 		} else {
963 			dns_fixedname_t ffound;
964 			dns_name_t *found;
965 			found = dns_fixedname_initname(&ffound);
966 			result = dns_db_find(
967 				db, newname, ver, dns_rdatatype_soa,
968 				DNS_DBFIND_NOWILD, 0, NULL, found, NULL, NULL);
969 			if (result == ISC_R_SUCCESS ||
970 			    result == DNS_R_EMPTYNAME ||
971 			    result == DNS_R_NXRRSET || result == DNS_R_CNAME ||
972 			    (result == DNS_R_DELEGATION &&
973 			     dns_name_equal(newname, found)))
974 			{
975 				has_nsec = true;
976 				result = ISC_R_SUCCESS;
977 			} else if (result != DNS_R_NXDOMAIN) {
978 				break;
979 			}
980 		}
981 	} while (!has_nsec);
982 failure:
983 	if (dbit != NULL) {
984 		dns_dbiterator_destroy(&dbit);
985 	}
986 
987 	return (result);
988 }
989 
990 /*%
991  * Add a NSEC record for "name", recording the change in "diff".
992  * The existing NSEC is removed.
993  */
994 static isc_result_t
add_nsec(dns_update_log_t * log,dns_zone_t * zone,dns_db_t * db,dns_dbversion_t * ver,dns_name_t * name,dns_ttl_t nsecttl,dns_diff_t * diff)995 add_nsec(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
996 	 dns_dbversion_t *ver, dns_name_t *name, dns_ttl_t nsecttl,
997 	 dns_diff_t *diff) {
998 	isc_result_t result;
999 	dns_dbnode_t *node = NULL;
1000 	unsigned char buffer[DNS_NSEC_BUFFERSIZE];
1001 	dns_rdata_t rdata = DNS_RDATA_INIT;
1002 	dns_difftuple_t *tuple = NULL;
1003 	dns_fixedname_t fixedname;
1004 	dns_name_t *target;
1005 
1006 	target = dns_fixedname_initname(&fixedname);
1007 
1008 	/*
1009 	 * Find the successor name, aka NSEC target.
1010 	 */
1011 	CHECK(next_active(log, zone, db, ver, name, target, true));
1012 
1013 	/*
1014 	 * Create the NSEC RDATA.
1015 	 */
1016 	CHECK(dns_db_findnode(db, name, false, &node));
1017 	dns_rdata_init(&rdata);
1018 	CHECK(dns_nsec_buildrdata(db, ver, node, target, buffer, &rdata));
1019 	dns_db_detachnode(db, &node);
1020 
1021 	/*
1022 	 * Delete the old NSEC and record the change.
1023 	 */
1024 	CHECK(delete_if(true_p, db, ver, name, dns_rdatatype_nsec, 0, NULL,
1025 			diff));
1026 	/*
1027 	 * Add the new NSEC and record the change.
1028 	 */
1029 	CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, name, nsecttl,
1030 				   &rdata, &tuple));
1031 	CHECK(do_one_tuple(&tuple, db, ver, diff));
1032 	INSIST(tuple == NULL);
1033 
1034 failure:
1035 	if (node != NULL) {
1036 		dns_db_detachnode(db, &node);
1037 	}
1038 	return (result);
1039 }
1040 
1041 /*%
1042  * Add a placeholder NSEC record for "name", recording the change in "diff".
1043  */
1044 static isc_result_t
add_placeholder_nsec(dns_db_t * db,dns_dbversion_t * ver,dns_name_t * name,dns_diff_t * diff)1045 add_placeholder_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
1046 		     dns_diff_t *diff) {
1047 	isc_result_t result;
1048 	dns_difftuple_t *tuple = NULL;
1049 	isc_region_t r;
1050 	unsigned char data[1] = { 0 }; /* The root domain, no bits. */
1051 	dns_rdata_t rdata = DNS_RDATA_INIT;
1052 
1053 	r.base = data;
1054 	r.length = sizeof(data);
1055 	dns_rdata_fromregion(&rdata, dns_db_class(db), dns_rdatatype_nsec, &r);
1056 	CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, name, 0, &rdata,
1057 				   &tuple));
1058 	CHECK(do_one_tuple(&tuple, db, ver, diff));
1059 failure:
1060 	return (result);
1061 }
1062 
1063 static isc_result_t
find_zone_keys(dns_zone_t * zone,dns_db_t * db,dns_dbversion_t * ver,isc_mem_t * mctx,unsigned int maxkeys,dst_key_t ** keys,unsigned int * nkeys)1064 find_zone_keys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
1065 	       isc_mem_t *mctx, unsigned int maxkeys, dst_key_t **keys,
1066 	       unsigned int *nkeys) {
1067 	isc_result_t result;
1068 	isc_stdtime_t now;
1069 	dns_dbnode_t *node = NULL;
1070 	const char *directory = dns_zone_getkeydirectory(zone);
1071 
1072 	CHECK(dns_db_findnode(db, dns_db_origin(db), false, &node));
1073 	isc_stdtime_get(&now);
1074 
1075 	dns_zone_lock_keyfiles(zone);
1076 	result = dns_dnssec_findzonekeys(db, ver, node, dns_db_origin(db),
1077 					 directory, now, mctx, maxkeys, keys,
1078 					 nkeys);
1079 	dns_zone_unlock_keyfiles(zone);
1080 
1081 failure:
1082 	if (node != NULL) {
1083 		dns_db_detachnode(db, &node);
1084 	}
1085 	return (result);
1086 }
1087 
1088 /*%
1089  * Add RRSIG records for an RRset, recording the change in "diff".
1090  */
1091 static isc_result_t
add_sigs(dns_update_log_t * log,dns_zone_t * zone,dns_db_t * db,dns_dbversion_t * ver,dns_name_t * name,dns_rdatatype_t type,dns_diff_t * diff,dst_key_t ** keys,unsigned int nkeys,isc_stdtime_t inception,isc_stdtime_t expire,bool check_ksk,bool keyset_kskonly)1092 add_sigs(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
1093 	 dns_dbversion_t *ver, dns_name_t *name, dns_rdatatype_t type,
1094 	 dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys,
1095 	 isc_stdtime_t inception, isc_stdtime_t expire, bool check_ksk,
1096 	 bool keyset_kskonly) {
1097 	isc_result_t result;
1098 	dns_dbnode_t *node = NULL;
1099 	dns_kasp_t *kasp = dns_zone_getkasp(zone);
1100 	dns_rdataset_t rdataset;
1101 	dns_rdata_t sig_rdata = DNS_RDATA_INIT;
1102 	dns_stats_t *dnssecsignstats = dns_zone_getdnssecsignstats(zone);
1103 	isc_buffer_t buffer;
1104 	unsigned char data[1024]; /* XXX */
1105 	unsigned int i, j;
1106 	bool added_sig = false;
1107 	bool use_kasp = false;
1108 	isc_mem_t *mctx = diff->mctx;
1109 
1110 	if (kasp != NULL) {
1111 		check_ksk = false;
1112 		keyset_kskonly = true;
1113 		use_kasp = true;
1114 	}
1115 
1116 	dns_rdataset_init(&rdataset);
1117 	isc_buffer_init(&buffer, data, sizeof(data));
1118 
1119 	/* Get the rdataset to sign. */
1120 	if (type == dns_rdatatype_nsec3) {
1121 		CHECK(dns_db_findnsec3node(db, name, false, &node));
1122 	} else {
1123 		CHECK(dns_db_findnode(db, name, false, &node));
1124 	}
1125 	CHECK(dns_db_findrdataset(db, node, ver, type, 0, (isc_stdtime_t)0,
1126 				  &rdataset, NULL));
1127 	dns_db_detachnode(db, &node);
1128 
1129 #define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
1130 #define KSK(x)	  ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
1131 #define ID(x)	  dst_key_id(x)
1132 #define ALG(x)	  dst_key_alg(x)
1133 
1134 	/*
1135 	 * If we are honoring KSK flags then we need to check that we
1136 	 * have both KSK and non-KSK keys that are not revoked per
1137 	 * algorithm.
1138 	 */
1139 	for (i = 0; i < nkeys; i++) {
1140 		bool both = false;
1141 
1142 		/* Don't add signatures for offline or inactive keys */
1143 		if (!dst_key_isprivate(keys[i])) {
1144 			continue;
1145 		}
1146 		if (dst_key_inactive(keys[i])) {
1147 			continue;
1148 		}
1149 
1150 		if (check_ksk && !REVOKE(keys[i])) {
1151 			bool have_ksk, have_nonksk;
1152 			if (KSK(keys[i])) {
1153 				have_ksk = true;
1154 				have_nonksk = false;
1155 			} else {
1156 				have_ksk = false;
1157 				have_nonksk = true;
1158 			}
1159 			for (j = 0; j < nkeys; j++) {
1160 				if (j == i || ALG(keys[i]) != ALG(keys[j])) {
1161 					continue;
1162 				}
1163 
1164 				/* Don't consider inactive keys, however
1165 				 * the KSK may be temporary offline, so do
1166 				 * consider KSKs which private key files are
1167 				 * unavailable.
1168 				 */
1169 				if (dst_key_inactive(keys[j])) {
1170 					continue;
1171 				}
1172 
1173 				if (REVOKE(keys[j])) {
1174 					continue;
1175 				}
1176 				if (KSK(keys[j])) {
1177 					have_ksk = true;
1178 				} else if (dst_key_isprivate(keys[j])) {
1179 					have_nonksk = true;
1180 				}
1181 				both = have_ksk && have_nonksk;
1182 				if (both) {
1183 					break;
1184 				}
1185 			}
1186 		}
1187 
1188 		if (use_kasp) {
1189 			/*
1190 			 * A dnssec-policy is found. Check what RRsets this
1191 			 * key should sign.
1192 			 */
1193 			isc_stdtime_t when;
1194 			isc_result_t kresult;
1195 			bool ksk = false;
1196 			bool zsk = false;
1197 
1198 			kresult = dst_key_getbool(keys[i], DST_BOOL_KSK, &ksk);
1199 			if (kresult != ISC_R_SUCCESS) {
1200 				if (KSK(keys[i])) {
1201 					ksk = true;
1202 				}
1203 			}
1204 			kresult = dst_key_getbool(keys[i], DST_BOOL_ZSK, &zsk);
1205 			if (kresult != ISC_R_SUCCESS) {
1206 				if (!KSK(keys[i])) {
1207 					zsk = true;
1208 				}
1209 			}
1210 
1211 			if (type == dns_rdatatype_dnskey ||
1212 			    type == dns_rdatatype_cdnskey ||
1213 			    type == dns_rdatatype_cds)
1214 			{
1215 				/*
1216 				 * DNSKEY RRset is signed with KSK.
1217 				 * CDS and CDNSKEY RRsets too (RFC 7344, 4.1).
1218 				 */
1219 				if (!ksk) {
1220 					continue;
1221 				}
1222 			} else if (!zsk) {
1223 				/*
1224 				 * Other RRsets are signed with ZSK.
1225 				 */
1226 				continue;
1227 			} else if (zsk &&
1228 				   !dst_key_is_signing(keys[i], DST_BOOL_ZSK,
1229 						       inception, &when))
1230 			{
1231 				/*
1232 				 * This key is not active for zone-signing.
1233 				 */
1234 				continue;
1235 			}
1236 
1237 			/*
1238 			 * If this key is revoked, it may only sign the
1239 			 * DNSKEY RRset.
1240 			 */
1241 			if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey) {
1242 				continue;
1243 			}
1244 		} else if (both) {
1245 			/*
1246 			 * CDS and CDNSKEY are signed with KSK (RFC 7344, 4.1).
1247 			 */
1248 			if (type == dns_rdatatype_dnskey ||
1249 			    type == dns_rdatatype_cdnskey ||
1250 			    type == dns_rdatatype_cds)
1251 			{
1252 				if (!KSK(keys[i]) && keyset_kskonly) {
1253 					continue;
1254 				}
1255 			} else if (KSK(keys[i])) {
1256 				continue;
1257 			}
1258 		} else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey) {
1259 			continue;
1260 		}
1261 
1262 		/* Calculate the signature, creating a RRSIG RDATA. */
1263 		CHECK(dns_dnssec_sign(name, &rdataset, keys[i], &inception,
1264 				      &expire, mctx, &buffer, &sig_rdata));
1265 
1266 		/* Update the database and journal with the RRSIG. */
1267 		/* XXX inefficient - will cause dataset merging */
1268 		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN, name,
1269 				    rdataset.ttl, &sig_rdata));
1270 		dns_rdata_reset(&sig_rdata);
1271 		isc_buffer_init(&buffer, data, sizeof(data));
1272 		added_sig = true;
1273 		/* Update DNSSEC sign statistics. */
1274 		if (dnssecsignstats != NULL) {
1275 			dns_dnssecsignstats_increment(dnssecsignstats,
1276 						      ID(keys[i]),
1277 						      (uint8_t)ALG(keys[i]),
1278 						      dns_dnssecsignstats_sign);
1279 		}
1280 	}
1281 	if (!added_sig) {
1282 		update_log(log, zone, ISC_LOG_ERROR,
1283 			   "found no active private keys, "
1284 			   "unable to generate any signatures");
1285 		result = ISC_R_NOTFOUND;
1286 	}
1287 
1288 failure:
1289 	if (dns_rdataset_isassociated(&rdataset)) {
1290 		dns_rdataset_disassociate(&rdataset);
1291 	}
1292 	if (node != NULL) {
1293 		dns_db_detachnode(db, &node);
1294 	}
1295 	return (result);
1296 }
1297 
1298 /*
1299  * Delete expired RRsigs and any RRsigs we are about to re-sign.
1300  * See also zone.c:del_sigs().
1301  */
1302 static isc_result_t
del_keysigs(dns_db_t * db,dns_dbversion_t * ver,dns_name_t * name,dns_diff_t * diff,dst_key_t ** keys,unsigned int nkeys)1303 del_keysigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
1304 	    dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys) {
1305 	isc_result_t result;
1306 	dns_dbnode_t *node = NULL;
1307 	dns_rdataset_t rdataset;
1308 	dns_rdata_t rdata = DNS_RDATA_INIT;
1309 	unsigned int i;
1310 	dns_rdata_rrsig_t rrsig;
1311 	bool found;
1312 
1313 	dns_rdataset_init(&rdataset);
1314 
1315 	result = dns_db_findnode(db, name, false, &node);
1316 	if (result == ISC_R_NOTFOUND) {
1317 		return (ISC_R_SUCCESS);
1318 	}
1319 	if (result != ISC_R_SUCCESS) {
1320 		goto failure;
1321 	}
1322 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig,
1323 				     dns_rdatatype_dnskey, (isc_stdtime_t)0,
1324 				     &rdataset, NULL);
1325 	dns_db_detachnode(db, &node);
1326 
1327 	if (result == ISC_R_NOTFOUND) {
1328 		return (ISC_R_SUCCESS);
1329 	}
1330 	if (result != ISC_R_SUCCESS) {
1331 		goto failure;
1332 	}
1333 
1334 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
1335 	     result = dns_rdataset_next(&rdataset))
1336 	{
1337 		dns_rdataset_current(&rdataset, &rdata);
1338 		result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
1339 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
1340 		found = false;
1341 		for (i = 0; i < nkeys; i++) {
1342 			if (rrsig.keyid == dst_key_id(keys[i])) {
1343 				found = true;
1344 				if (!dst_key_isprivate(keys[i]) &&
1345 				    !dst_key_inactive(keys[i]))
1346 				{
1347 					/*
1348 					 * The re-signing code in zone.c
1349 					 * will mark this as offline.
1350 					 * Just skip the record for now.
1351 					 */
1352 					break;
1353 				}
1354 				result = update_one_rr(db, ver, diff,
1355 						       DNS_DIFFOP_DEL, name,
1356 						       rdataset.ttl, &rdata);
1357 				break;
1358 			}
1359 		}
1360 		/*
1361 		 * If there is not a matching DNSKEY then delete the RRSIG.
1362 		 */
1363 		if (!found) {
1364 			result = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
1365 					       name, rdataset.ttl, &rdata);
1366 		}
1367 		dns_rdata_reset(&rdata);
1368 		if (result != ISC_R_SUCCESS) {
1369 			break;
1370 		}
1371 	}
1372 	dns_rdataset_disassociate(&rdataset);
1373 	if (result == ISC_R_NOMORE) {
1374 		result = ISC_R_SUCCESS;
1375 	}
1376 failure:
1377 	if (node != NULL) {
1378 		dns_db_detachnode(db, &node);
1379 	}
1380 	return (result);
1381 }
1382 
1383 static isc_result_t
add_exposed_sigs(dns_update_log_t * log,dns_zone_t * zone,dns_db_t * db,dns_dbversion_t * ver,dns_name_t * name,bool cut,dns_diff_t * diff,dst_key_t ** keys,unsigned int nkeys,isc_stdtime_t inception,isc_stdtime_t expire,bool check_ksk,bool keyset_kskonly,unsigned int * sigs)1384 add_exposed_sigs(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
1385 		 dns_dbversion_t *ver, dns_name_t *name, bool cut,
1386 		 dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys,
1387 		 isc_stdtime_t inception, isc_stdtime_t expire, bool check_ksk,
1388 		 bool keyset_kskonly, unsigned int *sigs) {
1389 	isc_result_t result;
1390 	dns_dbnode_t *node;
1391 	dns_rdatasetiter_t *iter;
1392 
1393 	node = NULL;
1394 	result = dns_db_findnode(db, name, false, &node);
1395 	if (result == ISC_R_NOTFOUND) {
1396 		return (ISC_R_SUCCESS);
1397 	}
1398 	if (result != ISC_R_SUCCESS) {
1399 		return (result);
1400 	}
1401 
1402 	iter = NULL;
1403 	result = dns_db_allrdatasets(db, node, ver, 0, (isc_stdtime_t)0, &iter);
1404 	if (result != ISC_R_SUCCESS) {
1405 		goto cleanup_node;
1406 	}
1407 
1408 	for (result = dns_rdatasetiter_first(iter); result == ISC_R_SUCCESS;
1409 	     result = dns_rdatasetiter_next(iter))
1410 	{
1411 		dns_rdataset_t rdataset;
1412 		dns_rdatatype_t type;
1413 		bool flag;
1414 
1415 		dns_rdataset_init(&rdataset);
1416 		dns_rdatasetiter_current(iter, &rdataset);
1417 		type = rdataset.type;
1418 		dns_rdataset_disassociate(&rdataset);
1419 
1420 		/*
1421 		 * We don't need to sign unsigned NSEC records at the cut
1422 		 * as they are handled elsewhere.
1423 		 */
1424 		if ((type == dns_rdatatype_rrsig) ||
1425 		    (cut && type != dns_rdatatype_ds))
1426 		{
1427 			continue;
1428 		}
1429 		result = rrset_exists(db, ver, name, dns_rdatatype_rrsig, type,
1430 				      &flag);
1431 		if (result != ISC_R_SUCCESS) {
1432 			goto cleanup_iterator;
1433 		}
1434 		if (flag) {
1435 			continue;
1436 		}
1437 		result = add_sigs(log, zone, db, ver, name, type, diff, keys,
1438 				  nkeys, inception, expire, check_ksk,
1439 				  keyset_kskonly);
1440 		if (result != ISC_R_SUCCESS) {
1441 			goto cleanup_iterator;
1442 		}
1443 		(*sigs)++;
1444 	}
1445 	if (result == ISC_R_NOMORE) {
1446 		result = ISC_R_SUCCESS;
1447 	}
1448 
1449 cleanup_iterator:
1450 	dns_rdatasetiter_destroy(&iter);
1451 
1452 cleanup_node:
1453 	dns_db_detachnode(db, &node);
1454 
1455 	return (result);
1456 }
1457 
1458 /*%
1459  * Update RRSIG, NSEC and NSEC3 records affected by an update.  The original
1460  * update, including the SOA serial update but excluding the RRSIG & NSEC
1461  * changes, is in "diff" and has already been applied to "newver" of "db".
1462  * The database version prior to the update is "oldver".
1463  *
1464  * The necessary RRSIG, NSEC and NSEC3 changes will be applied to "newver"
1465  * and added (as a minimal diff) to "diff".
1466  *
1467  * The RRSIGs generated will be valid for 'sigvalidityinterval' seconds.
1468  */
1469 isc_result_t
dns_update_signatures(dns_update_log_t * log,dns_zone_t * zone,dns_db_t * db,dns_dbversion_t * oldver,dns_dbversion_t * newver,dns_diff_t * diff,uint32_t sigvalidityinterval)1470 dns_update_signatures(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
1471 		      dns_dbversion_t *oldver, dns_dbversion_t *newver,
1472 		      dns_diff_t *diff, uint32_t sigvalidityinterval) {
1473 	return (dns_update_signaturesinc(log, zone, db, oldver, newver, diff,
1474 					 sigvalidityinterval, NULL));
1475 }
1476 
1477 struct dns_update_state {
1478 	unsigned int magic;
1479 	dns_diff_t diffnames;
1480 	dns_diff_t affected;
1481 	dns_diff_t sig_diff;
1482 	dns_diff_t nsec_diff;
1483 	dns_diff_t nsec_mindiff;
1484 	dns_diff_t work;
1485 	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
1486 	unsigned int nkeys;
1487 	isc_stdtime_t inception, expire, soaexpire, keyexpire;
1488 	dns_ttl_t nsecttl;
1489 	bool check_ksk, keyset_kskonly, build_nsec3;
1490 	enum {
1491 		sign_updates,
1492 		remove_orphaned,
1493 		build_chain,
1494 		process_nsec,
1495 		sign_nsec,
1496 		update_nsec3,
1497 		process_nsec3,
1498 		sign_nsec3
1499 	} state;
1500 };
1501 
1502 static uint32_t
dns__jitter_expire(dns_zone_t * zone,uint32_t sigvalidityinterval)1503 dns__jitter_expire(dns_zone_t *zone, uint32_t sigvalidityinterval) {
1504 	/* Spread out signatures over time */
1505 	if (sigvalidityinterval >= 3600U) {
1506 		uint32_t expiryinterval =
1507 			dns_zone_getsigresigninginterval(zone);
1508 
1509 		if (sigvalidityinterval < 7200U) {
1510 			expiryinterval = 1200;
1511 		} else if (expiryinterval > sigvalidityinterval) {
1512 			expiryinterval = sigvalidityinterval;
1513 		} else {
1514 			expiryinterval = sigvalidityinterval - expiryinterval;
1515 		}
1516 		uint32_t jitter = isc_random_uniform(expiryinterval);
1517 		sigvalidityinterval -= jitter;
1518 	}
1519 	return (sigvalidityinterval);
1520 }
1521 
1522 isc_result_t
dns_update_signaturesinc(dns_update_log_t * log,dns_zone_t * zone,dns_db_t * db,dns_dbversion_t * oldver,dns_dbversion_t * newver,dns_diff_t * diff,uint32_t sigvalidityinterval,dns_update_state_t ** statep)1523 dns_update_signaturesinc(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
1524 			 dns_dbversion_t *oldver, dns_dbversion_t *newver,
1525 			 dns_diff_t *diff, uint32_t sigvalidityinterval,
1526 			 dns_update_state_t **statep) {
1527 	isc_result_t result = ISC_R_SUCCESS;
1528 	dns_update_state_t mystate, *state;
1529 
1530 	dns_difftuple_t *t, *next;
1531 	bool flag, build_nsec;
1532 	unsigned int i;
1533 	isc_stdtime_t now;
1534 	dns_rdata_soa_t soa;
1535 	dns_rdata_t rdata = DNS_RDATA_INIT;
1536 	dns_rdataset_t rdataset;
1537 	dns_dbnode_t *node = NULL;
1538 	bool unsecure;
1539 	bool cut;
1540 	dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
1541 	unsigned int sigs = 0;
1542 	unsigned int maxsigs = dns_zone_getsignatures(zone);
1543 
1544 	if (statep == NULL || *statep == NULL) {
1545 		if (statep == NULL) {
1546 			state = &mystate;
1547 		} else {
1548 			state = isc_mem_get(diff->mctx, sizeof(*state));
1549 		}
1550 
1551 		dns_diff_init(diff->mctx, &state->diffnames);
1552 		dns_diff_init(diff->mctx, &state->affected);
1553 		dns_diff_init(diff->mctx, &state->sig_diff);
1554 		dns_diff_init(diff->mctx, &state->nsec_diff);
1555 		dns_diff_init(diff->mctx, &state->nsec_mindiff);
1556 		dns_diff_init(diff->mctx, &state->work);
1557 		state->nkeys = 0;
1558 		state->build_nsec3 = false;
1559 
1560 		result = find_zone_keys(zone, db, newver, diff->mctx,
1561 					DNS_MAXZONEKEYS, state->zone_keys,
1562 					&state->nkeys);
1563 		if (result != ISC_R_SUCCESS) {
1564 			update_log(log, zone, ISC_LOG_ERROR,
1565 				   "could not get zone keys for secure "
1566 				   "dynamic update");
1567 			goto failure;
1568 		}
1569 
1570 		isc_stdtime_get(&now);
1571 		state->inception = now - 3600; /* Allow for some clock skew. */
1572 		state->expire = now +
1573 				dns__jitter_expire(zone, sigvalidityinterval);
1574 		state->soaexpire = now + sigvalidityinterval;
1575 		state->keyexpire = dns_zone_getkeyvalidityinterval(zone);
1576 		if (state->keyexpire == 0) {
1577 			state->keyexpire = state->expire;
1578 		} else {
1579 			state->keyexpire += now;
1580 		}
1581 
1582 		/*
1583 		 * Do we look at the KSK flag on the DNSKEY to determining which
1584 		 * keys sign which RRsets?  First check the zone option then
1585 		 * check the keys flags to make sure at least one has a ksk set
1586 		 * and one doesn't.
1587 		 */
1588 		state->check_ksk = ((dns_zone_getoptions(zone) &
1589 				     DNS_ZONEOPT_UPDATECHECKKSK) != 0);
1590 		state->keyset_kskonly = ((dns_zone_getoptions(zone) &
1591 					  DNS_ZONEOPT_DNSKEYKSKONLY) != 0);
1592 
1593 		/*
1594 		 * Calculate the NSEC/NSEC3 TTL as a minimum of the SOA TTL and
1595 		 * MINIMUM field.
1596 		 */
1597 		CHECK(dns_db_findnode(db, dns_db_origin(db), false, &node));
1598 		dns_rdataset_init(&rdataset);
1599 		CHECK(dns_db_findrdataset(db, node, newver, dns_rdatatype_soa,
1600 					  0, (isc_stdtime_t)0, &rdataset,
1601 					  NULL));
1602 		CHECK(dns_rdataset_first(&rdataset));
1603 		dns_rdataset_current(&rdataset, &rdata);
1604 		CHECK(dns_rdata_tostruct(&rdata, &soa, NULL));
1605 		state->nsecttl = ISC_MIN(rdataset.ttl, soa.minimum);
1606 		dns_rdataset_disassociate(&rdataset);
1607 		dns_db_detachnode(db, &node);
1608 
1609 		/*
1610 		 * Find all RRsets directly affected by the update, and
1611 		 * update their RRSIGs.  Also build a list of names affected
1612 		 * by the update in "diffnames".
1613 		 */
1614 		CHECK(dns_diff_sort(diff, temp_order));
1615 		state->state = sign_updates;
1616 		state->magic = STATE_MAGIC;
1617 		if (statep != NULL) {
1618 			*statep = state;
1619 		}
1620 	} else {
1621 		REQUIRE(DNS_STATE_VALID(*statep));
1622 		state = *statep;
1623 	}
1624 
1625 next_state:
1626 	switch (state->state) {
1627 	case sign_updates:
1628 		t = ISC_LIST_HEAD(diff->tuples);
1629 		while (t != NULL) {
1630 			dns_name_t *name = &t->name;
1631 			/*
1632 			 * Now "name" is a new, unique name affected by the
1633 			 * update.
1634 			 */
1635 
1636 			CHECK(namelist_append_name(&state->diffnames, name));
1637 
1638 			while (t != NULL && dns_name_equal(&t->name, name)) {
1639 				dns_rdatatype_t type;
1640 				type = t->rdata.type;
1641 
1642 				/*
1643 				 * Now "name" and "type" denote a new unique
1644 				 * RRset affected by the update.
1645 				 */
1646 
1647 				/* Don't sign RRSIGs. */
1648 				if (type == dns_rdatatype_rrsig) {
1649 					goto skip;
1650 				}
1651 
1652 				/*
1653 				 * Delete all old RRSIGs covering this type,
1654 				 * since they are all invalid when the signed
1655 				 * RRset has changed.  We may not be able to
1656 				 * recreate all of them - tough.
1657 				 * Special case changes to the zone's DNSKEY
1658 				 * records to support offline KSKs.
1659 				 */
1660 				if (type == dns_rdatatype_dnskey) {
1661 					del_keysigs(db, newver, name,
1662 						    &state->sig_diff,
1663 						    state->zone_keys,
1664 						    state->nkeys);
1665 				} else {
1666 					CHECK(delete_if(
1667 						true_p, db, newver, name,
1668 						dns_rdatatype_rrsig, type, NULL,
1669 						&state->sig_diff));
1670 				}
1671 
1672 				/*
1673 				 * If this RRset is still visible after the
1674 				 * update, add a new signature for it.
1675 				 */
1676 				CHECK(rrset_visible(db, newver, name, type,
1677 						    &flag));
1678 				if (flag) {
1679 					isc_stdtime_t exp;
1680 					if (type == dns_rdatatype_dnskey ||
1681 					    type == dns_rdatatype_cdnskey ||
1682 					    type == dns_rdatatype_cds)
1683 					{
1684 						exp = state->keyexpire;
1685 					} else if (type == dns_rdatatype_soa) {
1686 						exp = state->soaexpire;
1687 					} else {
1688 						exp = state->expire;
1689 					}
1690 
1691 					CHECK(add_sigs(
1692 						log, zone, db, newver, name,
1693 						type, &state->sig_diff,
1694 						state->zone_keys, state->nkeys,
1695 						state->inception, exp,
1696 						state->check_ksk,
1697 						state->keyset_kskonly));
1698 					sigs++;
1699 				}
1700 			skip:
1701 				/* Skip any other updates to the same RRset. */
1702 				while (t != NULL &&
1703 				       dns_name_equal(&t->name, name) &&
1704 				       t->rdata.type == type)
1705 				{
1706 					next = ISC_LIST_NEXT(t, link);
1707 					ISC_LIST_UNLINK(diff->tuples, t, link);
1708 					ISC_LIST_APPEND(state->work.tuples, t,
1709 							link);
1710 					t = next;
1711 				}
1712 			}
1713 			if (state != &mystate && sigs > maxsigs) {
1714 				return (DNS_R_CONTINUE);
1715 			}
1716 		}
1717 		ISC_LIST_APPENDLIST(diff->tuples, state->work.tuples, link);
1718 
1719 		update_log(log, zone, ISC_LOG_DEBUG(3),
1720 			   "updated data signatures");
1721 		FALLTHROUGH;
1722 	case remove_orphaned:
1723 		state->state = remove_orphaned;
1724 
1725 		/* Remove orphaned NSECs and RRSIG NSECs. */
1726 		for (t = ISC_LIST_HEAD(state->diffnames.tuples); t != NULL;
1727 		     t = ISC_LIST_NEXT(t, link))
1728 		{
1729 			CHECK(non_nsec_rrset_exists(db, newver, &t->name,
1730 						    &flag));
1731 			if (!flag) {
1732 				CHECK(delete_if(true_p, db, newver, &t->name,
1733 						dns_rdatatype_any, 0, NULL,
1734 						&state->sig_diff));
1735 			}
1736 		}
1737 		update_log(log, zone, ISC_LOG_DEBUG(3),
1738 			   "removed any orphaned NSEC records");
1739 
1740 		/*
1741 		 * See if we need to build NSEC or NSEC3 chains.
1742 		 */
1743 		CHECK(dns_private_chains(db, newver, privatetype, &build_nsec,
1744 					 &state->build_nsec3));
1745 		if (!build_nsec) {
1746 			state->state = update_nsec3;
1747 			goto next_state;
1748 		}
1749 
1750 		update_log(log, zone, ISC_LOG_DEBUG(3),
1751 			   "rebuilding NSEC chain");
1752 
1753 		FALLTHROUGH;
1754 	case build_chain:
1755 		state->state = build_chain;
1756 		/*
1757 		 * When a name is created or deleted, its predecessor needs to
1758 		 * have its NSEC updated.
1759 		 */
1760 		for (t = ISC_LIST_HEAD(state->diffnames.tuples); t != NULL;
1761 		     t = ISC_LIST_NEXT(t, link))
1762 		{
1763 			bool existed, exists;
1764 			dns_fixedname_t fixedname;
1765 			dns_name_t *prevname;
1766 
1767 			prevname = dns_fixedname_initname(&fixedname);
1768 
1769 			if (oldver != NULL) {
1770 				CHECK(name_exists(db, oldver, &t->name,
1771 						  &existed));
1772 			} else {
1773 				existed = false;
1774 			}
1775 			CHECK(name_exists(db, newver, &t->name, &exists));
1776 			if (exists == existed) {
1777 				continue;
1778 			}
1779 
1780 			/*
1781 			 * Find the predecessor.
1782 			 * When names become obscured or unobscured in this
1783 			 * update transaction, we may find the wrong
1784 			 * predecessor because the NSECs have not yet been
1785 			 * updated to reflect the delegation change.  This
1786 			 * should not matter because in this case, the correct
1787 			 * predecessor is either the delegation node or a
1788 			 * newly unobscured node, and those nodes are on the
1789 			 * "affected" list in any case.
1790 			 */
1791 			CHECK(next_active(log, zone, db, newver, &t->name,
1792 					  prevname, false));
1793 			CHECK(namelist_append_name(&state->affected, prevname));
1794 		}
1795 
1796 		/*
1797 		 * Find names potentially affected by delegation changes
1798 		 * (obscured by adding an NS or DNAME, or unobscured by
1799 		 * removing one).
1800 		 */
1801 		for (t = ISC_LIST_HEAD(state->diffnames.tuples); t != NULL;
1802 		     t = ISC_LIST_NEXT(t, link))
1803 		{
1804 			bool ns_existed, dname_existed;
1805 			bool ns_exists, dname_exists;
1806 
1807 			if (oldver != NULL) {
1808 				CHECK(rrset_exists(db, oldver, &t->name,
1809 						   dns_rdatatype_ns, 0,
1810 						   &ns_existed));
1811 			} else {
1812 				ns_existed = false;
1813 			}
1814 			if (oldver != NULL) {
1815 				CHECK(rrset_exists(db, oldver, &t->name,
1816 						   dns_rdatatype_dname, 0,
1817 						   &dname_existed));
1818 			} else {
1819 				dname_existed = false;
1820 			}
1821 			CHECK(rrset_exists(db, newver, &t->name,
1822 					   dns_rdatatype_ns, 0, &ns_exists));
1823 			CHECK(rrset_exists(db, newver, &t->name,
1824 					   dns_rdatatype_dname, 0,
1825 					   &dname_exists));
1826 			if ((ns_exists || dname_exists) ==
1827 			    (ns_existed || dname_existed))
1828 			{
1829 				continue;
1830 			}
1831 			/*
1832 			 * There was a delegation change.  Mark all subdomains
1833 			 * of t->name as potentially needing a NSEC update.
1834 			 */
1835 			CHECK(namelist_append_subdomain(db, &t->name,
1836 							&state->affected));
1837 		}
1838 		ISC_LIST_APPENDLIST(state->affected.tuples,
1839 				    state->diffnames.tuples, link);
1840 		INSIST(ISC_LIST_EMPTY(state->diffnames.tuples));
1841 
1842 		CHECK(uniqify_name_list(&state->affected));
1843 
1844 		FALLTHROUGH;
1845 	case process_nsec:
1846 		state->state = process_nsec;
1847 
1848 		/*
1849 		 * Determine which names should have NSECs, and delete/create
1850 		 * NSECs to make it so.  We don't know the final NSEC targets
1851 		 * yet, so we just create placeholder NSECs with arbitrary
1852 		 * contents to indicate that their respective owner names
1853 		 * should be part of the NSEC chain.
1854 		 */
1855 		while ((t = ISC_LIST_HEAD(state->affected.tuples)) != NULL) {
1856 			bool exists;
1857 			dns_name_t *name = &t->name;
1858 
1859 			CHECK(name_exists(db, newver, name, &exists));
1860 			if (!exists) {
1861 				goto unlink;
1862 			}
1863 			CHECK(is_active(db, newver, name, &flag, &cut, NULL));
1864 			if (!flag) {
1865 				/*
1866 				 * This name is obscured.  Delete any
1867 				 * existing NSEC record.
1868 				 */
1869 				CHECK(delete_if(true_p, db, newver, name,
1870 						dns_rdatatype_nsec, 0, NULL,
1871 						&state->nsec_diff));
1872 				CHECK(delete_if(rrsig_p, db, newver, name,
1873 						dns_rdatatype_any, 0, NULL,
1874 						diff));
1875 			} else {
1876 				/*
1877 				 * This name is not obscured.  It needs to have
1878 				 * a NSEC unless it is the at the origin, in
1879 				 * which case it should already exist if there
1880 				 * is a complete NSEC chain and if there isn't
1881 				 * a complete NSEC chain we don't want to add
1882 				 * one as that would signal that there is a
1883 				 * complete NSEC chain.
1884 				 */
1885 				if (!dns_name_equal(name, dns_db_origin(db))) {
1886 					CHECK(rrset_exists(db, newver, name,
1887 							   dns_rdatatype_nsec,
1888 							   0, &flag));
1889 					if (!flag) {
1890 						CHECK(add_placeholder_nsec(
1891 							db, newver, name,
1892 							diff));
1893 					}
1894 				}
1895 				CHECK(add_exposed_sigs(
1896 					log, zone, db, newver, name, cut,
1897 					&state->sig_diff, state->zone_keys,
1898 					state->nkeys, state->inception,
1899 					state->expire, state->check_ksk,
1900 					state->keyset_kskonly, &sigs));
1901 			}
1902 		unlink:
1903 			ISC_LIST_UNLINK(state->affected.tuples, t, link);
1904 			ISC_LIST_APPEND(state->work.tuples, t, link);
1905 			if (state != &mystate && sigs > maxsigs) {
1906 				return (DNS_R_CONTINUE);
1907 			}
1908 		}
1909 		ISC_LIST_APPENDLIST(state->affected.tuples, state->work.tuples,
1910 				    link);
1911 
1912 		/*
1913 		 * Now we know which names are part of the NSEC chain.
1914 		 * Make them all point at their correct targets.
1915 		 */
1916 		for (t = ISC_LIST_HEAD(state->affected.tuples); t != NULL;
1917 		     t = ISC_LIST_NEXT(t, link))
1918 		{
1919 			CHECK(rrset_exists(db, newver, &t->name,
1920 					   dns_rdatatype_nsec, 0, &flag));
1921 			if (flag) {
1922 				/*
1923 				 * There is a NSEC, but we don't know if it
1924 				 * is correct. Delete it and create a correct
1925 				 * one to be sure. If the update was
1926 				 * unnecessary, the diff minimization
1927 				 * will take care of eliminating it from the
1928 				 * journal, IXFRs, etc.
1929 				 *
1930 				 * The RRSIG bit should always be set in the
1931 				 * NSECs we generate, because they will all
1932 				 * get RRSIG NSECs.
1933 				 * (XXX what if the zone keys are missing?).
1934 				 * Because the RRSIG NSECs have not necessarily
1935 				 * been created yet, the correctness of the
1936 				 * bit mask relies on the assumption that NSECs
1937 				 * are only created if there is other data, and
1938 				 * if there is other data, there are other
1939 				 * RRSIGs.
1940 				 */
1941 				CHECK(add_nsec(log, zone, db, newver, &t->name,
1942 					       state->nsecttl,
1943 					       &state->nsec_diff));
1944 			}
1945 		}
1946 
1947 		/*
1948 		 * Minimize the set of NSEC updates so that we don't
1949 		 * have to regenerate the RRSIG NSECs for NSECs that were
1950 		 * replaced with identical ones.
1951 		 */
1952 		while ((t = ISC_LIST_HEAD(state->nsec_diff.tuples)) != NULL) {
1953 			ISC_LIST_UNLINK(state->nsec_diff.tuples, t, link);
1954 			dns_diff_appendminimal(&state->nsec_mindiff, &t);
1955 		}
1956 
1957 		update_log(log, zone, ISC_LOG_DEBUG(3),
1958 			   "signing rebuilt NSEC chain");
1959 
1960 		FALLTHROUGH;
1961 	case sign_nsec:
1962 		state->state = sign_nsec;
1963 		/* Update RRSIG NSECs. */
1964 		while ((t = ISC_LIST_HEAD(state->nsec_mindiff.tuples)) != NULL)
1965 		{
1966 			if (t->op == DNS_DIFFOP_DEL) {
1967 				CHECK(delete_if(true_p, db, newver, &t->name,
1968 						dns_rdatatype_rrsig,
1969 						dns_rdatatype_nsec, NULL,
1970 						&state->sig_diff));
1971 			} else if (t->op == DNS_DIFFOP_ADD) {
1972 				CHECK(add_sigs(log, zone, db, newver, &t->name,
1973 					       dns_rdatatype_nsec,
1974 					       &state->sig_diff,
1975 					       state->zone_keys, state->nkeys,
1976 					       state->inception, state->expire,
1977 					       state->check_ksk,
1978 					       state->keyset_kskonly));
1979 				sigs++;
1980 			} else {
1981 				UNREACHABLE();
1982 			}
1983 			ISC_LIST_UNLINK(state->nsec_mindiff.tuples, t, link);
1984 			ISC_LIST_APPEND(state->work.tuples, t, link);
1985 			if (state != &mystate && sigs > maxsigs) {
1986 				return (DNS_R_CONTINUE);
1987 			}
1988 		}
1989 		ISC_LIST_APPENDLIST(state->nsec_mindiff.tuples,
1990 				    state->work.tuples, link);
1991 		FALLTHROUGH;
1992 	case update_nsec3:
1993 		state->state = update_nsec3;
1994 
1995 		/* Record our changes for the journal. */
1996 		while ((t = ISC_LIST_HEAD(state->sig_diff.tuples)) != NULL) {
1997 			ISC_LIST_UNLINK(state->sig_diff.tuples, t, link);
1998 			dns_diff_appendminimal(diff, &t);
1999 		}
2000 		while ((t = ISC_LIST_HEAD(state->nsec_mindiff.tuples)) != NULL)
2001 		{
2002 			ISC_LIST_UNLINK(state->nsec_mindiff.tuples, t, link);
2003 			dns_diff_appendminimal(diff, &t);
2004 		}
2005 
2006 		INSIST(ISC_LIST_EMPTY(state->sig_diff.tuples));
2007 		INSIST(ISC_LIST_EMPTY(state->nsec_diff.tuples));
2008 		INSIST(ISC_LIST_EMPTY(state->nsec_mindiff.tuples));
2009 
2010 		if (!state->build_nsec3) {
2011 			update_log(log, zone, ISC_LOG_DEBUG(3),
2012 				   "no NSEC3 chains to rebuild");
2013 			goto failure;
2014 		}
2015 
2016 		update_log(log, zone, ISC_LOG_DEBUG(3),
2017 			   "rebuilding NSEC3 chains");
2018 
2019 		dns_diff_clear(&state->diffnames);
2020 		dns_diff_clear(&state->affected);
2021 
2022 		CHECK(dns_diff_sort(diff, temp_order));
2023 
2024 		/*
2025 		 * Find names potentially affected by delegation changes
2026 		 * (obscured by adding an NS or DNAME, or unobscured by
2027 		 * removing one).
2028 		 */
2029 		t = ISC_LIST_HEAD(diff->tuples);
2030 		while (t != NULL) {
2031 			dns_name_t *name = &t->name;
2032 
2033 			bool ns_existed, dname_existed;
2034 			bool ns_exists, dname_exists;
2035 			bool exists, existed;
2036 
2037 			if (t->rdata.type == dns_rdatatype_nsec ||
2038 			    t->rdata.type == dns_rdatatype_rrsig)
2039 			{
2040 				t = ISC_LIST_NEXT(t, link);
2041 				continue;
2042 			}
2043 
2044 			CHECK(namelist_append_name(&state->affected, name));
2045 
2046 			if (oldver != NULL) {
2047 				CHECK(rrset_exists(db, oldver, name,
2048 						   dns_rdatatype_ns, 0,
2049 						   &ns_existed));
2050 			} else {
2051 				ns_existed = false;
2052 			}
2053 			if (oldver != NULL) {
2054 				CHECK(rrset_exists(db, oldver, name,
2055 						   dns_rdatatype_dname, 0,
2056 						   &dname_existed));
2057 			} else {
2058 				dname_existed = false;
2059 			}
2060 			CHECK(rrset_exists(db, newver, name, dns_rdatatype_ns,
2061 					   0, &ns_exists));
2062 			CHECK(rrset_exists(db, newver, name,
2063 					   dns_rdatatype_dname, 0,
2064 					   &dname_exists));
2065 
2066 			exists = ns_exists || dname_exists;
2067 			existed = ns_existed || dname_existed;
2068 			if (exists == existed) {
2069 				goto nextname;
2070 			}
2071 			/*
2072 			 * There was a delegation change.  Mark all subdomains
2073 			 * of t->name as potentially needing a NSEC3 update.
2074 			 */
2075 			CHECK(namelist_append_subdomain(db, name,
2076 							&state->affected));
2077 
2078 		nextname:
2079 			while (t != NULL && dns_name_equal(&t->name, name)) {
2080 				t = ISC_LIST_NEXT(t, link);
2081 			}
2082 		}
2083 
2084 		FALLTHROUGH;
2085 	case process_nsec3:
2086 		state->state = process_nsec3;
2087 		while ((t = ISC_LIST_HEAD(state->affected.tuples)) != NULL) {
2088 			dns_name_t *name = &t->name;
2089 
2090 			unsecure = false; /* Silence compiler warning. */
2091 			CHECK(is_active(db, newver, name, &flag, &cut,
2092 					&unsecure));
2093 
2094 			if (!flag) {
2095 				CHECK(delete_if(rrsig_p, db, newver, name,
2096 						dns_rdatatype_any, 0, NULL,
2097 						diff));
2098 				CHECK(dns_nsec3_delnsec3sx(db, newver, name,
2099 							   privatetype,
2100 							   &state->nsec_diff));
2101 			} else {
2102 				CHECK(add_exposed_sigs(
2103 					log, zone, db, newver, name, cut,
2104 					&state->sig_diff, state->zone_keys,
2105 					state->nkeys, state->inception,
2106 					state->expire, state->check_ksk,
2107 					state->keyset_kskonly, &sigs));
2108 				CHECK(dns_nsec3_addnsec3sx(
2109 					db, newver, name, state->nsecttl,
2110 					unsecure, privatetype,
2111 					&state->nsec_diff));
2112 			}
2113 			ISC_LIST_UNLINK(state->affected.tuples, t, link);
2114 			ISC_LIST_APPEND(state->work.tuples, t, link);
2115 			if (state != &mystate && sigs > maxsigs) {
2116 				return (DNS_R_CONTINUE);
2117 			}
2118 		}
2119 		ISC_LIST_APPENDLIST(state->affected.tuples, state->work.tuples,
2120 				    link);
2121 
2122 		/*
2123 		 * Minimize the set of NSEC3 updates so that we don't
2124 		 * have to regenerate the RRSIG NSEC3s for NSEC3s that were
2125 		 * replaced with identical ones.
2126 		 */
2127 		while ((t = ISC_LIST_HEAD(state->nsec_diff.tuples)) != NULL) {
2128 			ISC_LIST_UNLINK(state->nsec_diff.tuples, t, link);
2129 			dns_diff_appendminimal(&state->nsec_mindiff, &t);
2130 		}
2131 
2132 		update_log(log, zone, ISC_LOG_DEBUG(3),
2133 			   "signing rebuilt NSEC3 chain");
2134 
2135 		FALLTHROUGH;
2136 	case sign_nsec3:
2137 		state->state = sign_nsec3;
2138 		/* Update RRSIG NSEC3s. */
2139 		while ((t = ISC_LIST_HEAD(state->nsec_mindiff.tuples)) != NULL)
2140 		{
2141 			if (t->op == DNS_DIFFOP_DEL) {
2142 				CHECK(delete_if(true_p, db, newver, &t->name,
2143 						dns_rdatatype_rrsig,
2144 						dns_rdatatype_nsec3, NULL,
2145 						&state->sig_diff));
2146 			} else if (t->op == DNS_DIFFOP_ADD) {
2147 				CHECK(add_sigs(log, zone, db, newver, &t->name,
2148 					       dns_rdatatype_nsec3,
2149 					       &state->sig_diff,
2150 					       state->zone_keys, state->nkeys,
2151 					       state->inception, state->expire,
2152 					       state->check_ksk,
2153 					       state->keyset_kskonly));
2154 				sigs++;
2155 			} else {
2156 				UNREACHABLE();
2157 			}
2158 			ISC_LIST_UNLINK(state->nsec_mindiff.tuples, t, link);
2159 			ISC_LIST_APPEND(state->work.tuples, t, link);
2160 			if (state != &mystate && sigs > maxsigs) {
2161 				return (DNS_R_CONTINUE);
2162 			}
2163 		}
2164 		ISC_LIST_APPENDLIST(state->nsec_mindiff.tuples,
2165 				    state->work.tuples, link);
2166 
2167 		/* Record our changes for the journal. */
2168 		while ((t = ISC_LIST_HEAD(state->sig_diff.tuples)) != NULL) {
2169 			ISC_LIST_UNLINK(state->sig_diff.tuples, t, link);
2170 			dns_diff_appendminimal(diff, &t);
2171 		}
2172 		while ((t = ISC_LIST_HEAD(state->nsec_mindiff.tuples)) != NULL)
2173 		{
2174 			ISC_LIST_UNLINK(state->nsec_mindiff.tuples, t, link);
2175 			dns_diff_appendminimal(diff, &t);
2176 		}
2177 
2178 		INSIST(ISC_LIST_EMPTY(state->sig_diff.tuples));
2179 		INSIST(ISC_LIST_EMPTY(state->nsec_diff.tuples));
2180 		INSIST(ISC_LIST_EMPTY(state->nsec_mindiff.tuples));
2181 		break;
2182 	default:
2183 		UNREACHABLE();
2184 	}
2185 
2186 failure:
2187 	if (node != NULL) {
2188 		dns_db_detachnode(db, &node);
2189 	}
2190 
2191 	dns_diff_clear(&state->sig_diff);
2192 	dns_diff_clear(&state->nsec_diff);
2193 	dns_diff_clear(&state->nsec_mindiff);
2194 
2195 	dns_diff_clear(&state->affected);
2196 	dns_diff_clear(&state->diffnames);
2197 	dns_diff_clear(&state->work);
2198 
2199 	for (i = 0; i < state->nkeys; i++) {
2200 		dst_key_free(&state->zone_keys[i]);
2201 	}
2202 
2203 	if (state != &mystate) {
2204 		*statep = NULL;
2205 		state->magic = 0;
2206 		isc_mem_put(diff->mctx, state, sizeof(*state));
2207 	}
2208 
2209 	return (result);
2210 }
2211 
2212 static isc_stdtime_t
epoch_to_yyyymmdd(time_t when)2213 epoch_to_yyyymmdd(time_t when) {
2214 	struct tm t, *tm = localtime_r(&when, &t);
2215 	if (tm == NULL) {
2216 		return (0);
2217 	}
2218 	return (((tm->tm_year + 1900) * 10000) + ((tm->tm_mon + 1) * 100) +
2219 		tm->tm_mday);
2220 }
2221 
2222 static uint32_t
dns__update_soaserial(uint32_t serial,dns_updatemethod_t method)2223 dns__update_soaserial(uint32_t serial, dns_updatemethod_t method) {
2224 	isc_stdtime_t now;
2225 
2226 	switch (method) {
2227 	case dns_updatemethod_none:
2228 		return (serial);
2229 	case dns_updatemethod_unixtime:
2230 		isc_stdtime_get(&now);
2231 		return (now);
2232 	case dns_updatemethod_date:
2233 		isc_stdtime_get(&now);
2234 		return (epoch_to_yyyymmdd((time_t)now) * 100);
2235 	case dns_updatemethod_increment:
2236 		/* RFC1982 */
2237 		serial = (serial + 1) & 0xFFFFFFFF;
2238 		if (serial == 0) {
2239 			return (1);
2240 		}
2241 		return (serial);
2242 	default:
2243 		UNREACHABLE();
2244 	}
2245 }
2246 
2247 uint32_t
dns_update_soaserial(uint32_t serial,dns_updatemethod_t method,dns_updatemethod_t * used)2248 dns_update_soaserial(uint32_t serial, dns_updatemethod_t method,
2249 		     dns_updatemethod_t *used) {
2250 	uint32_t new_serial = dns__update_soaserial(serial, method);
2251 	switch (method) {
2252 	case dns_updatemethod_none:
2253 	case dns_updatemethod_increment:
2254 		break;
2255 	case dns_updatemethod_unixtime:
2256 	case dns_updatemethod_date:
2257 		if (!(new_serial != 0 && isc_serial_gt(new_serial, serial))) {
2258 			/*
2259 			 * If the new date serial following YYYYMMDD00 is equal
2260 			 * to or smaller than the current serial, but YYYYMMDD99
2261 			 * would be larger, pretend we have used the
2262 			 * "dns_updatemethod_date" method.
2263 			 */
2264 			if (method == dns_updatemethod_unixtime ||
2265 			    !isc_serial_gt(new_serial + 99, serial))
2266 			{
2267 				method = dns_updatemethod_increment;
2268 			}
2269 			new_serial = dns__update_soaserial(
2270 				serial, dns_updatemethod_increment);
2271 		}
2272 		break;
2273 	default:
2274 		UNREACHABLE();
2275 	}
2276 
2277 	if (used != NULL) {
2278 		*used = method;
2279 	}
2280 
2281 	return (new_serial);
2282 }
2283