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