xref: /netbsd/external/mpl/bind/dist/lib/dns/zone.c (revision a706c3b7)
1 /*	$NetBSD: zone.c,v 1.18 2023/06/26 22:03:00 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 /*! \file */
17 
18 #include <errno.h>
19 #include <inttypes.h>
20 #include <stdbool.h>
21 
22 #include <isc/atomic.h>
23 #include <isc/file.h>
24 #include <isc/hex.h>
25 #include <isc/md.h>
26 #include <isc/mutex.h>
27 #include <isc/pool.h>
28 #include <isc/print.h>
29 #include <isc/random.h>
30 #include <isc/ratelimiter.h>
31 #include <isc/refcount.h>
32 #include <isc/rwlock.h>
33 #include <isc/serial.h>
34 #include <isc/stats.h>
35 #include <isc/stdtime.h>
36 #include <isc/strerr.h>
37 #include <isc/string.h>
38 #include <isc/taskpool.h>
39 #include <isc/thread.h>
40 #include <isc/timer.h>
41 #include <isc/util.h>
42 
43 #include <dns/acl.h>
44 #include <dns/adb.h>
45 #include <dns/callbacks.h>
46 #include <dns/catz.h>
47 #include <dns/db.h>
48 #include <dns/dbiterator.h>
49 #include <dns/dlz.h>
50 #include <dns/dnssec.h>
51 #include <dns/events.h>
52 #include <dns/journal.h>
53 #include <dns/kasp.h>
54 #include <dns/keydata.h>
55 #include <dns/keymgr.h>
56 #include <dns/keytable.h>
57 #include <dns/keyvalues.h>
58 #include <dns/log.h>
59 #include <dns/master.h>
60 #include <dns/masterdump.h>
61 #include <dns/message.h>
62 #include <dns/name.h>
63 #include <dns/nsec.h>
64 #include <dns/nsec3.h>
65 #include <dns/opcode.h>
66 #include <dns/peer.h>
67 #include <dns/private.h>
68 #include <dns/rcode.h>
69 #include <dns/rdata.h>
70 #include <dns/rdataclass.h>
71 #include <dns/rdatalist.h>
72 #include <dns/rdataset.h>
73 #include <dns/rdatasetiter.h>
74 #include <dns/rdatastruct.h>
75 #include <dns/rdatatype.h>
76 #include <dns/request.h>
77 #include <dns/resolver.h>
78 #include <dns/result.h>
79 #include <dns/rriterator.h>
80 #include <dns/soa.h>
81 #include <dns/ssu.h>
82 #include <dns/stats.h>
83 #include <dns/time.h>
84 #include <dns/tsig.h>
85 #include <dns/update.h>
86 #include <dns/xfrin.h>
87 #include <dns/zone.h>
88 #include <dns/zoneverify.h>
89 #include <dns/zt.h>
90 
91 #include <dst/dst.h>
92 
93 #include "zone_p.h"
94 
95 #define ZONE_MAGIC	     ISC_MAGIC('Z', 'O', 'N', 'E')
96 #define DNS_ZONE_VALID(zone) ISC_MAGIC_VALID(zone, ZONE_MAGIC)
97 
98 #define NOTIFY_MAGIC		 ISC_MAGIC('N', 't', 'f', 'y')
99 #define DNS_NOTIFY_VALID(notify) ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)
100 
101 #define CHECKDS_MAGIC		   ISC_MAGIC('C', 'h', 'D', 'S')
102 #define DNS_CHECKDS_VALID(checkds) ISC_MAGIC_VALID(checkds, CHECKDS_MAGIC)
103 
104 #define STUB_MAGIC	     ISC_MAGIC('S', 't', 'u', 'b')
105 #define DNS_STUB_VALID(stub) ISC_MAGIC_VALID(stub, STUB_MAGIC)
106 
107 #define ZONEMGR_MAGIC		ISC_MAGIC('Z', 'm', 'g', 'r')
108 #define DNS_ZONEMGR_VALID(stub) ISC_MAGIC_VALID(stub, ZONEMGR_MAGIC)
109 
110 #define LOAD_MAGIC	     ISC_MAGIC('L', 'o', 'a', 'd')
111 #define DNS_LOAD_VALID(load) ISC_MAGIC_VALID(load, LOAD_MAGIC)
112 
113 #define FORWARD_MAGIC		ISC_MAGIC('F', 'o', 'r', 'w')
114 #define DNS_FORWARD_VALID(load) ISC_MAGIC_VALID(load, FORWARD_MAGIC)
115 
116 #define IO_MAGIC	   ISC_MAGIC('Z', 'm', 'I', 'O')
117 #define DNS_IO_VALID(load) ISC_MAGIC_VALID(load, IO_MAGIC)
118 
119 #define KEYMGMT_MAGIC		ISC_MAGIC('M', 'g', 'm', 't')
120 #define DNS_KEYMGMT_VALID(load) ISC_MAGIC_VALID(load, KEYMGMT_MAGIC)
121 
122 #define KEYFILEIO_MAGIC		  ISC_MAGIC('K', 'y', 'I', 'O')
123 #define DNS_KEYFILEIO_VALID(kfio) ISC_MAGIC_VALID(kfio, KEYFILEIO_MAGIC)
124 
125 /*%
126  * Ensure 'a' is at least 'min' but not more than 'max'.
127  */
128 #define RANGE(a, min, max) (((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max)))
129 
130 #define NSEC3REMOVE(x) (((x)&DNS_NSEC3FLAG_REMOVE) != 0)
131 
132 /*%
133  * Key flags
134  */
135 #define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
136 #define KSK(x)	  ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
137 #define ID(x)	  dst_key_id(x)
138 #define ALG(x)	  dst_key_alg(x)
139 
140 /*%
141  * KASP flags
142  */
143 #define KASP_LOCK(k)                  \
144 	if ((k) != NULL) {            \
145 		LOCK((&((k)->lock))); \
146 	}
147 
148 #define KASP_UNLOCK(k)                  \
149 	if ((k) != NULL) {              \
150 		UNLOCK((&((k)->lock))); \
151 	}
152 
153 /*
154  * Default values.
155  */
156 #define DNS_DEFAULT_IDLEIN  3600       /*%< 1 hour */
157 #define DNS_DEFAULT_IDLEOUT 3600       /*%< 1 hour */
158 #define MAX_XFER_TIME	    (2 * 3600) /*%< Documented default is 2 hours */
159 #define RESIGN_DELAY	    3600       /*%< 1 hour */
160 
161 #ifndef DNS_MAX_EXPIRE
162 #define DNS_MAX_EXPIRE 14515200 /*%< 24 weeks */
163 #endif				/* ifndef DNS_MAX_EXPIRE */
164 
165 #ifndef DNS_DUMP_DELAY
166 #define DNS_DUMP_DELAY 900 /*%< 15 minutes */
167 #endif			   /* ifndef DNS_DUMP_DELAY */
168 
169 typedef struct dns_notify dns_notify_t;
170 typedef struct dns_checkds dns_checkds_t;
171 typedef struct dns_stub dns_stub_t;
172 typedef struct dns_load dns_load_t;
173 typedef struct dns_forward dns_forward_t;
174 typedef ISC_LIST(dns_forward_t) dns_forwardlist_t;
175 typedef struct dns_io dns_io_t;
176 typedef ISC_LIST(dns_io_t) dns_iolist_t;
177 typedef struct dns_keymgmt dns_keymgmt_t;
178 typedef struct dns_signing dns_signing_t;
179 typedef ISC_LIST(dns_signing_t) dns_signinglist_t;
180 typedef struct dns_nsec3chain dns_nsec3chain_t;
181 typedef ISC_LIST(dns_nsec3chain_t) dns_nsec3chainlist_t;
182 typedef struct dns_keyfetch dns_keyfetch_t;
183 typedef struct dns_asyncload dns_asyncload_t;
184 typedef struct dns_include dns_include_t;
185 
186 #define DNS_ZONE_CHECKLOCK
187 #ifdef DNS_ZONE_CHECKLOCK
188 #define LOCK_ZONE(z)                  \
189 	do {                          \
190 		LOCK(&(z)->lock);     \
191 		INSIST(!(z)->locked); \
192 		(z)->locked = true;   \
193 	} while (0)
194 #define UNLOCK_ZONE(z)               \
195 	do {                         \
196 		(z)->locked = false; \
197 		UNLOCK(&(z)->lock);  \
198 	} while (0)
199 #define LOCKED_ZONE(z) ((z)->locked)
200 #define TRYLOCK_ZONE(result, z)                         \
201 	do {                                            \
202 		result = isc_mutex_trylock(&(z)->lock); \
203 		if (result == ISC_R_SUCCESS) {          \
204 			INSIST(!(z)->locked);           \
205 			(z)->locked = true;             \
206 		}                                       \
207 	} while (0)
208 #else /* ifdef DNS_ZONE_CHECKLOCK */
209 #define LOCK_ZONE(z)   LOCK(&(z)->lock)
210 #define UNLOCK_ZONE(z) UNLOCK(&(z)->lock)
211 #define LOCKED_ZONE(z) true
212 #define TRYLOCK_ZONE(result, z)                         \
213 	do {                                            \
214 		result = isc_mutex_trylock(&(z)->lock); \
215 	} while (0)
216 #endif /* ifdef DNS_ZONE_CHECKLOCK */
217 
218 #define ZONEDB_INITLOCK(l)    isc_rwlock_init((l), 0, 0)
219 #define ZONEDB_DESTROYLOCK(l) isc_rwlock_destroy(l)
220 #define ZONEDB_LOCK(l, t)     RWLOCK((l), (t))
221 #define ZONEDB_UNLOCK(l, t)   RWUNLOCK((l), (t))
222 
223 #ifdef ENABLE_AFL
224 extern bool dns_fuzzing_resolver;
225 #endif /* ifdef ENABLE_AFL */
226 
227 /*%
228  *	Hold key file IO locks.
229  */
230 typedef struct dns_keyfileio {
231 	unsigned int magic;
232 	struct dns_keyfileio *next;
233 	uint32_t hashval;
234 	dns_fixedname_t fname;
235 	dns_name_t *name;
236 	isc_refcount_t references;
237 	isc_mutex_t lock;
238 } dns_keyfileio_t;
239 
240 struct dns_keymgmt {
241 	unsigned int magic;
242 	isc_rwlock_t lock;
243 	isc_mem_t *mctx;
244 
245 	dns_keyfileio_t **table;
246 
247 	atomic_uint_fast32_t count;
248 
249 	uint32_t bits;
250 };
251 
252 struct dns_zone {
253 	/* Unlocked */
254 	unsigned int magic;
255 	isc_mutex_t lock;
256 #ifdef DNS_ZONE_CHECKLOCK
257 	bool locked;
258 #endif /* ifdef DNS_ZONE_CHECKLOCK */
259 	isc_mem_t *mctx;
260 	isc_refcount_t erefs;
261 
262 	isc_rwlock_t dblock;
263 	dns_db_t *db; /* Locked by dblock */
264 
265 	/* Locked */
266 	dns_zonemgr_t *zmgr;
267 	ISC_LINK(dns_zone_t) link; /* Used by zmgr. */
268 	isc_timer_t *timer;
269 	isc_refcount_t irefs;
270 	dns_name_t origin;
271 	char *masterfile;
272 	ISC_LIST(dns_include_t) includes;    /* Include files */
273 	ISC_LIST(dns_include_t) newincludes; /* Loading */
274 	unsigned int nincludes;
275 	dns_masterformat_t masterformat;
276 	const dns_master_style_t *masterstyle;
277 	char *journal;
278 	int32_t journalsize;
279 	dns_rdataclass_t rdclass;
280 	dns_zonetype_t type;
281 #ifdef __NetBSD__
282 	atomic_uint_fast32_t flags;
283 	atomic_uint_fast32_t options;
284 #else
285 	atomic_uint_fast64_t flags;
286 	atomic_uint_fast64_t options;
287 #endif
288 	unsigned int db_argc;
289 	char **db_argv;
290 	isc_time_t expiretime;
291 	isc_time_t refreshtime;
292 	isc_time_t dumptime;
293 	isc_time_t loadtime;
294 	isc_time_t notifytime;
295 	isc_time_t resigntime;
296 	isc_time_t keywarntime;
297 	isc_time_t signingtime;
298 	isc_time_t nsec3chaintime;
299 	isc_time_t refreshkeytime;
300 	uint32_t refreshkeyinterval;
301 	uint32_t refreshkeycount;
302 	uint32_t refresh;
303 	uint32_t retry;
304 	uint32_t expire;
305 	uint32_t minimum;
306 	isc_stdtime_t key_expiry;
307 	isc_stdtime_t log_key_expired_timer;
308 	char *keydirectory;
309 	dns_keyfileio_t *kfio;
310 
311 	uint32_t maxrefresh;
312 	uint32_t minrefresh;
313 	uint32_t maxretry;
314 	uint32_t minretry;
315 
316 	uint32_t maxrecords;
317 
318 	isc_sockaddr_t *masters;
319 	isc_dscp_t *masterdscps;
320 	dns_name_t **masterkeynames;
321 	bool *mastersok;
322 	unsigned int masterscnt;
323 	unsigned int curmaster;
324 	isc_sockaddr_t masteraddr;
325 
326 	isc_sockaddr_t *parentals;
327 	isc_dscp_t *parentaldscps;
328 	dns_name_t **parentalkeynames;
329 	dns_dnsseckeylist_t checkds_ok;
330 	unsigned int parentalscnt;
331 	isc_sockaddr_t parentaladdr;
332 
333 	dns_notifytype_t notifytype;
334 	isc_sockaddr_t *notify;
335 	dns_name_t **notifykeynames;
336 	isc_dscp_t *notifydscp;
337 	unsigned int notifycnt;
338 	isc_sockaddr_t notifyfrom;
339 	isc_task_t *task;
340 	isc_task_t *loadtask;
341 	isc_sockaddr_t notifysrc4;
342 	isc_sockaddr_t notifysrc6;
343 	isc_sockaddr_t parentalsrc4;
344 	isc_sockaddr_t parentalsrc6;
345 	isc_sockaddr_t xfrsource4;
346 	isc_sockaddr_t xfrsource6;
347 	isc_sockaddr_t altxfrsource4;
348 	isc_sockaddr_t altxfrsource6;
349 	isc_sockaddr_t sourceaddr;
350 	isc_dscp_t notifysrc4dscp;
351 	isc_dscp_t notifysrc6dscp;
352 	isc_dscp_t parentalsrc4dscp;
353 	isc_dscp_t parentalsrc6dscp;
354 	isc_dscp_t xfrsource4dscp;
355 	isc_dscp_t xfrsource6dscp;
356 	isc_dscp_t altxfrsource4dscp;
357 	isc_dscp_t altxfrsource6dscp;
358 	dns_xfrin_ctx_t *xfr;	/* task locked */
359 	dns_tsigkey_t *tsigkey; /* key used for xfr */
360 	/* Access Control Lists */
361 	dns_acl_t *update_acl;
362 	dns_acl_t *forward_acl;
363 	dns_acl_t *notify_acl;
364 	dns_acl_t *query_acl;
365 	dns_acl_t *queryon_acl;
366 	dns_acl_t *xfr_acl;
367 	bool update_disabled;
368 	bool zero_no_soa_ttl;
369 	dns_severity_t check_names;
370 	ISC_LIST(dns_notify_t) notifies;
371 	ISC_LIST(dns_checkds_t) checkds_requests;
372 	dns_request_t *request;
373 	dns_loadctx_t *lctx;
374 	dns_io_t *readio;
375 	dns_dumpctx_t *dctx;
376 	dns_io_t *writeio;
377 	uint32_t maxxfrin;
378 	uint32_t maxxfrout;
379 	uint32_t idlein;
380 	uint32_t idleout;
381 	isc_event_t ctlevent;
382 	dns_ssutable_t *ssutable;
383 	uint32_t sigvalidityinterval;
384 	uint32_t keyvalidityinterval;
385 	uint32_t sigresigninginterval;
386 	dns_view_t *view;
387 	dns_view_t *prev_view;
388 	dns_kasp_t *kasp;
389 	dns_checkmxfunc_t checkmx;
390 	dns_checksrvfunc_t checksrv;
391 	dns_checknsfunc_t checkns;
392 	/*%
393 	 * Zones in certain states such as "waiting for zone transfer"
394 	 * or "zone transfer in progress" are kept on per-state linked lists
395 	 * in the zone manager using the 'statelink' field.  The 'statelist'
396 	 * field points at the list the zone is currently on.  It the zone
397 	 * is not on any such list, statelist is NULL.
398 	 */
399 	ISC_LINK(dns_zone_t) statelink;
400 	dns_zonelist_t *statelist;
401 	/*%
402 	 * Statistics counters about zone management.
403 	 */
404 	isc_stats_t *stats;
405 	/*%
406 	 * Optional per-zone statistics counters.  Counted outside of this
407 	 * module.
408 	 */
409 	dns_zonestat_level_t statlevel;
410 	bool requeststats_on;
411 	isc_stats_t *requeststats;
412 	dns_stats_t *rcvquerystats;
413 	dns_stats_t *dnssecsignstats;
414 	uint32_t notifydelay;
415 	dns_isselffunc_t isself;
416 	void *isselfarg;
417 
418 	char *strnamerd;
419 	char *strname;
420 	char *strrdclass;
421 	char *strviewname;
422 
423 	/*%
424 	 * Serial number for deferred journal compaction.
425 	 */
426 	uint32_t compact_serial;
427 	/*%
428 	 * Keys that are signing the zone for the first time.
429 	 */
430 	dns_signinglist_t signing;
431 	dns_nsec3chainlist_t nsec3chain;
432 	/*%
433 	 * List of outstanding NSEC3PARAM change requests.
434 	 */
435 	isc_eventlist_t setnsec3param_queue;
436 	/*%
437 	 * Signing / re-signing quantum stopping parameters.
438 	 */
439 	uint32_t signatures;
440 	uint32_t nodes;
441 	dns_rdatatype_t privatetype;
442 
443 	/*%
444 	 * Autosigning/key-maintenance options
445 	 */
446 #ifdef __NetBSD__
447 	atomic_uint_fast32_t keyopts;
448 #else
449 	atomic_uint_fast64_t keyopts;
450 #endif
451 
452 	/*%
453 	 * True if added by "rndc addzone"
454 	 */
455 	bool added;
456 
457 	/*%
458 	 * True if added by automatically by named.
459 	 */
460 	bool automatic;
461 
462 	/*%
463 	 * response policy data to be relayed to the database
464 	 */
465 	dns_rpz_zones_t *rpzs;
466 	dns_rpz_num_t rpz_num;
467 
468 	/*%
469 	 * catalog zone data
470 	 */
471 	dns_catz_zones_t *catzs;
472 
473 	/*%
474 	 * parent catalog zone
475 	 */
476 	dns_catz_zone_t *parentcatz;
477 
478 	/*%
479 	 * Serial number update method.
480 	 */
481 	dns_updatemethod_t updatemethod;
482 
483 	/*%
484 	 * whether ixfr is requested
485 	 */
486 	bool requestixfr;
487 	uint32_t ixfr_ratio;
488 
489 	/*%
490 	 * whether EDNS EXPIRE is requested
491 	 */
492 	bool requestexpire;
493 
494 	/*%
495 	 * Outstanding forwarded UPDATE requests.
496 	 */
497 	dns_forwardlist_t forwards;
498 
499 	dns_zone_t *raw;
500 	dns_zone_t *secure;
501 
502 	bool sourceserialset;
503 	uint32_t sourceserial;
504 
505 	/*%
506 	 * soa and maximum zone ttl
507 	 */
508 	dns_ttl_t soattl;
509 	dns_ttl_t maxttl;
510 
511 	/*
512 	 * Inline zone signing state.
513 	 */
514 	dns_diff_t rss_diff;
515 	isc_eventlist_t rss_events;
516 	isc_eventlist_t rss_post;
517 	dns_dbversion_t *rss_newver;
518 	dns_dbversion_t *rss_oldver;
519 	dns_db_t *rss_db;
520 	dns_zone_t *rss_raw;
521 	isc_event_t *rss_event;
522 	dns_update_state_t *rss_state;
523 
524 	isc_stats_t *gluecachestats;
525 };
526 
527 #define zonediff_init(z, d)                \
528 	do {                               \
529 		dns__zonediff_t *_z = (z); \
530 		(_z)->diff = (d);          \
531 		(_z)->offline = false;     \
532 	} while (0)
533 
534 #define DNS_ZONE_FLAG(z, f)    ((atomic_load_relaxed(&(z)->flags) & (f)) != 0)
535 #define DNS_ZONE_SETFLAG(z, f) atomic_fetch_or(&(z)->flags, (f))
536 #define DNS_ZONE_CLRFLAG(z, f) atomic_fetch_and(&(z)->flags, ~(f))
537 typedef enum {
538 	DNS_ZONEFLG_REFRESH = 0x00000001U,     /*%< refresh check in progress */
539 	DNS_ZONEFLG_NEEDDUMP = 0x00000002U,    /*%< zone need consolidation */
540 	DNS_ZONEFLG_USEVC = 0x00000004U,       /*%< use tcp for refresh query */
541 	DNS_ZONEFLG_DUMPING = 0x00000008U,     /*%< a dump is in progress */
542 	DNS_ZONEFLG_HASINCLUDE = 0x00000010U,  /*%< $INCLUDE in zone file */
543 	DNS_ZONEFLG_LOADED = 0x00000020U,      /*%< database has loaded */
544 	DNS_ZONEFLG_EXITING = 0x00000040U,     /*%< zone is being destroyed */
545 	DNS_ZONEFLG_EXPIRED = 0x00000080U,     /*%< zone has expired */
546 	DNS_ZONEFLG_NEEDREFRESH = 0x00000100U, /*%< refresh check needed */
547 	DNS_ZONEFLG_UPTODATE = 0x00000200U,    /*%< zone contents are
548 						* up-to-date */
549 	DNS_ZONEFLG_NEEDNOTIFY = 0x00000400U,  /*%< need to send out notify
550 						* messages */
551 	DNS_ZONEFLG_FIXJOURNAL = 0x00000800U,  /*%< journal file had
552 						* recoverable error,
553 						* needs rewriting */
554 	DNS_ZONEFLG_NOMASTERS = 0x00001000U,   /*%< an attempt to refresh a
555 						* zone with no primaries
556 						* occurred */
557 	DNS_ZONEFLG_LOADING = 0x00002000U,     /*%< load from disk in progress*/
558 	DNS_ZONEFLG_HAVETIMERS = 0x00004000U,  /*%< timer values have been set
559 						* from SOA (if not set, we
560 						* are still using
561 						* default timer values) */
562 	DNS_ZONEFLG_FORCEXFER = 0x00008000U,   /*%< Force a zone xfer */
563 	DNS_ZONEFLG_NOREFRESH = 0x00010000U,
564 	DNS_ZONEFLG_DIALNOTIFY = 0x00020000U,
565 	DNS_ZONEFLG_DIALREFRESH = 0x00040000U,
566 	DNS_ZONEFLG_SHUTDOWN = 0x00080000U,
567 	DNS_ZONEFLG_NOIXFR = 0x00100000U, /*%< IXFR failed, force AXFR */
568 	DNS_ZONEFLG_FLUSH = 0x00200000U,
569 	DNS_ZONEFLG_NOEDNS = 0x00400000U,
570 	DNS_ZONEFLG_USEALTXFRSRC = 0x00800000U,
571 	DNS_ZONEFLG_SOABEFOREAXFR = 0x01000000U,
572 	DNS_ZONEFLG_NEEDCOMPACT = 0x02000000U,
573 	DNS_ZONEFLG_REFRESHING = 0x04000000U, /*%< Refreshing keydata */
574 	DNS_ZONEFLG_THAW = 0x08000000U,
575 	DNS_ZONEFLG_LOADPENDING = 0x10000000U, /*%< Loading scheduled */
576 	DNS_ZONEFLG_NODELAY = 0x20000000U,
577 	DNS_ZONEFLG_SENDSECURE = 0x40000000U,
578 	DNS_ZONEFLG_NEEDSTARTUPNOTIFY = 0x80000000U, /*%< need to send out
579 						      * notify due to the zone
580 						      * just being loaded for
581 						      * the first time. */
582 #ifndef __NetBSD__
583 	/*
584 	 * DO NOT add any new zone flags here until all platforms
585 	 * support 64-bit enum values. Currently they fail on
586 	 * Windows.
587 	 */
588 	DNS_ZONEFLG___MAX = UINT64_MAX, /* trick to make the ENUM 64-bit wide */
589 #endif
590 } dns_zoneflg_t;
591 
592 #define DNS_ZONE_OPTION(z, o)	 ((atomic_load_relaxed(&(z)->options) & (o)) != 0)
593 #define DNS_ZONE_SETOPTION(z, o) atomic_fetch_or(&(z)->options, (o))
594 #define DNS_ZONE_CLROPTION(z, o) atomic_fetch_and(&(z)->options, ~(o))
595 
596 #define DNS_ZONEKEY_OPTION(z, o) \
597 	((atomic_load_relaxed(&(z)->keyopts) & (o)) != 0)
598 #define DNS_ZONEKEY_SETOPTION(z, o) atomic_fetch_or(&(z)->keyopts, (o))
599 #define DNS_ZONEKEY_CLROPTION(z, o) atomic_fetch_and(&(z)->keyopts, ~(o))
600 
601 /* Flags for zone_load() */
602 typedef enum {
603 	DNS_ZONELOADFLAG_NOSTAT = 0x00000001U, /* Do not stat() master files */
604 	DNS_ZONELOADFLAG_THAW = 0x00000002U,   /* Thaw the zone on successful
605 						* load. */
606 } dns_zoneloadflag_t;
607 
608 #define UNREACH_CACHE_SIZE 10U
609 #define UNREACH_HOLD_TIME  600 /* 10 minutes */
610 
611 #define CHECK(op)                            \
612 	do {                                 \
613 		result = (op);               \
614 		if (result != ISC_R_SUCCESS) \
615 			goto failure;        \
616 	} while (0)
617 
618 struct dns_unreachable {
619 	isc_sockaddr_t remote;
620 	isc_sockaddr_t local;
621 	atomic_uint_fast32_t expire;
622 	atomic_uint_fast32_t last;
623 	uint32_t count;
624 };
625 
626 struct dns_zonemgr {
627 	unsigned int magic;
628 	isc_mem_t *mctx;
629 	isc_refcount_t refs;
630 	isc_taskmgr_t *taskmgr;
631 	isc_timermgr_t *timermgr;
632 	isc_socketmgr_t *socketmgr;
633 	isc_taskpool_t *zonetasks;
634 	isc_taskpool_t *loadtasks;
635 	isc_task_t *task;
636 	isc_pool_t *mctxpool;
637 	isc_ratelimiter_t *checkdsrl;
638 	isc_ratelimiter_t *notifyrl;
639 	isc_ratelimiter_t *refreshrl;
640 	isc_ratelimiter_t *startupnotifyrl;
641 	isc_ratelimiter_t *startuprefreshrl;
642 	isc_rwlock_t rwlock;
643 	isc_mutex_t iolock;
644 	isc_rwlock_t urlock;
645 
646 	/* Locked by rwlock. */
647 	dns_zonelist_t zones;
648 	dns_zonelist_t waiting_for_xfrin;
649 	dns_zonelist_t xfrin_in_progress;
650 
651 	/* Configuration data. */
652 	uint32_t transfersin;
653 	uint32_t transfersperns;
654 	unsigned int checkdsrate;
655 	unsigned int notifyrate;
656 	unsigned int startupnotifyrate;
657 	unsigned int serialqueryrate;
658 	unsigned int startupserialqueryrate;
659 
660 	/* Locked by iolock */
661 	uint32_t iolimit;
662 	uint32_t ioactive;
663 	dns_iolist_t high;
664 	dns_iolist_t low;
665 
666 	/* Locked by urlock. */
667 	/* LRU cache */
668 	struct dns_unreachable unreachable[UNREACH_CACHE_SIZE];
669 
670 	dns_keymgmt_t *keymgmt;
671 };
672 
673 /*%
674  * Hold notify state.
675  */
676 struct dns_notify {
677 	unsigned int magic;
678 	unsigned int flags;
679 	isc_mem_t *mctx;
680 	dns_zone_t *zone;
681 	dns_adbfind_t *find;
682 	dns_request_t *request;
683 	dns_name_t ns;
684 	isc_sockaddr_t dst;
685 	dns_tsigkey_t *key;
686 	isc_dscp_t dscp;
687 	ISC_LINK(dns_notify_t) link;
688 	isc_event_t *event;
689 };
690 
691 #define DNS_NOTIFY_NOSOA   0x0001U
692 #define DNS_NOTIFY_STARTUP 0x0002U
693 
694 /*%
695  * Hold checkds state.
696  */
697 struct dns_checkds {
698 	unsigned int magic;
699 	unsigned int flags;
700 	isc_mem_t *mctx;
701 	dns_zone_t *zone;
702 	dns_request_t *request;
703 	isc_sockaddr_t dst;
704 	dns_tsigkey_t *key;
705 	isc_dscp_t dscp;
706 	ISC_LINK(dns_checkds_t) link;
707 	isc_event_t *event;
708 };
709 
710 /*%
711  *	dns_stub holds state while performing a 'stub' transfer.
712  *	'db' is the zone's 'db' or a new one if this is the initial
713  *	transfer.
714  */
715 
716 struct dns_stub {
717 	unsigned int magic;
718 	isc_mem_t *mctx;
719 	dns_zone_t *zone;
720 	dns_db_t *db;
721 	dns_dbversion_t *version;
722 	atomic_uint_fast32_t pending_requests;
723 };
724 
725 /*%
726  *	Hold load state.
727  */
728 struct dns_load {
729 	unsigned int magic;
730 	isc_mem_t *mctx;
731 	dns_zone_t *zone;
732 	dns_db_t *db;
733 	isc_time_t loadtime;
734 	dns_rdatacallbacks_t callbacks;
735 };
736 
737 /*%
738  *	Hold forward state.
739  */
740 struct dns_forward {
741 	unsigned int magic;
742 	isc_mem_t *mctx;
743 	dns_zone_t *zone;
744 	isc_buffer_t *msgbuf;
745 	dns_request_t *request;
746 	uint32_t which;
747 	isc_sockaddr_t addr;
748 	dns_updatecallback_t callback;
749 	void *callback_arg;
750 	unsigned int options;
751 	ISC_LINK(dns_forward_t) link;
752 };
753 
754 /*%
755  *	Hold IO request state.
756  */
757 struct dns_io {
758 	unsigned int magic;
759 	dns_zonemgr_t *zmgr;
760 	bool high;
761 	isc_task_t *task;
762 	ISC_LINK(dns_io_t) link;
763 	isc_event_t *event;
764 };
765 
766 /*%
767  *	Hold state for when we are signing a zone with a new
768  *	DNSKEY as result of an update.
769  */
770 struct dns_signing {
771 	unsigned int magic;
772 	dns_db_t *db;
773 	dns_dbiterator_t *dbiterator;
774 	dns_secalg_t algorithm;
775 	uint16_t keyid;
776 	bool deleteit;
777 	bool done;
778 	ISC_LINK(dns_signing_t) link;
779 };
780 
781 struct dns_nsec3chain {
782 	unsigned int magic;
783 	dns_db_t *db;
784 	dns_dbiterator_t *dbiterator;
785 	dns_rdata_nsec3param_t nsec3param;
786 	unsigned char salt[255];
787 	bool done;
788 	bool seen_nsec;
789 	bool delete_nsec;
790 	bool save_delete_nsec;
791 	ISC_LINK(dns_nsec3chain_t) link;
792 };
793 
794 /*%<
795  * 'dbiterator' contains a iterator for the database.  If we are creating
796  * a NSEC3 chain only the non-NSEC3 nodes will be iterated.  If we are
797  * removing a NSEC3 chain then both NSEC3 and non-NSEC3 nodes will be
798  * iterated.
799  *
800  * 'nsec3param' contains the parameters of the NSEC3 chain being created
801  * or removed.
802  *
803  * 'salt' is buffer space and is referenced via 'nsec3param.salt'.
804  *
805  * 'seen_nsec' will be set to true if, while iterating the zone to create a
806  * NSEC3 chain, a NSEC record is seen.
807  *
808  * 'delete_nsec' will be set to true if, at the completion of the creation
809  * of a NSEC3 chain, 'seen_nsec' is true.  If 'delete_nsec' is true then we
810  * are in the process of deleting the NSEC chain.
811  *
812  * 'save_delete_nsec' is used to store the initial state of 'delete_nsec'
813  * so it can be recovered in the event of a error.
814  */
815 
816 struct dns_keyfetch {
817 	isc_mem_t *mctx;
818 	dns_fixedname_t name;
819 	dns_rdataset_t keydataset;
820 	dns_rdataset_t dnskeyset;
821 	dns_rdataset_t dnskeysigset;
822 	dns_zone_t *zone;
823 	dns_db_t *db;
824 	dns_fetch_t *fetch;
825 };
826 
827 /*%
828  * Hold state for an asynchronous load
829  */
830 struct dns_asyncload {
831 	dns_zone_t *zone;
832 	unsigned int flags;
833 	dns_zt_zoneloaded_t loaded;
834 	void *loaded_arg;
835 };
836 
837 /*%
838  * Reference to an include file encountered during loading
839  */
840 struct dns_include {
841 	char *name;
842 	isc_time_t filetime;
843 	ISC_LINK(dns_include_t) link;
844 };
845 
846 /*
847  * These can be overridden by the -T mkeytimers option on the command
848  * line, so that we can test with shorter periods than specified in
849  * RFC 5011.
850  */
851 #define HOUR  3600
852 #define DAY   (24 * HOUR)
853 #define MONTH (30 * DAY)
854 LIBDNS_EXTERNAL_DATA unsigned int dns_zone_mkey_hour = HOUR;
855 LIBDNS_EXTERNAL_DATA unsigned int dns_zone_mkey_day = DAY;
856 LIBDNS_EXTERNAL_DATA unsigned int dns_zone_mkey_month = MONTH;
857 
858 #define SEND_BUFFER_SIZE 2048
859 
860 static void
861 zone_settimer(dns_zone_t *, isc_time_t *);
862 static void
863 cancel_refresh(dns_zone_t *);
864 static void
865 zone_debuglog(dns_zone_t *zone, const char *, int debuglevel, const char *msg,
866 	      ...) ISC_FORMAT_PRINTF(4, 5);
867 static void
868 notify_log(dns_zone_t *zone, int level, const char *fmt, ...)
869 	ISC_FORMAT_PRINTF(3, 4);
870 static void
871 dnssec_log(dns_zone_t *zone, int level, const char *fmt, ...)
872 	ISC_FORMAT_PRINTF(3, 4);
873 static void
874 queue_xfrin(dns_zone_t *zone);
875 static isc_result_t
876 update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
877 	      dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
878 	      dns_rdata_t *rdata);
879 static void
880 zone_unload(dns_zone_t *zone);
881 static void
882 zone_expire(dns_zone_t *zone);
883 static void
884 zone_iattach(dns_zone_t *source, dns_zone_t **target);
885 static void
886 zone_idetach(dns_zone_t **zonep);
887 static isc_result_t
888 zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump);
889 static void
890 zone_attachdb(dns_zone_t *zone, dns_db_t *db);
891 static void
892 zone_detachdb(dns_zone_t *zone);
893 static void
894 zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs);
895 static void
896 zone_catz_disable(dns_zone_t *zone);
897 static isc_result_t
898 default_journal(dns_zone_t *zone);
899 static void
900 zone_xfrdone(dns_zone_t *zone, isc_result_t result);
901 static isc_result_t
902 zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
903 	      isc_result_t result);
904 static void
905 zone_needdump(dns_zone_t *zone, unsigned int delay);
906 static void
907 zone_shutdown(isc_task_t *, isc_event_t *);
908 static void
909 zone_loaddone(void *arg, isc_result_t result);
910 static isc_result_t
911 zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime);
912 static void
913 zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length);
914 static void
915 zone_name_tostr(dns_zone_t *zone, char *buf, size_t length);
916 static void
917 zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length);
918 static void
919 zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length);
920 static isc_result_t
921 zone_send_secureserial(dns_zone_t *zone, uint32_t serial);
922 static void
923 refresh_callback(isc_task_t *, isc_event_t *);
924 static void
925 stub_callback(isc_task_t *, isc_event_t *);
926 static void
927 queue_soa_query(dns_zone_t *zone);
928 static void
929 soa_query(isc_task_t *, isc_event_t *);
930 static void
931 ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub);
932 static int
933 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type);
934 static void
935 checkds_cancel(dns_zone_t *zone);
936 static void
937 checkds_send(dns_zone_t *zone);
938 static isc_result_t
939 checkds_createmessage(dns_zone_t *zone, dns_message_t **messagep);
940 static void
941 checkds_done(isc_task_t *task, isc_event_t *event);
942 static void
943 checkds_send_toaddr(isc_task_t *task, isc_event_t *event);
944 static void
945 notify_cancel(dns_zone_t *zone);
946 static void
947 notify_find_address(dns_notify_t *notify);
948 static void
949 notify_send(dns_notify_t *notify);
950 static isc_result_t
951 notify_createmessage(dns_zone_t *zone, unsigned int flags,
952 		     dns_message_t **messagep);
953 static void
954 notify_done(isc_task_t *task, isc_event_t *event);
955 static void
956 notify_send_toaddr(isc_task_t *task, isc_event_t *event);
957 static isc_result_t
958 zone_dump(dns_zone_t *, bool);
959 static void
960 got_transfer_quota(isc_task_t *task, isc_event_t *event);
961 static isc_result_t
962 zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone);
963 static void
964 zmgr_resume_xfrs(dns_zonemgr_t *zmgr, bool multi);
965 static void
966 zonemgr_free(dns_zonemgr_t *zmgr);
967 static isc_result_t
968 zonemgr_getio(dns_zonemgr_t *zmgr, bool high, isc_task_t *task,
969 	      isc_taskaction_t action, void *arg, dns_io_t **iop);
970 static void
971 zonemgr_putio(dns_io_t **iop);
972 static void
973 zonemgr_cancelio(dns_io_t *io);
974 static void
975 rss_post(dns_zone_t *, isc_event_t *);
976 
977 static isc_result_t
978 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
979 		 unsigned int *soacount, uint32_t *soattl, uint32_t *serial,
980 		 uint32_t *refresh, uint32_t *retry, uint32_t *expire,
981 		 uint32_t *minimum, unsigned int *errors);
982 
983 static void
984 zone_freedbargs(dns_zone_t *zone);
985 static void
986 forward_callback(isc_task_t *task, isc_event_t *event);
987 static void
988 zone_saveunique(dns_zone_t *zone, const char *path, const char *templat);
989 static void
990 zone_maintenance(dns_zone_t *zone);
991 static void
992 zone_notify(dns_zone_t *zone, isc_time_t *now);
993 static void
994 dump_done(void *arg, isc_result_t result);
995 static isc_result_t
996 zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid,
997 		 bool deleteit);
998 static isc_result_t
999 delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
1000 	    dns_name_t *name, dns_diff_t *diff);
1001 static void
1002 zone_rekey(dns_zone_t *zone);
1003 static isc_result_t
1004 zone_send_securedb(dns_zone_t *zone, dns_db_t *db);
1005 static dns_ttl_t
1006 zone_nsecttl(dns_zone_t *zone);
1007 static void
1008 setrl(isc_ratelimiter_t *rl, unsigned int *rate, unsigned int value);
1009 static void
1010 zone_journal_compact(dns_zone_t *zone, dns_db_t *db, uint32_t serial);
1011 static isc_result_t
1012 zone_journal_rollforward(dns_zone_t *zone, dns_db_t *db, bool *needdump,
1013 			 bool *fixjournal);
1014 
1015 #define ENTER zone_debuglog(zone, me, 1, "enter")
1016 
1017 static const unsigned int dbargc_default = 1;
1018 static const char *dbargv_default[] = { "rbt" };
1019 
1020 #define DNS_ZONE_JITTER_ADD(a, b, c)                                         \
1021 	do {                                                                 \
1022 		isc_interval_t _i;                                           \
1023 		uint32_t _j;                                                 \
1024 		_j = (b)-isc_random_uniform((b) / 4);                        \
1025 		isc_interval_set(&_i, _j, 0);                                \
1026 		if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) {          \
1027 			dns_zone_log(zone, ISC_LOG_WARNING,                  \
1028 				     "epoch approaching: upgrade required: " \
1029 				     "now + %s failed",                      \
1030 				     #b);                                    \
1031 			isc_interval_set(&_i, _j / 2, 0);                    \
1032 			(void)isc_time_add((a), &_i, (c));                   \
1033 		}                                                            \
1034 	} while (0)
1035 
1036 #define DNS_ZONE_TIME_ADD(a, b, c)                                           \
1037 	do {                                                                 \
1038 		isc_interval_t _i;                                           \
1039 		isc_interval_set(&_i, (b), 0);                               \
1040 		if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) {          \
1041 			dns_zone_log(zone, ISC_LOG_WARNING,                  \
1042 				     "epoch approaching: upgrade required: " \
1043 				     "now + %s failed",                      \
1044 				     #b);                                    \
1045 			isc_interval_set(&_i, (b) / 2, 0);                   \
1046 			(void)isc_time_add((a), &_i, (c));                   \
1047 		}                                                            \
1048 	} while (0)
1049 
1050 typedef struct nsec3param nsec3param_t;
1051 struct nsec3param {
1052 	dns_rdata_nsec3param_t rdata;
1053 	unsigned char data[DNS_NSEC3PARAM_BUFFERSIZE + 1];
1054 	unsigned int length;
1055 	bool nsec;
1056 	bool replace;
1057 	bool resalt;
1058 	bool lookup;
1059 	ISC_LINK(nsec3param_t) link;
1060 };
1061 typedef ISC_LIST(nsec3param_t) nsec3paramlist_t;
1062 struct np3event {
1063 	isc_event_t event;
1064 	nsec3param_t params;
1065 };
1066 
1067 struct ssevent {
1068 	isc_event_t event;
1069 	uint32_t serial;
1070 };
1071 
1072 struct stub_cb_args {
1073 	dns_stub_t *stub;
1074 	dns_tsigkey_t *tsig_key;
1075 	isc_dscp_t dscp;
1076 	uint16_t udpsize;
1077 	int timeout;
1078 	bool reqnsid;
1079 };
1080 
1081 struct stub_glue_request {
1082 	dns_request_t *request;
1083 	dns_name_t name;
1084 	struct stub_cb_args *args;
1085 	bool ipv4;
1086 };
1087 
1088 /*%
1089  * Increment resolver-related statistics counters.  Zone must be locked.
1090  */
1091 static void
inc_stats(dns_zone_t * zone,isc_statscounter_t counter)1092 inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
1093 	if (zone->stats != NULL) {
1094 		isc_stats_increment(zone->stats, counter);
1095 	}
1096 }
1097 
1098 /***
1099  ***	Public functions.
1100  ***/
1101 
1102 isc_result_t
dns_zone_create(dns_zone_t ** zonep,isc_mem_t * mctx)1103 dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
1104 	isc_result_t result;
1105 	isc_time_t now;
1106 	dns_zone_t *zone = NULL;
1107 	dns_zone_t z = { .masterformat = dns_masterformat_none,
1108 			 .journalsize = -1,
1109 			 .rdclass = dns_rdataclass_none,
1110 			 .type = dns_zone_none,
1111 			 .refresh = DNS_ZONE_DEFAULTREFRESH,
1112 			 .retry = DNS_ZONE_DEFAULTRETRY,
1113 			 .maxrefresh = DNS_ZONE_MAXREFRESH,
1114 			 .minrefresh = DNS_ZONE_MINREFRESH,
1115 			 .maxretry = DNS_ZONE_MAXRETRY,
1116 			 .minretry = DNS_ZONE_MINRETRY,
1117 			 .notifytype = dns_notifytype_yes,
1118 			 .zero_no_soa_ttl = true,
1119 			 .check_names = dns_severity_ignore,
1120 			 .idlein = DNS_DEFAULT_IDLEIN,
1121 			 .idleout = DNS_DEFAULT_IDLEOUT,
1122 			 .notifysrc4dscp = -1,
1123 			 .notifysrc6dscp = -1,
1124 			 .parentalsrc4dscp = -1,
1125 			 .parentalsrc6dscp = -1,
1126 			 .xfrsource4dscp = -1,
1127 			 .xfrsource6dscp = -1,
1128 			 .altxfrsource4dscp = -1,
1129 			 .altxfrsource6dscp = -1,
1130 			 .maxxfrin = MAX_XFER_TIME,
1131 			 .maxxfrout = MAX_XFER_TIME,
1132 			 .sigvalidityinterval = 30 * 24 * 3600,
1133 			 .sigresigninginterval = 7 * 24 * 3600,
1134 			 .statlevel = dns_zonestat_none,
1135 			 .notifydelay = 5,
1136 			 .signatures = 10,
1137 			 .nodes = 100,
1138 			 .privatetype = (dns_rdatatype_t)0xffffU,
1139 			 .rpz_num = DNS_RPZ_INVALID_NUM,
1140 			 .requestixfr = true,
1141 			 .ixfr_ratio = 100,
1142 			 .requestexpire = true,
1143 			 .updatemethod = dns_updatemethod_increment,
1144 			 .magic = ZONE_MAGIC };
1145 
1146 	REQUIRE(zonep != NULL && *zonep == NULL);
1147 	REQUIRE(mctx != NULL);
1148 
1149 	TIME_NOW(&now);
1150 	zone = isc_mem_get(mctx, sizeof(*zone));
1151 	*zone = z;
1152 
1153 	zone->mctx = NULL;
1154 	isc_mem_attach(mctx, &zone->mctx);
1155 	isc_mutex_init(&zone->lock);
1156 	ZONEDB_INITLOCK(&zone->dblock);
1157 	/* XXX MPA check that all elements are initialised */
1158 #ifdef DNS_ZONE_CHECKLOCK
1159 	zone->locked = false;
1160 #endif /* ifdef DNS_ZONE_CHECKLOCK */
1161 
1162 	zone->notifytime = now;
1163 
1164 	ISC_LINK_INIT(zone, link);
1165 	isc_refcount_init(&zone->erefs, 1);
1166 	isc_refcount_init(&zone->irefs, 0);
1167 	dns_name_init(&zone->origin, NULL);
1168 	ISC_LIST_INIT(zone->includes);
1169 	ISC_LIST_INIT(zone->newincludes);
1170 	atomic_init(&zone->flags, 0);
1171 	atomic_init(&zone->options, 0);
1172 	atomic_init(&zone->keyopts, 0);
1173 	isc_time_settoepoch(&zone->expiretime);
1174 	isc_time_settoepoch(&zone->refreshtime);
1175 	isc_time_settoepoch(&zone->dumptime);
1176 	isc_time_settoepoch(&zone->loadtime);
1177 	isc_time_settoepoch(&zone->resigntime);
1178 	isc_time_settoepoch(&zone->keywarntime);
1179 	isc_time_settoepoch(&zone->signingtime);
1180 	isc_time_settoepoch(&zone->nsec3chaintime);
1181 	isc_time_settoepoch(&zone->refreshkeytime);
1182 	ISC_LIST_INIT(zone->notifies);
1183 	ISC_LIST_INIT(zone->checkds_requests);
1184 	isc_sockaddr_any(&zone->notifysrc4);
1185 	isc_sockaddr_any6(&zone->notifysrc6);
1186 	isc_sockaddr_any(&zone->parentalsrc4);
1187 	isc_sockaddr_any6(&zone->parentalsrc6);
1188 	isc_sockaddr_any(&zone->xfrsource4);
1189 	isc_sockaddr_any6(&zone->xfrsource6);
1190 	isc_sockaddr_any(&zone->altxfrsource4);
1191 	isc_sockaddr_any6(&zone->altxfrsource6);
1192 	ISC_LINK_INIT(zone, statelink);
1193 	ISC_LIST_INIT(zone->signing);
1194 	ISC_LIST_INIT(zone->nsec3chain);
1195 	ISC_LIST_INIT(zone->setnsec3param_queue);
1196 	ISC_LIST_INIT(zone->forwards);
1197 	ISC_LIST_INIT(zone->rss_events);
1198 	ISC_LIST_INIT(zone->rss_post);
1199 
1200 	result = isc_stats_create(mctx, &zone->gluecachestats,
1201 				  dns_gluecachestatscounter_max);
1202 	if (result != ISC_R_SUCCESS) {
1203 		goto free_refs;
1204 	}
1205 
1206 	/* Must be after magic is set. */
1207 	dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
1208 
1209 	ISC_EVENT_INIT(&zone->ctlevent, sizeof(zone->ctlevent), 0, NULL,
1210 		       DNS_EVENT_ZONECONTROL, zone_shutdown, zone, zone, NULL,
1211 		       NULL);
1212 	*zonep = zone;
1213 	return (ISC_R_SUCCESS);
1214 
1215 free_refs:
1216 	isc_refcount_decrement0(&zone->erefs);
1217 	isc_refcount_destroy(&zone->erefs);
1218 	isc_refcount_destroy(&zone->irefs);
1219 	ZONEDB_DESTROYLOCK(&zone->dblock);
1220 	isc_mutex_destroy(&zone->lock);
1221 	isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
1222 	return (result);
1223 }
1224 
1225 static void
clear_keylist(dns_dnsseckeylist_t * list,isc_mem_t * mctx)1226 clear_keylist(dns_dnsseckeylist_t *list, isc_mem_t *mctx) {
1227 	dns_dnsseckey_t *key;
1228 	while (!ISC_LIST_EMPTY(*list)) {
1229 		key = ISC_LIST_HEAD(*list);
1230 		ISC_LIST_UNLINK(*list, key, link);
1231 		dns_dnsseckey_destroy(mctx, &key);
1232 	}
1233 }
1234 
1235 /*
1236  * Free a zone.  Because we require that there be no more
1237  * outstanding events or references, no locking is necessary.
1238  */
1239 static void
zone_free(dns_zone_t * zone)1240 zone_free(dns_zone_t *zone) {
1241 	dns_signing_t *signing;
1242 	dns_nsec3chain_t *nsec3chain;
1243 	isc_event_t *event;
1244 	dns_include_t *include;
1245 
1246 	REQUIRE(DNS_ZONE_VALID(zone));
1247 	isc_refcount_destroy(&zone->erefs);
1248 	isc_refcount_destroy(&zone->irefs);
1249 	REQUIRE(!LOCKED_ZONE(zone));
1250 	REQUIRE(zone->timer == NULL);
1251 	REQUIRE(zone->zmgr == NULL);
1252 
1253 	/*
1254 	 * Managed objects.  Order is important.
1255 	 */
1256 	if (zone->request != NULL) {
1257 		dns_request_destroy(&zone->request); /* XXXMPA */
1258 	}
1259 	INSIST(zone->readio == NULL);
1260 	INSIST(zone->statelist == NULL);
1261 	INSIST(zone->writeio == NULL);
1262 	INSIST(zone->view == NULL);
1263 	INSIST(zone->prev_view == NULL);
1264 
1265 	if (zone->task != NULL) {
1266 		isc_task_detach(&zone->task);
1267 	}
1268 	if (zone->loadtask != NULL) {
1269 		isc_task_detach(&zone->loadtask);
1270 	}
1271 
1272 	/* Unmanaged objects */
1273 	while (!ISC_LIST_EMPTY(zone->setnsec3param_queue)) {
1274 		event = ISC_LIST_HEAD(zone->setnsec3param_queue);
1275 		ISC_LIST_UNLINK(zone->setnsec3param_queue, event, ev_link);
1276 		isc_event_free(&event);
1277 	}
1278 	while (!ISC_LIST_EMPTY(zone->rss_post)) {
1279 		event = ISC_LIST_HEAD(zone->rss_post);
1280 		ISC_LIST_UNLINK(zone->rss_post, event, ev_link);
1281 		isc_event_free(&event);
1282 	}
1283 	for (signing = ISC_LIST_HEAD(zone->signing); signing != NULL;
1284 	     signing = ISC_LIST_HEAD(zone->signing))
1285 	{
1286 		ISC_LIST_UNLINK(zone->signing, signing, link);
1287 		dns_db_detach(&signing->db);
1288 		dns_dbiterator_destroy(&signing->dbiterator);
1289 		isc_mem_put(zone->mctx, signing, sizeof *signing);
1290 	}
1291 	for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain); nsec3chain != NULL;
1292 	     nsec3chain = ISC_LIST_HEAD(zone->nsec3chain))
1293 	{
1294 		ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
1295 		dns_db_detach(&nsec3chain->db);
1296 		dns_dbiterator_destroy(&nsec3chain->dbiterator);
1297 		isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
1298 	}
1299 	for (include = ISC_LIST_HEAD(zone->includes); include != NULL;
1300 	     include = ISC_LIST_HEAD(zone->includes))
1301 	{
1302 		ISC_LIST_UNLINK(zone->includes, include, link);
1303 		isc_mem_free(zone->mctx, include->name);
1304 		isc_mem_put(zone->mctx, include, sizeof *include);
1305 	}
1306 	for (include = ISC_LIST_HEAD(zone->newincludes); include != NULL;
1307 	     include = ISC_LIST_HEAD(zone->newincludes))
1308 	{
1309 		ISC_LIST_UNLINK(zone->newincludes, include, link);
1310 		isc_mem_free(zone->mctx, include->name);
1311 		isc_mem_put(zone->mctx, include, sizeof *include);
1312 	}
1313 	if (zone->masterfile != NULL) {
1314 		isc_mem_free(zone->mctx, zone->masterfile);
1315 	}
1316 	zone->masterfile = NULL;
1317 	if (zone->keydirectory != NULL) {
1318 		isc_mem_free(zone->mctx, zone->keydirectory);
1319 	}
1320 	zone->keydirectory = NULL;
1321 	if (zone->kasp != NULL) {
1322 		dns_kasp_detach(&zone->kasp);
1323 	}
1324 	if (!ISC_LIST_EMPTY(zone->checkds_ok)) {
1325 		clear_keylist(&zone->checkds_ok, zone->mctx);
1326 	}
1327 
1328 	zone->journalsize = -1;
1329 	if (zone->journal != NULL) {
1330 		isc_mem_free(zone->mctx, zone->journal);
1331 	}
1332 	zone->journal = NULL;
1333 	if (zone->stats != NULL) {
1334 		isc_stats_detach(&zone->stats);
1335 	}
1336 	if (zone->requeststats != NULL) {
1337 		isc_stats_detach(&zone->requeststats);
1338 	}
1339 	if (zone->rcvquerystats != NULL) {
1340 		dns_stats_detach(&zone->rcvquerystats);
1341 	}
1342 	if (zone->dnssecsignstats != NULL) {
1343 		dns_stats_detach(&zone->dnssecsignstats);
1344 	}
1345 	if (zone->db != NULL) {
1346 		zone_detachdb(zone);
1347 	}
1348 	if (zone->rpzs != NULL) {
1349 		REQUIRE(zone->rpz_num < zone->rpzs->p.num_zones);
1350 		dns_rpz_detach_rpzs(&zone->rpzs);
1351 		zone->rpz_num = DNS_RPZ_INVALID_NUM;
1352 	}
1353 	if (zone->catzs != NULL) {
1354 		dns_catz_catzs_detach(&zone->catzs);
1355 	}
1356 	zone_freedbargs(zone);
1357 
1358 	RUNTIME_CHECK(dns_zone_setparentals(zone, NULL, NULL, 0) ==
1359 		      ISC_R_SUCCESS);
1360 	RUNTIME_CHECK(dns_zone_setprimarieswithkeys(zone, NULL, NULL, 0) ==
1361 		      ISC_R_SUCCESS);
1362 	RUNTIME_CHECK(dns_zone_setalsonotify(zone, NULL, 0) == ISC_R_SUCCESS);
1363 	zone->check_names = dns_severity_ignore;
1364 	if (zone->update_acl != NULL) {
1365 		dns_acl_detach(&zone->update_acl);
1366 	}
1367 	if (zone->forward_acl != NULL) {
1368 		dns_acl_detach(&zone->forward_acl);
1369 	}
1370 	if (zone->notify_acl != NULL) {
1371 		dns_acl_detach(&zone->notify_acl);
1372 	}
1373 	if (zone->query_acl != NULL) {
1374 		dns_acl_detach(&zone->query_acl);
1375 	}
1376 	if (zone->queryon_acl != NULL) {
1377 		dns_acl_detach(&zone->queryon_acl);
1378 	}
1379 	if (zone->xfr_acl != NULL) {
1380 		dns_acl_detach(&zone->xfr_acl);
1381 	}
1382 	if (dns_name_dynamic(&zone->origin)) {
1383 		dns_name_free(&zone->origin, zone->mctx);
1384 	}
1385 	if (zone->strnamerd != NULL) {
1386 		isc_mem_free(zone->mctx, zone->strnamerd);
1387 	}
1388 	if (zone->strname != NULL) {
1389 		isc_mem_free(zone->mctx, zone->strname);
1390 	}
1391 	if (zone->strrdclass != NULL) {
1392 		isc_mem_free(zone->mctx, zone->strrdclass);
1393 	}
1394 	if (zone->strviewname != NULL) {
1395 		isc_mem_free(zone->mctx, zone->strviewname);
1396 	}
1397 	if (zone->ssutable != NULL) {
1398 		dns_ssutable_detach(&zone->ssutable);
1399 	}
1400 	if (zone->gluecachestats != NULL) {
1401 		isc_stats_detach(&zone->gluecachestats);
1402 	}
1403 
1404 	/* last stuff */
1405 	ZONEDB_DESTROYLOCK(&zone->dblock);
1406 	isc_mutex_destroy(&zone->lock);
1407 	zone->magic = 0;
1408 	isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
1409 }
1410 
1411 /*
1412  * Returns true iff this the signed side of an inline-signing zone.
1413  * Caller should hold zone lock.
1414  */
1415 static bool
inline_secure(dns_zone_t * zone)1416 inline_secure(dns_zone_t *zone) {
1417 	REQUIRE(DNS_ZONE_VALID(zone));
1418 	if (zone->raw != NULL) {
1419 		return (true);
1420 	}
1421 	return (false);
1422 }
1423 
1424 /*
1425  * Returns true iff this the unsigned side of an inline-signing zone
1426  * Caller should hold zone lock.
1427  */
1428 static bool
inline_raw(dns_zone_t * zone)1429 inline_raw(dns_zone_t *zone) {
1430 	REQUIRE(DNS_ZONE_VALID(zone));
1431 	if (zone->secure != NULL) {
1432 		return (true);
1433 	}
1434 	return (false);
1435 }
1436 
1437 /*
1438  *	Single shot.
1439  */
1440 void
dns_zone_setclass(dns_zone_t * zone,dns_rdataclass_t rdclass)1441 dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
1442 	char namebuf[1024];
1443 
1444 	REQUIRE(DNS_ZONE_VALID(zone));
1445 	REQUIRE(rdclass != dns_rdataclass_none);
1446 
1447 	/*
1448 	 * Test and set.
1449 	 */
1450 	LOCK_ZONE(zone);
1451 	INSIST(zone != zone->raw);
1452 	REQUIRE(zone->rdclass == dns_rdataclass_none ||
1453 		zone->rdclass == rdclass);
1454 	zone->rdclass = rdclass;
1455 
1456 	if (zone->strnamerd != NULL) {
1457 		isc_mem_free(zone->mctx, zone->strnamerd);
1458 	}
1459 	if (zone->strrdclass != NULL) {
1460 		isc_mem_free(zone->mctx, zone->strrdclass);
1461 	}
1462 
1463 	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1464 	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1465 	zone_rdclass_tostr(zone, namebuf, sizeof namebuf);
1466 	zone->strrdclass = isc_mem_strdup(zone->mctx, namebuf);
1467 
1468 	if (inline_secure(zone)) {
1469 		dns_zone_setclass(zone->raw, rdclass);
1470 	}
1471 	UNLOCK_ZONE(zone);
1472 }
1473 
1474 dns_rdataclass_t
dns_zone_getclass(dns_zone_t * zone)1475 dns_zone_getclass(dns_zone_t *zone) {
1476 	REQUIRE(DNS_ZONE_VALID(zone));
1477 
1478 	return (zone->rdclass);
1479 }
1480 
1481 void
dns_zone_setnotifytype(dns_zone_t * zone,dns_notifytype_t notifytype)1482 dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
1483 	REQUIRE(DNS_ZONE_VALID(zone));
1484 
1485 	LOCK_ZONE(zone);
1486 	zone->notifytype = notifytype;
1487 	UNLOCK_ZONE(zone);
1488 }
1489 
1490 isc_result_t
dns_zone_getserial(dns_zone_t * zone,uint32_t * serialp)1491 dns_zone_getserial(dns_zone_t *zone, uint32_t *serialp) {
1492 	isc_result_t result;
1493 	unsigned int soacount;
1494 
1495 	REQUIRE(DNS_ZONE_VALID(zone));
1496 	REQUIRE(serialp != NULL);
1497 
1498 	LOCK_ZONE(zone);
1499 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1500 	if (zone->db != NULL) {
1501 		result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL,
1502 					  serialp, NULL, NULL, NULL, NULL,
1503 					  NULL);
1504 		if (result == ISC_R_SUCCESS && soacount == 0) {
1505 			result = ISC_R_FAILURE;
1506 		}
1507 	} else {
1508 		result = DNS_R_NOTLOADED;
1509 	}
1510 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1511 	UNLOCK_ZONE(zone);
1512 
1513 	return (result);
1514 }
1515 
1516 /*
1517  *	Single shot.
1518  */
1519 void
dns_zone_settype(dns_zone_t * zone,dns_zonetype_t type)1520 dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) {
1521 	char namebuf[1024];
1522 
1523 	REQUIRE(DNS_ZONE_VALID(zone));
1524 	REQUIRE(type != dns_zone_none);
1525 
1526 	/*
1527 	 * Test and set.
1528 	 */
1529 	LOCK_ZONE(zone);
1530 	REQUIRE(zone->type == dns_zone_none || zone->type == type);
1531 	zone->type = type;
1532 
1533 	if (zone->strnamerd != NULL) {
1534 		isc_mem_free(zone->mctx, zone->strnamerd);
1535 	}
1536 
1537 	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1538 	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1539 	UNLOCK_ZONE(zone);
1540 }
1541 
1542 static void
zone_freedbargs(dns_zone_t * zone)1543 zone_freedbargs(dns_zone_t *zone) {
1544 	unsigned int i;
1545 
1546 	/* Free the old database argument list. */
1547 	if (zone->db_argv != NULL) {
1548 		for (i = 0; i < zone->db_argc; i++) {
1549 			isc_mem_free(zone->mctx, zone->db_argv[i]);
1550 		}
1551 		isc_mem_put(zone->mctx, zone->db_argv,
1552 			    zone->db_argc * sizeof(*zone->db_argv));
1553 	}
1554 	zone->db_argc = 0;
1555 	zone->db_argv = NULL;
1556 }
1557 
1558 isc_result_t
dns_zone_getdbtype(dns_zone_t * zone,char *** argv,isc_mem_t * mctx)1559 dns_zone_getdbtype(dns_zone_t *zone, char ***argv, isc_mem_t *mctx) {
1560 	size_t size = 0;
1561 	unsigned int i;
1562 	isc_result_t result = ISC_R_SUCCESS;
1563 	void *mem;
1564 	char **tmp, *tmp2, *base;
1565 
1566 	REQUIRE(DNS_ZONE_VALID(zone));
1567 	REQUIRE(argv != NULL && *argv == NULL);
1568 
1569 	LOCK_ZONE(zone);
1570 	size = (zone->db_argc + 1) * sizeof(char *);
1571 	for (i = 0; i < zone->db_argc; i++) {
1572 		size += strlen(zone->db_argv[i]) + 1;
1573 	}
1574 	mem = isc_mem_allocate(mctx, size);
1575 	{
1576 		tmp = mem;
1577 		tmp2 = mem;
1578 		base = mem;
1579 		tmp2 += (zone->db_argc + 1) * sizeof(char *);
1580 		for (i = 0; i < zone->db_argc; i++) {
1581 			*tmp++ = tmp2;
1582 			strlcpy(tmp2, zone->db_argv[i], size - (tmp2 - base));
1583 			tmp2 += strlen(tmp2) + 1;
1584 		}
1585 		*tmp = NULL;
1586 	}
1587 	UNLOCK_ZONE(zone);
1588 	*argv = mem;
1589 	return (result);
1590 }
1591 
1592 void
dns_zone_setdbtype(dns_zone_t * zone,unsigned int dbargc,const char * const * dbargv)1593 dns_zone_setdbtype(dns_zone_t *zone, unsigned int dbargc,
1594 		   const char *const *dbargv) {
1595 	char **argv = NULL;
1596 	unsigned int i;
1597 
1598 	REQUIRE(DNS_ZONE_VALID(zone));
1599 	REQUIRE(dbargc >= 1);
1600 	REQUIRE(dbargv != NULL);
1601 
1602 	LOCK_ZONE(zone);
1603 
1604 	/* Set up a new database argument list. */
1605 	argv = isc_mem_get(zone->mctx, dbargc * sizeof(*argv));
1606 	for (i = 0; i < dbargc; i++) {
1607 		argv[i] = NULL;
1608 	}
1609 	for (i = 0; i < dbargc; i++) {
1610 		argv[i] = isc_mem_strdup(zone->mctx, dbargv[i]);
1611 	}
1612 
1613 	/* Free the old list. */
1614 	zone_freedbargs(zone);
1615 
1616 	zone->db_argc = dbargc;
1617 	zone->db_argv = argv;
1618 
1619 	UNLOCK_ZONE(zone);
1620 }
1621 
1622 static void
dns_zone_setview_helper(dns_zone_t * zone,dns_view_t * view)1623 dns_zone_setview_helper(dns_zone_t *zone, dns_view_t *view) {
1624 	char namebuf[1024];
1625 
1626 	if (zone->prev_view == NULL && zone->view != NULL) {
1627 		dns_view_weakattach(zone->view, &zone->prev_view);
1628 	}
1629 
1630 	INSIST(zone != zone->raw);
1631 	if (zone->view != NULL) {
1632 		dns_view_weakdetach(&zone->view);
1633 	}
1634 	dns_view_weakattach(view, &zone->view);
1635 
1636 	if (zone->strviewname != NULL) {
1637 		isc_mem_free(zone->mctx, zone->strviewname);
1638 	}
1639 	if (zone->strnamerd != NULL) {
1640 		isc_mem_free(zone->mctx, zone->strnamerd);
1641 	}
1642 
1643 	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1644 	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1645 	zone_viewname_tostr(zone, namebuf, sizeof namebuf);
1646 	zone->strviewname = isc_mem_strdup(zone->mctx, namebuf);
1647 
1648 	if (inline_secure(zone)) {
1649 		dns_zone_setview(zone->raw, view);
1650 	}
1651 }
1652 
1653 void
dns_zone_setview(dns_zone_t * zone,dns_view_t * view)1654 dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
1655 	REQUIRE(DNS_ZONE_VALID(zone));
1656 
1657 	LOCK_ZONE(zone);
1658 	dns_zone_setview_helper(zone, view);
1659 	UNLOCK_ZONE(zone);
1660 }
1661 
1662 dns_view_t *
dns_zone_getview(dns_zone_t * zone)1663 dns_zone_getview(dns_zone_t *zone) {
1664 	REQUIRE(DNS_ZONE_VALID(zone));
1665 
1666 	return (zone->view);
1667 }
1668 
1669 void
dns_zone_setviewcommit(dns_zone_t * zone)1670 dns_zone_setviewcommit(dns_zone_t *zone) {
1671 	REQUIRE(DNS_ZONE_VALID(zone));
1672 
1673 	LOCK_ZONE(zone);
1674 	if (zone->prev_view != NULL) {
1675 		dns_view_weakdetach(&zone->prev_view);
1676 	}
1677 	if (inline_secure(zone)) {
1678 		dns_zone_setviewcommit(zone->raw);
1679 	}
1680 	UNLOCK_ZONE(zone);
1681 }
1682 
1683 void
dns_zone_setviewrevert(dns_zone_t * zone)1684 dns_zone_setviewrevert(dns_zone_t *zone) {
1685 	REQUIRE(DNS_ZONE_VALID(zone));
1686 
1687 	LOCK_ZONE(zone);
1688 	if (zone->prev_view != NULL) {
1689 		dns_zone_setview_helper(zone, zone->prev_view);
1690 		dns_view_weakdetach(&zone->prev_view);
1691 	}
1692 	if (zone->catzs != NULL) {
1693 		zone_catz_enable(zone, zone->catzs);
1694 	}
1695 	if (inline_secure(zone)) {
1696 		dns_zone_setviewrevert(zone->raw);
1697 	}
1698 	UNLOCK_ZONE(zone);
1699 }
1700 
1701 isc_result_t
dns_zone_setorigin(dns_zone_t * zone,const dns_name_t * origin)1702 dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
1703 	isc_result_t result = ISC_R_SUCCESS;
1704 	char namebuf[1024];
1705 
1706 	REQUIRE(DNS_ZONE_VALID(zone));
1707 	REQUIRE(origin != NULL);
1708 
1709 	LOCK_ZONE(zone);
1710 	INSIST(zone != zone->raw);
1711 	if (dns_name_dynamic(&zone->origin)) {
1712 		dns_name_free(&zone->origin, zone->mctx);
1713 		dns_name_init(&zone->origin, NULL);
1714 	}
1715 	dns_name_dup(origin, zone->mctx, &zone->origin);
1716 
1717 	if (zone->strnamerd != NULL) {
1718 		isc_mem_free(zone->mctx, zone->strnamerd);
1719 	}
1720 	if (zone->strname != NULL) {
1721 		isc_mem_free(zone->mctx, zone->strname);
1722 	}
1723 
1724 	zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1725 	zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1726 	zone_name_tostr(zone, namebuf, sizeof namebuf);
1727 	zone->strname = isc_mem_strdup(zone->mctx, namebuf);
1728 
1729 	if (inline_secure(zone)) {
1730 		result = dns_zone_setorigin(zone->raw, origin);
1731 	}
1732 	UNLOCK_ZONE(zone);
1733 	return (result);
1734 }
1735 
1736 static isc_result_t
dns_zone_setstring(dns_zone_t * zone,char ** field,const char * value)1737 dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
1738 	char *copy;
1739 
1740 	if (value != NULL) {
1741 		copy = isc_mem_strdup(zone->mctx, value);
1742 	} else {
1743 		copy = NULL;
1744 	}
1745 
1746 	if (*field != NULL) {
1747 		isc_mem_free(zone->mctx, *field);
1748 	}
1749 
1750 	*field = copy;
1751 	return (ISC_R_SUCCESS);
1752 }
1753 
1754 isc_result_t
dns_zone_setfile(dns_zone_t * zone,const char * file,dns_masterformat_t format,const dns_master_style_t * style)1755 dns_zone_setfile(dns_zone_t *zone, const char *file, dns_masterformat_t format,
1756 		 const dns_master_style_t *style) {
1757 	isc_result_t result = ISC_R_SUCCESS;
1758 
1759 	REQUIRE(DNS_ZONE_VALID(zone));
1760 
1761 	LOCK_ZONE(zone);
1762 	result = dns_zone_setstring(zone, &zone->masterfile, file);
1763 	if (result == ISC_R_SUCCESS) {
1764 		zone->masterformat = format;
1765 		if (format == dns_masterformat_text) {
1766 			zone->masterstyle = style;
1767 		}
1768 		result = default_journal(zone);
1769 	}
1770 	UNLOCK_ZONE(zone);
1771 
1772 	return (result);
1773 }
1774 
1775 const char *
dns_zone_getfile(dns_zone_t * zone)1776 dns_zone_getfile(dns_zone_t *zone) {
1777 	REQUIRE(DNS_ZONE_VALID(zone));
1778 
1779 	return (zone->masterfile);
1780 }
1781 
1782 dns_ttl_t
dns_zone_getmaxttl(dns_zone_t * zone)1783 dns_zone_getmaxttl(dns_zone_t *zone) {
1784 	REQUIRE(DNS_ZONE_VALID(zone));
1785 
1786 	return (zone->maxttl);
1787 }
1788 
1789 void
dns_zone_setmaxttl(dns_zone_t * zone,dns_ttl_t maxttl)1790 dns_zone_setmaxttl(dns_zone_t *zone, dns_ttl_t maxttl) {
1791 	REQUIRE(DNS_ZONE_VALID(zone));
1792 
1793 	LOCK_ZONE(zone);
1794 	if (maxttl != 0) {
1795 		DNS_ZONE_SETOPTION(zone, DNS_ZONEOPT_CHECKTTL);
1796 	} else {
1797 		DNS_ZONE_CLROPTION(zone, DNS_ZONEOPT_CHECKTTL);
1798 	}
1799 	zone->maxttl = maxttl;
1800 	UNLOCK_ZONE(zone);
1801 
1802 	return;
1803 }
1804 
1805 static isc_result_t
default_journal(dns_zone_t * zone)1806 default_journal(dns_zone_t *zone) {
1807 	isc_result_t result;
1808 	char *journal;
1809 
1810 	REQUIRE(DNS_ZONE_VALID(zone));
1811 	REQUIRE(LOCKED_ZONE(zone));
1812 
1813 	if (zone->masterfile != NULL) {
1814 		/* Calculate string length including '\0'. */
1815 		int len = strlen(zone->masterfile) + sizeof(".jnl");
1816 		journal = isc_mem_allocate(zone->mctx, len);
1817 		strlcpy(journal, zone->masterfile, len);
1818 		strlcat(journal, ".jnl", len);
1819 	} else {
1820 		journal = NULL;
1821 	}
1822 	result = dns_zone_setstring(zone, &zone->journal, journal);
1823 	if (journal != NULL) {
1824 		isc_mem_free(zone->mctx, journal);
1825 	}
1826 	return (result);
1827 }
1828 
1829 isc_result_t
dns_zone_setjournal(dns_zone_t * zone,const char * myjournal)1830 dns_zone_setjournal(dns_zone_t *zone, const char *myjournal) {
1831 	isc_result_t result = ISC_R_SUCCESS;
1832 
1833 	REQUIRE(DNS_ZONE_VALID(zone));
1834 
1835 	LOCK_ZONE(zone);
1836 	result = dns_zone_setstring(zone, &zone->journal, myjournal);
1837 	UNLOCK_ZONE(zone);
1838 
1839 	return (result);
1840 }
1841 
1842 char *
dns_zone_getjournal(dns_zone_t * zone)1843 dns_zone_getjournal(dns_zone_t *zone) {
1844 	REQUIRE(DNS_ZONE_VALID(zone));
1845 
1846 	return (zone->journal);
1847 }
1848 
1849 /*
1850  * Return true iff the zone is "dynamic", in the sense that the zone's
1851  * master file (if any) is written by the server, rather than being
1852  * updated manually and read by the server.
1853  *
1854  * This is true for slave zones, mirror zones, stub zones, key zones,
1855  * and zones that allow dynamic updates either by having an update
1856  * policy ("ssutable") or an "allow-update" ACL with a value other than
1857  * exactly "{ none; }".
1858  */
1859 bool
dns_zone_isdynamic(dns_zone_t * zone,bool ignore_freeze)1860 dns_zone_isdynamic(dns_zone_t *zone, bool ignore_freeze) {
1861 	REQUIRE(DNS_ZONE_VALID(zone));
1862 
1863 	if (zone->type == dns_zone_secondary || zone->type == dns_zone_mirror ||
1864 	    zone->type == dns_zone_stub || zone->type == dns_zone_key ||
1865 	    (zone->type == dns_zone_redirect && zone->masters != NULL))
1866 	{
1867 		return (true);
1868 	}
1869 
1870 	/* Inline zones are always dynamic. */
1871 	if (zone->type == dns_zone_primary && zone->raw != NULL) {
1872 		return (true);
1873 	}
1874 
1875 	/* If !ignore_freeze, we need check whether updates are disabled.  */
1876 	if (zone->type == dns_zone_primary &&
1877 	    (!zone->update_disabled || ignore_freeze) &&
1878 	    ((zone->ssutable != NULL) ||
1879 	     (zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl))))
1880 	{
1881 		return (true);
1882 	}
1883 
1884 	return (false);
1885 }
1886 
1887 /*
1888  * Set the response policy index and information for a zone.
1889  */
1890 isc_result_t
dns_zone_rpz_enable(dns_zone_t * zone,dns_rpz_zones_t * rpzs,dns_rpz_num_t rpz_num)1891 dns_zone_rpz_enable(dns_zone_t *zone, dns_rpz_zones_t *rpzs,
1892 		    dns_rpz_num_t rpz_num) {
1893 	/*
1894 	 * Only RBTDB zones can be used for response policy zones,
1895 	 * because only they have the code to create the summary data.
1896 	 * Only zones that are loaded instead of mmap()ed create the
1897 	 * summary data and so can be policy zones.
1898 	 */
1899 	if (strcmp(zone->db_argv[0], "rbt") != 0 &&
1900 	    strcmp(zone->db_argv[0], "rbt64") != 0)
1901 	{
1902 		return (ISC_R_NOTIMPLEMENTED);
1903 	}
1904 	if (zone->masterformat == dns_masterformat_map) {
1905 		return (ISC_R_NOTIMPLEMENTED);
1906 	}
1907 
1908 	/*
1909 	 * This must happen only once or be redundant.
1910 	 */
1911 	LOCK_ZONE(zone);
1912 	if (zone->rpzs != NULL) {
1913 		REQUIRE(zone->rpzs == rpzs && zone->rpz_num == rpz_num);
1914 	} else {
1915 		REQUIRE(zone->rpz_num == DNS_RPZ_INVALID_NUM);
1916 		dns_rpz_attach_rpzs(rpzs, &zone->rpzs);
1917 		zone->rpz_num = rpz_num;
1918 	}
1919 	rpzs->defined |= DNS_RPZ_ZBIT(rpz_num);
1920 	UNLOCK_ZONE(zone);
1921 
1922 	return (ISC_R_SUCCESS);
1923 }
1924 
1925 dns_rpz_num_t
dns_zone_get_rpz_num(dns_zone_t * zone)1926 dns_zone_get_rpz_num(dns_zone_t *zone) {
1927 	return (zone->rpz_num);
1928 }
1929 
1930 /*
1931  * If a zone is a response policy zone, mark its new database.
1932  */
1933 void
dns_zone_rpz_enable_db(dns_zone_t * zone,dns_db_t * db)1934 dns_zone_rpz_enable_db(dns_zone_t *zone, dns_db_t *db) {
1935 	isc_result_t result;
1936 	if (zone->rpz_num == DNS_RPZ_INVALID_NUM) {
1937 		return;
1938 	}
1939 	REQUIRE(zone->rpzs != NULL);
1940 	result = dns_db_updatenotify_register(db, dns_rpz_dbupdate_callback,
1941 					      zone->rpzs->zones[zone->rpz_num]);
1942 	REQUIRE(result == ISC_R_SUCCESS);
1943 }
1944 
1945 static void
dns_zone_rpz_disable_db(dns_zone_t * zone,dns_db_t * db)1946 dns_zone_rpz_disable_db(dns_zone_t *zone, dns_db_t *db) {
1947 	if (zone->rpz_num == DNS_RPZ_INVALID_NUM) {
1948 		return;
1949 	}
1950 	REQUIRE(zone->rpzs != NULL);
1951 	(void)dns_db_updatenotify_unregister(db, dns_rpz_dbupdate_callback,
1952 					     zone->rpzs->zones[zone->rpz_num]);
1953 }
1954 
1955 /*
1956  * If a zone is a catalog zone, attach it to update notification in database.
1957  */
1958 void
dns_zone_catz_enable_db(dns_zone_t * zone,dns_db_t * db)1959 dns_zone_catz_enable_db(dns_zone_t *zone, dns_db_t *db) {
1960 	REQUIRE(DNS_ZONE_VALID(zone));
1961 	REQUIRE(db != NULL);
1962 
1963 	if (zone->catzs != NULL) {
1964 		dns_db_updatenotify_register(db, dns_catz_dbupdate_callback,
1965 					     zone->catzs);
1966 	}
1967 }
1968 
1969 static void
dns_zone_catz_disable_db(dns_zone_t * zone,dns_db_t * db)1970 dns_zone_catz_disable_db(dns_zone_t *zone, dns_db_t *db) {
1971 	REQUIRE(DNS_ZONE_VALID(zone));
1972 	REQUIRE(db != NULL);
1973 
1974 	if (zone->catzs != NULL) {
1975 		dns_db_updatenotify_unregister(db, dns_catz_dbupdate_callback,
1976 					       zone->catzs);
1977 	}
1978 }
1979 
1980 static void
zone_catz_enable(dns_zone_t * zone,dns_catz_zones_t * catzs)1981 zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs) {
1982 	REQUIRE(DNS_ZONE_VALID(zone));
1983 	REQUIRE(catzs != NULL);
1984 
1985 	INSIST(zone->catzs == NULL || zone->catzs == catzs);
1986 	dns_catz_catzs_set_view(catzs, zone->view);
1987 	if (zone->catzs == NULL) {
1988 		dns_catz_catzs_attach(catzs, &zone->catzs);
1989 	}
1990 }
1991 
1992 void
dns_zone_catz_enable(dns_zone_t * zone,dns_catz_zones_t * catzs)1993 dns_zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs) {
1994 	REQUIRE(DNS_ZONE_VALID(zone));
1995 
1996 	LOCK_ZONE(zone);
1997 	zone_catz_enable(zone, catzs);
1998 	UNLOCK_ZONE(zone);
1999 }
2000 
2001 static void
zone_catz_disable(dns_zone_t * zone)2002 zone_catz_disable(dns_zone_t *zone) {
2003 	REQUIRE(DNS_ZONE_VALID(zone));
2004 
2005 	if (zone->catzs != NULL) {
2006 		if (zone->db != NULL) {
2007 			dns_zone_catz_disable_db(zone, zone->db);
2008 		}
2009 		dns_catz_catzs_detach(&zone->catzs);
2010 	}
2011 }
2012 
2013 void
dns_zone_catz_disable(dns_zone_t * zone)2014 dns_zone_catz_disable(dns_zone_t *zone) {
2015 	REQUIRE(DNS_ZONE_VALID(zone));
2016 
2017 	LOCK_ZONE(zone);
2018 	zone_catz_disable(zone);
2019 	UNLOCK_ZONE(zone);
2020 }
2021 
2022 bool
dns_zone_catz_is_enabled(dns_zone_t * zone)2023 dns_zone_catz_is_enabled(dns_zone_t *zone) {
2024 	REQUIRE(DNS_ZONE_VALID(zone));
2025 
2026 	return (zone->catzs != NULL);
2027 }
2028 
2029 /*
2030  * Set catalog zone ownership of the zone
2031  */
2032 void
dns_zone_set_parentcatz(dns_zone_t * zone,dns_catz_zone_t * catz)2033 dns_zone_set_parentcatz(dns_zone_t *zone, dns_catz_zone_t *catz) {
2034 	REQUIRE(DNS_ZONE_VALID(zone));
2035 	REQUIRE(catz != NULL);
2036 	LOCK_ZONE(zone);
2037 	INSIST(zone->parentcatz == NULL || zone->parentcatz == catz);
2038 	zone->parentcatz = catz;
2039 	UNLOCK_ZONE(zone);
2040 }
2041 
2042 dns_catz_zone_t *
dns_zone_get_parentcatz(const dns_zone_t * zone)2043 dns_zone_get_parentcatz(const dns_zone_t *zone) {
2044 	REQUIRE(DNS_ZONE_VALID(zone));
2045 	return (zone->parentcatz);
2046 }
2047 
2048 static bool
zone_touched(dns_zone_t * zone)2049 zone_touched(dns_zone_t *zone) {
2050 	isc_result_t result;
2051 	isc_time_t modtime;
2052 	dns_include_t *include;
2053 
2054 	REQUIRE(DNS_ZONE_VALID(zone));
2055 
2056 	result = isc_file_getmodtime(zone->masterfile, &modtime);
2057 	if (result != ISC_R_SUCCESS ||
2058 	    isc_time_compare(&modtime, &zone->loadtime) > 0)
2059 	{
2060 		return (true);
2061 	}
2062 
2063 	for (include = ISC_LIST_HEAD(zone->includes); include != NULL;
2064 	     include = ISC_LIST_NEXT(include, link))
2065 	{
2066 		result = isc_file_getmodtime(include->name, &modtime);
2067 		if (result != ISC_R_SUCCESS ||
2068 		    isc_time_compare(&modtime, &include->filetime) > 0)
2069 		{
2070 			return (true);
2071 		}
2072 	}
2073 
2074 	return (false);
2075 }
2076 
2077 /*
2078  * Note: when dealing with inline-signed zones, external callers will always
2079  * call zone_load() for the secure zone; zone_load() calls itself recursively
2080  * in order to load the raw zone.
2081  */
2082 static isc_result_t
zone_load(dns_zone_t * zone,unsigned int flags,bool locked)2083 zone_load(dns_zone_t *zone, unsigned int flags, bool locked) {
2084 	isc_result_t result;
2085 	isc_time_t now;
2086 	isc_time_t loadtime;
2087 	dns_db_t *db = NULL;
2088 	bool rbt, hasraw, is_dynamic;
2089 
2090 	REQUIRE(DNS_ZONE_VALID(zone));
2091 
2092 	if (!locked) {
2093 		LOCK_ZONE(zone);
2094 	}
2095 
2096 	INSIST(zone != zone->raw);
2097 	hasraw = inline_secure(zone);
2098 	if (hasraw) {
2099 		/*
2100 		 * We are trying to load an inline-signed zone.  First call
2101 		 * self recursively to try loading the raw version of the zone.
2102 		 * Assuming the raw zone file is readable, there are two
2103 		 * possibilities:
2104 		 *
2105 		 *  a) the raw zone was not yet loaded and thus it will be
2106 		 *     loaded now, synchronously; if this succeeds, a
2107 		 *     subsequent attempt to load the signed zone file will
2108 		 *     take place and thus zone_postload() will be called
2109 		 *     twice: first for the raw zone and then for the secure
2110 		 *     zone; the latter call will take care of syncing the raw
2111 		 *     version with the secure version,
2112 		 *
2113 		 *  b) the raw zone was already loaded and we are trying to
2114 		 *     reload it, which will happen asynchronously; this means
2115 		 *     zone_postload() will only be called for the raw zone
2116 		 *     because "result" returned by the zone_load() call below
2117 		 *     will not be ISC_R_SUCCESS but rather DNS_R_CONTINUE;
2118 		 *     zone_postload() called for the raw zone will take care
2119 		 *     of syncing the raw version with the secure version.
2120 		 */
2121 		result = zone_load(zone->raw, flags, false);
2122 		if (result != ISC_R_SUCCESS) {
2123 			if (!locked) {
2124 				UNLOCK_ZONE(zone);
2125 			}
2126 			return (result);
2127 		}
2128 		LOCK_ZONE(zone->raw);
2129 	}
2130 
2131 	TIME_NOW(&now);
2132 
2133 	INSIST(zone->type != dns_zone_none);
2134 
2135 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
2136 		if ((flags & DNS_ZONELOADFLAG_THAW) != 0) {
2137 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
2138 		}
2139 		result = DNS_R_CONTINUE;
2140 		goto cleanup;
2141 	}
2142 
2143 	INSIST(zone->db_argc >= 1);
2144 
2145 	rbt = strcmp(zone->db_argv[0], "rbt") == 0 ||
2146 	      strcmp(zone->db_argv[0], "rbt64") == 0;
2147 
2148 	if (zone->db != NULL && zone->masterfile == NULL && rbt) {
2149 		/*
2150 		 * The zone has no master file configured.
2151 		 */
2152 		result = ISC_R_SUCCESS;
2153 		goto cleanup;
2154 	}
2155 
2156 	is_dynamic = dns_zone_isdynamic(zone, false);
2157 	if (zone->db != NULL && is_dynamic) {
2158 		/*
2159 		 * This is a slave, stub, or dynamically updated zone being
2160 		 * reloaded.  Do nothing - the database we already
2161 		 * have is guaranteed to be up-to-date.
2162 		 */
2163 		if (zone->type == dns_zone_primary && !hasraw) {
2164 			result = DNS_R_DYNAMIC;
2165 		} else {
2166 			result = ISC_R_SUCCESS;
2167 		}
2168 		goto cleanup;
2169 	}
2170 
2171 	/*
2172 	 * Store the current time before the zone is loaded, so that if the
2173 	 * file changes between the time of the load and the time that
2174 	 * zone->loadtime is set, then the file will still be reloaded
2175 	 * the next time dns_zone_load is called.
2176 	 */
2177 	TIME_NOW(&loadtime);
2178 
2179 	/*
2180 	 * Don't do the load if the file that stores the zone is older
2181 	 * than the last time the zone was loaded.  If the zone has not
2182 	 * been loaded yet, zone->loadtime will be the epoch.
2183 	 */
2184 	if (zone->masterfile != NULL) {
2185 		isc_time_t filetime;
2186 
2187 		/*
2188 		 * The file is already loaded.	If we are just doing a
2189 		 * "rndc reconfig", we are done.
2190 		 */
2191 		if (!isc_time_isepoch(&zone->loadtime) &&
2192 		    (flags & DNS_ZONELOADFLAG_NOSTAT) != 0)
2193 		{
2194 			result = ISC_R_SUCCESS;
2195 			goto cleanup;
2196 		}
2197 
2198 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
2199 		    !zone_touched(zone))
2200 		{
2201 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2202 				      ISC_LOG_DEBUG(1),
2203 				      "skipping load: master file "
2204 				      "older than last load");
2205 			result = DNS_R_UPTODATE;
2206 			goto cleanup;
2207 		}
2208 
2209 		/*
2210 		 * If the file modification time is in the past
2211 		 * set loadtime to that value.
2212 		 */
2213 		result = isc_file_getmodtime(zone->masterfile, &filetime);
2214 		if (result == ISC_R_SUCCESS &&
2215 		    isc_time_compare(&loadtime, &filetime) > 0)
2216 		{
2217 			loadtime = filetime;
2218 		}
2219 	}
2220 
2221 	/*
2222 	 * Built in zones (with the exception of empty zones) don't need
2223 	 * to be reloaded.
2224 	 */
2225 	if (zone->type == dns_zone_primary &&
2226 	    strcmp(zone->db_argv[0], "_builtin") == 0 &&
2227 	    (zone->db_argc < 2 || strcmp(zone->db_argv[1], "empty") != 0) &&
2228 	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
2229 	{
2230 		result = ISC_R_SUCCESS;
2231 		goto cleanup;
2232 	}
2233 
2234 	/*
2235 	 * Zones associated with a DLZ don't need to be loaded either,
2236 	 * but we need to associate the database with the zone object.
2237 	 */
2238 	if (strcmp(zone->db_argv[0], "dlz") == 0) {
2239 		dns_dlzdb_t *dlzdb;
2240 		dns_dlzfindzone_t findzone;
2241 
2242 		for (dlzdb = ISC_LIST_HEAD(zone->view->dlz_unsearched);
2243 		     dlzdb != NULL; dlzdb = ISC_LIST_NEXT(dlzdb, link))
2244 		{
2245 			INSIST(DNS_DLZ_VALID(dlzdb));
2246 			if (strcmp(zone->db_argv[1], dlzdb->dlzname) == 0) {
2247 				break;
2248 			}
2249 		}
2250 
2251 		if (dlzdb == NULL) {
2252 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2253 				      ISC_LOG_ERROR,
2254 				      "DLZ %s does not exist or is set "
2255 				      "to 'search yes;'",
2256 				      zone->db_argv[1]);
2257 			result = ISC_R_NOTFOUND;
2258 			goto cleanup;
2259 		}
2260 
2261 		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
2262 		/* ask SDLZ driver if the zone is supported */
2263 		findzone = dlzdb->implementation->methods->findzone;
2264 		result = (*findzone)(dlzdb->implementation->driverarg,
2265 				     dlzdb->dbdata, dlzdb->mctx,
2266 				     zone->view->rdclass, &zone->origin, NULL,
2267 				     NULL, &db);
2268 		if (result != ISC_R_NOTFOUND) {
2269 			if (zone->db != NULL) {
2270 				zone_detachdb(zone);
2271 			}
2272 			zone_attachdb(zone, db);
2273 			dns_db_detach(&db);
2274 			result = ISC_R_SUCCESS;
2275 		}
2276 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
2277 
2278 		if (result == ISC_R_SUCCESS) {
2279 			if (dlzdb->configure_callback == NULL) {
2280 				goto cleanup;
2281 			}
2282 
2283 			result = (*dlzdb->configure_callback)(zone->view, dlzdb,
2284 							      zone);
2285 			if (result != ISC_R_SUCCESS) {
2286 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2287 					      ISC_LOG_ERROR,
2288 					      "DLZ configuration callback: %s",
2289 					      isc_result_totext(result));
2290 			}
2291 		}
2292 		goto cleanup;
2293 	}
2294 
2295 	if ((zone->type == dns_zone_secondary ||
2296 	     zone->type == dns_zone_mirror || zone->type == dns_zone_stub ||
2297 	     (zone->type == dns_zone_redirect && zone->masters != NULL)) &&
2298 	    rbt)
2299 	{
2300 		if (zone->masterfile == NULL ||
2301 		    !isc_file_exists(zone->masterfile))
2302 		{
2303 			if (zone->masterfile != NULL) {
2304 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2305 					      ISC_LOG_DEBUG(1),
2306 					      "no master file");
2307 			}
2308 			zone->refreshtime = now;
2309 			if (zone->task != NULL) {
2310 				zone_settimer(zone, &now);
2311 			}
2312 			result = ISC_R_SUCCESS;
2313 			goto cleanup;
2314 		}
2315 	}
2316 
2317 	dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
2318 		      "starting load");
2319 
2320 	result = dns_db_create(zone->mctx, zone->db_argv[0], &zone->origin,
2321 			       (zone->type == dns_zone_stub) ? dns_dbtype_stub
2322 							     : dns_dbtype_zone,
2323 			       zone->rdclass, zone->db_argc - 1,
2324 			       zone->db_argv + 1, &db);
2325 
2326 	if (result != ISC_R_SUCCESS) {
2327 		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
2328 			      "loading zone: creating database: %s",
2329 			      isc_result_totext(result));
2330 		goto cleanup;
2331 	}
2332 	dns_db_settask(db, zone->task);
2333 
2334 	if (zone->type == dns_zone_primary ||
2335 	    zone->type == dns_zone_secondary || zone->type == dns_zone_mirror)
2336 	{
2337 		result = dns_db_setgluecachestats(db, zone->gluecachestats);
2338 		if (result == ISC_R_NOTIMPLEMENTED) {
2339 			result = ISC_R_SUCCESS;
2340 		}
2341 		if (result != ISC_R_SUCCESS) {
2342 			goto cleanup;
2343 		}
2344 	}
2345 
2346 	if (!dns_db_ispersistent(db)) {
2347 		if (zone->masterfile != NULL) {
2348 			result = zone_startload(db, zone, loadtime);
2349 		} else {
2350 			result = DNS_R_NOMASTERFILE;
2351 			if (zone->type == dns_zone_primary ||
2352 			    (zone->type == dns_zone_redirect &&
2353 			     zone->masters == NULL))
2354 			{
2355 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2356 					      ISC_LOG_ERROR,
2357 					      "loading zone: "
2358 					      "no master file configured");
2359 				goto cleanup;
2360 			}
2361 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2362 				      ISC_LOG_INFO,
2363 				      "loading zone: "
2364 				      "no master file configured: continuing");
2365 		}
2366 	}
2367 
2368 	if (result == DNS_R_CONTINUE) {
2369 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING);
2370 		if ((flags & DNS_ZONELOADFLAG_THAW) != 0) {
2371 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
2372 		}
2373 		goto cleanup;
2374 	}
2375 
2376 	result = zone_postload(zone, db, loadtime, result);
2377 
2378 cleanup:
2379 	if (hasraw) {
2380 		UNLOCK_ZONE(zone->raw);
2381 	}
2382 	if (!locked) {
2383 		UNLOCK_ZONE(zone);
2384 	}
2385 	if (db != NULL) {
2386 		dns_db_detach(&db);
2387 	}
2388 	return (result);
2389 }
2390 
2391 isc_result_t
dns_zone_load(dns_zone_t * zone,bool newonly)2392 dns_zone_load(dns_zone_t *zone, bool newonly) {
2393 	return (zone_load(zone, newonly ? DNS_ZONELOADFLAG_NOSTAT : 0, false));
2394 }
2395 
2396 static void
zone_asyncload(isc_task_t * task,isc_event_t * event)2397 zone_asyncload(isc_task_t *task, isc_event_t *event) {
2398 	dns_asyncload_t *asl = event->ev_arg;
2399 	dns_zone_t *zone = asl->zone;
2400 	isc_result_t result;
2401 
2402 	UNUSED(task);
2403 
2404 	REQUIRE(DNS_ZONE_VALID(zone));
2405 
2406 	isc_event_free(&event);
2407 
2408 	LOCK_ZONE(zone);
2409 	result = zone_load(zone, asl->flags, true);
2410 	if (result != DNS_R_CONTINUE) {
2411 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
2412 	}
2413 	UNLOCK_ZONE(zone);
2414 
2415 	/* Inform the zone table we've finished loading */
2416 	if (asl->loaded != NULL) {
2417 		(asl->loaded)(asl->loaded_arg, zone, task);
2418 	}
2419 
2420 	/* Reduce the quantum */
2421 	isc_task_setquantum(zone->loadtask, 1);
2422 
2423 	isc_mem_put(zone->mctx, asl, sizeof(*asl));
2424 	dns_zone_idetach(&zone);
2425 }
2426 
2427 isc_result_t
dns_zone_asyncload(dns_zone_t * zone,bool newonly,dns_zt_zoneloaded_t done,void * arg)2428 dns_zone_asyncload(dns_zone_t *zone, bool newonly, dns_zt_zoneloaded_t done,
2429 		   void *arg) {
2430 	isc_event_t *e;
2431 	dns_asyncload_t *asl = NULL;
2432 
2433 	REQUIRE(DNS_ZONE_VALID(zone));
2434 
2435 	if (zone->zmgr == NULL) {
2436 		return (ISC_R_FAILURE);
2437 	}
2438 
2439 	/* If we already have a load pending, stop now */
2440 	LOCK_ZONE(zone);
2441 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING)) {
2442 		UNLOCK_ZONE(zone);
2443 		return (ISC_R_ALREADYRUNNING);
2444 	}
2445 
2446 	asl = isc_mem_get(zone->mctx, sizeof(*asl));
2447 
2448 	asl->zone = NULL;
2449 	asl->flags = newonly ? DNS_ZONELOADFLAG_NOSTAT : 0;
2450 	asl->loaded = done;
2451 	asl->loaded_arg = arg;
2452 
2453 	e = isc_event_allocate(zone->zmgr->mctx, zone->zmgr, DNS_EVENT_ZONELOAD,
2454 			       zone_asyncload, asl, sizeof(isc_event_t));
2455 
2456 	zone_iattach(zone, &asl->zone);
2457 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADPENDING);
2458 	isc_task_send(zone->loadtask, &e);
2459 	UNLOCK_ZONE(zone);
2460 
2461 	return (ISC_R_SUCCESS);
2462 }
2463 
2464 bool
dns__zone_loadpending(dns_zone_t * zone)2465 dns__zone_loadpending(dns_zone_t *zone) {
2466 	REQUIRE(DNS_ZONE_VALID(zone));
2467 
2468 	return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING));
2469 }
2470 
2471 isc_result_t
dns_zone_loadandthaw(dns_zone_t * zone)2472 dns_zone_loadandthaw(dns_zone_t *zone) {
2473 	isc_result_t result;
2474 
2475 	if (inline_raw(zone)) {
2476 		result = zone_load(zone->secure, DNS_ZONELOADFLAG_THAW, false);
2477 	} else {
2478 		/*
2479 		 * When thawing a zone, we don't know what changes
2480 		 * have been made. If we do DNSSEC maintenance on this
2481 		 * zone, schedule a full sign for this zone.
2482 		 */
2483 		if (zone->type == dns_zone_primary &&
2484 		    DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
2485 		{
2486 			DNS_ZONEKEY_SETOPTION(zone, DNS_ZONEKEY_FULLSIGN);
2487 		}
2488 		result = zone_load(zone, DNS_ZONELOADFLAG_THAW, false);
2489 	}
2490 
2491 	switch (result) {
2492 	case DNS_R_CONTINUE:
2493 		/* Deferred thaw. */
2494 		break;
2495 	case DNS_R_UPTODATE:
2496 	case ISC_R_SUCCESS:
2497 	case DNS_R_SEENINCLUDE:
2498 		zone->update_disabled = false;
2499 		break;
2500 	case DNS_R_NOMASTERFILE:
2501 		zone->update_disabled = false;
2502 		break;
2503 	default:
2504 		/* Error, remain in disabled state. */
2505 		break;
2506 	}
2507 	return (result);
2508 }
2509 
2510 static unsigned int
get_master_options(dns_zone_t * zone)2511 get_master_options(dns_zone_t *zone) {
2512 	unsigned int options;
2513 
2514 	options = DNS_MASTER_ZONE | DNS_MASTER_RESIGN;
2515 	if (zone->type == dns_zone_secondary || zone->type == dns_zone_mirror ||
2516 	    (zone->type == dns_zone_redirect && zone->masters == NULL))
2517 	{
2518 		options |= DNS_MASTER_SLAVE;
2519 	}
2520 	if (zone->type == dns_zone_key) {
2521 		options |= DNS_MASTER_KEY;
2522 	}
2523 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS)) {
2524 		options |= DNS_MASTER_CHECKNS;
2525 	}
2526 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS)) {
2527 		options |= DNS_MASTER_FATALNS;
2528 	}
2529 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES)) {
2530 		options |= DNS_MASTER_CHECKNAMES;
2531 	}
2532 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) {
2533 		options |= DNS_MASTER_CHECKNAMESFAIL;
2534 	}
2535 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMX)) {
2536 		options |= DNS_MASTER_CHECKMX;
2537 	}
2538 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL)) {
2539 		options |= DNS_MASTER_CHECKMXFAIL;
2540 	}
2541 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKWILDCARD)) {
2542 		options |= DNS_MASTER_CHECKWILDCARD;
2543 	}
2544 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKTTL)) {
2545 		options |= DNS_MASTER_CHECKTTL;
2546 	}
2547 
2548 	return (options);
2549 }
2550 
2551 static void
zone_registerinclude(const char * filename,void * arg)2552 zone_registerinclude(const char *filename, void *arg) {
2553 	isc_result_t result;
2554 	dns_zone_t *zone = (dns_zone_t *)arg;
2555 	dns_include_t *inc = NULL;
2556 
2557 	REQUIRE(DNS_ZONE_VALID(zone));
2558 
2559 	if (filename == NULL) {
2560 		return;
2561 	}
2562 
2563 	/*
2564 	 * Suppress duplicates.
2565 	 */
2566 	for (inc = ISC_LIST_HEAD(zone->newincludes); inc != NULL;
2567 	     inc = ISC_LIST_NEXT(inc, link))
2568 	{
2569 		if (strcmp(filename, inc->name) == 0) {
2570 			return;
2571 		}
2572 	}
2573 
2574 	inc = isc_mem_get(zone->mctx, sizeof(dns_include_t));
2575 	inc->name = isc_mem_strdup(zone->mctx, filename);
2576 	ISC_LINK_INIT(inc, link);
2577 
2578 	result = isc_file_getmodtime(filename, &inc->filetime);
2579 	if (result != ISC_R_SUCCESS) {
2580 		isc_time_settoepoch(&inc->filetime);
2581 	}
2582 
2583 	ISC_LIST_APPEND(zone->newincludes, inc, link);
2584 }
2585 
2586 static void
zone_gotreadhandle(isc_task_t * task,isc_event_t * event)2587 zone_gotreadhandle(isc_task_t *task, isc_event_t *event) {
2588 	dns_load_t *load = event->ev_arg;
2589 	isc_result_t result = ISC_R_SUCCESS;
2590 	unsigned int options;
2591 
2592 	REQUIRE(DNS_LOAD_VALID(load));
2593 
2594 	if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) {
2595 		result = ISC_R_CANCELED;
2596 	}
2597 	isc_event_free(&event);
2598 	if (result == ISC_R_CANCELED) {
2599 		goto fail;
2600 	}
2601 
2602 	options = get_master_options(load->zone);
2603 
2604 	result = dns_master_loadfileinc(
2605 		load->zone->masterfile, dns_db_origin(load->db),
2606 		dns_db_origin(load->db), load->zone->rdclass, options, 0,
2607 		&load->callbacks, task, zone_loaddone, load, &load->zone->lctx,
2608 		zone_registerinclude, load->zone, load->zone->mctx,
2609 		load->zone->masterformat, load->zone->maxttl);
2610 	if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE &&
2611 	    result != DNS_R_SEENINCLUDE)
2612 	{
2613 		goto fail;
2614 	}
2615 	return;
2616 
2617 fail:
2618 	zone_loaddone(load, result);
2619 }
2620 
2621 static void
get_raw_serial(dns_zone_t * raw,dns_masterrawheader_t * rawdata)2622 get_raw_serial(dns_zone_t *raw, dns_masterrawheader_t *rawdata) {
2623 	isc_result_t result;
2624 	unsigned int soacount;
2625 
2626 	LOCK(&raw->lock);
2627 	if (raw->db != NULL) {
2628 		result = zone_get_from_db(raw, raw->db, NULL, &soacount, NULL,
2629 					  &rawdata->sourceserial, NULL, NULL,
2630 					  NULL, NULL, NULL);
2631 		if (result == ISC_R_SUCCESS && soacount > 0U) {
2632 			rawdata->flags |= DNS_MASTERRAW_SOURCESERIALSET;
2633 		}
2634 	}
2635 	UNLOCK(&raw->lock);
2636 }
2637 
2638 static void
zone_gotwritehandle(isc_task_t * task,isc_event_t * event)2639 zone_gotwritehandle(isc_task_t *task, isc_event_t *event) {
2640 	const char me[] = "zone_gotwritehandle";
2641 	dns_zone_t *zone = event->ev_arg;
2642 	isc_result_t result = ISC_R_SUCCESS;
2643 	dns_dbversion_t *version = NULL;
2644 	dns_masterrawheader_t rawdata;
2645 	dns_db_t *db = NULL;
2646 
2647 	REQUIRE(DNS_ZONE_VALID(zone));
2648 	INSIST(task == zone->task);
2649 	ENTER;
2650 
2651 	if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) {
2652 		result = ISC_R_CANCELED;
2653 	}
2654 	isc_event_free(&event);
2655 	if (result == ISC_R_CANCELED) {
2656 		goto fail;
2657 	}
2658 
2659 	LOCK_ZONE(zone);
2660 	INSIST(zone != zone->raw);
2661 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
2662 	if (zone->db != NULL) {
2663 		dns_db_attach(zone->db, &db);
2664 	}
2665 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
2666 	if (db != NULL) {
2667 		const dns_master_style_t *output_style;
2668 		dns_db_currentversion(db, &version);
2669 		dns_master_initrawheader(&rawdata);
2670 		if (inline_secure(zone)) {
2671 			get_raw_serial(zone->raw, &rawdata);
2672 		}
2673 		if (zone->type == dns_zone_key) {
2674 			output_style = &dns_master_style_keyzone;
2675 		} else if (zone->masterstyle != NULL) {
2676 			output_style = zone->masterstyle;
2677 		} else {
2678 			output_style = &dns_master_style_default;
2679 		}
2680 		result = dns_master_dumpasync(
2681 			zone->mctx, db, version, output_style, zone->masterfile,
2682 			zone->task, dump_done, zone, &zone->dctx,
2683 			zone->masterformat, &rawdata);
2684 		dns_db_closeversion(db, &version, false);
2685 	} else {
2686 		result = ISC_R_CANCELED;
2687 	}
2688 	if (db != NULL) {
2689 		dns_db_detach(&db);
2690 	}
2691 	UNLOCK_ZONE(zone);
2692 	if (result != DNS_R_CONTINUE) {
2693 		goto fail;
2694 	}
2695 	return;
2696 
2697 fail:
2698 	dump_done(zone, result);
2699 }
2700 
2701 /*
2702  * Save the raw serial number for inline-signing zones.
2703  * (XXX: Other information from the header will be used
2704  * for other purposes in the future, but for now this is
2705  * all we're interested in.)
2706  */
2707 static void
zone_setrawdata(dns_zone_t * zone,dns_masterrawheader_t * header)2708 zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
2709 	if ((header->flags & DNS_MASTERRAW_SOURCESERIALSET) == 0) {
2710 		return;
2711 	}
2712 
2713 	zone->sourceserial = header->sourceserial;
2714 	zone->sourceserialset = true;
2715 }
2716 
2717 void
dns_zone_setrawdata(dns_zone_t * zone,dns_masterrawheader_t * header)2718 dns_zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
2719 	if (zone == NULL) {
2720 		return;
2721 	}
2722 
2723 	LOCK_ZONE(zone);
2724 	zone_setrawdata(zone, header);
2725 	UNLOCK_ZONE(zone);
2726 }
2727 
2728 static isc_result_t
zone_startload(dns_db_t * db,dns_zone_t * zone,isc_time_t loadtime)2729 zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
2730 	const char me[] = "zone_startload";
2731 	dns_load_t *load;
2732 	isc_result_t result;
2733 	isc_result_t tresult;
2734 	unsigned int options;
2735 
2736 	ENTER;
2737 
2738 	dns_zone_rpz_enable_db(zone, db);
2739 	dns_zone_catz_enable_db(zone, db);
2740 
2741 	options = get_master_options(zone);
2742 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS)) {
2743 		options |= DNS_MASTER_MANYERRORS;
2744 	}
2745 
2746 	if (zone->zmgr != NULL && zone->db != NULL && zone->loadtask != NULL) {
2747 		load = isc_mem_get(zone->mctx, sizeof(*load));
2748 
2749 		load->mctx = NULL;
2750 		load->zone = NULL;
2751 		load->db = NULL;
2752 		load->loadtime = loadtime;
2753 		load->magic = LOAD_MAGIC;
2754 
2755 		isc_mem_attach(zone->mctx, &load->mctx);
2756 		zone_iattach(zone, &load->zone);
2757 		dns_db_attach(db, &load->db);
2758 		dns_rdatacallbacks_init(&load->callbacks);
2759 		load->callbacks.rawdata = zone_setrawdata;
2760 		zone_iattach(zone, &load->callbacks.zone);
2761 		result = dns_db_beginload(db, &load->callbacks);
2762 		if (result != ISC_R_SUCCESS) {
2763 			goto cleanup;
2764 		}
2765 		result = zonemgr_getio(zone->zmgr, true, zone->loadtask,
2766 				       zone_gotreadhandle, load, &zone->readio);
2767 		if (result != ISC_R_SUCCESS) {
2768 			/*
2769 			 * We can't report multiple errors so ignore
2770 			 * the result of dns_db_endload().
2771 			 */
2772 			(void)dns_db_endload(load->db, &load->callbacks);
2773 			goto cleanup;
2774 		} else {
2775 			result = DNS_R_CONTINUE;
2776 		}
2777 	} else {
2778 		dns_rdatacallbacks_t callbacks;
2779 
2780 		dns_rdatacallbacks_init(&callbacks);
2781 		callbacks.rawdata = zone_setrawdata;
2782 		zone_iattach(zone, &callbacks.zone);
2783 		result = dns_db_beginload(db, &callbacks);
2784 		if (result != ISC_R_SUCCESS) {
2785 			zone_idetach(&callbacks.zone);
2786 			return (result);
2787 		}
2788 		result = dns_master_loadfile(
2789 			zone->masterfile, &zone->origin, &zone->origin,
2790 			zone->rdclass, options, 0, &callbacks,
2791 			zone_registerinclude, zone, zone->mctx,
2792 			zone->masterformat, zone->maxttl);
2793 		tresult = dns_db_endload(db, &callbacks);
2794 		if (result == ISC_R_SUCCESS) {
2795 			result = tresult;
2796 		}
2797 		zone_idetach(&callbacks.zone);
2798 	}
2799 
2800 	return (result);
2801 
2802 cleanup:
2803 	load->magic = 0;
2804 	dns_db_detach(&load->db);
2805 	zone_idetach(&load->zone);
2806 	zone_idetach(&load->callbacks.zone);
2807 	isc_mem_detach(&load->mctx);
2808 	isc_mem_put(zone->mctx, load, sizeof(*load));
2809 	return (result);
2810 }
2811 
2812 static bool
zone_check_mx(dns_zone_t * zone,dns_db_t * db,dns_name_t * name,dns_name_t * owner)2813 zone_check_mx(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2814 	      dns_name_t *owner) {
2815 	isc_result_t result;
2816 	char ownerbuf[DNS_NAME_FORMATSIZE];
2817 	char namebuf[DNS_NAME_FORMATSIZE];
2818 	char altbuf[DNS_NAME_FORMATSIZE];
2819 	dns_fixedname_t fixed;
2820 	dns_name_t *foundname;
2821 	int level;
2822 
2823 	/*
2824 	 * "." means the services does not exist.
2825 	 */
2826 	if (dns_name_equal(name, dns_rootname)) {
2827 		return (true);
2828 	}
2829 
2830 	/*
2831 	 * Outside of zone.
2832 	 */
2833 	if (!dns_name_issubdomain(name, &zone->origin)) {
2834 		if (zone->checkmx != NULL) {
2835 			return ((zone->checkmx)(zone, name, owner));
2836 		}
2837 		return (true);
2838 	}
2839 
2840 	if (zone->type == dns_zone_primary) {
2841 		level = ISC_LOG_ERROR;
2842 	} else {
2843 		level = ISC_LOG_WARNING;
2844 	}
2845 
2846 	foundname = dns_fixedname_initname(&fixed);
2847 
2848 	result = dns_db_find(db, name, NULL, dns_rdatatype_a, 0, 0, NULL,
2849 			     foundname, NULL, NULL);
2850 	if (result == ISC_R_SUCCESS) {
2851 		return (true);
2852 	}
2853 
2854 	if (result == DNS_R_NXRRSET) {
2855 		result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa, 0, 0,
2856 				     NULL, foundname, NULL, NULL);
2857 		if (result == ISC_R_SUCCESS) {
2858 			return (true);
2859 		}
2860 	}
2861 
2862 	dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2863 	dns_name_format(name, namebuf, sizeof namebuf);
2864 	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2865 	    result == DNS_R_EMPTYNAME)
2866 	{
2867 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL)) {
2868 			level = ISC_LOG_WARNING;
2869 		}
2870 		dns_zone_log(zone, level,
2871 			     "%s/MX '%s' has no address records (A or AAAA)",
2872 			     ownerbuf, namebuf);
2873 		return ((level == ISC_LOG_WARNING) ? true : false);
2874 	}
2875 
2876 	if (result == DNS_R_CNAME) {
2877 		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
2878 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2879 		{
2880 			level = ISC_LOG_WARNING;
2881 		}
2882 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
2883 			dns_zone_log(zone, level,
2884 				     "%s/MX '%s' is a CNAME (illegal)",
2885 				     ownerbuf, namebuf);
2886 		}
2887 		return ((level == ISC_LOG_WARNING) ? true : false);
2888 	}
2889 
2890 	if (result == DNS_R_DNAME) {
2891 		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
2892 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2893 		{
2894 			level = ISC_LOG_WARNING;
2895 		}
2896 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
2897 			dns_name_format(foundname, altbuf, sizeof altbuf);
2898 			dns_zone_log(zone, level,
2899 				     "%s/MX '%s' is below a DNAME"
2900 				     " '%s' (illegal)",
2901 				     ownerbuf, namebuf, altbuf);
2902 		}
2903 		return ((level == ISC_LOG_WARNING) ? true : false);
2904 	}
2905 
2906 	if (zone->checkmx != NULL && result == DNS_R_DELEGATION) {
2907 		return ((zone->checkmx)(zone, name, owner));
2908 	}
2909 
2910 	return (true);
2911 }
2912 
2913 static bool
zone_check_srv(dns_zone_t * zone,dns_db_t * db,dns_name_t * name,dns_name_t * owner)2914 zone_check_srv(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2915 	       dns_name_t *owner) {
2916 	isc_result_t result;
2917 	char ownerbuf[DNS_NAME_FORMATSIZE];
2918 	char namebuf[DNS_NAME_FORMATSIZE];
2919 	char altbuf[DNS_NAME_FORMATSIZE];
2920 	dns_fixedname_t fixed;
2921 	dns_name_t *foundname;
2922 	int level;
2923 
2924 	/*
2925 	 * "." means the services does not exist.
2926 	 */
2927 	if (dns_name_equal(name, dns_rootname)) {
2928 		return (true);
2929 	}
2930 
2931 	/*
2932 	 * Outside of zone.
2933 	 */
2934 	if (!dns_name_issubdomain(name, &zone->origin)) {
2935 		if (zone->checksrv != NULL) {
2936 			return ((zone->checksrv)(zone, name, owner));
2937 		}
2938 		return (true);
2939 	}
2940 
2941 	if (zone->type == dns_zone_primary) {
2942 		level = ISC_LOG_ERROR;
2943 	} else {
2944 		level = ISC_LOG_WARNING;
2945 	}
2946 
2947 	foundname = dns_fixedname_initname(&fixed);
2948 
2949 	result = dns_db_find(db, name, NULL, dns_rdatatype_a, 0, 0, NULL,
2950 			     foundname, NULL, NULL);
2951 	if (result == ISC_R_SUCCESS) {
2952 		return (true);
2953 	}
2954 
2955 	if (result == DNS_R_NXRRSET) {
2956 		result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa, 0, 0,
2957 				     NULL, foundname, NULL, NULL);
2958 		if (result == ISC_R_SUCCESS) {
2959 			return (true);
2960 		}
2961 	}
2962 
2963 	dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2964 	dns_name_format(name, namebuf, sizeof namebuf);
2965 	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2966 	    result == DNS_R_EMPTYNAME)
2967 	{
2968 		dns_zone_log(zone, level,
2969 			     "%s/SRV '%s' has no address records (A or AAAA)",
2970 			     ownerbuf, namebuf);
2971 		/* XXX950 make fatal for 9.5.0. */
2972 		return (true);
2973 	}
2974 
2975 	if (result == DNS_R_CNAME) {
2976 		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
2977 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2978 		{
2979 			level = ISC_LOG_WARNING;
2980 		}
2981 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
2982 			dns_zone_log(zone, level,
2983 				     "%s/SRV '%s' is a CNAME (illegal)",
2984 				     ownerbuf, namebuf);
2985 		}
2986 		return ((level == ISC_LOG_WARNING) ? true : false);
2987 	}
2988 
2989 	if (result == DNS_R_DNAME) {
2990 		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
2991 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2992 		{
2993 			level = ISC_LOG_WARNING;
2994 		}
2995 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
2996 			dns_name_format(foundname, altbuf, sizeof altbuf);
2997 			dns_zone_log(zone, level,
2998 				     "%s/SRV '%s' is below a "
2999 				     "DNAME '%s' (illegal)",
3000 				     ownerbuf, namebuf, altbuf);
3001 		}
3002 		return ((level == ISC_LOG_WARNING) ? true : false);
3003 	}
3004 
3005 	if (zone->checksrv != NULL && result == DNS_R_DELEGATION) {
3006 		return ((zone->checksrv)(zone, name, owner));
3007 	}
3008 
3009 	return (true);
3010 }
3011 
3012 static bool
zone_check_glue(dns_zone_t * zone,dns_db_t * db,dns_name_t * name,dns_name_t * owner)3013 zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
3014 		dns_name_t *owner) {
3015 	bool answer = true;
3016 	isc_result_t result, tresult;
3017 	char ownerbuf[DNS_NAME_FORMATSIZE];
3018 	char namebuf[DNS_NAME_FORMATSIZE];
3019 	char altbuf[DNS_NAME_FORMATSIZE];
3020 	dns_fixedname_t fixed;
3021 	dns_name_t *foundname;
3022 	dns_rdataset_t a;
3023 	dns_rdataset_t aaaa;
3024 	int level;
3025 
3026 	/*
3027 	 * Outside of zone.
3028 	 */
3029 	if (!dns_name_issubdomain(name, &zone->origin)) {
3030 		if (zone->checkns != NULL) {
3031 			return ((zone->checkns)(zone, name, owner, NULL, NULL));
3032 		}
3033 		return (true);
3034 	}
3035 
3036 	if (zone->type == dns_zone_primary) {
3037 		level = ISC_LOG_ERROR;
3038 	} else {
3039 		level = ISC_LOG_WARNING;
3040 	}
3041 
3042 	foundname = dns_fixedname_initname(&fixed);
3043 	dns_rdataset_init(&a);
3044 	dns_rdataset_init(&aaaa);
3045 
3046 	/*
3047 	 * Perform a regular lookup to catch DNAME records then look
3048 	 * for glue.
3049 	 */
3050 	result = dns_db_find(db, name, NULL, dns_rdatatype_a, 0, 0, NULL,
3051 			     foundname, &a, NULL);
3052 	switch (result) {
3053 	case ISC_R_SUCCESS:
3054 	case DNS_R_DNAME:
3055 	case DNS_R_CNAME:
3056 		break;
3057 	default:
3058 		if (dns_rdataset_isassociated(&a)) {
3059 			dns_rdataset_disassociate(&a);
3060 		}
3061 		result = dns_db_find(db, name, NULL, dns_rdatatype_a,
3062 				     DNS_DBFIND_GLUEOK, 0, NULL, foundname, &a,
3063 				     NULL);
3064 	}
3065 	if (result == ISC_R_SUCCESS) {
3066 		dns_rdataset_disassociate(&a);
3067 		return (true);
3068 	} else if (result == DNS_R_DELEGATION) {
3069 		dns_rdataset_disassociate(&a);
3070 	}
3071 
3072 	if (result == DNS_R_NXRRSET || result == DNS_R_DELEGATION ||
3073 	    result == DNS_R_GLUE)
3074 	{
3075 		tresult = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
3076 				      DNS_DBFIND_GLUEOK, 0, NULL, foundname,
3077 				      &aaaa, NULL);
3078 		if (tresult == ISC_R_SUCCESS) {
3079 			if (dns_rdataset_isassociated(&a)) {
3080 				dns_rdataset_disassociate(&a);
3081 			}
3082 			dns_rdataset_disassociate(&aaaa);
3083 			return (true);
3084 		}
3085 		if (tresult == DNS_R_DELEGATION || tresult == DNS_R_DNAME) {
3086 			dns_rdataset_disassociate(&aaaa);
3087 		}
3088 		if (result == DNS_R_GLUE || tresult == DNS_R_GLUE) {
3089 			/*
3090 			 * Check glue against child zone.
3091 			 */
3092 			if (zone->checkns != NULL) {
3093 				answer = (zone->checkns)(zone, name, owner, &a,
3094 							 &aaaa);
3095 			}
3096 			if (dns_rdataset_isassociated(&a)) {
3097 				dns_rdataset_disassociate(&a);
3098 			}
3099 			if (dns_rdataset_isassociated(&aaaa)) {
3100 				dns_rdataset_disassociate(&aaaa);
3101 			}
3102 			return (answer);
3103 		}
3104 	}
3105 
3106 	dns_name_format(owner, ownerbuf, sizeof ownerbuf);
3107 	dns_name_format(name, namebuf, sizeof namebuf);
3108 	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
3109 	    result == DNS_R_EMPTYNAME || result == DNS_R_DELEGATION)
3110 	{
3111 		const char *what;
3112 		bool required = false;
3113 		if (dns_name_issubdomain(name, owner)) {
3114 			what = "REQUIRED GLUE ";
3115 			required = true;
3116 		} else if (result == DNS_R_DELEGATION) {
3117 			what = "SIBLING GLUE ";
3118 		} else {
3119 			what = "";
3120 		}
3121 
3122 		if (result != DNS_R_DELEGATION || required ||
3123 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSIBLING))
3124 		{
3125 			dns_zone_log(zone, level,
3126 				     "%s/NS '%s' has no %s"
3127 				     "address records (A or AAAA)",
3128 				     ownerbuf, namebuf, what);
3129 			/*
3130 			 * Log missing address record.
3131 			 */
3132 			if (result == DNS_R_DELEGATION && zone->checkns != NULL)
3133 			{
3134 				(void)(zone->checkns)(zone, name, owner, &a,
3135 						      &aaaa);
3136 			}
3137 			/* XXX950 make fatal for 9.5.0. */
3138 			/* answer = false; */
3139 		}
3140 	} else if (result == DNS_R_CNAME) {
3141 		dns_zone_log(zone, level, "%s/NS '%s' is a CNAME (illegal)",
3142 			     ownerbuf, namebuf);
3143 		/* XXX950 make fatal for 9.5.0. */
3144 		/* answer = false; */
3145 	} else if (result == DNS_R_DNAME) {
3146 		dns_name_format(foundname, altbuf, sizeof altbuf);
3147 		dns_zone_log(zone, level,
3148 			     "%s/NS '%s' is below a DNAME '%s' (illegal)",
3149 			     ownerbuf, namebuf, altbuf);
3150 		/* XXX950 make fatal for 9.5.0. */
3151 		/* answer = false; */
3152 	}
3153 
3154 	if (dns_rdataset_isassociated(&a)) {
3155 		dns_rdataset_disassociate(&a);
3156 	}
3157 	if (dns_rdataset_isassociated(&aaaa)) {
3158 		dns_rdataset_disassociate(&aaaa);
3159 	}
3160 	return (answer);
3161 }
3162 
3163 static bool
zone_rrset_check_dup(dns_zone_t * zone,dns_name_t * owner,dns_rdataset_t * rdataset)3164 zone_rrset_check_dup(dns_zone_t *zone, dns_name_t *owner,
3165 		     dns_rdataset_t *rdataset) {
3166 	dns_rdataset_t tmprdataset;
3167 	isc_result_t result;
3168 	bool answer = true;
3169 	bool format = true;
3170 	int level = ISC_LOG_WARNING;
3171 	char ownerbuf[DNS_NAME_FORMATSIZE];
3172 	char typebuf[DNS_RDATATYPE_FORMATSIZE];
3173 	unsigned int count1 = 0;
3174 
3175 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRRFAIL)) {
3176 		level = ISC_LOG_ERROR;
3177 	}
3178 
3179 	dns_rdataset_init(&tmprdataset);
3180 	for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
3181 	     result = dns_rdataset_next(rdataset))
3182 	{
3183 		dns_rdata_t rdata1 = DNS_RDATA_INIT;
3184 		unsigned int count2 = 0;
3185 
3186 		count1++;
3187 		dns_rdataset_current(rdataset, &rdata1);
3188 		dns_rdataset_clone(rdataset, &tmprdataset);
3189 		for (result = dns_rdataset_first(&tmprdataset);
3190 		     result == ISC_R_SUCCESS;
3191 		     result = dns_rdataset_next(&tmprdataset))
3192 		{
3193 			dns_rdata_t rdata2 = DNS_RDATA_INIT;
3194 			count2++;
3195 			if (count1 >= count2) {
3196 				continue;
3197 			}
3198 			dns_rdataset_current(&tmprdataset, &rdata2);
3199 			if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) {
3200 				if (format) {
3201 					dns_name_format(owner, ownerbuf,
3202 							sizeof ownerbuf);
3203 					dns_rdatatype_format(rdata1.type,
3204 							     typebuf,
3205 							     sizeof(typebuf));
3206 					format = false;
3207 				}
3208 				dns_zone_log(zone, level,
3209 					     "%s/%s has "
3210 					     "semantically identical records",
3211 					     ownerbuf, typebuf);
3212 				if (level == ISC_LOG_ERROR) {
3213 					answer = false;
3214 				}
3215 				break;
3216 			}
3217 		}
3218 		dns_rdataset_disassociate(&tmprdataset);
3219 		if (!format) {
3220 			break;
3221 		}
3222 	}
3223 	return (answer);
3224 }
3225 
3226 static bool
zone_check_dup(dns_zone_t * zone,dns_db_t * db)3227 zone_check_dup(dns_zone_t *zone, dns_db_t *db) {
3228 	dns_dbiterator_t *dbiterator = NULL;
3229 	dns_dbnode_t *node = NULL;
3230 	dns_fixedname_t fixed;
3231 	dns_name_t *name;
3232 	dns_rdataset_t rdataset;
3233 	dns_rdatasetiter_t *rdsit = NULL;
3234 	bool ok = true;
3235 	isc_result_t result;
3236 
3237 	name = dns_fixedname_initname(&fixed);
3238 	dns_rdataset_init(&rdataset);
3239 
3240 	result = dns_db_createiterator(db, 0, &dbiterator);
3241 	if (result != ISC_R_SUCCESS) {
3242 		return (true);
3243 	}
3244 
3245 	for (result = dns_dbiterator_first(dbiterator); result == ISC_R_SUCCESS;
3246 	     result = dns_dbiterator_next(dbiterator))
3247 	{
3248 		result = dns_dbiterator_current(dbiterator, &node, name);
3249 		if (result != ISC_R_SUCCESS) {
3250 			continue;
3251 		}
3252 
3253 		result = dns_db_allrdatasets(db, node, NULL, 0, 0, &rdsit);
3254 		if (result != ISC_R_SUCCESS) {
3255 			continue;
3256 		}
3257 
3258 		for (result = dns_rdatasetiter_first(rdsit);
3259 		     result == ISC_R_SUCCESS;
3260 		     result = dns_rdatasetiter_next(rdsit))
3261 		{
3262 			dns_rdatasetiter_current(rdsit, &rdataset);
3263 			if (!zone_rrset_check_dup(zone, name, &rdataset)) {
3264 				ok = false;
3265 			}
3266 			dns_rdataset_disassociate(&rdataset);
3267 		}
3268 		dns_rdatasetiter_destroy(&rdsit);
3269 		dns_db_detachnode(db, &node);
3270 	}
3271 
3272 	if (node != NULL) {
3273 		dns_db_detachnode(db, &node);
3274 	}
3275 	dns_dbiterator_destroy(&dbiterator);
3276 
3277 	return (ok);
3278 }
3279 
3280 static bool
isspf(const dns_rdata_t * rdata)3281 isspf(const dns_rdata_t *rdata) {
3282 	char buf[1024];
3283 	const unsigned char *data = rdata->data;
3284 	unsigned int rdl = rdata->length, i = 0, tl, len;
3285 
3286 	while (rdl > 0U) {
3287 		len = tl = *data;
3288 		++data;
3289 		--rdl;
3290 		INSIST(tl <= rdl);
3291 		if (len > sizeof(buf) - i - 1) {
3292 			len = sizeof(buf) - i - 1;
3293 		}
3294 		memmove(buf + i, data, len);
3295 		i += len;
3296 		data += tl;
3297 		rdl -= tl;
3298 	}
3299 
3300 	if (i < 6U) {
3301 		return (false);
3302 	}
3303 
3304 	buf[i] = 0;
3305 	if (strncmp(buf, "v=spf1", 6) == 0 && (buf[6] == 0 || buf[6] == ' ')) {
3306 		return (true);
3307 	}
3308 	return (false);
3309 }
3310 
3311 static bool
integrity_checks(dns_zone_t * zone,dns_db_t * db)3312 integrity_checks(dns_zone_t *zone, dns_db_t *db) {
3313 	dns_dbiterator_t *dbiterator = NULL;
3314 	dns_dbnode_t *node = NULL;
3315 	dns_rdataset_t rdataset;
3316 	dns_fixedname_t fixed;
3317 	dns_fixedname_t fixedbottom;
3318 	dns_rdata_mx_t mx;
3319 	dns_rdata_ns_t ns;
3320 	dns_rdata_in_srv_t srv;
3321 	dns_rdata_t rdata;
3322 	dns_name_t *name;
3323 	dns_name_t *bottom;
3324 	isc_result_t result;
3325 	bool ok = true, have_spf, have_txt;
3326 
3327 	name = dns_fixedname_initname(&fixed);
3328 	bottom = dns_fixedname_initname(&fixedbottom);
3329 	dns_rdataset_init(&rdataset);
3330 	dns_rdata_init(&rdata);
3331 
3332 	result = dns_db_createiterator(db, 0, &dbiterator);
3333 	if (result != ISC_R_SUCCESS) {
3334 		return (true);
3335 	}
3336 
3337 	result = dns_dbiterator_first(dbiterator);
3338 	while (result == ISC_R_SUCCESS) {
3339 		result = dns_dbiterator_current(dbiterator, &node, name);
3340 		if (result != ISC_R_SUCCESS) {
3341 			goto cleanup;
3342 		}
3343 
3344 		/*
3345 		 * Is this name visible in the zone?
3346 		 */
3347 		if (!dns_name_issubdomain(name, &zone->origin) ||
3348 		    (dns_name_countlabels(bottom) > 0 &&
3349 		     dns_name_issubdomain(name, bottom)))
3350 		{
3351 			goto next;
3352 		}
3353 
3354 		dns_dbiterator_pause(dbiterator);
3355 
3356 		/*
3357 		 * Don't check the NS records at the origin.
3358 		 */
3359 		if (dns_name_equal(name, &zone->origin)) {
3360 			goto checkfordname;
3361 		}
3362 
3363 		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ns,
3364 					     0, 0, &rdataset, NULL);
3365 		if (result != ISC_R_SUCCESS) {
3366 			goto checkfordname;
3367 		}
3368 		/*
3369 		 * Remember bottom of zone due to NS.
3370 		 */
3371 		dns_name_copynf(name, bottom);
3372 
3373 		result = dns_rdataset_first(&rdataset);
3374 		while (result == ISC_R_SUCCESS) {
3375 			dns_rdataset_current(&rdataset, &rdata);
3376 			result = dns_rdata_tostruct(&rdata, &ns, NULL);
3377 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
3378 			if (!zone_check_glue(zone, db, &ns.name, name)) {
3379 				ok = false;
3380 			}
3381 			dns_rdata_reset(&rdata);
3382 			result = dns_rdataset_next(&rdataset);
3383 		}
3384 		dns_rdataset_disassociate(&rdataset);
3385 		goto next;
3386 
3387 	checkfordname:
3388 		result = dns_db_findrdataset(db, node, NULL,
3389 					     dns_rdatatype_dname, 0, 0,
3390 					     &rdataset, NULL);
3391 		if (result == ISC_R_SUCCESS) {
3392 			/*
3393 			 * Remember bottom of zone due to DNAME.
3394 			 */
3395 			dns_name_copynf(name, bottom);
3396 			dns_rdataset_disassociate(&rdataset);
3397 		}
3398 
3399 		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_mx,
3400 					     0, 0, &rdataset, NULL);
3401 		if (result != ISC_R_SUCCESS) {
3402 			goto checksrv;
3403 		}
3404 		result = dns_rdataset_first(&rdataset);
3405 		while (result == ISC_R_SUCCESS) {
3406 			dns_rdataset_current(&rdataset, &rdata);
3407 			result = dns_rdata_tostruct(&rdata, &mx, NULL);
3408 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
3409 			if (!zone_check_mx(zone, db, &mx.mx, name)) {
3410 				ok = false;
3411 			}
3412 			dns_rdata_reset(&rdata);
3413 			result = dns_rdataset_next(&rdataset);
3414 		}
3415 		dns_rdataset_disassociate(&rdataset);
3416 
3417 	checksrv:
3418 		if (zone->rdclass != dns_rdataclass_in) {
3419 			goto next;
3420 		}
3421 		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_srv,
3422 					     0, 0, &rdataset, NULL);
3423 		if (result != ISC_R_SUCCESS) {
3424 			goto checkspf;
3425 		}
3426 		result = dns_rdataset_first(&rdataset);
3427 		while (result == ISC_R_SUCCESS) {
3428 			dns_rdataset_current(&rdataset, &rdata);
3429 			result = dns_rdata_tostruct(&rdata, &srv, NULL);
3430 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
3431 			if (!zone_check_srv(zone, db, &srv.target, name)) {
3432 				ok = false;
3433 			}
3434 			dns_rdata_reset(&rdata);
3435 			result = dns_rdataset_next(&rdataset);
3436 		}
3437 		dns_rdataset_disassociate(&rdataset);
3438 
3439 	checkspf:
3440 		/*
3441 		 * Check if there is a type SPF record without an
3442 		 * SPF-formatted type TXT record also being present.
3443 		 */
3444 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSPF)) {
3445 			goto next;
3446 		}
3447 		if (zone->rdclass != dns_rdataclass_in) {
3448 			goto next;
3449 		}
3450 		have_spf = have_txt = false;
3451 		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_spf,
3452 					     0, 0, &rdataset, NULL);
3453 		if (result == ISC_R_SUCCESS) {
3454 			dns_rdataset_disassociate(&rdataset);
3455 			have_spf = true;
3456 		}
3457 		result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_txt,
3458 					     0, 0, &rdataset, NULL);
3459 		if (result != ISC_R_SUCCESS) {
3460 			goto notxt;
3461 		}
3462 		result = dns_rdataset_first(&rdataset);
3463 		while (result == ISC_R_SUCCESS) {
3464 			dns_rdataset_current(&rdataset, &rdata);
3465 			have_txt = isspf(&rdata);
3466 			dns_rdata_reset(&rdata);
3467 			if (have_txt) {
3468 				break;
3469 			}
3470 			result = dns_rdataset_next(&rdataset);
3471 		}
3472 		dns_rdataset_disassociate(&rdataset);
3473 
3474 	notxt:
3475 		if (have_spf && !have_txt) {
3476 			char namebuf[DNS_NAME_FORMATSIZE];
3477 
3478 			dns_name_format(name, namebuf, sizeof(namebuf));
3479 			dns_zone_log(zone, ISC_LOG_WARNING,
3480 				     "'%s' found type "
3481 				     "SPF record but no SPF TXT record found, "
3482 				     "add matching type TXT record",
3483 				     namebuf);
3484 		}
3485 
3486 	next:
3487 		dns_db_detachnode(db, &node);
3488 		result = dns_dbiterator_next(dbiterator);
3489 	}
3490 
3491 cleanup:
3492 	if (node != NULL) {
3493 		dns_db_detachnode(db, &node);
3494 	}
3495 	dns_dbiterator_destroy(&dbiterator);
3496 
3497 	return (ok);
3498 }
3499 
3500 /*
3501  * OpenSSL verification of RSA keys with exponent 3 is known to be
3502  * broken prior OpenSSL 0.9.8c/0.9.7k.	Look for such keys and warn
3503  * if they are in use.
3504  */
3505 static void
zone_check_dnskeys(dns_zone_t * zone,dns_db_t * db)3506 zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
3507 	dns_dbnode_t *node = NULL;
3508 	dns_dbversion_t *version = NULL;
3509 	dns_rdata_dnskey_t dnskey;
3510 	dns_rdata_t rdata = DNS_RDATA_INIT;
3511 	dns_rdataset_t rdataset;
3512 	isc_result_t result;
3513 
3514 	result = dns_db_findnode(db, &zone->origin, false, &node);
3515 	if (result != ISC_R_SUCCESS) {
3516 		goto cleanup;
3517 	}
3518 
3519 	dns_db_currentversion(db, &version);
3520 	dns_rdataset_init(&rdataset);
3521 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
3522 				     dns_rdatatype_none, 0, &rdataset, NULL);
3523 	if (result != ISC_R_SUCCESS) {
3524 		goto cleanup;
3525 	}
3526 
3527 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
3528 	     result = dns_rdataset_next(&rdataset))
3529 	{
3530 		dns_rdataset_current(&rdataset, &rdata);
3531 		result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
3532 		INSIST(result == ISC_R_SUCCESS);
3533 
3534 		/*
3535 		 * RFC 3110, section 4: Performance Considerations:
3536 		 *
3537 		 * A public exponent of 3 minimizes the effort needed to verify
3538 		 * a signature.  Use of 3 as the public exponent is weak for
3539 		 * confidentiality uses since, if the same data can be collected
3540 		 * encrypted under three different keys with an exponent of 3
3541 		 * then, using the Chinese Remainder Theorem [NETSEC], the
3542 		 * original plain text can be easily recovered.  If a key is
3543 		 * known to be used only for authentication, as is the case with
3544 		 * DNSSEC, then an exponent of 3 is acceptable.  However other
3545 		 * applications in the future may wish to leverage DNS
3546 		 * distributed keys for applications that do require
3547 		 * confidentiality.  For keys which might have such other uses,
3548 		 * a more conservative choice would be 65537 (F4, the fourth
3549 		 * fermat number).
3550 		 */
3551 		if (dnskey.datalen > 1 && dnskey.data[0] == 1 &&
3552 		    dnskey.data[1] == 3 &&
3553 		    (dnskey.algorithm == DNS_KEYALG_RSAMD5 ||
3554 		     dnskey.algorithm == DNS_KEYALG_RSASHA1 ||
3555 		     dnskey.algorithm == DNS_KEYALG_NSEC3RSASHA1 ||
3556 		     dnskey.algorithm == DNS_KEYALG_RSASHA256 ||
3557 		     dnskey.algorithm == DNS_KEYALG_RSASHA512))
3558 		{
3559 			char algorithm[DNS_SECALG_FORMATSIZE];
3560 			isc_region_t r;
3561 
3562 			dns_rdata_toregion(&rdata, &r);
3563 			dns_secalg_format(dnskey.algorithm, algorithm,
3564 					  sizeof(algorithm));
3565 
3566 			dnssec_log(zone, ISC_LOG_WARNING,
3567 				   "weak %s (%u) key found (exponent=3, id=%u)",
3568 				   algorithm, dnskey.algorithm,
3569 				   dst_region_computeid(&r));
3570 		}
3571 		dns_rdata_reset(&rdata);
3572 	}
3573 	dns_rdataset_disassociate(&rdataset);
3574 
3575 cleanup:
3576 	if (node != NULL) {
3577 		dns_db_detachnode(db, &node);
3578 	}
3579 	if (version != NULL) {
3580 		dns_db_closeversion(db, &version, false);
3581 	}
3582 }
3583 
3584 static void
resume_signingwithkey(dns_zone_t * zone)3585 resume_signingwithkey(dns_zone_t *zone) {
3586 	dns_dbnode_t *node = NULL;
3587 	dns_dbversion_t *version = NULL;
3588 	dns_rdata_t rdata = DNS_RDATA_INIT;
3589 	dns_rdataset_t rdataset;
3590 	isc_result_t result;
3591 	dns_db_t *db = NULL;
3592 
3593 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3594 	if (zone->db != NULL) {
3595 		dns_db_attach(zone->db, &db);
3596 	}
3597 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3598 	if (db == NULL) {
3599 		goto cleanup;
3600 	}
3601 
3602 	result = dns_db_findnode(db, &zone->origin, false, &node);
3603 	if (result != ISC_R_SUCCESS) {
3604 		goto cleanup;
3605 	}
3606 
3607 	dns_db_currentversion(db, &version);
3608 	dns_rdataset_init(&rdataset);
3609 	result = dns_db_findrdataset(db, node, version, zone->privatetype,
3610 				     dns_rdatatype_none, 0, &rdataset, NULL);
3611 	if (result != ISC_R_SUCCESS) {
3612 		INSIST(!dns_rdataset_isassociated(&rdataset));
3613 		goto cleanup;
3614 	}
3615 
3616 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
3617 	     result = dns_rdataset_next(&rdataset))
3618 	{
3619 		dns_rdataset_current(&rdataset, &rdata);
3620 		if (rdata.length != 5 || rdata.data[0] == 0 ||
3621 		    rdata.data[4] != 0)
3622 		{
3623 			dns_rdata_reset(&rdata);
3624 			continue;
3625 		}
3626 
3627 		result = zone_signwithkey(zone, rdata.data[0],
3628 					  (rdata.data[1] << 8) | rdata.data[2],
3629 					  rdata.data[3]);
3630 		if (result != ISC_R_SUCCESS) {
3631 			dnssec_log(zone, ISC_LOG_ERROR,
3632 				   "zone_signwithkey failed: %s",
3633 				   dns_result_totext(result));
3634 		}
3635 		dns_rdata_reset(&rdata);
3636 	}
3637 	dns_rdataset_disassociate(&rdataset);
3638 
3639 cleanup:
3640 	if (db != NULL) {
3641 		if (node != NULL) {
3642 			dns_db_detachnode(db, &node);
3643 		}
3644 		if (version != NULL) {
3645 			dns_db_closeversion(db, &version, false);
3646 		}
3647 		dns_db_detach(&db);
3648 	}
3649 }
3650 
3651 /*
3652  * Initiate adding/removing NSEC3 records belonging to the chain defined by the
3653  * supplied NSEC3PARAM RDATA.
3654  *
3655  * Zone must be locked by caller.
3656  */
3657 static isc_result_t
zone_addnsec3chain(dns_zone_t * zone,dns_rdata_nsec3param_t * nsec3param)3658 zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
3659 	dns_nsec3chain_t *nsec3chain, *current;
3660 	dns_dbversion_t *version = NULL;
3661 	bool nseconly = false, nsec3ok = false;
3662 	isc_result_t result;
3663 	isc_time_t now;
3664 	unsigned int options = 0;
3665 	char saltbuf[255 * 2 + 1];
3666 	char flags[sizeof("INITIAL|REMOVE|CREATE|NONSEC|OPTOUT")];
3667 	dns_db_t *db = NULL;
3668 
3669 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3670 	if (zone->db != NULL) {
3671 		dns_db_attach(zone->db, &db);
3672 	}
3673 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3674 
3675 	if (db == NULL) {
3676 		result = ISC_R_SUCCESS;
3677 		goto cleanup;
3678 	}
3679 
3680 	/*
3681 	 * If this zone is not NSEC3-capable, attempting to remove any NSEC3
3682 	 * chain from it is pointless as it would not be possible for the
3683 	 * latter to exist in the first place.
3684 	 */
3685 	dns_db_currentversion(db, &version);
3686 	result = dns_nsec_nseconly(db, version, &nseconly);
3687 	nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
3688 	dns_db_closeversion(db, &version, false);
3689 	if (!nsec3ok && (nsec3param->flags & DNS_NSEC3FLAG_REMOVE) == 0) {
3690 		result = ISC_R_SUCCESS;
3691 		goto cleanup;
3692 	}
3693 
3694 	/*
3695 	 * Allocate and initialize structure preserving state of
3696 	 * adding/removing records belonging to this NSEC3 chain between
3697 	 * separate zone_nsec3chain() calls.
3698 	 */
3699 	nsec3chain = isc_mem_get(zone->mctx, sizeof *nsec3chain);
3700 
3701 	nsec3chain->magic = 0;
3702 	nsec3chain->done = false;
3703 	nsec3chain->db = NULL;
3704 	nsec3chain->dbiterator = NULL;
3705 	nsec3chain->nsec3param.common.rdclass = nsec3param->common.rdclass;
3706 	nsec3chain->nsec3param.common.rdtype = nsec3param->common.rdtype;
3707 	nsec3chain->nsec3param.hash = nsec3param->hash;
3708 	nsec3chain->nsec3param.iterations = nsec3param->iterations;
3709 	nsec3chain->nsec3param.flags = nsec3param->flags;
3710 	nsec3chain->nsec3param.salt_length = nsec3param->salt_length;
3711 	memmove(nsec3chain->salt, nsec3param->salt, nsec3param->salt_length);
3712 	nsec3chain->nsec3param.salt = nsec3chain->salt;
3713 	nsec3chain->seen_nsec = false;
3714 	nsec3chain->delete_nsec = false;
3715 	nsec3chain->save_delete_nsec = false;
3716 
3717 	/*
3718 	 * Log NSEC3 parameters defined by supplied NSEC3PARAM RDATA.
3719 	 */
3720 	if (nsec3param->flags == 0) {
3721 		strlcpy(flags, "NONE", sizeof(flags));
3722 	} else {
3723 		flags[0] = '\0';
3724 		if ((nsec3param->flags & DNS_NSEC3FLAG_REMOVE) != 0) {
3725 			strlcat(flags, "REMOVE", sizeof(flags));
3726 		}
3727 		if ((nsec3param->flags & DNS_NSEC3FLAG_INITIAL) != 0) {
3728 			if (flags[0] == '\0') {
3729 				strlcpy(flags, "INITIAL", sizeof(flags));
3730 			} else {
3731 				strlcat(flags, "|INITIAL", sizeof(flags));
3732 			}
3733 		}
3734 		if ((nsec3param->flags & DNS_NSEC3FLAG_CREATE) != 0) {
3735 			if (flags[0] == '\0') {
3736 				strlcpy(flags, "CREATE", sizeof(flags));
3737 			} else {
3738 				strlcat(flags, "|CREATE", sizeof(flags));
3739 			}
3740 		}
3741 		if ((nsec3param->flags & DNS_NSEC3FLAG_NONSEC) != 0) {
3742 			if (flags[0] == '\0') {
3743 				strlcpy(flags, "NONSEC", sizeof(flags));
3744 			} else {
3745 				strlcat(flags, "|NONSEC", sizeof(flags));
3746 			}
3747 		}
3748 		if ((nsec3param->flags & DNS_NSEC3FLAG_OPTOUT) != 0) {
3749 			if (flags[0] == '\0') {
3750 				strlcpy(flags, "OPTOUT", sizeof(flags));
3751 			} else {
3752 				strlcat(flags, "|OPTOUT", sizeof(flags));
3753 			}
3754 		}
3755 	}
3756 	result = dns_nsec3param_salttotext(nsec3param, saltbuf,
3757 					   sizeof(saltbuf));
3758 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
3759 	dnssec_log(zone, ISC_LOG_INFO, "zone_addnsec3chain(%u,%s,%u,%s)",
3760 		   nsec3param->hash, flags, nsec3param->iterations, saltbuf);
3761 
3762 	/*
3763 	 * If the NSEC3 chain defined by the supplied NSEC3PARAM RDATA is
3764 	 * currently being processed, interrupt its processing to avoid
3765 	 * simultaneously adding and removing records for the same NSEC3 chain.
3766 	 */
3767 	for (current = ISC_LIST_HEAD(zone->nsec3chain); current != NULL;
3768 	     current = ISC_LIST_NEXT(current, link))
3769 	{
3770 		if ((current->db == db) &&
3771 		    (current->nsec3param.hash == nsec3param->hash) &&
3772 		    (current->nsec3param.iterations ==
3773 		     nsec3param->iterations) &&
3774 		    (current->nsec3param.salt_length ==
3775 		     nsec3param->salt_length) &&
3776 		    memcmp(current->nsec3param.salt, nsec3param->salt,
3777 			   nsec3param->salt_length) == 0)
3778 		{
3779 			current->done = true;
3780 		}
3781 	}
3782 
3783 	/*
3784 	 * Attach zone database to the structure initialized above and create
3785 	 * an iterator for it with appropriate options in order to avoid
3786 	 * creating NSEC3 records for NSEC3 records.
3787 	 */
3788 	dns_db_attach(db, &nsec3chain->db);
3789 	if ((nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0) {
3790 		options = DNS_DB_NONSEC3;
3791 	}
3792 	result = dns_db_createiterator(nsec3chain->db, options,
3793 				       &nsec3chain->dbiterator);
3794 	if (result == ISC_R_SUCCESS) {
3795 		result = dns_dbiterator_first(nsec3chain->dbiterator);
3796 	}
3797 	if (result == ISC_R_SUCCESS) {
3798 		/*
3799 		 * Database iterator initialization succeeded.  We are now
3800 		 * ready to kick off adding/removing records belonging to this
3801 		 * NSEC3 chain.  Append the structure initialized above to the
3802 		 * "nsec3chain" list for the zone and set the appropriate zone
3803 		 * timer so that zone_nsec3chain() is called as soon as
3804 		 * possible.
3805 		 */
3806 		dns_dbiterator_pause(nsec3chain->dbiterator);
3807 		ISC_LIST_INITANDAPPEND(zone->nsec3chain, nsec3chain, link);
3808 		nsec3chain = NULL;
3809 		if (isc_time_isepoch(&zone->nsec3chaintime)) {
3810 			TIME_NOW(&now);
3811 			zone->nsec3chaintime = now;
3812 			if (zone->task != NULL) {
3813 				zone_settimer(zone, &now);
3814 			}
3815 		}
3816 	}
3817 
3818 	if (nsec3chain != NULL) {
3819 		if (nsec3chain->db != NULL) {
3820 			dns_db_detach(&nsec3chain->db);
3821 		}
3822 		if (nsec3chain->dbiterator != NULL) {
3823 			dns_dbiterator_destroy(&nsec3chain->dbiterator);
3824 		}
3825 		isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
3826 	}
3827 
3828 cleanup:
3829 	if (db != NULL) {
3830 		dns_db_detach(&db);
3831 	}
3832 	return (result);
3833 }
3834 
3835 /*
3836  * Find private-type records at the zone apex which signal that an NSEC3 chain
3837  * should be added or removed.  For each such record, extract NSEC3PARAM RDATA
3838  * and pass it to zone_addnsec3chain().
3839  *
3840  * Zone must be locked by caller.
3841  */
3842 static void
resume_addnsec3chain(dns_zone_t * zone)3843 resume_addnsec3chain(dns_zone_t *zone) {
3844 	dns_dbnode_t *node = NULL;
3845 	dns_dbversion_t *version = NULL;
3846 	dns_rdataset_t rdataset;
3847 	isc_result_t result;
3848 	dns_rdata_nsec3param_t nsec3param;
3849 	bool nseconly = false, nsec3ok = false;
3850 	dns_db_t *db = NULL;
3851 
3852 	INSIST(LOCKED_ZONE(zone));
3853 
3854 	if (zone->privatetype == 0) {
3855 		return;
3856 	}
3857 
3858 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3859 	if (zone->db != NULL) {
3860 		dns_db_attach(zone->db, &db);
3861 	}
3862 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3863 	if (db == NULL) {
3864 		goto cleanup;
3865 	}
3866 
3867 	result = dns_db_findnode(db, &zone->origin, false, &node);
3868 	if (result != ISC_R_SUCCESS) {
3869 		goto cleanup;
3870 	}
3871 
3872 	dns_db_currentversion(db, &version);
3873 
3874 	/*
3875 	 * In order to create NSEC3 chains we need the DNSKEY RRset at zone
3876 	 * apex to exist and contain no keys using NSEC-only algorithms.
3877 	 */
3878 	result = dns_nsec_nseconly(db, version, &nseconly);
3879 	nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
3880 
3881 	/*
3882 	 * Get the RRset containing all private-type records at the zone apex.
3883 	 */
3884 	dns_rdataset_init(&rdataset);
3885 	result = dns_db_findrdataset(db, node, version, zone->privatetype,
3886 				     dns_rdatatype_none, 0, &rdataset, NULL);
3887 	if (result != ISC_R_SUCCESS) {
3888 		INSIST(!dns_rdataset_isassociated(&rdataset));
3889 		goto cleanup;
3890 	}
3891 
3892 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
3893 	     result = dns_rdataset_next(&rdataset))
3894 	{
3895 		unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
3896 		dns_rdata_t rdata = DNS_RDATA_INIT;
3897 		dns_rdata_t private = DNS_RDATA_INIT;
3898 
3899 		dns_rdataset_current(&rdataset, &private);
3900 		/*
3901 		 * Try extracting NSEC3PARAM RDATA from this private-type
3902 		 * record.  Failure means this private-type record does not
3903 		 * represent an NSEC3PARAM record, so skip it.
3904 		 */
3905 		if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
3906 						sizeof(buf)))
3907 		{
3908 			continue;
3909 		}
3910 		result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
3911 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
3912 		if (((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) ||
3913 		    ((nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0 && nsec3ok))
3914 		{
3915 			/*
3916 			 * Pass the NSEC3PARAM RDATA contained in this
3917 			 * private-type record to zone_addnsec3chain() so that
3918 			 * it can kick off adding or removing NSEC3 records.
3919 			 */
3920 			result = zone_addnsec3chain(zone, &nsec3param);
3921 			if (result != ISC_R_SUCCESS) {
3922 				dnssec_log(zone, ISC_LOG_ERROR,
3923 					   "zone_addnsec3chain failed: %s",
3924 					   dns_result_totext(result));
3925 			}
3926 		}
3927 	}
3928 	dns_rdataset_disassociate(&rdataset);
3929 
3930 cleanup:
3931 	if (db != NULL) {
3932 		if (node != NULL) {
3933 			dns_db_detachnode(db, &node);
3934 		}
3935 		if (version != NULL) {
3936 			dns_db_closeversion(db, &version, false);
3937 		}
3938 		dns_db_detach(&db);
3939 	}
3940 }
3941 
3942 static void
set_resigntime(dns_zone_t * zone)3943 set_resigntime(dns_zone_t *zone) {
3944 	dns_rdataset_t rdataset;
3945 	dns_fixedname_t fixed;
3946 	unsigned int resign;
3947 	isc_result_t result;
3948 	uint32_t nanosecs;
3949 	dns_db_t *db = NULL;
3950 
3951 	INSIST(LOCKED_ZONE(zone));
3952 
3953 	/* We only re-sign zones that can be dynamically updated */
3954 	if (zone->update_disabled) {
3955 		return;
3956 	}
3957 
3958 	if (!inline_secure(zone) &&
3959 	    (zone->type != dns_zone_primary ||
3960 	     (zone->ssutable == NULL &&
3961 	      (zone->update_acl == NULL || dns_acl_isnone(zone->update_acl)))))
3962 	{
3963 		return;
3964 	}
3965 
3966 	dns_rdataset_init(&rdataset);
3967 	dns_fixedname_init(&fixed);
3968 
3969 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3970 	if (zone->db != NULL) {
3971 		dns_db_attach(zone->db, &db);
3972 	}
3973 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3974 	if (db == NULL) {
3975 		isc_time_settoepoch(&zone->resigntime);
3976 		return;
3977 	}
3978 
3979 	result = dns_db_getsigningtime(db, &rdataset,
3980 				       dns_fixedname_name(&fixed));
3981 	if (result != ISC_R_SUCCESS) {
3982 		isc_time_settoepoch(&zone->resigntime);
3983 		goto cleanup;
3984 	}
3985 
3986 	resign = rdataset.resign - dns_zone_getsigresigninginterval(zone);
3987 	dns_rdataset_disassociate(&rdataset);
3988 	nanosecs = isc_random_uniform(1000000000);
3989 	isc_time_set(&zone->resigntime, resign, nanosecs);
3990 
3991 cleanup:
3992 	dns_db_detach(&db);
3993 	return;
3994 }
3995 
3996 static isc_result_t
check_nsec3param(dns_zone_t * zone,dns_db_t * db)3997 check_nsec3param(dns_zone_t *zone, dns_db_t *db) {
3998 	bool ok = false;
3999 	dns_dbnode_t *node = NULL;
4000 	dns_dbversion_t *version = NULL;
4001 	dns_rdata_nsec3param_t nsec3param;
4002 	dns_rdataset_t rdataset;
4003 	isc_result_t result;
4004 	bool dynamic = (zone->type == dns_zone_primary)
4005 			       ? dns_zone_isdynamic(zone, false)
4006 			       : false;
4007 
4008 	dns_rdataset_init(&rdataset);
4009 	result = dns_db_findnode(db, &zone->origin, false, &node);
4010 	if (result != ISC_R_SUCCESS) {
4011 		dns_zone_log(zone, ISC_LOG_ERROR,
4012 			     "nsec3param lookup failure: %s",
4013 			     dns_result_totext(result));
4014 		return (result);
4015 	}
4016 	dns_db_currentversion(db, &version);
4017 
4018 	result = dns_db_findrdataset(db, node, version,
4019 				     dns_rdatatype_nsec3param,
4020 				     dns_rdatatype_none, 0, &rdataset, NULL);
4021 	if (result == ISC_R_NOTFOUND) {
4022 		INSIST(!dns_rdataset_isassociated(&rdataset));
4023 		result = ISC_R_SUCCESS;
4024 		goto cleanup;
4025 	}
4026 	if (result != ISC_R_SUCCESS) {
4027 		INSIST(!dns_rdataset_isassociated(&rdataset));
4028 		dns_zone_log(zone, ISC_LOG_ERROR,
4029 			     "nsec3param lookup failure: %s",
4030 			     dns_result_totext(result));
4031 		goto cleanup;
4032 	}
4033 
4034 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
4035 	     result = dns_rdataset_next(&rdataset))
4036 	{
4037 		dns_rdata_t rdata = DNS_RDATA_INIT;
4038 
4039 		dns_rdataset_current(&rdataset, &rdata);
4040 		result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
4041 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
4042 
4043 		/*
4044 		 * For dynamic zones we must support every algorithm so we
4045 		 * can regenerate all the NSEC3 chains.
4046 		 * For non-dynamic zones we only need to find a supported
4047 		 * algorithm.
4048 		 */
4049 		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NSEC3TESTZONE) &&
4050 		    nsec3param.hash == DNS_NSEC3_UNKNOWNALG && !dynamic)
4051 		{
4052 			dns_zone_log(zone, ISC_LOG_WARNING,
4053 				     "nsec3 test \"unknown\" hash algorithm "
4054 				     "found: %u",
4055 				     nsec3param.hash);
4056 			ok = true;
4057 		} else if (!dns_nsec3_supportedhash(nsec3param.hash)) {
4058 			if (dynamic) {
4059 				dns_zone_log(zone, ISC_LOG_ERROR,
4060 					     "unsupported nsec3 hash algorithm"
4061 					     " in dynamic zone: %u",
4062 					     nsec3param.hash);
4063 				result = DNS_R_BADZONE;
4064 				/* Stop second error message. */
4065 				ok = true;
4066 				break;
4067 			} else {
4068 				dns_zone_log(zone, ISC_LOG_WARNING,
4069 					     "unsupported nsec3 hash "
4070 					     "algorithm: %u",
4071 					     nsec3param.hash);
4072 			}
4073 		} else {
4074 			ok = true;
4075 		}
4076 
4077 		/*
4078 		 * Warn if the zone has excessive NSEC3 iterations.
4079 		 */
4080 		if (nsec3param.iterations > dns_nsec3_maxiterations()) {
4081 			dnssec_log(zone, ISC_LOG_WARNING,
4082 				   "excessive NSEC3PARAM iterations %u > %u",
4083 				   nsec3param.iterations,
4084 				   dns_nsec3_maxiterations());
4085 		}
4086 	}
4087 	if (result == ISC_R_NOMORE) {
4088 		result = ISC_R_SUCCESS;
4089 	}
4090 
4091 	if (!ok) {
4092 		result = DNS_R_BADZONE;
4093 		dns_zone_log(zone, ISC_LOG_ERROR,
4094 			     "no supported nsec3 hash algorithm");
4095 	}
4096 
4097 cleanup:
4098 	if (dns_rdataset_isassociated(&rdataset)) {
4099 		dns_rdataset_disassociate(&rdataset);
4100 	}
4101 	dns_db_closeversion(db, &version, false);
4102 	dns_db_detachnode(db, &node);
4103 	return (result);
4104 }
4105 
4106 /*
4107  * Set the timer for refreshing the key zone to the soonest future time
4108  * of the set (current timer, keydata->refresh, keydata->addhd,
4109  * keydata->removehd).
4110  */
4111 static void
set_refreshkeytimer(dns_zone_t * zone,dns_rdata_keydata_t * key,isc_stdtime_t now,bool force)4112 set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key,
4113 		    isc_stdtime_t now, bool force) {
4114 	const char me[] = "set_refreshkeytimer";
4115 	isc_stdtime_t then;
4116 	isc_time_t timenow, timethen;
4117 	char timebuf[80];
4118 
4119 	ENTER;
4120 	then = key->refresh;
4121 	if (force) {
4122 		then = now;
4123 	}
4124 	if (key->addhd > now && key->addhd < then) {
4125 		then = key->addhd;
4126 	}
4127 	if (key->removehd > now && key->removehd < then) {
4128 		then = key->removehd;
4129 	}
4130 
4131 	TIME_NOW(&timenow);
4132 	if (then > now) {
4133 		DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
4134 	} else {
4135 		timethen = timenow;
4136 	}
4137 	if (isc_time_compare(&zone->refreshkeytime, &timenow) < 0 ||
4138 	    isc_time_compare(&timethen, &zone->refreshkeytime) < 0)
4139 	{
4140 		zone->refreshkeytime = timethen;
4141 	}
4142 
4143 	isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
4144 	dns_zone_log(zone, ISC_LOG_DEBUG(1), "next key refresh: %s", timebuf);
4145 	zone_settimer(zone, &timenow);
4146 }
4147 
4148 /*
4149  * If keynode references a key or a DS rdataset, and if the key
4150  * zone does not contain a KEYDATA record for the corresponding name,
4151  * then create an empty KEYDATA and push it into the zone as a placeholder,
4152  * then schedule a key refresh immediately. This new KEYDATA record will be
4153  * updated during the refresh.
4154  *
4155  * If the key zone is changed, set '*changed' to true.
4156  */
4157 static isc_result_t
create_keydata(dns_zone_t * zone,dns_db_t * db,dns_dbversion_t * ver,dns_diff_t * diff,dns_keynode_t * keynode,dns_name_t * keyname,bool * changed)4158 create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
4159 	       dns_diff_t *diff, dns_keynode_t *keynode, dns_name_t *keyname,
4160 	       bool *changed) {
4161 	const char me[] = "create_keydata";
4162 	isc_result_t result = ISC_R_SUCCESS;
4163 	dns_rdata_t rdata = DNS_RDATA_INIT;
4164 	dns_rdata_keydata_t kd;
4165 	unsigned char rrdata[4096];
4166 	isc_buffer_t rrdatabuf;
4167 	isc_stdtime_t now;
4168 
4169 	REQUIRE(keynode != NULL);
4170 
4171 	ENTER;
4172 	isc_stdtime_get(&now);
4173 
4174 	/*
4175 	 * If the keynode has no trust anchor set, we shouldn't be here.
4176 	 */
4177 	if (!dns_keynode_dsset(keynode, NULL)) {
4178 		return (ISC_R_FAILURE);
4179 	}
4180 
4181 	memset(&kd, 0, sizeof(kd));
4182 	kd.common.rdclass = zone->rdclass;
4183 	kd.common.rdtype = dns_rdatatype_keydata;
4184 	ISC_LINK_INIT(&kd.common, link);
4185 
4186 	isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
4187 
4188 	CHECK(dns_rdata_fromstruct(&rdata, zone->rdclass, dns_rdatatype_keydata,
4189 				   &kd, &rrdatabuf));
4190 	/* Add rdata to zone. */
4191 	CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, keyname, 0, &rdata));
4192 	*changed = true;
4193 
4194 	/* Refresh new keys from the zone apex as soon as possible. */
4195 	set_refreshkeytimer(zone, &kd, now, true);
4196 	return (ISC_R_SUCCESS);
4197 
4198 failure:
4199 	return (result);
4200 }
4201 
4202 /*
4203  * Remove from the key zone all the KEYDATA records found in rdataset.
4204  */
4205 static isc_result_t
delete_keydata(dns_db_t * db,dns_dbversion_t * ver,dns_diff_t * diff,dns_name_t * name,dns_rdataset_t * rdataset)4206 delete_keydata(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
4207 	       dns_name_t *name, dns_rdataset_t *rdataset) {
4208 	dns_rdata_t rdata = DNS_RDATA_INIT;
4209 	isc_result_t result, uresult;
4210 
4211 	for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
4212 	     result = dns_rdataset_next(rdataset))
4213 	{
4214 		dns_rdata_reset(&rdata);
4215 		dns_rdataset_current(rdataset, &rdata);
4216 		uresult = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name, 0,
4217 					&rdata);
4218 		if (uresult != ISC_R_SUCCESS) {
4219 			return (uresult);
4220 		}
4221 	}
4222 	if (result == ISC_R_NOMORE) {
4223 		result = ISC_R_SUCCESS;
4224 	}
4225 	return (result);
4226 }
4227 
4228 /*
4229  * Compute the DNSSEC key ID for a DNSKEY record.
4230  */
4231 static isc_result_t
compute_tag(dns_name_t * name,dns_rdata_dnskey_t * dnskey,isc_mem_t * mctx,dns_keytag_t * tag)4232 compute_tag(dns_name_t *name, dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx,
4233 	    dns_keytag_t *tag) {
4234 	isc_result_t result;
4235 	dns_rdata_t rdata = DNS_RDATA_INIT;
4236 	unsigned char data[4096];
4237 	isc_buffer_t buffer;
4238 	dst_key_t *dstkey = NULL;
4239 
4240 	isc_buffer_init(&buffer, data, sizeof(data));
4241 	dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
4242 			     dns_rdatatype_dnskey, dnskey, &buffer);
4243 
4244 	result = dns_dnssec_keyfromrdata(name, &rdata, mctx, &dstkey);
4245 	if (result == ISC_R_SUCCESS) {
4246 		*tag = dst_key_id(dstkey);
4247 		dst_key_free(&dstkey);
4248 	}
4249 
4250 	return (result);
4251 }
4252 
4253 /*
4254  * Add key to the security roots.
4255  */
4256 static void
trust_key(dns_zone_t * zone,dns_name_t * keyname,dns_rdata_dnskey_t * dnskey,bool initial)4257 trust_key(dns_zone_t *zone, dns_name_t *keyname, dns_rdata_dnskey_t *dnskey,
4258 	  bool initial) {
4259 	isc_result_t result;
4260 	dns_rdata_t rdata = DNS_RDATA_INIT;
4261 	unsigned char data[4096], digest[ISC_MAX_MD_SIZE];
4262 	isc_buffer_t buffer;
4263 	dns_keytable_t *sr = NULL;
4264 	dns_rdata_ds_t ds;
4265 
4266 	result = dns_view_getsecroots(zone->view, &sr);
4267 	if (result != ISC_R_SUCCESS) {
4268 		return;
4269 	}
4270 
4271 	/* Build DS record for key. */
4272 	isc_buffer_init(&buffer, data, sizeof(data));
4273 	dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
4274 			     dns_rdatatype_dnskey, dnskey, &buffer);
4275 	CHECK(dns_ds_fromkeyrdata(keyname, &rdata, DNS_DSDIGEST_SHA256, digest,
4276 				  &ds));
4277 	CHECK(dns_keytable_add(sr, true, initial, keyname, &ds));
4278 
4279 	dns_keytable_detach(&sr);
4280 
4281 failure:
4282 	if (sr != NULL) {
4283 		dns_keytable_detach(&sr);
4284 	}
4285 	return;
4286 }
4287 
4288 /*
4289  * Add a null key to the security roots for so that all queries
4290  * to the zone will fail.
4291  */
4292 static void
fail_secure(dns_zone_t * zone,dns_name_t * keyname)4293 fail_secure(dns_zone_t *zone, dns_name_t *keyname) {
4294 	isc_result_t result;
4295 	dns_keytable_t *sr = NULL;
4296 
4297 	result = dns_view_getsecroots(zone->view, &sr);
4298 	if (result == ISC_R_SUCCESS) {
4299 		dns_keytable_marksecure(sr, keyname);
4300 		dns_keytable_detach(&sr);
4301 	}
4302 }
4303 
4304 /*
4305  * Scan a set of KEYDATA records from the key zone.  The ones that are
4306  * valid (i.e., the add holddown timer has expired) become trusted keys.
4307  */
4308 static void
load_secroots(dns_zone_t * zone,dns_name_t * name,dns_rdataset_t * rdataset)4309 load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
4310 	isc_result_t result;
4311 	dns_rdata_t rdata = DNS_RDATA_INIT;
4312 	dns_rdata_keydata_t keydata;
4313 	dns_rdata_dnskey_t dnskey;
4314 	int trusted = 0, revoked = 0, pending = 0;
4315 	isc_stdtime_t now;
4316 	dns_keytable_t *sr = NULL;
4317 
4318 	isc_stdtime_get(&now);
4319 
4320 	result = dns_view_getsecroots(zone->view, &sr);
4321 	if (result == ISC_R_SUCCESS) {
4322 		dns_keytable_delete(sr, name);
4323 		dns_keytable_detach(&sr);
4324 	}
4325 
4326 	/* Now insert all the accepted trust anchors from this keydata set. */
4327 	for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
4328 	     result = dns_rdataset_next(rdataset))
4329 	{
4330 		dns_rdata_reset(&rdata);
4331 		dns_rdataset_current(rdataset, &rdata);
4332 
4333 		/* Convert rdata to keydata. */
4334 		result = dns_rdata_tostruct(&rdata, &keydata, NULL);
4335 		if (result == ISC_R_UNEXPECTEDEND) {
4336 			continue;
4337 		}
4338 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
4339 
4340 		/* Set the key refresh timer to force a fast refresh. */
4341 		set_refreshkeytimer(zone, &keydata, now, true);
4342 
4343 		/* If the removal timer is nonzero, this key was revoked. */
4344 		if (keydata.removehd != 0) {
4345 			revoked++;
4346 			continue;
4347 		}
4348 
4349 		/*
4350 		 * If the add timer is still pending, this key is not
4351 		 * trusted yet.
4352 		 */
4353 		if (now < keydata.addhd) {
4354 			pending++;
4355 			continue;
4356 		}
4357 
4358 		/* Convert keydata to dnskey. */
4359 		dns_keydata_todnskey(&keydata, &dnskey, NULL);
4360 
4361 		/* Add to keytables. */
4362 		trusted++;
4363 		trust_key(zone, name, &dnskey, (keydata.addhd == 0));
4364 	}
4365 
4366 	if (trusted == 0 && pending != 0) {
4367 		char namebuf[DNS_NAME_FORMATSIZE];
4368 		dns_name_format(name, namebuf, sizeof namebuf);
4369 		dnssec_log(zone, ISC_LOG_ERROR,
4370 			   "No valid trust anchors for '%s'!", namebuf);
4371 		dnssec_log(zone, ISC_LOG_ERROR,
4372 			   "%d key(s) revoked, %d still pending", revoked,
4373 			   pending);
4374 		dnssec_log(zone, ISC_LOG_ERROR, "All queries to '%s' will fail",
4375 			   namebuf);
4376 		fail_secure(zone, name);
4377 	}
4378 }
4379 
4380 static isc_result_t
do_one_tuple(dns_difftuple_t ** tuple,dns_db_t * db,dns_dbversion_t * ver,dns_diff_t * diff)4381 do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
4382 	     dns_diff_t *diff) {
4383 	dns_diff_t temp_diff;
4384 	isc_result_t result;
4385 
4386 	/*
4387 	 * Create a singleton diff.
4388 	 */
4389 	dns_diff_init(diff->mctx, &temp_diff);
4390 	ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
4391 
4392 	/*
4393 	 * Apply it to the database.
4394 	 */
4395 	result = dns_diff_apply(&temp_diff, db, ver);
4396 	ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
4397 	if (result != ISC_R_SUCCESS) {
4398 		dns_difftuple_free(tuple);
4399 		return (result);
4400 	}
4401 
4402 	/*
4403 	 * Merge it into the current pending journal entry.
4404 	 */
4405 	dns_diff_appendminimal(diff, tuple);
4406 
4407 	/*
4408 	 * Do not clear temp_diff.
4409 	 */
4410 	return (ISC_R_SUCCESS);
4411 }
4412 
4413 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)4414 update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
4415 	      dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
4416 	      dns_rdata_t *rdata) {
4417 	dns_difftuple_t *tuple = NULL;
4418 	isc_result_t result;
4419 	result = dns_difftuple_create(diff->mctx, op, name, ttl, rdata, &tuple);
4420 	if (result != ISC_R_SUCCESS) {
4421 		return (result);
4422 	}
4423 	return (do_one_tuple(&tuple, db, ver, diff));
4424 }
4425 
4426 static isc_result_t
update_soa_serial(dns_zone_t * zone,dns_db_t * db,dns_dbversion_t * ver,dns_diff_t * diff,isc_mem_t * mctx,dns_updatemethod_t method)4427 update_soa_serial(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
4428 		  dns_diff_t *diff, isc_mem_t *mctx,
4429 		  dns_updatemethod_t method) {
4430 	dns_difftuple_t *deltuple = NULL;
4431 	dns_difftuple_t *addtuple = NULL;
4432 	uint32_t serial;
4433 	isc_result_t result;
4434 	dns_updatemethod_t used = dns_updatemethod_none;
4435 
4436 	INSIST(method != dns_updatemethod_none);
4437 
4438 	CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple));
4439 	CHECK(dns_difftuple_copy(deltuple, &addtuple));
4440 	addtuple->op = DNS_DIFFOP_ADD;
4441 
4442 	serial = dns_soa_getserial(&addtuple->rdata);
4443 	serial = dns_update_soaserial(serial, method, &used);
4444 	if (method != used) {
4445 		dns_zone_log(zone, ISC_LOG_WARNING,
4446 			     "update_soa_serial:new serial would be lower than "
4447 			     "old serial, using increment method instead");
4448 	}
4449 	dns_soa_setserial(serial, &addtuple->rdata);
4450 	CHECK(do_one_tuple(&deltuple, db, ver, diff));
4451 	CHECK(do_one_tuple(&addtuple, db, ver, diff));
4452 	result = ISC_R_SUCCESS;
4453 
4454 failure:
4455 	if (addtuple != NULL) {
4456 		dns_difftuple_free(&addtuple);
4457 	}
4458 	if (deltuple != NULL) {
4459 		dns_difftuple_free(&deltuple);
4460 	}
4461 	return (result);
4462 }
4463 
4464 /*
4465  * Write all transactions in 'diff' to the zone journal file.
4466  */
4467 static isc_result_t
zone_journal(dns_zone_t * zone,dns_diff_t * diff,uint32_t * sourceserial,const char * caller)4468 zone_journal(dns_zone_t *zone, dns_diff_t *diff, uint32_t *sourceserial,
4469 	     const char *caller) {
4470 	const char me[] = "zone_journal";
4471 	const char *journalfile;
4472 	isc_result_t result = ISC_R_SUCCESS;
4473 	dns_journal_t *journal = NULL;
4474 	unsigned int mode = DNS_JOURNAL_CREATE | DNS_JOURNAL_WRITE;
4475 
4476 	ENTER;
4477 	journalfile = dns_zone_getjournal(zone);
4478 	if (journalfile != NULL) {
4479 		result = dns_journal_open(zone->mctx, journalfile, mode,
4480 					  &journal);
4481 		if (result != ISC_R_SUCCESS) {
4482 			dns_zone_log(zone, ISC_LOG_ERROR,
4483 				     "%s:dns_journal_open -> %s", caller,
4484 				     dns_result_totext(result));
4485 			return (result);
4486 		}
4487 
4488 		if (sourceserial != NULL) {
4489 			dns_journal_set_sourceserial(journal, *sourceserial);
4490 		}
4491 
4492 		result = dns_journal_write_transaction(journal, diff);
4493 		if (result != ISC_R_SUCCESS) {
4494 			dns_zone_log(zone, ISC_LOG_ERROR,
4495 				     "%s:dns_journal_write_transaction -> %s",
4496 				     caller, dns_result_totext(result));
4497 		}
4498 		dns_journal_destroy(&journal);
4499 	}
4500 
4501 	return (result);
4502 }
4503 
4504 /*
4505  * Create an SOA record for a newly-created zone
4506  */
4507 static isc_result_t
add_soa(dns_zone_t * zone,dns_db_t * db)4508 add_soa(dns_zone_t *zone, dns_db_t *db) {
4509 	isc_result_t result;
4510 	dns_rdata_t rdata = DNS_RDATA_INIT;
4511 	unsigned char buf[DNS_SOA_BUFFERSIZE];
4512 	dns_dbversion_t *ver = NULL;
4513 	dns_diff_t diff;
4514 
4515 	dns_zone_log(zone, ISC_LOG_DEBUG(1), "creating SOA");
4516 
4517 	dns_diff_init(zone->mctx, &diff);
4518 	result = dns_db_newversion(db, &ver);
4519 	if (result != ISC_R_SUCCESS) {
4520 		dns_zone_log(zone, ISC_LOG_ERROR,
4521 			     "add_soa:dns_db_newversion -> %s",
4522 			     dns_result_totext(result));
4523 		goto failure;
4524 	}
4525 
4526 	/* Build SOA record */
4527 	result = dns_soa_buildrdata(&zone->origin, dns_rootname, zone->rdclass,
4528 				    0, 0, 0, 0, 0, buf, &rdata);
4529 	if (result != ISC_R_SUCCESS) {
4530 		dns_zone_log(zone, ISC_LOG_ERROR,
4531 			     "add_soa:dns_soa_buildrdata -> %s",
4532 			     dns_result_totext(result));
4533 		goto failure;
4534 	}
4535 
4536 	result = update_one_rr(db, ver, &diff, DNS_DIFFOP_ADD, &zone->origin, 0,
4537 			       &rdata);
4538 
4539 failure:
4540 	dns_diff_clear(&diff);
4541 	if (ver != NULL) {
4542 		dns_db_closeversion(db, &ver, (result == ISC_R_SUCCESS));
4543 	}
4544 
4545 	INSIST(ver == NULL);
4546 
4547 	return (result);
4548 }
4549 
4550 struct addifmissing_arg {
4551 	dns_db_t *db;
4552 	dns_dbversion_t *ver;
4553 	dns_diff_t *diff;
4554 	dns_zone_t *zone;
4555 	bool *changed;
4556 	isc_result_t result;
4557 };
4558 
4559 static void
addifmissing(dns_keytable_t * keytable,dns_keynode_t * keynode,dns_name_t * keyname,void * arg)4560 addifmissing(dns_keytable_t *keytable, dns_keynode_t *keynode,
4561 	     dns_name_t *keyname, void *arg) {
4562 	dns_db_t *db = ((struct addifmissing_arg *)arg)->db;
4563 	dns_dbversion_t *ver = ((struct addifmissing_arg *)arg)->ver;
4564 	dns_diff_t *diff = ((struct addifmissing_arg *)arg)->diff;
4565 	dns_zone_t *zone = ((struct addifmissing_arg *)arg)->zone;
4566 	bool *changed = ((struct addifmissing_arg *)arg)->changed;
4567 	isc_result_t result;
4568 	dns_fixedname_t fname;
4569 
4570 	UNUSED(keytable);
4571 
4572 	if (((struct addifmissing_arg *)arg)->result != ISC_R_SUCCESS) {
4573 		return;
4574 	}
4575 
4576 	if (!dns_keynode_managed(keynode)) {
4577 		return;
4578 	}
4579 
4580 	/*
4581 	 * If the keynode has no trust anchor set, return.
4582 	 */
4583 	if (!dns_keynode_dsset(keynode, NULL)) {
4584 		return;
4585 	}
4586 
4587 	/*
4588 	 * Check whether there's already a KEYDATA entry for this name;
4589 	 * if so, we don't need to add another.
4590 	 */
4591 	dns_fixedname_init(&fname);
4592 	result = dns_db_find(db, keyname, ver, dns_rdatatype_keydata,
4593 			     DNS_DBFIND_NOWILD, 0, NULL,
4594 			     dns_fixedname_name(&fname), NULL, NULL);
4595 	if (result == ISC_R_SUCCESS) {
4596 		return;
4597 	}
4598 
4599 	/*
4600 	 * Create the keydata.
4601 	 */
4602 	result = create_keydata(zone, db, ver, diff, keynode, keyname, changed);
4603 	if (result != ISC_R_SUCCESS && result != ISC_R_NOMORE) {
4604 		((struct addifmissing_arg *)arg)->result = result;
4605 	}
4606 }
4607 
4608 /*
4609  * Synchronize the set of initializing keys found in managed-keys {}
4610  * statements with the set of trust anchors found in the managed-keys.bind
4611  * zone.  If a domain is no longer named in managed-keys, delete all keys
4612  * from that domain from the key zone.	If a domain is configured as an
4613  * initial-key in trust-anchors, but there are no references to it in the
4614  * key zone, load the key zone with the initializing key(s) for that
4615  * domain and schedule a key refresh. If a domain is configured as
4616  * an initial-ds in trust-anchors, fetch the DNSKEY RRset, load the key
4617  * zone with the matching key, and schedule a key refresh.
4618  */
4619 static isc_result_t
sync_keyzone(dns_zone_t * zone,dns_db_t * db)4620 sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
4621 	isc_result_t result = ISC_R_SUCCESS;
4622 	bool changed = false;
4623 	bool commit = false;
4624 	dns_keynode_t *keynode = NULL;
4625 	dns_view_t *view = zone->view;
4626 	dns_keytable_t *sr = NULL;
4627 	dns_dbversion_t *ver = NULL;
4628 	dns_diff_t diff;
4629 	dns_rriterator_t rrit;
4630 	struct addifmissing_arg arg;
4631 
4632 	dns_zone_log(zone, ISC_LOG_DEBUG(1), "synchronizing trusted keys");
4633 
4634 	dns_diff_init(zone->mctx, &diff);
4635 
4636 	CHECK(dns_view_getsecroots(view, &sr));
4637 
4638 	result = dns_db_newversion(db, &ver);
4639 	if (result != ISC_R_SUCCESS) {
4640 		dnssec_log(zone, ISC_LOG_ERROR,
4641 			   "sync_keyzone:dns_db_newversion -> %s",
4642 			   dns_result_totext(result));
4643 		goto failure;
4644 	}
4645 
4646 	/*
4647 	 * Walk the zone DB.  If we find any keys whose names are no longer
4648 	 * in trust-anchors, or which have been changed from initial to static,
4649 	 * (meaning they are permanent and not RFC5011-maintained), delete
4650 	 * them from the zone.  Otherwise call load_secroots(), which
4651 	 * loads keys into secroots as appropriate.
4652 	 */
4653 	dns_rriterator_init(&rrit, db, ver, 0);
4654 	for (result = dns_rriterator_first(&rrit); result == ISC_R_SUCCESS;
4655 	     result = dns_rriterator_nextrrset(&rrit))
4656 	{
4657 		dns_rdataset_t *rdataset = NULL;
4658 		dns_rdata_t rdata = DNS_RDATA_INIT;
4659 		dns_rdata_keydata_t keydata;
4660 		isc_stdtime_t now;
4661 		bool load = true;
4662 		dns_name_t *rrname = NULL;
4663 		uint32_t ttl;
4664 
4665 		isc_stdtime_get(&now);
4666 
4667 		dns_rriterator_current(&rrit, &rrname, &ttl, &rdataset, NULL);
4668 		if (!dns_rdataset_isassociated(rdataset)) {
4669 			dns_rriterator_destroy(&rrit);
4670 			goto failure;
4671 		}
4672 
4673 		if (rdataset->type != dns_rdatatype_keydata) {
4674 			continue;
4675 		}
4676 
4677 		/*
4678 		 * The managed-keys zone can contain a placeholder instead of
4679 		 * legitimate data, in which case we will not use it, and we
4680 		 * will try to refresh it.
4681 		 */
4682 		for (result = dns_rdataset_first(rdataset);
4683 		     result == ISC_R_SUCCESS;
4684 		     result = dns_rdataset_next(rdataset))
4685 		{
4686 			isc_result_t iresult;
4687 
4688 			dns_rdata_reset(&rdata);
4689 			dns_rdataset_current(rdataset, &rdata);
4690 
4691 			iresult = dns_rdata_tostruct(&rdata, &keydata, NULL);
4692 			/* Do we have a valid placeholder KEYDATA record? */
4693 			if (iresult == ISC_R_SUCCESS && keydata.flags == 0 &&
4694 			    keydata.protocol == 0 && keydata.algorithm == 0)
4695 			{
4696 				set_refreshkeytimer(zone, &keydata, now, true);
4697 				load = false;
4698 			}
4699 		}
4700 
4701 		/*
4702 		 * Release db wrlock to prevent LOR reports against
4703 		 * dns_keytable_forall() call below.
4704 		 */
4705 		dns_rriterator_pause(&rrit);
4706 		result = dns_keytable_find(sr, rrname, &keynode);
4707 		if (result != ISC_R_SUCCESS || !dns_keynode_managed(keynode)) {
4708 			CHECK(delete_keydata(db, ver, &diff, rrname, rdataset));
4709 			changed = true;
4710 		} else if (load) {
4711 			load_secroots(zone, rrname, rdataset);
4712 		}
4713 
4714 		if (keynode != NULL) {
4715 			dns_keytable_detachkeynode(sr, &keynode);
4716 		}
4717 	}
4718 	dns_rriterator_destroy(&rrit);
4719 
4720 	/*
4721 	 * Walk secroots to find any initial keys that aren't in
4722 	 * the zone.  If we find any, add them to the zone directly.
4723 	 * If any DS-style initial keys are found, refresh the key
4724 	 * zone so that they'll be looked up.
4725 	 */
4726 	arg.db = db;
4727 	arg.ver = ver;
4728 	arg.result = ISC_R_SUCCESS;
4729 	arg.diff = &diff;
4730 	arg.zone = zone;
4731 	arg.changed = &changed;
4732 	dns_keytable_forall(sr, addifmissing, &arg);
4733 	result = arg.result;
4734 	if (changed) {
4735 		/* Write changes to journal file. */
4736 		CHECK(update_soa_serial(zone, db, ver, &diff, zone->mctx,
4737 					zone->updatemethod));
4738 		CHECK(zone_journal(zone, &diff, NULL, "sync_keyzone"));
4739 
4740 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
4741 		zone_needdump(zone, 30);
4742 		commit = true;
4743 	}
4744 
4745 failure:
4746 	if (result != ISC_R_SUCCESS) {
4747 		dnssec_log(zone, ISC_LOG_ERROR,
4748 			   "unable to synchronize managed keys: %s",
4749 			   dns_result_totext(result));
4750 		isc_time_settoepoch(&zone->refreshkeytime);
4751 	}
4752 	if (keynode != NULL) {
4753 		dns_keytable_detachkeynode(sr, &keynode);
4754 	}
4755 	if (sr != NULL) {
4756 		dns_keytable_detach(&sr);
4757 	}
4758 	if (ver != NULL) {
4759 		dns_db_closeversion(db, &ver, commit);
4760 	}
4761 	dns_diff_clear(&diff);
4762 
4763 	INSIST(ver == NULL);
4764 
4765 	return (result);
4766 }
4767 
4768 isc_result_t
dns_zone_synckeyzone(dns_zone_t * zone)4769 dns_zone_synckeyzone(dns_zone_t *zone) {
4770 	isc_result_t result;
4771 	dns_db_t *db = NULL;
4772 
4773 	if (zone->type != dns_zone_key) {
4774 		return (DNS_R_BADZONE);
4775 	}
4776 
4777 	CHECK(dns_zone_getdb(zone, &db));
4778 
4779 	LOCK_ZONE(zone);
4780 	result = sync_keyzone(zone, db);
4781 	UNLOCK_ZONE(zone);
4782 
4783 failure:
4784 	if (db != NULL) {
4785 		dns_db_detach(&db);
4786 	}
4787 	return (result);
4788 }
4789 
4790 static void
maybe_send_secure(dns_zone_t * zone)4791 maybe_send_secure(dns_zone_t *zone) {
4792 	isc_result_t result;
4793 
4794 	/*
4795 	 * We've finished loading, or else failed to load, an inline-signing
4796 	 * 'secure' zone.  We now need information about the status of the
4797 	 * 'raw' zone.  If we failed to load, then we need it to send a
4798 	 * copy of its database; if we succeeded, we need it to send its
4799 	 * serial number so that we can sync with it.  If it has not yet
4800 	 * loaded, we set a flag so that it will send the necessary
4801 	 * information when it has finished loading.
4802 	 */
4803 	if (zone->raw->db != NULL) {
4804 		if (zone->db != NULL) {
4805 			uint32_t serial;
4806 			unsigned int soacount;
4807 
4808 			result = zone_get_from_db(
4809 				zone->raw, zone->raw->db, NULL, &soacount, NULL,
4810 				&serial, NULL, NULL, NULL, NULL, NULL);
4811 			if (result == ISC_R_SUCCESS && soacount > 0U) {
4812 				zone_send_secureserial(zone->raw, serial);
4813 			}
4814 		} else {
4815 			zone_send_securedb(zone->raw, zone->raw->db);
4816 		}
4817 	} else {
4818 		DNS_ZONE_SETFLAG(zone->raw, DNS_ZONEFLG_SENDSECURE);
4819 	}
4820 }
4821 
4822 static bool
zone_unchanged(dns_db_t * db1,dns_db_t * db2,isc_mem_t * mctx)4823 zone_unchanged(dns_db_t *db1, dns_db_t *db2, isc_mem_t *mctx) {
4824 	isc_result_t result;
4825 	bool answer = false;
4826 	dns_diff_t diff;
4827 
4828 	dns_diff_init(mctx, &diff);
4829 	result = dns_db_diffx(&diff, db1, NULL, db2, NULL, NULL);
4830 	if (result == ISC_R_SUCCESS && ISC_LIST_EMPTY(diff.tuples)) {
4831 		answer = true;
4832 	}
4833 	dns_diff_clear(&diff);
4834 	return (answer);
4835 }
4836 
4837 /*
4838  * The zone is presumed to be locked.
4839  * If this is a inline_raw zone the secure version is also locked.
4840  */
4841 static isc_result_t
zone_postload(dns_zone_t * zone,dns_db_t * db,isc_time_t loadtime,isc_result_t result)4842 zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
4843 	      isc_result_t result) {
4844 	unsigned int soacount = 0;
4845 	unsigned int nscount = 0;
4846 	unsigned int errors = 0;
4847 	uint32_t serial, oldserial, refresh, retry, expire, minimum, soattl;
4848 	isc_time_t now;
4849 	bool needdump = false;
4850 	bool fixjournal = false;
4851 	bool hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE);
4852 	bool nomaster = false;
4853 	bool had_db = false;
4854 	dns_include_t *inc;
4855 	bool is_dynamic = false;
4856 
4857 	INSIST(LOCKED_ZONE(zone));
4858 	if (inline_raw(zone)) {
4859 		INSIST(LOCKED_ZONE(zone->secure));
4860 	}
4861 
4862 	TIME_NOW(&now);
4863 
4864 	/*
4865 	 * Initiate zone transfer?  We may need a error code that
4866 	 * indicates that the "permanent" form does not exist.
4867 	 * XXX better error feedback to log.
4868 	 */
4869 	if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
4870 		if (zone->type == dns_zone_secondary ||
4871 		    zone->type == dns_zone_mirror ||
4872 		    zone->type == dns_zone_stub ||
4873 		    (zone->type == dns_zone_redirect && zone->masters == NULL))
4874 		{
4875 			if (result == ISC_R_FILENOTFOUND) {
4876 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4877 					      ISC_LOG_DEBUG(1),
4878 					      "no master file");
4879 			} else if (result != DNS_R_NOMASTERFILE) {
4880 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4881 					      ISC_LOG_ERROR,
4882 					      "loading from master file %s "
4883 					      "failed: %s",
4884 					      zone->masterfile,
4885 					      dns_result_totext(result));
4886 			}
4887 		} else if (zone->type == dns_zone_primary &&
4888 			   inline_secure(zone) && result == ISC_R_FILENOTFOUND)
4889 		{
4890 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4891 				      ISC_LOG_DEBUG(1),
4892 				      "no master file, requesting db");
4893 			maybe_send_secure(zone);
4894 		} else {
4895 			int level = ISC_LOG_ERROR;
4896 			if (zone->type == dns_zone_key &&
4897 			    result == ISC_R_FILENOTFOUND)
4898 			{
4899 				level = ISC_LOG_DEBUG(1);
4900 			}
4901 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, level,
4902 				      "loading from master file %s failed: %s",
4903 				      zone->masterfile,
4904 				      dns_result_totext(result));
4905 			nomaster = true;
4906 		}
4907 
4908 		if (zone->type != dns_zone_key) {
4909 			goto cleanup;
4910 		}
4911 	}
4912 
4913 	dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(2),
4914 		      "number of nodes in database: %u", dns_db_nodecount(db));
4915 
4916 	if (result == DNS_R_SEENINCLUDE) {
4917 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
4918 	} else {
4919 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
4920 	}
4921 
4922 	/*
4923 	 * If there's no master file for a key zone, then the zone is new:
4924 	 * create an SOA record.  (We do this now, instead of later, so that
4925 	 * if there happens to be a journal file, we can roll forward from
4926 	 * a sane starting point.)
4927 	 */
4928 	if (nomaster && zone->type == dns_zone_key) {
4929 		result = add_soa(zone, db);
4930 		if (result != ISC_R_SUCCESS) {
4931 			goto cleanup;
4932 		}
4933 	}
4934 
4935 	/*
4936 	 * Apply update log, if any, on initial load.
4937 	 */
4938 	if (zone->journal != NULL &&
4939 	    !DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE) &&
4940 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
4941 	{
4942 		result = zone_journal_rollforward(zone, db, &needdump,
4943 						  &fixjournal);
4944 		if (result != ISC_R_SUCCESS) {
4945 			goto cleanup;
4946 		}
4947 	}
4948 
4949 	/*
4950 	 * Obtain ns, soa and cname counts for top of zone.
4951 	 */
4952 	INSIST(db != NULL);
4953 	result = zone_get_from_db(zone, db, &nscount, &soacount, &soattl,
4954 				  &serial, &refresh, &retry, &expire, &minimum,
4955 				  &errors);
4956 	if (result != ISC_R_SUCCESS && zone->type != dns_zone_key) {
4957 		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
4958 			      "could not find NS and/or SOA records");
4959 	}
4960 
4961 	/*
4962 	 * Process any queued NSEC3PARAM change requests. Only for dynamic
4963 	 * zones, an inline-signing zone will perform this action when
4964 	 * receiving the secure db (receive_secure_db).
4965 	 */
4966 	is_dynamic = dns_zone_isdynamic(zone, true);
4967 	if (is_dynamic) {
4968 		isc_event_t *setnsec3param_event;
4969 		dns_zone_t *dummy;
4970 
4971 		while (!ISC_LIST_EMPTY(zone->setnsec3param_queue)) {
4972 			setnsec3param_event =
4973 				ISC_LIST_HEAD(zone->setnsec3param_queue);
4974 			ISC_LIST_UNLINK(zone->setnsec3param_queue,
4975 					setnsec3param_event, ev_link);
4976 			dummy = NULL;
4977 			zone_iattach(zone, &dummy);
4978 			isc_task_send(zone->task, &setnsec3param_event);
4979 		}
4980 	}
4981 
4982 	/*
4983 	 * Check to make sure the journal is up to date, and remove the
4984 	 * journal file if it isn't, as we wouldn't be able to apply
4985 	 * updates otherwise.
4986 	 */
4987 	if (zone->journal != NULL && is_dynamic &&
4988 	    !DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS))
4989 	{
4990 		uint32_t jserial;
4991 		dns_journal_t *journal = NULL;
4992 		bool empty = false;
4993 
4994 		result = dns_journal_open(zone->mctx, zone->journal,
4995 					  DNS_JOURNAL_READ, &journal);
4996 		if (result == ISC_R_SUCCESS) {
4997 			jserial = dns_journal_last_serial(journal);
4998 			empty = dns_journal_empty(journal);
4999 			dns_journal_destroy(&journal);
5000 		} else {
5001 			jserial = serial;
5002 			result = ISC_R_SUCCESS;
5003 		}
5004 
5005 		if (jserial != serial) {
5006 			if (!empty) {
5007 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5008 					      ISC_LOG_INFO,
5009 					      "journal file is out of date: "
5010 					      "removing journal file");
5011 			}
5012 			if (remove(zone->journal) < 0 && errno != ENOENT) {
5013 				char strbuf[ISC_STRERRORSIZE];
5014 				strerror_r(errno, strbuf, sizeof(strbuf));
5015 				isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
5016 					      DNS_LOGMODULE_ZONE,
5017 					      ISC_LOG_WARNING,
5018 					      "unable to remove journal "
5019 					      "'%s': '%s'",
5020 					      zone->journal, strbuf);
5021 			}
5022 		}
5023 	}
5024 
5025 	dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
5026 		      "loaded; checking validity");
5027 
5028 	/*
5029 	 * Master / Slave / Mirror / Stub zones require both NS and SOA records
5030 	 * at the top of the zone.
5031 	 */
5032 
5033 	switch (zone->type) {
5034 	case dns_zone_dlz:
5035 	case dns_zone_primary:
5036 	case dns_zone_secondary:
5037 	case dns_zone_mirror:
5038 	case dns_zone_stub:
5039 	case dns_zone_redirect:
5040 		if (soacount != 1) {
5041 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5042 				      ISC_LOG_ERROR, "has %d SOA records",
5043 				      soacount);
5044 			result = DNS_R_BADZONE;
5045 		}
5046 		if (nscount == 0) {
5047 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5048 				      ISC_LOG_ERROR, "has no NS records");
5049 			result = DNS_R_BADZONE;
5050 		}
5051 		if (result != ISC_R_SUCCESS) {
5052 			goto cleanup;
5053 		}
5054 		if (zone->type == dns_zone_primary && errors != 0) {
5055 			result = DNS_R_BADZONE;
5056 			goto cleanup;
5057 		}
5058 		if (zone->type != dns_zone_stub &&
5059 		    zone->type != dns_zone_redirect)
5060 		{
5061 			result = check_nsec3param(zone, db);
5062 			if (result != ISC_R_SUCCESS) {
5063 				goto cleanup;
5064 			}
5065 		}
5066 		if (zone->type == dns_zone_primary &&
5067 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKINTEGRITY) &&
5068 		    !integrity_checks(zone, db))
5069 		{
5070 			result = DNS_R_BADZONE;
5071 			goto cleanup;
5072 		}
5073 		if (zone->type == dns_zone_primary &&
5074 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRR) &&
5075 		    !zone_check_dup(zone, db))
5076 		{
5077 			result = DNS_R_BADZONE;
5078 			goto cleanup;
5079 		}
5080 
5081 		if (zone->type == dns_zone_primary) {
5082 			result = dns_zone_cdscheck(zone, db, NULL);
5083 			if (result != ISC_R_SUCCESS) {
5084 				dns_zone_log(zone, ISC_LOG_ERROR,
5085 					     "CDS/CDNSKEY consistency checks "
5086 					     "failed");
5087 				goto cleanup;
5088 			}
5089 		}
5090 
5091 		result = dns_zone_verifydb(zone, db, NULL);
5092 		if (result != ISC_R_SUCCESS) {
5093 			goto cleanup;
5094 		}
5095 
5096 		if (zone->db != NULL) {
5097 			unsigned int oldsoacount;
5098 
5099 			/*
5100 			 * This is checked in zone_replacedb() for slave zones
5101 			 * as they don't reload from disk.
5102 			 */
5103 			result = zone_get_from_db(
5104 				zone, zone->db, NULL, &oldsoacount, NULL,
5105 				&oldserial, NULL, NULL, NULL, NULL, NULL);
5106 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
5107 			RUNTIME_CHECK(oldsoacount > 0U);
5108 			if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
5109 			    !isc_serial_gt(serial, oldserial))
5110 			{
5111 				uint32_t serialmin, serialmax;
5112 
5113 				INSIST(zone->type == dns_zone_primary);
5114 				INSIST(zone->raw == NULL);
5115 
5116 				if (serial == oldserial &&
5117 				    zone_unchanged(zone->db, db, zone->mctx))
5118 				{
5119 					dns_zone_logc(zone,
5120 						      DNS_LOGCATEGORY_ZONELOAD,
5121 						      ISC_LOG_INFO,
5122 						      "ixfr-from-differences: "
5123 						      "unchanged");
5124 					zone->loadtime = loadtime;
5125 					goto done;
5126 				}
5127 
5128 				serialmin = (oldserial + 1) & 0xffffffffU;
5129 				serialmax = (oldserial + 0x7fffffffU) &
5130 					    0xffffffffU;
5131 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5132 					      ISC_LOG_ERROR,
5133 					      "ixfr-from-differences: "
5134 					      "new serial (%u) out of range "
5135 					      "[%u - %u]",
5136 					      serial, serialmin, serialmax);
5137 				result = DNS_R_BADZONE;
5138 				goto cleanup;
5139 			} else if (!isc_serial_ge(serial, oldserial)) {
5140 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5141 					      ISC_LOG_ERROR,
5142 					      "zone serial (%u/%u) has gone "
5143 					      "backwards",
5144 					      serial, oldserial);
5145 			} else if (serial == oldserial && !hasinclude &&
5146 				   strcmp(zone->db_argv[0], "_builtin") != 0)
5147 			{
5148 				dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5149 					      ISC_LOG_ERROR,
5150 					      "zone serial (%u) unchanged. "
5151 					      "zone may fail to transfer "
5152 					      "to slaves.",
5153 					      serial);
5154 			}
5155 		}
5156 
5157 		if (zone->type == dns_zone_primary &&
5158 		    (zone->update_acl != NULL || zone->ssutable != NULL) &&
5159 		    dns_zone_getsigresigninginterval(zone) < (3 * refresh) &&
5160 		    dns_db_issecure(db))
5161 		{
5162 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5163 				      ISC_LOG_WARNING,
5164 				      "sig-re-signing-interval less than "
5165 				      "3 * refresh.");
5166 		}
5167 
5168 		zone->refresh = RANGE(refresh, zone->minrefresh,
5169 				      zone->maxrefresh);
5170 		zone->retry = RANGE(retry, zone->minretry, zone->maxretry);
5171 		zone->expire = RANGE(expire, zone->refresh + zone->retry,
5172 				     DNS_MAX_EXPIRE);
5173 		zone->soattl = soattl;
5174 		zone->minimum = minimum;
5175 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
5176 
5177 		if (zone->type == dns_zone_secondary ||
5178 		    zone->type == dns_zone_mirror ||
5179 		    zone->type == dns_zone_stub ||
5180 		    (zone->type == dns_zone_redirect && zone->masters != NULL))
5181 		{
5182 			isc_time_t t;
5183 			uint32_t delay;
5184 
5185 			result = isc_file_getmodtime(zone->journal, &t);
5186 			if (result != ISC_R_SUCCESS) {
5187 				result = isc_file_getmodtime(zone->masterfile,
5188 							     &t);
5189 			}
5190 			if (result == ISC_R_SUCCESS) {
5191 				DNS_ZONE_TIME_ADD(&t, zone->expire,
5192 						  &zone->expiretime);
5193 			} else {
5194 				DNS_ZONE_TIME_ADD(&now, zone->retry,
5195 						  &zone->expiretime);
5196 			}
5197 
5198 			delay = (zone->retry -
5199 				 isc_random_uniform((zone->retry * 3) / 4));
5200 			DNS_ZONE_TIME_ADD(&now, delay, &zone->refreshtime);
5201 			if (isc_time_compare(&zone->refreshtime,
5202 					     &zone->expiretime) >= 0)
5203 			{
5204 				zone->refreshtime = now;
5205 			}
5206 		}
5207 
5208 		break;
5209 
5210 	case dns_zone_key:
5211 		/* Nothing needs to be done now */
5212 		break;
5213 
5214 	default:
5215 		UNEXPECTED_ERROR(__FILE__, __LINE__, "unexpected zone type %d",
5216 				 zone->type);
5217 		result = ISC_R_UNEXPECTED;
5218 		goto cleanup;
5219 	}
5220 
5221 	/*
5222 	 * Check for weak DNSKEY's.
5223 	 */
5224 	if (zone->type == dns_zone_primary) {
5225 		zone_check_dnskeys(zone, db);
5226 	}
5227 
5228 	/*
5229 	 * Schedule DNSSEC key refresh.
5230 	 */
5231 	if (zone->type == dns_zone_primary &&
5232 	    DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
5233 	{
5234 		zone->refreshkeytime = now;
5235 	}
5236 
5237 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
5238 	if (zone->db != NULL) {
5239 		had_db = true;
5240 		result = zone_replacedb(zone, db, false);
5241 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
5242 		if (result != ISC_R_SUCCESS) {
5243 			goto cleanup;
5244 		}
5245 	} else {
5246 		zone_attachdb(zone, db);
5247 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
5248 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED |
5249 					       DNS_ZONEFLG_NEEDSTARTUPNOTIFY);
5250 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SENDSECURE) &&
5251 		    inline_raw(zone))
5252 		{
5253 			if (zone->secure->db == NULL) {
5254 				zone_send_securedb(zone, db);
5255 			} else {
5256 				zone_send_secureserial(zone, serial);
5257 			}
5258 		}
5259 	}
5260 
5261 	/*
5262 	 * Finished loading inline-signing zone; need to get status
5263 	 * from the raw side now.
5264 	 */
5265 	if (zone->type == dns_zone_primary && inline_secure(zone)) {
5266 		maybe_send_secure(zone);
5267 	}
5268 
5269 	result = ISC_R_SUCCESS;
5270 
5271 	if (fixjournal) {
5272 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FIXJOURNAL);
5273 		zone_journal_compact(zone, zone->db, 0);
5274 	}
5275 	if (needdump) {
5276 		if (zone->type == dns_zone_key) {
5277 			zone_needdump(zone, 30);
5278 		} else {
5279 			zone_needdump(zone, DNS_DUMP_DELAY);
5280 		}
5281 	}
5282 
5283 	if (zone->task != NULL) {
5284 		if (zone->type == dns_zone_primary) {
5285 			set_resigntime(zone);
5286 			resume_signingwithkey(zone);
5287 			resume_addnsec3chain(zone);
5288 		}
5289 
5290 		is_dynamic = dns_zone_isdynamic(zone, false);
5291 		if (zone->type == dns_zone_primary &&
5292 		    !DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN) &&
5293 		    is_dynamic && dns_db_issecure(db))
5294 		{
5295 			dns_name_t *name;
5296 			dns_fixedname_t fixed;
5297 			dns_rdataset_t next;
5298 
5299 			dns_rdataset_init(&next);
5300 			name = dns_fixedname_initname(&fixed);
5301 
5302 			result = dns_db_getsigningtime(db, &next, name);
5303 			if (result == ISC_R_SUCCESS) {
5304 				isc_stdtime_t timenow;
5305 				char namebuf[DNS_NAME_FORMATSIZE];
5306 				char typebuf[DNS_RDATATYPE_FORMATSIZE];
5307 
5308 				isc_stdtime_get(&timenow);
5309 				dns_name_format(name, namebuf, sizeof(namebuf));
5310 				dns_rdatatype_format(next.covers, typebuf,
5311 						     sizeof(typebuf));
5312 				dnssec_log(
5313 					zone, ISC_LOG_DEBUG(3),
5314 					"next resign: %s/%s "
5315 					"in %d seconds",
5316 					namebuf, typebuf,
5317 					next.resign - timenow -
5318 						dns_zone_getsigresigninginterval(
5319 							zone));
5320 				dns_rdataset_disassociate(&next);
5321 			} else {
5322 				dnssec_log(zone, ISC_LOG_WARNING,
5323 					   "signed dynamic zone has no "
5324 					   "resign event scheduled");
5325 			}
5326 		}
5327 
5328 		zone_settimer(zone, &now);
5329 	}
5330 
5331 	/*
5332 	 * Clear old include list.
5333 	 */
5334 	for (inc = ISC_LIST_HEAD(zone->includes); inc != NULL;
5335 	     inc = ISC_LIST_HEAD(zone->includes))
5336 	{
5337 		ISC_LIST_UNLINK(zone->includes, inc, link);
5338 		isc_mem_free(zone->mctx, inc->name);
5339 		isc_mem_put(zone->mctx, inc, sizeof(*inc));
5340 	}
5341 	zone->nincludes = 0;
5342 
5343 	/*
5344 	 * Transfer new include list.
5345 	 */
5346 	for (inc = ISC_LIST_HEAD(zone->newincludes); inc != NULL;
5347 	     inc = ISC_LIST_HEAD(zone->newincludes))
5348 	{
5349 		ISC_LIST_UNLINK(zone->newincludes, inc, link);
5350 		ISC_LIST_APPEND(zone->includes, inc, link);
5351 		zone->nincludes++;
5352 	}
5353 
5354 	if (!dns_db_ispersistent(db)) {
5355 		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_INFO,
5356 			      "loaded serial %u%s", serial,
5357 			      dns_db_issecure(db) ? " (DNSSEC signed)" : "");
5358 	}
5359 
5360 	if (!had_db && zone->type == dns_zone_mirror) {
5361 		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_INFO,
5362 			      "mirror zone is now in use");
5363 	}
5364 
5365 	zone->loadtime = loadtime;
5366 	goto done;
5367 
5368 cleanup:
5369 	if (result != ISC_R_SUCCESS) {
5370 		dns_zone_rpz_disable_db(zone, db);
5371 		dns_zone_catz_disable_db(zone, db);
5372 	}
5373 
5374 	for (inc = ISC_LIST_HEAD(zone->newincludes); inc != NULL;
5375 	     inc = ISC_LIST_HEAD(zone->newincludes))
5376 	{
5377 		ISC_LIST_UNLINK(zone->newincludes, inc, link);
5378 		isc_mem_free(zone->mctx, inc->name);
5379 		isc_mem_put(zone->mctx, inc, sizeof(*inc));
5380 	}
5381 	if (zone->type == dns_zone_secondary || zone->type == dns_zone_mirror ||
5382 	    zone->type == dns_zone_stub || zone->type == dns_zone_key ||
5383 	    (zone->type == dns_zone_redirect && zone->masters != NULL))
5384 	{
5385 		if (result != ISC_R_NOMEMORY) {
5386 			if (zone->journal != NULL) {
5387 				zone_saveunique(zone, zone->journal,
5388 						"jn-XXXXXXXX");
5389 			}
5390 			if (zone->masterfile != NULL) {
5391 				zone_saveunique(zone, zone->masterfile,
5392 						"db-XXXXXXXX");
5393 			}
5394 		}
5395 
5396 		/* Mark the zone for immediate refresh. */
5397 		zone->refreshtime = now;
5398 		if (zone->task != NULL) {
5399 			zone_settimer(zone, &now);
5400 		}
5401 		result = ISC_R_SUCCESS;
5402 	} else if (zone->type == dns_zone_primary ||
5403 		   zone->type == dns_zone_redirect)
5404 	{
5405 		if (!(inline_secure(zone) && result == ISC_R_FILENOTFOUND)) {
5406 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5407 				      ISC_LOG_ERROR,
5408 				      "not loaded due to errors.");
5409 		} else if (zone->type == dns_zone_primary) {
5410 			result = ISC_R_SUCCESS;
5411 		}
5412 	}
5413 
5414 done:
5415 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
5416 	/*
5417 	 * If this is an inline-signed zone and we were called for the raw
5418 	 * zone, we need to clear DNS_ZONEFLG_LOADPENDING for the secure zone
5419 	 * as well, but only if this is a reload, not an initial zone load: in
5420 	 * the former case, zone_postload() will not be run for the secure
5421 	 * zone; in the latter case, it will be.  Check which case we are
5422 	 * dealing with by consulting the DNS_ZONEFLG_LOADED flag for the
5423 	 * secure zone: if it is set, this must be a reload.
5424 	 */
5425 	if (inline_raw(zone) && DNS_ZONE_FLAG(zone->secure, DNS_ZONEFLG_LOADED))
5426 	{
5427 		DNS_ZONE_CLRFLAG(zone->secure, DNS_ZONEFLG_LOADPENDING);
5428 		/*
5429 		 * Re-start zone maintenance if it had been stalled
5430 		 * due to DNS_ZONEFLG_LOADPENDING being set when
5431 		 * zone_maintenance was called.
5432 		 */
5433 		if (zone->secure->task != NULL) {
5434 			zone_settimer(zone->secure, &now);
5435 		}
5436 	}
5437 
5438 	zone_debuglog(zone, "zone_postload", 99, "done");
5439 
5440 	return (result);
5441 }
5442 
5443 static bool
exit_check(dns_zone_t * zone)5444 exit_check(dns_zone_t *zone) {
5445 	REQUIRE(LOCKED_ZONE(zone));
5446 
5447 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) &&
5448 	    isc_refcount_current(&zone->irefs) == 0)
5449 	{
5450 		/*
5451 		 * DNS_ZONEFLG_SHUTDOWN can only be set if erefs == 0.
5452 		 */
5453 		INSIST(isc_refcount_current(&zone->erefs) == 0);
5454 		return (true);
5455 	}
5456 	return (false);
5457 }
5458 
5459 static bool
zone_check_ns(dns_zone_t * zone,dns_db_t * db,dns_dbversion_t * version,dns_name_t * name,bool logit)5460 zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
5461 	      dns_name_t *name, bool logit) {
5462 	isc_result_t result;
5463 	char namebuf[DNS_NAME_FORMATSIZE];
5464 	char altbuf[DNS_NAME_FORMATSIZE];
5465 	dns_fixedname_t fixed;
5466 	dns_name_t *foundname;
5467 	int level;
5468 
5469 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOCHECKNS)) {
5470 		return (true);
5471 	}
5472 
5473 	if (zone->type == dns_zone_primary) {
5474 		level = ISC_LOG_ERROR;
5475 	} else {
5476 		level = ISC_LOG_WARNING;
5477 	}
5478 
5479 	foundname = dns_fixedname_initname(&fixed);
5480 
5481 	result = dns_db_find(db, name, version, dns_rdatatype_a, 0, 0, NULL,
5482 			     foundname, NULL, NULL);
5483 	if (result == ISC_R_SUCCESS) {
5484 		return (true);
5485 	}
5486 
5487 	if (result == DNS_R_NXRRSET) {
5488 		result = dns_db_find(db, name, version, dns_rdatatype_aaaa, 0,
5489 				     0, NULL, foundname, NULL, NULL);
5490 		if (result == ISC_R_SUCCESS) {
5491 			return (true);
5492 		}
5493 	}
5494 
5495 	if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
5496 	    result == DNS_R_EMPTYNAME)
5497 	{
5498 		if (logit) {
5499 			dns_name_format(name, namebuf, sizeof namebuf);
5500 			dns_zone_log(zone, level,
5501 				     "NS '%s' has no address "
5502 				     "records (A or AAAA)",
5503 				     namebuf);
5504 		}
5505 		return (false);
5506 	}
5507 
5508 	if (result == DNS_R_CNAME) {
5509 		if (logit) {
5510 			dns_name_format(name, namebuf, sizeof namebuf);
5511 			dns_zone_log(zone, level,
5512 				     "NS '%s' is a CNAME "
5513 				     "(illegal)",
5514 				     namebuf);
5515 		}
5516 		return (false);
5517 	}
5518 
5519 	if (result == DNS_R_DNAME) {
5520 		if (logit) {
5521 			dns_name_format(name, namebuf, sizeof namebuf);
5522 			dns_name_format(foundname, altbuf, sizeof altbuf);
5523 			dns_zone_log(zone, level,
5524 				     "NS '%s' is below a DNAME "
5525 				     "'%s' (illegal)",
5526 				     namebuf, altbuf);
5527 		}
5528 		return (false);
5529 	}
5530 
5531 	return (true);
5532 }
5533 
5534 static isc_result_t
zone_count_ns_rr(dns_zone_t * zone,dns_db_t * db,dns_dbnode_t * node,dns_dbversion_t * version,unsigned int * nscount,unsigned int * errors,bool logit)5535 zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
5536 		 dns_dbversion_t *version, unsigned int *nscount,
5537 		 unsigned int *errors, bool logit) {
5538 	isc_result_t result;
5539 	unsigned int count = 0;
5540 	unsigned int ecount = 0;
5541 	dns_rdataset_t rdataset;
5542 	dns_rdata_t rdata;
5543 	dns_rdata_ns_t ns;
5544 
5545 	dns_rdataset_init(&rdataset);
5546 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns,
5547 				     dns_rdatatype_none, 0, &rdataset, NULL);
5548 	if (result == ISC_R_NOTFOUND) {
5549 		INSIST(!dns_rdataset_isassociated(&rdataset));
5550 		goto success;
5551 	}
5552 	if (result != ISC_R_SUCCESS) {
5553 		INSIST(!dns_rdataset_isassociated(&rdataset));
5554 		goto invalidate_rdataset;
5555 	}
5556 
5557 	result = dns_rdataset_first(&rdataset);
5558 	while (result == ISC_R_SUCCESS) {
5559 		if (errors != NULL && zone->rdclass == dns_rdataclass_in &&
5560 		    (zone->type == dns_zone_primary ||
5561 		     zone->type == dns_zone_secondary ||
5562 		     zone->type == dns_zone_mirror))
5563 		{
5564 			dns_rdata_init(&rdata);
5565 			dns_rdataset_current(&rdataset, &rdata);
5566 			result = dns_rdata_tostruct(&rdata, &ns, NULL);
5567 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
5568 			if (dns_name_issubdomain(&ns.name, &zone->origin) &&
5569 			    !zone_check_ns(zone, db, version, &ns.name, logit))
5570 			{
5571 				ecount++;
5572 			}
5573 		}
5574 		count++;
5575 		result = dns_rdataset_next(&rdataset);
5576 	}
5577 	dns_rdataset_disassociate(&rdataset);
5578 
5579 success:
5580 	if (nscount != NULL) {
5581 		*nscount = count;
5582 	}
5583 	if (errors != NULL) {
5584 		*errors = ecount;
5585 	}
5586 
5587 	result = ISC_R_SUCCESS;
5588 
5589 invalidate_rdataset:
5590 	dns_rdataset_invalidate(&rdataset);
5591 
5592 	return (result);
5593 }
5594 
5595 #define SET_IF_NOT_NULL(obj, val) \
5596 	if (obj != NULL) {        \
5597 		*obj = val;       \
5598 	}
5599 
5600 #define SET_SOA_VALUES(soattl_v, serial_v, refresh_v, retry_v, expire_v, \
5601 		       minimum_v)                                        \
5602 	{                                                                \
5603 		SET_IF_NOT_NULL(soattl, soattl_v);                       \
5604 		SET_IF_NOT_NULL(serial, serial_v);                       \
5605 		SET_IF_NOT_NULL(refresh, refresh_v);                     \
5606 		SET_IF_NOT_NULL(retry, retry_v);                         \
5607 		SET_IF_NOT_NULL(expire, expire_v);                       \
5608 		SET_IF_NOT_NULL(minimum, minimum_v);                     \
5609 	}
5610 
5611 #define CLR_SOA_VALUES()                          \
5612 	{                                         \
5613 		SET_SOA_VALUES(0, 0, 0, 0, 0, 0); \
5614 	}
5615 
5616 static isc_result_t
zone_load_soa_rr(dns_db_t * db,dns_dbnode_t * node,dns_dbversion_t * version,unsigned int * soacount,uint32_t * soattl,uint32_t * serial,uint32_t * refresh,uint32_t * retry,uint32_t * expire,uint32_t * minimum)5617 zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
5618 		 unsigned int *soacount, uint32_t *soattl, uint32_t *serial,
5619 		 uint32_t *refresh, uint32_t *retry, uint32_t *expire,
5620 		 uint32_t *minimum) {
5621 	isc_result_t result;
5622 	unsigned int count = 0;
5623 	dns_rdataset_t rdataset;
5624 	dns_rdata_t rdata = DNS_RDATA_INIT;
5625 
5626 	dns_rdataset_init(&rdataset);
5627 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
5628 				     dns_rdatatype_none, 0, &rdataset, NULL);
5629 	if (result == ISC_R_NOTFOUND) {
5630 		INSIST(!dns_rdataset_isassociated(&rdataset));
5631 		result = ISC_R_SUCCESS;
5632 		goto invalidate_rdataset;
5633 	}
5634 	if (result != ISC_R_SUCCESS) {
5635 		INSIST(!dns_rdataset_isassociated(&rdataset));
5636 		goto invalidate_rdataset;
5637 	}
5638 
5639 	result = dns_rdataset_first(&rdataset);
5640 	while (result == ISC_R_SUCCESS) {
5641 		dns_rdata_init(&rdata);
5642 		dns_rdataset_current(&rdataset, &rdata);
5643 		count++;
5644 		if (count == 1) {
5645 			dns_rdata_soa_t soa;
5646 			result = dns_rdata_tostruct(&rdata, &soa, NULL);
5647 			SET_SOA_VALUES(rdataset.ttl, soa.serial, soa.refresh,
5648 				       soa.retry, soa.expire, soa.minimum);
5649 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
5650 		}
5651 
5652 		result = dns_rdataset_next(&rdataset);
5653 		dns_rdata_reset(&rdata);
5654 	}
5655 	dns_rdataset_disassociate(&rdataset);
5656 
5657 	result = ISC_R_SUCCESS;
5658 
5659 invalidate_rdataset:
5660 	SET_IF_NOT_NULL(soacount, count);
5661 	if (count == 0) {
5662 		CLR_SOA_VALUES();
5663 	}
5664 
5665 	dns_rdataset_invalidate(&rdataset);
5666 
5667 	return (result);
5668 }
5669 
5670 /*
5671  * zone must be locked.
5672  */
5673 static isc_result_t
zone_get_from_db(dns_zone_t * zone,dns_db_t * db,unsigned int * nscount,unsigned int * soacount,uint32_t * soattl,uint32_t * serial,uint32_t * refresh,uint32_t * retry,uint32_t * expire,uint32_t * minimum,unsigned int * errors)5674 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
5675 		 unsigned int *soacount, uint32_t *soattl, uint32_t *serial,
5676 		 uint32_t *refresh, uint32_t *retry, uint32_t *expire,
5677 		 uint32_t *minimum, unsigned int *errors) {
5678 	isc_result_t result;
5679 	isc_result_t answer = ISC_R_SUCCESS;
5680 	dns_dbversion_t *version = NULL;
5681 	dns_dbnode_t *node;
5682 
5683 	REQUIRE(db != NULL);
5684 	REQUIRE(zone != NULL);
5685 
5686 	dns_db_currentversion(db, &version);
5687 
5688 	SET_IF_NOT_NULL(nscount, 0);
5689 	SET_IF_NOT_NULL(soacount, 0);
5690 	SET_IF_NOT_NULL(errors, 0);
5691 	CLR_SOA_VALUES();
5692 
5693 	node = NULL;
5694 	result = dns_db_findnode(db, &zone->origin, false, &node);
5695 	if (result != ISC_R_SUCCESS) {
5696 		answer = result;
5697 		goto closeversion;
5698 	}
5699 
5700 	if (nscount != NULL || errors != NULL) {
5701 		result = zone_count_ns_rr(zone, db, node, version, nscount,
5702 					  errors, true);
5703 		if (result != ISC_R_SUCCESS) {
5704 			answer = result;
5705 		}
5706 	}
5707 
5708 	if (soacount != NULL || soattl != NULL || serial != NULL ||
5709 	    refresh != NULL || retry != NULL || expire != NULL ||
5710 	    minimum != NULL)
5711 	{
5712 		result = zone_load_soa_rr(db, node, version, soacount, soattl,
5713 					  serial, refresh, retry, expire,
5714 					  minimum);
5715 		if (result != ISC_R_SUCCESS) {
5716 			answer = result;
5717 		}
5718 	}
5719 
5720 	dns_db_detachnode(db, &node);
5721 closeversion:
5722 	dns_db_closeversion(db, &version, false);
5723 
5724 	return (answer);
5725 }
5726 
5727 void
dns_zone_attach(dns_zone_t * source,dns_zone_t ** target)5728 dns_zone_attach(dns_zone_t *source, dns_zone_t **target) {
5729 	REQUIRE(DNS_ZONE_VALID(source));
5730 	REQUIRE(target != NULL && *target == NULL);
5731 	isc_refcount_increment(&source->erefs);
5732 	*target = source;
5733 }
5734 
5735 void
dns_zone_detach(dns_zone_t ** zonep)5736 dns_zone_detach(dns_zone_t **zonep) {
5737 	REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
5738 
5739 	dns_zone_t *zone = *zonep;
5740 	*zonep = NULL;
5741 
5742 	if (isc_refcount_decrement(&zone->erefs) == 1) {
5743 		isc_event_t *ev = &zone->ctlevent;
5744 
5745 		isc_refcount_destroy(&zone->erefs);
5746 
5747 		/*
5748 		 * Stop things being restarted after we cancel them below.
5749 		 */
5750 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
5751 		dns_zone_log(zone, ISC_LOG_DEBUG(1),
5752 			     "final reference detached");
5753 		if (zone->task != NULL) {
5754 			/*
5755 			 * This zone has a task; it can clean
5756 			 * itself up asynchronously.
5757 			 */
5758 			isc_task_send(zone->task, &ev);
5759 			return;
5760 		}
5761 
5762 		/*
5763 		 * This zone is unmanaged; we're probably running in
5764 		 * named-checkzone or a unit test. There's no task,
5765 		 * so we need to free it immediately.
5766 		 *
5767 		 * Unmanaged zones must not have null views; we have no way
5768 		 * of detaching from the view here without causing deadlock
5769 		 * because this code is called with the view already
5770 		 * locked.
5771 		 */
5772 		INSIST(zone->view == NULL);
5773 
5774 		zone_shutdown(zone->task, ev);
5775 		ev = NULL;
5776 	}
5777 }
5778 
5779 void
dns_zone_iattach(dns_zone_t * source,dns_zone_t ** target)5780 dns_zone_iattach(dns_zone_t *source, dns_zone_t **target) {
5781 	REQUIRE(DNS_ZONE_VALID(source));
5782 
5783 	LOCK_ZONE(source);
5784 	zone_iattach(source, target);
5785 	UNLOCK_ZONE(source);
5786 }
5787 
5788 static void
zone_iattach(dns_zone_t * source,dns_zone_t ** target)5789 zone_iattach(dns_zone_t *source, dns_zone_t **target) {
5790 	REQUIRE(DNS_ZONE_VALID(source));
5791 	REQUIRE(LOCKED_ZONE(source));
5792 	REQUIRE(target != NULL && *target == NULL);
5793 	INSIST(isc_refcount_increment0(&source->irefs) +
5794 		       isc_refcount_current(&source->erefs) >
5795 	       0);
5796 	*target = source;
5797 }
5798 
5799 static void
zone_idetach(dns_zone_t ** zonep)5800 zone_idetach(dns_zone_t **zonep) {
5801 	dns_zone_t *zone;
5802 
5803 	/*
5804 	 * 'zone' locked by caller.
5805 	 */
5806 	REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
5807 	REQUIRE(LOCKED_ZONE(*zonep));
5808 
5809 	zone = *zonep;
5810 	*zonep = NULL;
5811 
5812 	INSIST(isc_refcount_decrement(&zone->irefs) - 1 +
5813 		       isc_refcount_current(&zone->erefs) >
5814 	       0);
5815 }
5816 
5817 void
dns_zone_idetach(dns_zone_t ** zonep)5818 dns_zone_idetach(dns_zone_t **zonep) {
5819 	dns_zone_t *zone;
5820 
5821 	REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
5822 
5823 	zone = *zonep;
5824 	*zonep = NULL;
5825 
5826 	if (isc_refcount_decrement(&zone->irefs) == 1) {
5827 		bool free_needed;
5828 		LOCK_ZONE(zone);
5829 		free_needed = exit_check(zone);
5830 		UNLOCK_ZONE(zone);
5831 		if (free_needed) {
5832 			zone_free(zone);
5833 		}
5834 	}
5835 }
5836 
5837 isc_mem_t *
dns_zone_getmctx(dns_zone_t * zone)5838 dns_zone_getmctx(dns_zone_t *zone) {
5839 	REQUIRE(DNS_ZONE_VALID(zone));
5840 
5841 	return (zone->mctx);
5842 }
5843 
5844 dns_zonemgr_t *
dns_zone_getmgr(dns_zone_t * zone)5845 dns_zone_getmgr(dns_zone_t *zone) {
5846 	REQUIRE(DNS_ZONE_VALID(zone));
5847 
5848 	return (zone->zmgr);
5849 }
5850 
5851 void
dns_zone_setkasp(dns_zone_t * zone,dns_kasp_t * kasp)5852 dns_zone_setkasp(dns_zone_t *zone, dns_kasp_t *kasp) {
5853 	REQUIRE(DNS_ZONE_VALID(zone));
5854 
5855 	LOCK_ZONE(zone);
5856 	if (zone->kasp != NULL) {
5857 		dns_kasp_detach(&zone->kasp);
5858 	}
5859 	if (kasp != NULL) {
5860 		dns_kasp_attach(kasp, &zone->kasp);
5861 	}
5862 	UNLOCK_ZONE(zone);
5863 }
5864 
5865 dns_kasp_t *
dns_zone_getkasp(dns_zone_t * zone)5866 dns_zone_getkasp(dns_zone_t *zone) {
5867 	REQUIRE(DNS_ZONE_VALID(zone));
5868 
5869 	return (zone->kasp);
5870 }
5871 
5872 void
dns_zone_setoption(dns_zone_t * zone,dns_zoneopt_t option,bool value)5873 dns_zone_setoption(dns_zone_t *zone, dns_zoneopt_t option, bool value) {
5874 	REQUIRE(DNS_ZONE_VALID(zone));
5875 
5876 	if (value) {
5877 		DNS_ZONE_SETOPTION(zone, option);
5878 	} else {
5879 		DNS_ZONE_CLROPTION(zone, option);
5880 	}
5881 }
5882 
5883 dns_zoneopt_t
dns_zone_getoptions(dns_zone_t * zone)5884 dns_zone_getoptions(dns_zone_t *zone) {
5885 	REQUIRE(DNS_ZONE_VALID(zone));
5886 
5887 	return (atomic_load_relaxed(&zone->options));
5888 }
5889 
5890 void
dns_zone_setkeyopt(dns_zone_t * zone,unsigned int keyopt,bool value)5891 dns_zone_setkeyopt(dns_zone_t *zone, unsigned int keyopt, bool value) {
5892 	REQUIRE(DNS_ZONE_VALID(zone));
5893 
5894 	if (value) {
5895 		DNS_ZONEKEY_SETOPTION(zone, keyopt);
5896 	} else {
5897 		DNS_ZONEKEY_CLROPTION(zone, keyopt);
5898 	}
5899 }
5900 
5901 unsigned int
dns_zone_getkeyopts(dns_zone_t * zone)5902 dns_zone_getkeyopts(dns_zone_t *zone) {
5903 	REQUIRE(DNS_ZONE_VALID(zone));
5904 
5905 	return (atomic_load_relaxed(&zone->keyopts));
5906 }
5907 
5908 isc_result_t
dns_zone_setxfrsource4(dns_zone_t * zone,const isc_sockaddr_t * xfrsource)5909 dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
5910 	REQUIRE(DNS_ZONE_VALID(zone));
5911 
5912 	LOCK_ZONE(zone);
5913 	zone->xfrsource4 = *xfrsource;
5914 	UNLOCK_ZONE(zone);
5915 
5916 	return (ISC_R_SUCCESS);
5917 }
5918 
5919 isc_sockaddr_t *
dns_zone_getxfrsource4(dns_zone_t * zone)5920 dns_zone_getxfrsource4(dns_zone_t *zone) {
5921 	REQUIRE(DNS_ZONE_VALID(zone));
5922 	return (&zone->xfrsource4);
5923 }
5924 
5925 isc_result_t
dns_zone_setxfrsource4dscp(dns_zone_t * zone,isc_dscp_t dscp)5926 dns_zone_setxfrsource4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5927 	REQUIRE(DNS_ZONE_VALID(zone));
5928 
5929 	LOCK_ZONE(zone);
5930 	zone->xfrsource4dscp = dscp;
5931 	UNLOCK_ZONE(zone);
5932 
5933 	return (ISC_R_SUCCESS);
5934 }
5935 
5936 isc_dscp_t
dns_zone_getxfrsource4dscp(dns_zone_t * zone)5937 dns_zone_getxfrsource4dscp(dns_zone_t *zone) {
5938 	REQUIRE(DNS_ZONE_VALID(zone));
5939 	return (zone->xfrsource4dscp);
5940 }
5941 
5942 isc_result_t
dns_zone_setxfrsource6(dns_zone_t * zone,const isc_sockaddr_t * xfrsource)5943 dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
5944 	REQUIRE(DNS_ZONE_VALID(zone));
5945 
5946 	LOCK_ZONE(zone);
5947 	zone->xfrsource6 = *xfrsource;
5948 	UNLOCK_ZONE(zone);
5949 
5950 	return (ISC_R_SUCCESS);
5951 }
5952 
5953 isc_sockaddr_t *
dns_zone_getxfrsource6(dns_zone_t * zone)5954 dns_zone_getxfrsource6(dns_zone_t *zone) {
5955 	REQUIRE(DNS_ZONE_VALID(zone));
5956 	return (&zone->xfrsource6);
5957 }
5958 
5959 isc_dscp_t
dns_zone_getxfrsource6dscp(dns_zone_t * zone)5960 dns_zone_getxfrsource6dscp(dns_zone_t *zone) {
5961 	REQUIRE(DNS_ZONE_VALID(zone));
5962 	return (zone->xfrsource6dscp);
5963 }
5964 
5965 isc_result_t
dns_zone_setxfrsource6dscp(dns_zone_t * zone,isc_dscp_t dscp)5966 dns_zone_setxfrsource6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5967 	REQUIRE(DNS_ZONE_VALID(zone));
5968 
5969 	LOCK_ZONE(zone);
5970 	zone->xfrsource6dscp = dscp;
5971 	UNLOCK_ZONE(zone);
5972 
5973 	return (ISC_R_SUCCESS);
5974 }
5975 
5976 isc_result_t
dns_zone_setaltxfrsource4(dns_zone_t * zone,const isc_sockaddr_t * altxfrsource)5977 dns_zone_setaltxfrsource4(dns_zone_t *zone,
5978 			  const isc_sockaddr_t *altxfrsource) {
5979 	REQUIRE(DNS_ZONE_VALID(zone));
5980 
5981 	LOCK_ZONE(zone);
5982 	zone->altxfrsource4 = *altxfrsource;
5983 	UNLOCK_ZONE(zone);
5984 
5985 	return (ISC_R_SUCCESS);
5986 }
5987 
5988 isc_sockaddr_t *
dns_zone_getaltxfrsource4(dns_zone_t * zone)5989 dns_zone_getaltxfrsource4(dns_zone_t *zone) {
5990 	REQUIRE(DNS_ZONE_VALID(zone));
5991 	return (&zone->altxfrsource4);
5992 }
5993 
5994 isc_result_t
dns_zone_setaltxfrsource4dscp(dns_zone_t * zone,isc_dscp_t dscp)5995 dns_zone_setaltxfrsource4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5996 	REQUIRE(DNS_ZONE_VALID(zone));
5997 
5998 	LOCK_ZONE(zone);
5999 	zone->altxfrsource4dscp = dscp;
6000 	UNLOCK_ZONE(zone);
6001 
6002 	return (ISC_R_SUCCESS);
6003 }
6004 
6005 isc_dscp_t
dns_zone_getaltxfrsource4dscp(dns_zone_t * zone)6006 dns_zone_getaltxfrsource4dscp(dns_zone_t *zone) {
6007 	REQUIRE(DNS_ZONE_VALID(zone));
6008 	return (zone->altxfrsource4dscp);
6009 }
6010 
6011 isc_result_t
dns_zone_setaltxfrsource6(dns_zone_t * zone,const isc_sockaddr_t * altxfrsource)6012 dns_zone_setaltxfrsource6(dns_zone_t *zone,
6013 			  const isc_sockaddr_t *altxfrsource) {
6014 	REQUIRE(DNS_ZONE_VALID(zone));
6015 
6016 	LOCK_ZONE(zone);
6017 	zone->altxfrsource6 = *altxfrsource;
6018 	UNLOCK_ZONE(zone);
6019 
6020 	return (ISC_R_SUCCESS);
6021 }
6022 
6023 isc_sockaddr_t *
dns_zone_getaltxfrsource6(dns_zone_t * zone)6024 dns_zone_getaltxfrsource6(dns_zone_t *zone) {
6025 	REQUIRE(DNS_ZONE_VALID(zone));
6026 	return (&zone->altxfrsource6);
6027 }
6028 
6029 isc_result_t
dns_zone_setaltxfrsource6dscp(dns_zone_t * zone,isc_dscp_t dscp)6030 dns_zone_setaltxfrsource6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
6031 	REQUIRE(DNS_ZONE_VALID(zone));
6032 
6033 	LOCK_ZONE(zone);
6034 	zone->altxfrsource6dscp = dscp;
6035 	UNLOCK_ZONE(zone);
6036 
6037 	return (ISC_R_SUCCESS);
6038 }
6039 
6040 isc_dscp_t
dns_zone_getaltxfrsource6dscp(dns_zone_t * zone)6041 dns_zone_getaltxfrsource6dscp(dns_zone_t *zone) {
6042 	REQUIRE(DNS_ZONE_VALID(zone));
6043 	return (zone->altxfrsource6dscp);
6044 }
6045 
6046 isc_result_t
dns_zone_setparentalsrc4(dns_zone_t * zone,const isc_sockaddr_t * parentalsrc)6047 dns_zone_setparentalsrc4(dns_zone_t *zone, const isc_sockaddr_t *parentalsrc) {
6048 	REQUIRE(DNS_ZONE_VALID(zone));
6049 
6050 	LOCK_ZONE(zone);
6051 	zone->parentalsrc4 = *parentalsrc;
6052 	UNLOCK_ZONE(zone);
6053 
6054 	return (ISC_R_SUCCESS);
6055 }
6056 
6057 isc_sockaddr_t *
dns_zone_getparentalsrc4(dns_zone_t * zone)6058 dns_zone_getparentalsrc4(dns_zone_t *zone) {
6059 	REQUIRE(DNS_ZONE_VALID(zone));
6060 	return (&zone->parentalsrc4);
6061 }
6062 
6063 isc_result_t
dns_zone_setparentalsrc4dscp(dns_zone_t * zone,isc_dscp_t dscp)6064 dns_zone_setparentalsrc4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
6065 	REQUIRE(DNS_ZONE_VALID(zone));
6066 
6067 	LOCK_ZONE(zone);
6068 	zone->parentalsrc4dscp = dscp;
6069 	UNLOCK_ZONE(zone);
6070 
6071 	return (ISC_R_SUCCESS);
6072 }
6073 
6074 isc_dscp_t
dns_zone_getparentalsrc4dscp(dns_zone_t * zone)6075 dns_zone_getparentalsrc4dscp(dns_zone_t *zone) {
6076 	REQUIRE(DNS_ZONE_VALID(zone));
6077 	return (zone->parentalsrc4dscp);
6078 }
6079 
6080 isc_result_t
dns_zone_setparentalsrc6(dns_zone_t * zone,const isc_sockaddr_t * parentalsrc)6081 dns_zone_setparentalsrc6(dns_zone_t *zone, const isc_sockaddr_t *parentalsrc) {
6082 	REQUIRE(DNS_ZONE_VALID(zone));
6083 
6084 	LOCK_ZONE(zone);
6085 	zone->parentalsrc6 = *parentalsrc;
6086 	UNLOCK_ZONE(zone);
6087 
6088 	return (ISC_R_SUCCESS);
6089 }
6090 
6091 isc_sockaddr_t *
dns_zone_getparentalsrc6(dns_zone_t * zone)6092 dns_zone_getparentalsrc6(dns_zone_t *zone) {
6093 	REQUIRE(DNS_ZONE_VALID(zone));
6094 	return (&zone->parentalsrc6);
6095 }
6096 
6097 isc_result_t
dns_zone_setparentalsrc6dscp(dns_zone_t * zone,isc_dscp_t dscp)6098 dns_zone_setparentalsrc6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
6099 	REQUIRE(DNS_ZONE_VALID(zone));
6100 
6101 	LOCK_ZONE(zone);
6102 	zone->parentalsrc6dscp = dscp;
6103 	UNLOCK_ZONE(zone);
6104 
6105 	return (ISC_R_SUCCESS);
6106 }
6107 
6108 isc_dscp_t
dns_zone_getparentalsrc6dscp(dns_zone_t * zone)6109 dns_zone_getparentalsrc6dscp(dns_zone_t *zone) {
6110 	REQUIRE(DNS_ZONE_VALID(zone));
6111 	return (zone->parentalsrc6dscp);
6112 }
6113 
6114 isc_result_t
dns_zone_setnotifysrc4(dns_zone_t * zone,const isc_sockaddr_t * notifysrc)6115 dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
6116 	REQUIRE(DNS_ZONE_VALID(zone));
6117 
6118 	LOCK_ZONE(zone);
6119 	zone->notifysrc4 = *notifysrc;
6120 	UNLOCK_ZONE(zone);
6121 
6122 	return (ISC_R_SUCCESS);
6123 }
6124 
6125 isc_sockaddr_t *
dns_zone_getnotifysrc4(dns_zone_t * zone)6126 dns_zone_getnotifysrc4(dns_zone_t *zone) {
6127 	REQUIRE(DNS_ZONE_VALID(zone));
6128 	return (&zone->notifysrc4);
6129 }
6130 
6131 isc_result_t
dns_zone_setnotifysrc4dscp(dns_zone_t * zone,isc_dscp_t dscp)6132 dns_zone_setnotifysrc4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
6133 	REQUIRE(DNS_ZONE_VALID(zone));
6134 
6135 	LOCK_ZONE(zone);
6136 	zone->notifysrc4dscp = dscp;
6137 	UNLOCK_ZONE(zone);
6138 
6139 	return (ISC_R_SUCCESS);
6140 }
6141 
6142 isc_dscp_t
dns_zone_getnotifysrc4dscp(dns_zone_t * zone)6143 dns_zone_getnotifysrc4dscp(dns_zone_t *zone) {
6144 	REQUIRE(DNS_ZONE_VALID(zone));
6145 	return (zone->notifysrc4dscp);
6146 }
6147 
6148 isc_result_t
dns_zone_setnotifysrc6(dns_zone_t * zone,const isc_sockaddr_t * notifysrc)6149 dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
6150 	REQUIRE(DNS_ZONE_VALID(zone));
6151 
6152 	LOCK_ZONE(zone);
6153 	zone->notifysrc6 = *notifysrc;
6154 	UNLOCK_ZONE(zone);
6155 
6156 	return (ISC_R_SUCCESS);
6157 }
6158 
6159 isc_sockaddr_t *
dns_zone_getnotifysrc6(dns_zone_t * zone)6160 dns_zone_getnotifysrc6(dns_zone_t *zone) {
6161 	REQUIRE(DNS_ZONE_VALID(zone));
6162 	return (&zone->notifysrc6);
6163 }
6164 
6165 isc_result_t
dns_zone_setnotifysrc6dscp(dns_zone_t * zone,isc_dscp_t dscp)6166 dns_zone_setnotifysrc6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
6167 	REQUIRE(DNS_ZONE_VALID(zone));
6168 
6169 	LOCK_ZONE(zone);
6170 	zone->notifysrc6dscp = dscp;
6171 	UNLOCK_ZONE(zone);
6172 
6173 	return (ISC_R_SUCCESS);
6174 }
6175 
6176 isc_dscp_t
dns_zone_getnotifysrc6dscp(dns_zone_t * zone)6177 dns_zone_getnotifysrc6dscp(dns_zone_t *zone) {
6178 	REQUIRE(DNS_ZONE_VALID(zone));
6179 	return (zone->notifysrc6dscp);
6180 }
6181 
6182 static bool
same_addrs(isc_sockaddr_t const * oldlist,isc_sockaddr_t const * newlist,uint32_t count)6183 same_addrs(isc_sockaddr_t const *oldlist, isc_sockaddr_t const *newlist,
6184 	   uint32_t count) {
6185 	unsigned int i;
6186 
6187 	for (i = 0; i < count; i++) {
6188 		if (!isc_sockaddr_equal(&oldlist[i], &newlist[i])) {
6189 			return (false);
6190 		}
6191 	}
6192 	return (true);
6193 }
6194 
6195 static bool
same_keynames(dns_name_t * const * oldlist,dns_name_t * const * newlist,uint32_t count)6196 same_keynames(dns_name_t *const *oldlist, dns_name_t *const *newlist,
6197 	      uint32_t count) {
6198 	unsigned int i;
6199 
6200 	if (oldlist == NULL && newlist == NULL) {
6201 		return (true);
6202 	}
6203 	if (oldlist == NULL || newlist == NULL) {
6204 		return (false);
6205 	}
6206 
6207 	for (i = 0; i < count; i++) {
6208 		if (oldlist[i] == NULL && newlist[i] == NULL) {
6209 			continue;
6210 		}
6211 		if (oldlist[i] == NULL || newlist[i] == NULL ||
6212 		    !dns_name_equal(oldlist[i], newlist[i]))
6213 		{
6214 			return (false);
6215 		}
6216 	}
6217 	return (true);
6218 }
6219 
6220 static void
clear_serverslist(isc_sockaddr_t ** addrsp,isc_dscp_t ** dscpsp,dns_name_t *** keynamesp,unsigned int * countp,isc_mem_t * mctx)6221 clear_serverslist(isc_sockaddr_t **addrsp, isc_dscp_t **dscpsp,
6222 		  dns_name_t ***keynamesp, unsigned int *countp,
6223 		  isc_mem_t *mctx) {
6224 	unsigned int count;
6225 	isc_sockaddr_t *addrs;
6226 	isc_dscp_t *dscps;
6227 	dns_name_t **keynames;
6228 
6229 	REQUIRE(countp != NULL && addrsp != NULL && dscpsp != NULL &&
6230 		keynamesp != NULL);
6231 
6232 	count = *countp;
6233 	*countp = 0;
6234 	addrs = *addrsp;
6235 	*addrsp = NULL;
6236 	dscps = *dscpsp;
6237 	*dscpsp = NULL;
6238 	keynames = *keynamesp;
6239 	*keynamesp = NULL;
6240 
6241 	if (addrs != NULL) {
6242 		isc_mem_put(mctx, addrs, count * sizeof(isc_sockaddr_t));
6243 	}
6244 
6245 	if (dscps != NULL) {
6246 		isc_mem_put(mctx, dscps, count * sizeof(isc_dscp_t));
6247 	}
6248 
6249 	if (keynames != NULL) {
6250 		unsigned int i;
6251 		for (i = 0; i < count; i++) {
6252 			if (keynames[i] != NULL) {
6253 				dns_name_free(keynames[i], mctx);
6254 				isc_mem_put(mctx, keynames[i],
6255 					    sizeof(dns_name_t));
6256 				keynames[i] = NULL;
6257 			}
6258 		}
6259 		isc_mem_put(mctx, keynames, count * sizeof(dns_name_t *));
6260 	}
6261 }
6262 
6263 static isc_result_t
set_serverslist(unsigned int count,const isc_sockaddr_t * addrs,isc_sockaddr_t ** newaddrsp,const isc_dscp_t * dscp,isc_dscp_t ** newdscpp,dns_name_t ** names,dns_name_t *** newnamesp,isc_mem_t * mctx)6264 set_serverslist(unsigned int count, const isc_sockaddr_t *addrs,
6265 		isc_sockaddr_t **newaddrsp, const isc_dscp_t *dscp,
6266 		isc_dscp_t **newdscpp, dns_name_t **names,
6267 		dns_name_t ***newnamesp, isc_mem_t *mctx) {
6268 	isc_sockaddr_t *newaddrs = NULL;
6269 	isc_dscp_t *newdscp = NULL;
6270 	dns_name_t **newnames = NULL;
6271 	unsigned int i;
6272 
6273 	REQUIRE(newaddrsp != NULL && *newaddrsp == NULL);
6274 	REQUIRE(newdscpp != NULL && *newdscpp == NULL);
6275 	REQUIRE(newnamesp != NULL && *newnamesp == NULL);
6276 
6277 	newaddrs = isc_mem_get(mctx, count * sizeof(*newaddrs));
6278 	memmove(newaddrs, addrs, count * sizeof(*newaddrs));
6279 
6280 	if (dscp != NULL) {
6281 		newdscp = isc_mem_get(mctx, count * sizeof(*newdscp));
6282 		memmove(newdscp, dscp, count * sizeof(*newdscp));
6283 	} else {
6284 		newdscp = NULL;
6285 	}
6286 
6287 	if (names != NULL) {
6288 		newnames = isc_mem_get(mctx, count * sizeof(*newnames));
6289 		for (i = 0; i < count; i++) {
6290 			newnames[i] = NULL;
6291 		}
6292 		for (i = 0; i < count; i++) {
6293 			if (names[i] != NULL) {
6294 				newnames[i] = isc_mem_get(mctx,
6295 							  sizeof(dns_name_t));
6296 				dns_name_init(newnames[i], NULL);
6297 				dns_name_dup(names[i], mctx, newnames[i]);
6298 			}
6299 		}
6300 	} else {
6301 		newnames = NULL;
6302 	}
6303 
6304 	*newdscpp = newdscp;
6305 	*newaddrsp = newaddrs;
6306 	*newnamesp = newnames;
6307 	return (ISC_R_SUCCESS);
6308 }
6309 
6310 isc_result_t
dns_zone_setalsonotify(dns_zone_t * zone,const isc_sockaddr_t * notify,uint32_t count)6311 dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify,
6312 		       uint32_t count) {
6313 	return (dns_zone_setalsonotifydscpkeys(zone, notify, NULL, NULL,
6314 					       count));
6315 }
6316 
6317 isc_result_t
dns_zone_setalsonotifywithkeys(dns_zone_t * zone,const isc_sockaddr_t * notify,dns_name_t ** keynames,uint32_t count)6318 dns_zone_setalsonotifywithkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
6319 			       dns_name_t **keynames, uint32_t count) {
6320 	return (dns_zone_setalsonotifydscpkeys(zone, notify, NULL, keynames,
6321 					       count));
6322 }
6323 
6324 isc_result_t
dns_zone_setalsonotifydscpkeys(dns_zone_t * zone,const isc_sockaddr_t * notify,const isc_dscp_t * dscps,dns_name_t ** keynames,uint32_t count)6325 dns_zone_setalsonotifydscpkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
6326 			       const isc_dscp_t *dscps, dns_name_t **keynames,
6327 			       uint32_t count) {
6328 	isc_result_t result;
6329 	isc_sockaddr_t *newaddrs = NULL;
6330 	isc_dscp_t *newdscps = NULL;
6331 	dns_name_t **newnames = NULL;
6332 
6333 	REQUIRE(DNS_ZONE_VALID(zone));
6334 	REQUIRE(count == 0 || notify != NULL);
6335 	if (keynames != NULL) {
6336 		REQUIRE(count != 0);
6337 	}
6338 
6339 	LOCK_ZONE(zone);
6340 
6341 	if (count == zone->notifycnt &&
6342 	    same_addrs(zone->notify, notify, count) &&
6343 	    same_keynames(zone->notifykeynames, keynames, count))
6344 	{
6345 		goto unlock;
6346 	}
6347 
6348 	clear_serverslist(&zone->notify, &zone->notifydscp,
6349 			  &zone->notifykeynames, &zone->notifycnt, zone->mctx);
6350 
6351 	if (count == 0) {
6352 		goto unlock;
6353 	}
6354 
6355 	/*
6356 	 * Set up the notify and notifykey lists
6357 	 */
6358 	result = set_serverslist(count, notify, &newaddrs, dscps, &newdscps,
6359 				 keynames, &newnames, zone->mctx);
6360 	if (result != ISC_R_SUCCESS) {
6361 		goto unlock;
6362 	}
6363 
6364 	/*
6365 	 * Everything is ok so attach to the zone.
6366 	 */
6367 	zone->notify = newaddrs;
6368 	zone->notifydscp = newdscps;
6369 	zone->notifykeynames = newnames;
6370 	zone->notifycnt = count;
6371 unlock:
6372 	UNLOCK_ZONE(zone);
6373 	return (ISC_R_SUCCESS);
6374 }
6375 
6376 isc_result_t
dns_zone_setprimaries(dns_zone_t * zone,const isc_sockaddr_t * masters,uint32_t count)6377 dns_zone_setprimaries(dns_zone_t *zone, const isc_sockaddr_t *masters,
6378 		      uint32_t count) {
6379 	isc_result_t result;
6380 
6381 	result = dns_zone_setprimarieswithkeys(zone, masters, NULL, count);
6382 	return (result);
6383 }
6384 
6385 isc_result_t
dns_zone_setprimarieswithkeys(dns_zone_t * zone,const isc_sockaddr_t * masters,dns_name_t ** keynames,uint32_t count)6386 dns_zone_setprimarieswithkeys(dns_zone_t *zone, const isc_sockaddr_t *masters,
6387 			      dns_name_t **keynames, uint32_t count) {
6388 	isc_result_t result = ISC_R_SUCCESS;
6389 	isc_sockaddr_t *newaddrs = NULL;
6390 	isc_dscp_t *newdscps = NULL;
6391 	dns_name_t **newnames = NULL;
6392 	bool *newok;
6393 	unsigned int i;
6394 
6395 	REQUIRE(DNS_ZONE_VALID(zone));
6396 	REQUIRE(count == 0 || masters != NULL);
6397 	if (keynames != NULL) {
6398 		REQUIRE(count != 0);
6399 	}
6400 
6401 	LOCK_ZONE(zone);
6402 	/*
6403 	 * The refresh code assumes that 'primaries' wouldn't change under it.
6404 	 * If it will change then kill off any current refresh in progress
6405 	 * and update the primaries info.  If it won't change then we can just
6406 	 * unlock and exit.
6407 	 */
6408 	if (count != zone->masterscnt ||
6409 	    !same_addrs(zone->masters, masters, count) ||
6410 	    !same_keynames(zone->masterkeynames, keynames, count))
6411 	{
6412 		if (zone->request != NULL) {
6413 			dns_request_cancel(zone->request);
6414 		}
6415 	} else {
6416 		goto unlock;
6417 	}
6418 
6419 	/*
6420 	 * This needs to happen before clear_addresskeylist() sets
6421 	 * zone->masterscnt to 0:
6422 	 */
6423 	if (zone->mastersok != NULL) {
6424 		isc_mem_put(zone->mctx, zone->mastersok,
6425 			    zone->masterscnt * sizeof(bool));
6426 		zone->mastersok = NULL;
6427 	}
6428 	clear_serverslist(&zone->masters, &zone->masterdscps,
6429 			  &zone->masterkeynames, &zone->masterscnt, zone->mctx);
6430 	/*
6431 	 * If count == 0, don't allocate any space for masters, mastersok or
6432 	 * keynames so internally, those pointers are NULL if count == 0
6433 	 */
6434 	if (count == 0) {
6435 		goto unlock;
6436 	}
6437 
6438 	/*
6439 	 * mastersok must contain count elements
6440 	 */
6441 	newok = isc_mem_get(zone->mctx, count * sizeof(*newok));
6442 	for (i = 0; i < count; i++) {
6443 		newok[i] = false;
6444 	}
6445 
6446 	/*
6447 	 * Now set up the primaries and primary key lists
6448 	 */
6449 	result = set_serverslist(count, masters, &newaddrs, NULL, &newdscps,
6450 				 keynames, &newnames, zone->mctx);
6451 	INSIST(newdscps == NULL);
6452 	if (result != ISC_R_SUCCESS) {
6453 		isc_mem_put(zone->mctx, newok, count * sizeof(*newok));
6454 		goto unlock;
6455 	}
6456 
6457 	/*
6458 	 * Everything is ok so attach to the zone.
6459 	 */
6460 	zone->curmaster = 0;
6461 	zone->mastersok = newok;
6462 	zone->masters = newaddrs;
6463 	zone->masterdscps = newdscps;
6464 	zone->masterkeynames = newnames;
6465 	zone->masterscnt = count;
6466 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS);
6467 
6468 unlock:
6469 	UNLOCK_ZONE(zone);
6470 	return (result);
6471 }
6472 
6473 isc_result_t
dns_zone_setparentals(dns_zone_t * zone,const isc_sockaddr_t * parentals,dns_name_t ** keynames,uint32_t count)6474 dns_zone_setparentals(dns_zone_t *zone, const isc_sockaddr_t *parentals,
6475 		      dns_name_t **keynames, uint32_t count) {
6476 	isc_result_t result = ISC_R_SUCCESS;
6477 	isc_sockaddr_t *newaddrs = NULL;
6478 	isc_dscp_t *newdscps = NULL;
6479 	dns_name_t **newkeynames = NULL;
6480 
6481 	REQUIRE(DNS_ZONE_VALID(zone));
6482 	REQUIRE(count == 0 || parentals != NULL);
6483 	if (keynames != NULL) {
6484 		REQUIRE(count != 0);
6485 	}
6486 
6487 	LOCK_ZONE(zone);
6488 
6489 	clear_serverslist(&zone->parentals, &zone->parentaldscps,
6490 			  &zone->parentalkeynames, &zone->parentalscnt,
6491 			  zone->mctx);
6492 	/*
6493 	 * If count == 0, don't allocate any space for parentals, or keynames
6494 	 * so internally, those pointers are NULL if count == 0
6495 	 */
6496 	if (count == 0) {
6497 		goto unlock;
6498 	}
6499 
6500 	/*
6501 	 * Now set up the parentals and parental key lists
6502 	 */
6503 	result = set_serverslist(count, parentals, &newaddrs, NULL, &newdscps,
6504 				 keynames, &newkeynames, zone->mctx);
6505 	INSIST(newdscps == NULL);
6506 	if (result != ISC_R_SUCCESS) {
6507 		goto unlock;
6508 	}
6509 
6510 	/*
6511 	 * Everything is ok so attach to the zone.
6512 	 */
6513 	zone->parentals = newaddrs;
6514 	zone->parentaldscps = newdscps;
6515 	zone->parentalkeynames = newkeynames;
6516 	zone->parentalscnt = count;
6517 
6518 	dns_zone_log(zone, ISC_LOG_NOTICE, "checkds: set %u parentals", count);
6519 
6520 unlock:
6521 	UNLOCK_ZONE(zone);
6522 	return (result);
6523 }
6524 
6525 isc_result_t
dns_zone_getdb(dns_zone_t * zone,dns_db_t ** dpb)6526 dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) {
6527 	isc_result_t result = ISC_R_SUCCESS;
6528 
6529 	REQUIRE(DNS_ZONE_VALID(zone));
6530 
6531 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6532 	if (zone->db == NULL) {
6533 		result = DNS_R_NOTLOADED;
6534 	} else {
6535 		dns_db_attach(zone->db, dpb);
6536 	}
6537 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6538 
6539 	return (result);
6540 }
6541 
6542 void
dns_zone_setdb(dns_zone_t * zone,dns_db_t * db)6543 dns_zone_setdb(dns_zone_t *zone, dns_db_t *db) {
6544 	REQUIRE(DNS_ZONE_VALID(zone));
6545 	REQUIRE(zone->type == dns_zone_staticstub);
6546 
6547 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
6548 	REQUIRE(zone->db == NULL);
6549 	dns_db_attach(db, &zone->db);
6550 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
6551 }
6552 
6553 /*
6554  * Coordinates the starting of routine jobs.
6555  */
6556 void
dns_zone_maintenance(dns_zone_t * zone)6557 dns_zone_maintenance(dns_zone_t *zone) {
6558 	const char me[] = "dns_zone_maintenance";
6559 	isc_time_t now;
6560 
6561 	REQUIRE(DNS_ZONE_VALID(zone));
6562 	ENTER;
6563 
6564 	LOCK_ZONE(zone);
6565 	TIME_NOW(&now);
6566 	zone_settimer(zone, &now);
6567 	UNLOCK_ZONE(zone);
6568 }
6569 
6570 static bool
was_dumping(dns_zone_t * zone)6571 was_dumping(dns_zone_t *zone) {
6572 	REQUIRE(LOCKED_ZONE(zone));
6573 
6574 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
6575 		return (true);
6576 	}
6577 
6578 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
6579 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
6580 	isc_time_settoepoch(&zone->dumptime);
6581 	return (false);
6582 }
6583 
6584 /*%
6585  * Find up to 'maxkeys' DNSSEC keys used for signing version 'ver' of database
6586  * 'db' for zone 'zone' in its key directory, then load these keys into 'keys'.
6587  * Only load the public part of a given key if it is not active at timestamp
6588  * 'now'.  Store the number of keys found in 'nkeys'.
6589  */
6590 isc_result_t
dns__zone_findkeys(dns_zone_t * zone,dns_db_t * db,dns_dbversion_t * ver,isc_stdtime_t now,isc_mem_t * mctx,unsigned int maxkeys,dst_key_t ** keys,unsigned int * nkeys)6591 dns__zone_findkeys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
6592 		   isc_stdtime_t now, isc_mem_t *mctx, unsigned int maxkeys,
6593 		   dst_key_t **keys, unsigned int *nkeys) {
6594 	isc_result_t result;
6595 	dns_dbnode_t *node = NULL;
6596 	const char *directory = dns_zone_getkeydirectory(zone);
6597 
6598 	CHECK(dns_db_findnode(db, dns_db_origin(db), false, &node));
6599 	memset(keys, 0, sizeof(*keys) * maxkeys);
6600 
6601 	dns_zone_lock_keyfiles(zone);
6602 
6603 	result = dns_dnssec_findzonekeys(db, ver, node, dns_db_origin(db),
6604 					 directory, now, mctx, maxkeys, keys,
6605 					 nkeys);
6606 
6607 	dns_zone_unlock_keyfiles(zone);
6608 
6609 	if (result == ISC_R_NOTFOUND) {
6610 		result = ISC_R_SUCCESS;
6611 	}
6612 
6613 failure:
6614 
6615 	if (node != NULL) {
6616 		dns_db_detachnode(db, &node);
6617 	}
6618 	return (result);
6619 }
6620 
6621 /*%
6622  * Find DNSSEC keys used for signing zone with dnssec-policy. Load these keys
6623  * into 'keys'. Requires KASP to be locked.
6624  */
6625 isc_result_t
dns_zone_getdnsseckeys(dns_zone_t * zone,dns_db_t * db,dns_dbversion_t * ver,isc_stdtime_t now,dns_dnsseckeylist_t * keys)6626 dns_zone_getdnsseckeys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
6627 		       isc_stdtime_t now, dns_dnsseckeylist_t *keys) {
6628 	isc_result_t result;
6629 	const char *dir = dns_zone_getkeydirectory(zone);
6630 	dns_dbnode_t *node = NULL;
6631 	dns_dnsseckey_t *key, *key_next;
6632 	dns_dnsseckeylist_t dnskeys;
6633 	dns_name_t *origin = dns_zone_getorigin(zone);
6634 	dns_kasp_t *kasp = dns_zone_getkasp(zone);
6635 	dns_rdataset_t keyset;
6636 
6637 	REQUIRE(DNS_ZONE_VALID(zone));
6638 	REQUIRE(kasp != NULL);
6639 
6640 	ISC_LIST_INIT(dnskeys);
6641 
6642 	dns_rdataset_init(&keyset);
6643 
6644 	CHECK(dns_db_findnode(db, origin, false, &node));
6645 
6646 	/* Get keys from private key files. */
6647 	dns_zone_lock_keyfiles(zone);
6648 	result = dns_dnssec_findmatchingkeys(origin, dir, now,
6649 					     dns_zone_getmctx(zone), keys);
6650 	dns_zone_unlock_keyfiles(zone);
6651 
6652 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
6653 		goto failure;
6654 	}
6655 
6656 	/* Get public keys (dnskeys). */
6657 	dns_rdataset_init(&keyset);
6658 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
6659 				     dns_rdatatype_none, 0, &keyset, NULL);
6660 	if (result == ISC_R_SUCCESS) {
6661 		CHECK(dns_dnssec_keylistfromrdataset(
6662 			origin, dir, dns_zone_getmctx(zone), &keyset, NULL,
6663 			NULL, false, false, &dnskeys));
6664 	} else if (result != ISC_R_NOTFOUND) {
6665 		CHECK(result);
6666 	}
6667 
6668 	/* Add new 'dnskeys' to 'keys'. */
6669 	for (dns_dnsseckey_t *k1 = ISC_LIST_HEAD(dnskeys); k1 != NULL;
6670 	     k1 = key_next)
6671 	{
6672 		dns_dnsseckey_t *k2 = NULL;
6673 		key_next = ISC_LIST_NEXT(k1, link);
6674 
6675 		for (k2 = ISC_LIST_HEAD(*keys); k2 != NULL;
6676 		     k2 = ISC_LIST_NEXT(k2, link))
6677 		{
6678 			if (dst_key_compare(k1->key, k2->key)) {
6679 				break;
6680 			}
6681 		}
6682 		/* No match found, add the new key. */
6683 		if (k2 == NULL) {
6684 			ISC_LIST_UNLINK(dnskeys, k1, link);
6685 			ISC_LIST_APPEND(*keys, k1, link);
6686 		}
6687 	}
6688 
6689 failure:
6690 	if (dns_rdataset_isassociated(&keyset)) {
6691 		dns_rdataset_disassociate(&keyset);
6692 	}
6693 	if (node != NULL) {
6694 		dns_db_detachnode(db, &node);
6695 	}
6696 	while (!ISC_LIST_EMPTY(dnskeys)) {
6697 		key = ISC_LIST_HEAD(dnskeys);
6698 		ISC_LIST_UNLINK(dnskeys, key, link);
6699 		dns_dnsseckey_destroy(dns_zone_getmctx(zone), &key);
6700 	}
6701 	return (result);
6702 }
6703 
6704 static isc_result_t
offline(dns_db_t * db,dns_dbversion_t * ver,dns__zonediff_t * zonediff,dns_name_t * name,dns_ttl_t ttl,dns_rdata_t * rdata)6705 offline(dns_db_t *db, dns_dbversion_t *ver, dns__zonediff_t *zonediff,
6706 	dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata) {
6707 	isc_result_t result;
6708 
6709 	if ((rdata->flags & DNS_RDATA_OFFLINE) != 0) {
6710 		return (ISC_R_SUCCESS);
6711 	}
6712 	result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_DELRESIGN,
6713 			       name, ttl, rdata);
6714 	if (result != ISC_R_SUCCESS) {
6715 		return (result);
6716 	}
6717 	rdata->flags |= DNS_RDATA_OFFLINE;
6718 	result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_ADDRESIGN,
6719 			       name, ttl, rdata);
6720 	zonediff->offline = true;
6721 	return (result);
6722 }
6723 
6724 static void
set_key_expiry_warning(dns_zone_t * zone,isc_stdtime_t when,isc_stdtime_t now)6725 set_key_expiry_warning(dns_zone_t *zone, isc_stdtime_t when,
6726 		       isc_stdtime_t now) {
6727 	unsigned int delta;
6728 	char timebuf[80];
6729 
6730 	LOCK_ZONE(zone);
6731 	zone->key_expiry = when;
6732 	if (when <= now) {
6733 		dns_zone_log(zone, ISC_LOG_ERROR,
6734 			     "DNSKEY RRSIG(s) have expired");
6735 		isc_time_settoepoch(&zone->keywarntime);
6736 	} else if (when < now + 7 * 24 * 3600) {
6737 		isc_time_t t;
6738 		isc_time_set(&t, when, 0);
6739 		isc_time_formattimestamp(&t, timebuf, 80);
6740 		dns_zone_log(zone, ISC_LOG_WARNING,
6741 			     "DNSKEY RRSIG(s) will expire within 7 days: %s",
6742 			     timebuf);
6743 		delta = when - now;
6744 		delta--;	    /* loop prevention */
6745 		delta /= 24 * 3600; /* to whole days */
6746 		delta *= 24 * 3600; /* to seconds */
6747 		isc_time_set(&zone->keywarntime, when - delta, 0);
6748 	} else {
6749 		isc_time_set(&zone->keywarntime, when - 7 * 24 * 3600, 0);
6750 		isc_time_formattimestamp(&zone->keywarntime, timebuf, 80);
6751 		dns_zone_log(zone, ISC_LOG_NOTICE, "setting keywarntime to %s",
6752 			     timebuf);
6753 	}
6754 	UNLOCK_ZONE(zone);
6755 }
6756 
6757 /*
6758  * Helper function to del_sigs(). We don't want to delete RRSIGs that
6759  * have no new key.
6760  */
6761 static bool
delsig_ok(dns_rdata_rrsig_t * rrsig_ptr,dst_key_t ** keys,unsigned int nkeys,bool kasp,bool * warn)6762 delsig_ok(dns_rdata_rrsig_t *rrsig_ptr, dst_key_t **keys, unsigned int nkeys,
6763 	  bool kasp, bool *warn) {
6764 	unsigned int i = 0;
6765 	isc_result_t ret;
6766 	bool have_ksk = false, have_zsk = false;
6767 	bool have_pksk = false, have_pzsk = false;
6768 
6769 	for (i = 0; i < nkeys; i++) {
6770 		bool ksk, zsk;
6771 
6772 		if (have_pksk && have_ksk && have_pzsk && have_zsk) {
6773 			break;
6774 		}
6775 
6776 		if (rrsig_ptr->algorithm != dst_key_alg(keys[i])) {
6777 			continue;
6778 		}
6779 
6780 		ret = dst_key_getbool(keys[i], DST_BOOL_KSK, &ksk);
6781 		if (ret != ISC_R_SUCCESS) {
6782 			ksk = KSK(keys[i]);
6783 		}
6784 		ret = dst_key_getbool(keys[i], DST_BOOL_ZSK, &zsk);
6785 		if (ret != ISC_R_SUCCESS) {
6786 			zsk = !KSK(keys[i]);
6787 		}
6788 
6789 		if (ksk) {
6790 			have_ksk = true;
6791 			if (dst_key_isprivate(keys[i])) {
6792 				have_pksk = true;
6793 			}
6794 		}
6795 		if (zsk) {
6796 			have_zsk = true;
6797 			if (dst_key_isprivate(keys[i])) {
6798 				have_pzsk = true;
6799 			}
6800 		}
6801 	}
6802 
6803 	if (have_zsk && have_ksk && !have_pzsk) {
6804 		*warn = true;
6805 	}
6806 
6807 	if (have_pksk && have_pzsk) {
6808 		return (true);
6809 	}
6810 
6811 	/*
6812 	 * Deleting the SOA RRSIG is always okay.
6813 	 */
6814 	if (rrsig_ptr->covered == dns_rdatatype_soa) {
6815 		return (true);
6816 	}
6817 
6818 	/*
6819 	 * It's okay to delete a signature if there is an active key with the
6820 	 * same algorithm to replace it, unless that violates the DNSSEC
6821 	 * policy.
6822 	 */
6823 	if (have_pksk || have_pzsk) {
6824 		if (kasp && have_pzsk) {
6825 			return (true);
6826 		}
6827 		return (!kasp);
6828 	}
6829 
6830 	/*
6831 	 * Failing that, it is *not* okay to delete a signature
6832 	 * if the associated public key is still in the DNSKEY RRset
6833 	 */
6834 	for (i = 0; i < nkeys; i++) {
6835 		if ((rrsig_ptr->algorithm == dst_key_alg(keys[i])) &&
6836 		    (rrsig_ptr->keyid == dst_key_id(keys[i])))
6837 		{
6838 			return (false);
6839 		}
6840 	}
6841 
6842 	/*
6843 	 * But if the key is gone, then go ahead.
6844 	 */
6845 	return (true);
6846 }
6847 
6848 /*
6849  * Delete expired RRsigs and any RRsigs we are about to re-sign.
6850  * See also update.c:del_keysigs().
6851  */
6852 static isc_result_t
del_sigs(dns_zone_t * zone,dns_db_t * db,dns_dbversion_t * ver,dns_name_t * name,dns_rdatatype_t type,dns__zonediff_t * zonediff,dst_key_t ** keys,unsigned int nkeys,isc_stdtime_t now,bool incremental)6853 del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
6854 	 dns_rdatatype_t type, dns__zonediff_t *zonediff, dst_key_t **keys,
6855 	 unsigned int nkeys, isc_stdtime_t now, bool incremental) {
6856 	isc_result_t result;
6857 	dns_dbnode_t *node = NULL;
6858 	dns_rdataset_t rdataset;
6859 	unsigned int i;
6860 	dns_rdata_rrsig_t rrsig;
6861 	bool kasp = (dns_zone_getkasp(zone) != NULL);
6862 	bool found;
6863 	int64_t timewarn = 0, timemaybe = 0;
6864 
6865 	dns_rdataset_init(&rdataset);
6866 
6867 	if (type == dns_rdatatype_nsec3) {
6868 		result = dns_db_findnsec3node(db, name, false, &node);
6869 	} else {
6870 		result = dns_db_findnode(db, name, false, &node);
6871 	}
6872 	if (result == ISC_R_NOTFOUND) {
6873 		return (ISC_R_SUCCESS);
6874 	}
6875 	if (result != ISC_R_SUCCESS) {
6876 		goto failure;
6877 	}
6878 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig, type,
6879 				     (isc_stdtime_t)0, &rdataset, NULL);
6880 	dns_db_detachnode(db, &node);
6881 
6882 	if (result == ISC_R_NOTFOUND) {
6883 		INSIST(!dns_rdataset_isassociated(&rdataset));
6884 		return (ISC_R_SUCCESS);
6885 	}
6886 	if (result != ISC_R_SUCCESS) {
6887 		INSIST(!dns_rdataset_isassociated(&rdataset));
6888 		goto failure;
6889 	}
6890 
6891 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
6892 	     result = dns_rdataset_next(&rdataset))
6893 	{
6894 		dns_rdata_t rdata = DNS_RDATA_INIT;
6895 
6896 		dns_rdataset_current(&rdataset, &rdata);
6897 		result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
6898 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
6899 
6900 		if (type != dns_rdatatype_dnskey && type != dns_rdatatype_cds &&
6901 		    type != dns_rdatatype_cdnskey)
6902 		{
6903 			bool warn = false, deleted = false;
6904 			if (delsig_ok(&rrsig, keys, nkeys, kasp, &warn)) {
6905 				result = update_one_rr(db, ver, zonediff->diff,
6906 						       DNS_DIFFOP_DELRESIGN,
6907 						       name, rdataset.ttl,
6908 						       &rdata);
6909 				if (result != ISC_R_SUCCESS) {
6910 					break;
6911 				}
6912 				deleted = true;
6913 			}
6914 			if (warn && !deleted) {
6915 				/*
6916 				 * At this point, we've got an RRSIG,
6917 				 * which is signed by an inactive key.
6918 				 * An administrator needs to provide a new
6919 				 * key/alg, but until that time, we want to
6920 				 * keep the old RRSIG.  Marking the key as
6921 				 * offline will prevent us spinning waiting
6922 				 * for the private part.
6923 				 */
6924 				if (incremental) {
6925 					result = offline(db, ver, zonediff,
6926 							 name, rdataset.ttl,
6927 							 &rdata);
6928 					if (result != ISC_R_SUCCESS) {
6929 						break;
6930 					}
6931 				}
6932 
6933 				/*
6934 				 * Log the key id and algorithm of
6935 				 * the inactive key with no replacement
6936 				 */
6937 				if (zone->log_key_expired_timer <= now) {
6938 					char origin[DNS_NAME_FORMATSIZE];
6939 					char algbuf[DNS_NAME_FORMATSIZE];
6940 					dns_name_format(&zone->origin, origin,
6941 							sizeof(origin));
6942 					dns_secalg_format(rrsig.algorithm,
6943 							  algbuf,
6944 							  sizeof(algbuf));
6945 					dns_zone_log(zone, ISC_LOG_WARNING,
6946 						     "Key %s/%s/%d "
6947 						     "missing or inactive "
6948 						     "and has no replacement: "
6949 						     "retaining signatures.",
6950 						     origin, algbuf,
6951 						     rrsig.keyid);
6952 					zone->log_key_expired_timer = now +
6953 								      3600;
6954 				}
6955 			}
6956 			continue;
6957 		}
6958 
6959 		/*
6960 		 * KSK RRSIGs requires special processing.
6961 		 */
6962 		found = false;
6963 		for (i = 0; i < nkeys; i++) {
6964 			if (rrsig.algorithm == dst_key_alg(keys[i]) &&
6965 			    rrsig.keyid == dst_key_id(keys[i]))
6966 			{
6967 				found = true;
6968 				/*
6969 				 * Mark offline DNSKEY.
6970 				 * We want the earliest offline expire time
6971 				 * iff there is a new offline signature.
6972 				 */
6973 				if (!dst_key_inactive(keys[i]) &&
6974 				    !dst_key_isprivate(keys[i]))
6975 				{
6976 					int64_t timeexpire = dns_time64_from32(
6977 						rrsig.timeexpire);
6978 					if (timewarn != 0 &&
6979 					    timewarn > timeexpire)
6980 					{
6981 						timewarn = timeexpire;
6982 					}
6983 					if (rdata.flags & DNS_RDATA_OFFLINE) {
6984 						if (timemaybe == 0 ||
6985 						    timemaybe > timeexpire)
6986 						{
6987 							timemaybe = timeexpire;
6988 						}
6989 						break;
6990 					}
6991 					if (timewarn == 0) {
6992 						timewarn = timemaybe;
6993 					}
6994 					if (timewarn == 0 ||
6995 					    timewarn > timeexpire)
6996 					{
6997 						timewarn = timeexpire;
6998 					}
6999 					result = offline(db, ver, zonediff,
7000 							 name, rdataset.ttl,
7001 							 &rdata);
7002 					break;
7003 				}
7004 				result = update_one_rr(db, ver, zonediff->diff,
7005 						       DNS_DIFFOP_DELRESIGN,
7006 						       name, rdataset.ttl,
7007 						       &rdata);
7008 				break;
7009 			}
7010 		}
7011 
7012 		/*
7013 		 * If there is not a matching DNSKEY then
7014 		 * delete the RRSIG.
7015 		 */
7016 		if (!found) {
7017 			result = update_one_rr(db, ver, zonediff->diff,
7018 					       DNS_DIFFOP_DELRESIGN, name,
7019 					       rdataset.ttl, &rdata);
7020 		}
7021 		if (result != ISC_R_SUCCESS) {
7022 			break;
7023 		}
7024 	}
7025 
7026 	dns_rdataset_disassociate(&rdataset);
7027 	if (result == ISC_R_NOMORE) {
7028 		result = ISC_R_SUCCESS;
7029 	}
7030 	if (timewarn > 0) {
7031 		isc_stdtime_t stdwarn = (isc_stdtime_t)timewarn;
7032 		if (timewarn == stdwarn) {
7033 			set_key_expiry_warning(zone, (isc_stdtime_t)timewarn,
7034 					       now);
7035 		} else {
7036 			dns_zone_log(zone, ISC_LOG_ERROR,
7037 				     "key expiry warning time out of range");
7038 		}
7039 	}
7040 failure:
7041 	if (node != NULL) {
7042 		dns_db_detachnode(db, &node);
7043 	}
7044 	return (result);
7045 }
7046 
7047 static isc_result_t
add_sigs(dns_db_t * db,dns_dbversion_t * ver,dns_name_t * name,dns_zone_t * zone,dns_rdatatype_t type,dns_diff_t * diff,dst_key_t ** keys,unsigned int nkeys,isc_mem_t * mctx,isc_stdtime_t inception,isc_stdtime_t expire,bool check_ksk,bool keyset_kskonly)7048 add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_zone_t *zone,
7049 	 dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
7050 	 unsigned int nkeys, isc_mem_t *mctx, isc_stdtime_t inception,
7051 	 isc_stdtime_t expire, bool check_ksk, bool keyset_kskonly) {
7052 	isc_result_t result;
7053 	dns_dbnode_t *node = NULL;
7054 	dns_stats_t *dnssecsignstats;
7055 	dns_rdataset_t rdataset;
7056 	dns_rdata_t sig_rdata = DNS_RDATA_INIT;
7057 	unsigned char data[1024]; /* XXX */
7058 	isc_buffer_t buffer;
7059 	unsigned int i, j;
7060 	bool use_kasp = false;
7061 
7062 	if (dns_zone_getkasp(zone) != NULL) {
7063 		check_ksk = false;
7064 		keyset_kskonly = true;
7065 		use_kasp = true;
7066 	}
7067 
7068 	dns_rdataset_init(&rdataset);
7069 	isc_buffer_init(&buffer, data, sizeof(data));
7070 
7071 	if (type == dns_rdatatype_nsec3) {
7072 		result = dns_db_findnsec3node(db, name, false, &node);
7073 	} else {
7074 		result = dns_db_findnode(db, name, false, &node);
7075 	}
7076 	if (result == ISC_R_NOTFOUND) {
7077 		return (ISC_R_SUCCESS);
7078 	}
7079 	if (result != ISC_R_SUCCESS) {
7080 		goto failure;
7081 	}
7082 	result = dns_db_findrdataset(db, node, ver, type, 0, (isc_stdtime_t)0,
7083 				     &rdataset, NULL);
7084 	dns_db_detachnode(db, &node);
7085 	if (result == ISC_R_NOTFOUND) {
7086 		INSIST(!dns_rdataset_isassociated(&rdataset));
7087 		return (ISC_R_SUCCESS);
7088 	}
7089 	if (result != ISC_R_SUCCESS) {
7090 		INSIST(!dns_rdataset_isassociated(&rdataset));
7091 		goto failure;
7092 	}
7093 
7094 	for (i = 0; i < nkeys; i++) {
7095 		bool both = false;
7096 
7097 		/* Don't add signatures for offline or inactive keys */
7098 		if (!dst_key_isprivate(keys[i])) {
7099 			continue;
7100 		}
7101 		if (dst_key_inactive(keys[i])) {
7102 			continue;
7103 		}
7104 
7105 		if (check_ksk && !REVOKE(keys[i])) {
7106 			bool have_ksk, have_nonksk;
7107 			if (KSK(keys[i])) {
7108 				have_ksk = true;
7109 				have_nonksk = false;
7110 			} else {
7111 				have_ksk = false;
7112 				have_nonksk = true;
7113 			}
7114 
7115 			for (j = 0; j < nkeys; j++) {
7116 				if (j == i || ALG(keys[i]) != ALG(keys[j])) {
7117 					continue;
7118 				}
7119 
7120 				/*
7121 				 * Don't consider inactive keys, however
7122 				 * the KSK may be temporary offline, so do
7123 				 * consider keys which private key files are
7124 				 * unavailable.
7125 				 */
7126 				if (dst_key_inactive(keys[j])) {
7127 					continue;
7128 				}
7129 
7130 				if (REVOKE(keys[j])) {
7131 					continue;
7132 				}
7133 				if (KSK(keys[j])) {
7134 					have_ksk = true;
7135 				} else if (dst_key_isprivate(keys[j])) {
7136 					have_nonksk = true;
7137 				}
7138 				both = have_ksk && have_nonksk;
7139 				if (both) {
7140 					break;
7141 				}
7142 			}
7143 		}
7144 		if (use_kasp) {
7145 			/*
7146 			 * A dnssec-policy is found. Check what RRsets this
7147 			 * key should sign.
7148 			 */
7149 			isc_result_t kresult;
7150 			isc_stdtime_t when;
7151 			bool ksk = false;
7152 			bool zsk = false;
7153 			bool have_ksk = false;
7154 			bool have_zsk = false;
7155 
7156 			kresult = dst_key_getbool(keys[i], DST_BOOL_KSK, &ksk);
7157 			if (kresult != ISC_R_SUCCESS) {
7158 				if (KSK(keys[i])) {
7159 					ksk = true;
7160 				}
7161 			}
7162 			kresult = dst_key_getbool(keys[i], DST_BOOL_ZSK, &zsk);
7163 			if (kresult != ISC_R_SUCCESS) {
7164 				if (!KSK(keys[i])) {
7165 					zsk = true;
7166 				}
7167 			}
7168 
7169 			have_ksk = ksk;
7170 			have_zsk = zsk;
7171 			both = have_ksk && have_zsk;
7172 
7173 			for (j = 0; j < nkeys; j++) {
7174 				if (both) {
7175 					break;
7176 				}
7177 
7178 				if (j == i || ALG(keys[i]) != ALG(keys[j])) {
7179 					continue;
7180 				}
7181 
7182 				/*
7183 				 * Don't consider inactive keys or offline keys.
7184 				 */
7185 				if (!dst_key_isprivate(keys[j])) {
7186 					continue;
7187 				}
7188 				if (dst_key_inactive(keys[j])) {
7189 					continue;
7190 				}
7191 
7192 				if (REVOKE(keys[j])) {
7193 					continue;
7194 				}
7195 
7196 				if (!have_ksk) {
7197 					kresult = dst_key_getbool(keys[j],
7198 								  DST_BOOL_KSK,
7199 								  &have_ksk);
7200 					if (kresult != ISC_R_SUCCESS) {
7201 						if (KSK(keys[j])) {
7202 							have_ksk = true;
7203 						}
7204 					}
7205 				}
7206 				if (!have_zsk) {
7207 					kresult = dst_key_getbool(keys[j],
7208 								  DST_BOOL_ZSK,
7209 								  &have_zsk);
7210 					if (kresult != ISC_R_SUCCESS) {
7211 						if (!KSK(keys[j])) {
7212 							have_zsk = true;
7213 						}
7214 					}
7215 				}
7216 				both = have_ksk && have_zsk;
7217 			}
7218 
7219 			if (type == dns_rdatatype_dnskey ||
7220 			    type == dns_rdatatype_cdnskey ||
7221 			    type == dns_rdatatype_cds)
7222 			{
7223 				/*
7224 				 * DNSKEY RRset is signed with KSK.
7225 				 * CDS and CDNSKEY RRsets too (RFC 7344, 4.1).
7226 				 */
7227 				if (!ksk) {
7228 					continue;
7229 				}
7230 			} else if (!zsk) {
7231 				/*
7232 				 * Other RRsets are signed with ZSK.
7233 				 */
7234 				if (type != dns_rdatatype_soa &&
7235 				    type != zone->privatetype)
7236 				{
7237 					continue;
7238 				}
7239 				if (have_zsk) {
7240 					continue;
7241 				}
7242 			} else if (!dst_key_is_signing(keys[i], DST_BOOL_ZSK,
7243 						       inception, &when))
7244 			{
7245 				/*
7246 				 * This key is not active for zone-signing.
7247 				 */
7248 				continue;
7249 			}
7250 
7251 			/*
7252 			 * If this key is revoked, it may only sign the
7253 			 * DNSKEY RRset.
7254 			 */
7255 			if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey) {
7256 				continue;
7257 			}
7258 		} else if (both) {
7259 			/*
7260 			 * CDS and CDNSKEY are signed with KSK (RFC 7344, 4.1).
7261 			 */
7262 			if (type == dns_rdatatype_dnskey ||
7263 			    type == dns_rdatatype_cdnskey ||
7264 			    type == dns_rdatatype_cds)
7265 			{
7266 				if (!KSK(keys[i]) && keyset_kskonly) {
7267 					continue;
7268 				}
7269 			} else if (KSK(keys[i])) {
7270 				continue;
7271 			}
7272 		} else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey) {
7273 			continue;
7274 		}
7275 
7276 		/* Calculate the signature, creating a RRSIG RDATA. */
7277 		isc_buffer_clear(&buffer);
7278 		CHECK(dns_dnssec_sign(name, &rdataset, keys[i], &inception,
7279 				      &expire, mctx, &buffer, &sig_rdata));
7280 
7281 		/* Update the database and journal with the RRSIG. */
7282 		/* XXX inefficient - will cause dataset merging */
7283 		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN, name,
7284 				    rdataset.ttl, &sig_rdata));
7285 		dns_rdata_reset(&sig_rdata);
7286 		isc_buffer_init(&buffer, data, sizeof(data));
7287 
7288 		/* Update DNSSEC sign statistics. */
7289 		dnssecsignstats = dns_zone_getdnssecsignstats(zone);
7290 		if (dnssecsignstats != NULL) {
7291 			/* Generated a new signature. */
7292 			dns_dnssecsignstats_increment(dnssecsignstats,
7293 						      ID(keys[i]),
7294 						      (uint8_t)ALG(keys[i]),
7295 						      dns_dnssecsignstats_sign);
7296 			/* This is a refresh. */
7297 			dns_dnssecsignstats_increment(
7298 				dnssecsignstats, ID(keys[i]),
7299 				(uint8_t)ALG(keys[i]),
7300 				dns_dnssecsignstats_refresh);
7301 		}
7302 	}
7303 
7304 failure:
7305 	if (dns_rdataset_isassociated(&rdataset)) {
7306 		dns_rdataset_disassociate(&rdataset);
7307 	}
7308 	if (node != NULL) {
7309 		dns_db_detachnode(db, &node);
7310 	}
7311 	return (result);
7312 }
7313 
7314 static void
zone_resigninc(dns_zone_t * zone)7315 zone_resigninc(dns_zone_t *zone) {
7316 	const char *me = "zone_resigninc";
7317 	dns_db_t *db = NULL;
7318 	dns_dbversion_t *version = NULL;
7319 	dns_diff_t _sig_diff;
7320 	dns__zonediff_t zonediff;
7321 	dns_fixedname_t fixed;
7322 	dns_name_t *name;
7323 	dns_rdataset_t rdataset;
7324 	dns_rdatatype_t covers;
7325 	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
7326 	bool check_ksk, keyset_kskonly = false;
7327 	isc_result_t result;
7328 	isc_stdtime_t now, inception, soaexpire, expire, fullexpire, stop;
7329 	uint32_t sigvalidityinterval, expiryinterval;
7330 	unsigned int i;
7331 	unsigned int nkeys = 0;
7332 	unsigned int resign;
7333 
7334 	ENTER;
7335 
7336 	dns_rdataset_init(&rdataset);
7337 	dns_diff_init(zone->mctx, &_sig_diff);
7338 	zonediff_init(&zonediff, &_sig_diff);
7339 
7340 	/*
7341 	 * Zone is frozen or automatic resigning is disabled.
7342 	 * Pause for 5 minutes.
7343 	 */
7344 	if (zone->update_disabled ||
7345 	    DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN))
7346 	{
7347 		result = ISC_R_FAILURE;
7348 		goto failure;
7349 	}
7350 
7351 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
7352 	if (zone->db != NULL) {
7353 		dns_db_attach(zone->db, &db);
7354 	}
7355 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7356 	if (db == NULL) {
7357 		result = ISC_R_FAILURE;
7358 		goto failure;
7359 	}
7360 
7361 	result = dns_db_newversion(db, &version);
7362 	if (result != ISC_R_SUCCESS) {
7363 		dns_zone_log(zone, ISC_LOG_ERROR,
7364 			     "zone_resigninc:dns_db_newversion -> %s",
7365 			     dns_result_totext(result));
7366 		goto failure;
7367 	}
7368 
7369 	isc_stdtime_get(&now);
7370 
7371 	result = dns__zone_findkeys(zone, db, version, now, zone->mctx,
7372 				    DNS_MAXZONEKEYS, zone_keys, &nkeys);
7373 	if (result != ISC_R_SUCCESS) {
7374 		dns_zone_log(zone, ISC_LOG_ERROR,
7375 			     "zone_resigninc:dns__zone_findkeys -> %s",
7376 			     dns_result_totext(result));
7377 		goto failure;
7378 	}
7379 
7380 	sigvalidityinterval = dns_zone_getsigvalidityinterval(zone);
7381 	inception = now - 3600; /* Allow for clock skew. */
7382 	soaexpire = now + sigvalidityinterval;
7383 	expiryinterval = dns_zone_getsigresigninginterval(zone);
7384 	if (expiryinterval > sigvalidityinterval) {
7385 		expiryinterval = sigvalidityinterval;
7386 	} else {
7387 		expiryinterval = sigvalidityinterval - expiryinterval;
7388 	}
7389 
7390 	/*
7391 	 * Spread out signatures over time if they happen to be
7392 	 * clumped.  We don't do this for each add_sigs() call as
7393 	 * we still want some clustering to occur.  In normal operations
7394 	 * the records should be re-signed as they fall due and they should
7395 	 * already be spread out.  However if the server is off for a
7396 	 * period we need to ensure that the clusters don't become
7397 	 * synchronised by using the full jitter range.
7398 	 */
7399 	if (sigvalidityinterval >= 3600U) {
7400 		uint32_t normaljitter, fulljitter;
7401 		if (sigvalidityinterval > 7200U) {
7402 			normaljitter = isc_random_uniform(3600);
7403 			fulljitter = isc_random_uniform(expiryinterval);
7404 		} else {
7405 			normaljitter = fulljitter = isc_random_uniform(1200);
7406 		}
7407 		expire = soaexpire - normaljitter - 1;
7408 		fullexpire = soaexpire - fulljitter - 1;
7409 	} else {
7410 		expire = fullexpire = soaexpire - 1;
7411 	}
7412 	stop = now + 5;
7413 
7414 	check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
7415 	keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
7416 
7417 	name = dns_fixedname_initname(&fixed);
7418 	result = dns_db_getsigningtime(db, &rdataset, name);
7419 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
7420 		dns_zone_log(zone, ISC_LOG_ERROR,
7421 			     "zone_resigninc:dns_db_getsigningtime -> %s",
7422 			     dns_result_totext(result));
7423 	}
7424 
7425 	i = 0;
7426 	while (result == ISC_R_SUCCESS) {
7427 		resign = rdataset.resign -
7428 			 dns_zone_getsigresigninginterval(zone);
7429 		covers = rdataset.covers;
7430 		dns_rdataset_disassociate(&rdataset);
7431 
7432 		/*
7433 		 * Stop if we hit the SOA as that means we have walked the
7434 		 * entire zone.  The SOA record should always be the most
7435 		 * recent signature.
7436 		 */
7437 		/* XXXMPA increase number of RRsets signed pre call */
7438 		if ((covers == dns_rdatatype_soa &&
7439 		     dns_name_equal(name, &zone->origin)) ||
7440 		    i++ > zone->signatures || resign > stop)
7441 		{
7442 			break;
7443 		}
7444 
7445 		result = del_sigs(zone, db, version, name, covers, &zonediff,
7446 				  zone_keys, nkeys, now, true);
7447 		if (result != ISC_R_SUCCESS) {
7448 			dns_zone_log(zone, ISC_LOG_ERROR,
7449 				     "zone_resigninc:del_sigs -> %s",
7450 				     dns_result_totext(result));
7451 			break;
7452 		}
7453 
7454 		/*
7455 		 * If re-signing is over 5 minutes late use 'fullexpire'
7456 		 * to redistribute the signature over the complete
7457 		 * re-signing window, otherwise only add a small amount
7458 		 * of jitter.
7459 		 */
7460 		result = add_sigs(db, version, name, zone, covers,
7461 				  zonediff.diff, zone_keys, nkeys, zone->mctx,
7462 				  inception,
7463 				  resign > (now - 300) ? expire : fullexpire,
7464 				  check_ksk, keyset_kskonly);
7465 		if (result != ISC_R_SUCCESS) {
7466 			dns_zone_log(zone, ISC_LOG_ERROR,
7467 				     "zone_resigninc:add_sigs -> %s",
7468 				     dns_result_totext(result));
7469 			break;
7470 		}
7471 		result = dns_db_getsigningtime(db, &rdataset, name);
7472 		if (nkeys == 0 && result == ISC_R_NOTFOUND) {
7473 			result = ISC_R_SUCCESS;
7474 			break;
7475 		}
7476 		if (result != ISC_R_SUCCESS) {
7477 			dns_zone_log(zone, ISC_LOG_ERROR,
7478 				     "zone_resigninc:dns_db_getsigningtime -> "
7479 				     "%s",
7480 				     dns_result_totext(result));
7481 		}
7482 	}
7483 
7484 	if (result != ISC_R_NOMORE && result != ISC_R_SUCCESS) {
7485 		goto failure;
7486 	}
7487 
7488 	result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
7489 			  &zonediff, zone_keys, nkeys, now, true);
7490 	if (result != ISC_R_SUCCESS) {
7491 		dns_zone_log(zone, ISC_LOG_ERROR,
7492 			     "zone_resigninc:del_sigs -> %s",
7493 			     dns_result_totext(result));
7494 		goto failure;
7495 	}
7496 
7497 	/*
7498 	 * Did we change anything in the zone?
7499 	 */
7500 	if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
7501 		/*
7502 		 * Commit the changes if any key has been marked as offline.
7503 		 */
7504 		if (zonediff.offline) {
7505 			dns_db_closeversion(db, &version, true);
7506 		}
7507 		goto failure;
7508 	}
7509 
7510 	/* Increment SOA serial if we have made changes */
7511 	result = update_soa_serial(zone, db, version, zonediff.diff, zone->mctx,
7512 				   zone->updatemethod);
7513 	if (result != ISC_R_SUCCESS) {
7514 		dns_zone_log(zone, ISC_LOG_ERROR,
7515 			     "zone_resigninc:update_soa_serial -> %s",
7516 			     dns_result_totext(result));
7517 		goto failure;
7518 	}
7519 
7520 	/*
7521 	 * Generate maximum life time signatures so that the above loop
7522 	 * termination is sensible.
7523 	 */
7524 	result = add_sigs(db, version, &zone->origin, zone, dns_rdatatype_soa,
7525 			  zonediff.diff, zone_keys, nkeys, zone->mctx,
7526 			  inception, soaexpire, check_ksk, keyset_kskonly);
7527 	if (result != ISC_R_SUCCESS) {
7528 		dns_zone_log(zone, ISC_LOG_ERROR,
7529 			     "zone_resigninc:add_sigs -> %s",
7530 			     dns_result_totext(result));
7531 		goto failure;
7532 	}
7533 
7534 	/* Write changes to journal file. */
7535 	CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_resigninc"));
7536 
7537 	/* Everything has succeeded. Commit the changes. */
7538 	dns_db_closeversion(db, &version, true);
7539 
7540 failure:
7541 	dns_diff_clear(&_sig_diff);
7542 	for (i = 0; i < nkeys; i++) {
7543 		dst_key_free(&zone_keys[i]);
7544 	}
7545 	if (version != NULL) {
7546 		dns_db_closeversion(db, &version, false);
7547 		dns_db_detach(&db);
7548 	} else if (db != NULL) {
7549 		dns_db_detach(&db);
7550 	}
7551 
7552 	LOCK_ZONE(zone);
7553 	if (result == ISC_R_SUCCESS) {
7554 		set_resigntime(zone);
7555 		zone_needdump(zone, DNS_DUMP_DELAY);
7556 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
7557 	} else {
7558 		/*
7559 		 * Something failed.  Retry in 5 minutes.
7560 		 */
7561 		isc_interval_t ival;
7562 		isc_interval_set(&ival, 300, 0);
7563 		isc_time_nowplusinterval(&zone->resigntime, &ival);
7564 	}
7565 	UNLOCK_ZONE(zone);
7566 
7567 	INSIST(version == NULL);
7568 }
7569 
7570 static isc_result_t
next_active(dns_db_t * db,dns_dbversion_t * version,dns_name_t * oldname,dns_name_t * newname,bool bottom)7571 next_active(dns_db_t *db, dns_dbversion_t *version, dns_name_t *oldname,
7572 	    dns_name_t *newname, bool bottom) {
7573 	isc_result_t result;
7574 	dns_dbiterator_t *dbit = NULL;
7575 	dns_rdatasetiter_t *rdsit = NULL;
7576 	dns_dbnode_t *node = NULL;
7577 
7578 	CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit));
7579 	CHECK(dns_dbiterator_seek(dbit, oldname));
7580 	do {
7581 		result = dns_dbiterator_next(dbit);
7582 		if (result == ISC_R_NOMORE) {
7583 			CHECK(dns_dbiterator_first(dbit));
7584 		}
7585 		CHECK(dns_dbiterator_current(dbit, &node, newname));
7586 		if (bottom && dns_name_issubdomain(newname, oldname) &&
7587 		    !dns_name_equal(newname, oldname))
7588 		{
7589 			dns_db_detachnode(db, &node);
7590 			continue;
7591 		}
7592 		/*
7593 		 * Is this node empty?
7594 		 */
7595 		CHECK(dns_db_allrdatasets(db, node, version, 0, 0, &rdsit));
7596 		result = dns_rdatasetiter_first(rdsit);
7597 		dns_db_detachnode(db, &node);
7598 		dns_rdatasetiter_destroy(&rdsit);
7599 		if (result != ISC_R_NOMORE) {
7600 			break;
7601 		}
7602 	} while (1);
7603 failure:
7604 	if (node != NULL) {
7605 		dns_db_detachnode(db, &node);
7606 	}
7607 	if (dbit != NULL) {
7608 		dns_dbiterator_destroy(&dbit);
7609 	}
7610 	return (result);
7611 }
7612 
7613 static bool
signed_with_good_key(dns_zone_t * zone,dns_db_t * db,dns_dbnode_t * node,dns_dbversion_t * version,dns_rdatatype_t type,dst_key_t * key)7614 signed_with_good_key(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
7615 		     dns_dbversion_t *version, dns_rdatatype_t type,
7616 		     dst_key_t *key) {
7617 	isc_result_t result;
7618 	dns_rdataset_t rdataset;
7619 	dns_rdata_t rdata = DNS_RDATA_INIT;
7620 	dns_rdata_rrsig_t rrsig;
7621 	int count = 0;
7622 	dns_kasp_t *kasp = dns_zone_getkasp(zone);
7623 
7624 	dns_rdataset_init(&rdataset);
7625 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_rrsig,
7626 				     type, 0, &rdataset, NULL);
7627 	if (result != ISC_R_SUCCESS) {
7628 		INSIST(!dns_rdataset_isassociated(&rdataset));
7629 		return (false);
7630 	}
7631 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
7632 	     result = dns_rdataset_next(&rdataset))
7633 	{
7634 		dns_rdataset_current(&rdataset, &rdata);
7635 		result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
7636 		INSIST(result == ISC_R_SUCCESS);
7637 		if (rrsig.algorithm == dst_key_alg(key) &&
7638 		    rrsig.keyid == dst_key_id(key))
7639 		{
7640 			dns_rdataset_disassociate(&rdataset);
7641 			return (true);
7642 		}
7643 		if (rrsig.algorithm == dst_key_alg(key)) {
7644 			count++;
7645 		}
7646 		dns_rdata_reset(&rdata);
7647 	}
7648 
7649 	if (dns_zone_getkasp(zone) != NULL) {
7650 		dns_kasp_key_t *kkey;
7651 		int zsk_count = 0;
7652 		bool approved;
7653 
7654 		KASP_LOCK(kasp);
7655 		for (kkey = ISC_LIST_HEAD(dns_kasp_keys(kasp)); kkey != NULL;
7656 		     kkey = ISC_LIST_NEXT(kkey, link))
7657 		{
7658 			if (dns_kasp_key_algorithm(kkey) != dst_key_alg(key)) {
7659 				continue;
7660 			}
7661 			if (dns_kasp_key_zsk(kkey)) {
7662 				zsk_count++;
7663 			}
7664 		}
7665 		KASP_UNLOCK(kasp);
7666 
7667 		if (type == dns_rdatatype_dnskey ||
7668 		    type == dns_rdatatype_cdnskey || type == dns_rdatatype_cds)
7669 		{
7670 			/*
7671 			 * CDS and CDNSKEY are signed with KSK like DNSKEY.
7672 			 * (RFC 7344, section 4.1 specifies that they must
7673 			 * be signed with a key in the current DS RRset,
7674 			 * which would only include KSK's.)
7675 			 */
7676 			approved = false;
7677 		} else {
7678 			approved = (zsk_count == count);
7679 		}
7680 
7681 		dns_rdataset_disassociate(&rdataset);
7682 		return (approved);
7683 	}
7684 
7685 	dns_rdataset_disassociate(&rdataset);
7686 	return (false);
7687 }
7688 
7689 static isc_result_t
add_nsec(dns_db_t * db,dns_dbversion_t * version,dns_name_t * name,dns_dbnode_t * node,dns_ttl_t ttl,bool bottom,dns_diff_t * diff)7690 add_nsec(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
7691 	 dns_dbnode_t *node, dns_ttl_t ttl, bool bottom, dns_diff_t *diff) {
7692 	dns_fixedname_t fixed;
7693 	dns_name_t *next;
7694 	dns_rdata_t rdata = DNS_RDATA_INIT;
7695 	isc_result_t result;
7696 	unsigned char nsecbuffer[DNS_NSEC_BUFFERSIZE];
7697 
7698 	next = dns_fixedname_initname(&fixed);
7699 
7700 	CHECK(next_active(db, version, name, next, bottom));
7701 	CHECK(dns_nsec_buildrdata(db, version, node, next, nsecbuffer, &rdata));
7702 	CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADD, name, ttl,
7703 			    &rdata));
7704 failure:
7705 	return (result);
7706 }
7707 
7708 static isc_result_t
check_if_bottom_of_zone(dns_db_t * db,dns_dbnode_t * node,dns_dbversion_t * version,bool * is_bottom_of_zone)7709 check_if_bottom_of_zone(dns_db_t *db, dns_dbnode_t *node,
7710 			dns_dbversion_t *version, bool *is_bottom_of_zone) {
7711 	isc_result_t result;
7712 	dns_rdatasetiter_t *iterator = NULL;
7713 	dns_rdataset_t rdataset;
7714 	bool seen_soa = false, seen_ns = false, seen_dname = false;
7715 
7716 	REQUIRE(is_bottom_of_zone != NULL);
7717 
7718 	result = dns_db_allrdatasets(db, node, version, 0, 0, &iterator);
7719 	if (result != ISC_R_SUCCESS) {
7720 		if (result == ISC_R_NOTFOUND) {
7721 			result = ISC_R_SUCCESS;
7722 		}
7723 		return (result);
7724 	}
7725 
7726 	dns_rdataset_init(&rdataset);
7727 	for (result = dns_rdatasetiter_first(iterator); result == ISC_R_SUCCESS;
7728 	     result = dns_rdatasetiter_next(iterator))
7729 	{
7730 		dns_rdatasetiter_current(iterator, &rdataset);
7731 		switch (rdataset.type) {
7732 		case dns_rdatatype_soa:
7733 			seen_soa = true;
7734 			break;
7735 		case dns_rdatatype_ns:
7736 			seen_ns = true;
7737 			break;
7738 		case dns_rdatatype_dname:
7739 			seen_dname = true;
7740 			break;
7741 		}
7742 		dns_rdataset_disassociate(&rdataset);
7743 	}
7744 	if (result != ISC_R_NOMORE) {
7745 		goto failure;
7746 	}
7747 	if ((seen_ns && !seen_soa) || seen_dname) {
7748 		*is_bottom_of_zone = true;
7749 	}
7750 	result = ISC_R_SUCCESS;
7751 
7752 failure:
7753 	dns_rdatasetiter_destroy(&iterator);
7754 
7755 	return (result);
7756 }
7757 
7758 static isc_result_t
sign_a_node(dns_db_t * db,dns_zone_t * zone,dns_name_t * name,dns_dbnode_t * node,dns_dbversion_t * version,bool build_nsec3,bool build_nsec,dst_key_t * key,isc_stdtime_t inception,isc_stdtime_t expire,dns_ttl_t nsecttl,bool is_ksk,bool is_zsk,bool keyset_kskonly,bool is_bottom_of_zone,dns_diff_t * diff,int32_t * signatures,isc_mem_t * mctx)7759 sign_a_node(dns_db_t *db, dns_zone_t *zone, dns_name_t *name,
7760 	    dns_dbnode_t *node, dns_dbversion_t *version, bool build_nsec3,
7761 	    bool build_nsec, dst_key_t *key, isc_stdtime_t inception,
7762 	    isc_stdtime_t expire, dns_ttl_t nsecttl, bool is_ksk, bool is_zsk,
7763 	    bool keyset_kskonly, bool is_bottom_of_zone, dns_diff_t *diff,
7764 	    int32_t *signatures, isc_mem_t *mctx) {
7765 	isc_result_t result;
7766 	dns_rdatasetiter_t *iterator = NULL;
7767 	dns_rdataset_t rdataset;
7768 	dns_rdata_t rdata = DNS_RDATA_INIT;
7769 	dns_stats_t *dnssecsignstats;
7770 
7771 	isc_buffer_t buffer;
7772 	unsigned char data[1024];
7773 	bool seen_soa, seen_ns, seen_rr, seen_nsec, seen_nsec3, seen_ds;
7774 
7775 	result = dns_db_allrdatasets(db, node, version, 0, 0, &iterator);
7776 	if (result != ISC_R_SUCCESS) {
7777 		if (result == ISC_R_NOTFOUND) {
7778 			result = ISC_R_SUCCESS;
7779 		}
7780 		return (result);
7781 	}
7782 
7783 	dns_rdataset_init(&rdataset);
7784 	isc_buffer_init(&buffer, data, sizeof(data));
7785 	seen_rr = seen_soa = seen_ns = seen_nsec = seen_nsec3 = seen_ds = false;
7786 	for (result = dns_rdatasetiter_first(iterator); result == ISC_R_SUCCESS;
7787 	     result = dns_rdatasetiter_next(iterator))
7788 	{
7789 		dns_rdatasetiter_current(iterator, &rdataset);
7790 		if (rdataset.type == dns_rdatatype_soa) {
7791 			seen_soa = true;
7792 		} else if (rdataset.type == dns_rdatatype_ns) {
7793 			seen_ns = true;
7794 		} else if (rdataset.type == dns_rdatatype_ds) {
7795 			seen_ds = true;
7796 		} else if (rdataset.type == dns_rdatatype_nsec) {
7797 			seen_nsec = true;
7798 		} else if (rdataset.type == dns_rdatatype_nsec3) {
7799 			seen_nsec3 = true;
7800 		}
7801 		if (rdataset.type != dns_rdatatype_rrsig) {
7802 			seen_rr = true;
7803 		}
7804 		dns_rdataset_disassociate(&rdataset);
7805 	}
7806 	if (result != ISC_R_NOMORE) {
7807 		goto failure;
7808 	}
7809 	/*
7810 	 * Going from insecure to NSEC3.
7811 	 * Don't generate NSEC3 records for NSEC3 records.
7812 	 */
7813 	if (build_nsec3 && !seen_nsec3 && seen_rr) {
7814 		bool unsecure = !seen_ds && seen_ns && !seen_soa;
7815 		CHECK(dns_nsec3_addnsec3s(db, version, name, nsecttl, unsecure,
7816 					  diff));
7817 		(*signatures)--;
7818 	}
7819 	/*
7820 	 * Going from insecure to NSEC.
7821 	 * Don't generate NSEC records for NSEC3 records.
7822 	 */
7823 	if (build_nsec && !seen_nsec3 && !seen_nsec && seen_rr) {
7824 		/*
7825 		 * Build a NSEC record except at the origin.
7826 		 */
7827 		if (!dns_name_equal(name, dns_db_origin(db))) {
7828 			CHECK(add_nsec(db, version, name, node, nsecttl,
7829 				       is_bottom_of_zone, diff));
7830 			/* Count a NSEC generation as a signature generation. */
7831 			(*signatures)--;
7832 		}
7833 	}
7834 	result = dns_rdatasetiter_first(iterator);
7835 	while (result == ISC_R_SUCCESS) {
7836 		isc_stdtime_t when;
7837 
7838 		dns_rdatasetiter_current(iterator, &rdataset);
7839 		if (rdataset.type == dns_rdatatype_soa ||
7840 		    rdataset.type == dns_rdatatype_rrsig)
7841 		{
7842 			goto next_rdataset;
7843 		}
7844 		if (rdataset.type == dns_rdatatype_dnskey ||
7845 		    rdataset.type == dns_rdatatype_cdnskey ||
7846 		    rdataset.type == dns_rdatatype_cds)
7847 		{
7848 			/*
7849 			 * CDS and CDNSKEY are signed with KSK like DNSKEY.
7850 			 * (RFC 7344, section 4.1 specifies that they must
7851 			 * be signed with a key in the current DS RRset,
7852 			 * which would only include KSK's.)
7853 			 */
7854 			if (!is_ksk && keyset_kskonly) {
7855 				goto next_rdataset;
7856 			}
7857 		} else if (!is_zsk) {
7858 			goto next_rdataset;
7859 		} else if (is_zsk && !dst_key_is_signing(key, DST_BOOL_ZSK,
7860 							 inception, &when))
7861 		{
7862 			/* Only applies to dnssec-policy. */
7863 			if (dns_zone_getkasp(zone) != NULL) {
7864 				goto next_rdataset;
7865 			}
7866 		}
7867 
7868 		if (seen_ns && !seen_soa && rdataset.type != dns_rdatatype_ds &&
7869 		    rdataset.type != dns_rdatatype_nsec)
7870 		{
7871 			goto next_rdataset;
7872 		}
7873 		if (signed_with_good_key(zone, db, node, version, rdataset.type,
7874 					 key))
7875 		{
7876 			goto next_rdataset;
7877 		}
7878 
7879 		/* Calculate the signature, creating a RRSIG RDATA. */
7880 		isc_buffer_clear(&buffer);
7881 		CHECK(dns_dnssec_sign(name, &rdataset, key, &inception, &expire,
7882 				      mctx, &buffer, &rdata));
7883 		/* Update the database and journal with the RRSIG. */
7884 		/* XXX inefficient - will cause dataset merging */
7885 		CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADDRESIGN,
7886 				    name, rdataset.ttl, &rdata));
7887 		dns_rdata_reset(&rdata);
7888 
7889 		/* Update DNSSEC sign statistics. */
7890 		dnssecsignstats = dns_zone_getdnssecsignstats(zone);
7891 		if (dnssecsignstats != NULL) {
7892 			/* Generated a new signature. */
7893 			dns_dnssecsignstats_increment(dnssecsignstats, ID(key),
7894 						      ALG(key),
7895 						      dns_dnssecsignstats_sign);
7896 			/* This is a refresh. */
7897 			dns_dnssecsignstats_increment(
7898 				dnssecsignstats, ID(key), ALG(key),
7899 				dns_dnssecsignstats_refresh);
7900 		}
7901 
7902 		(*signatures)--;
7903 	next_rdataset:
7904 		dns_rdataset_disassociate(&rdataset);
7905 		result = dns_rdatasetiter_next(iterator);
7906 	}
7907 	if (result == ISC_R_NOMORE) {
7908 		result = ISC_R_SUCCESS;
7909 	}
7910 failure:
7911 	if (dns_rdataset_isassociated(&rdataset)) {
7912 		dns_rdataset_disassociate(&rdataset);
7913 	}
7914 	if (iterator != NULL) {
7915 		dns_rdatasetiter_destroy(&iterator);
7916 	}
7917 	return (result);
7918 }
7919 
7920 /*
7921  * If 'update_only' is set then don't create a NSEC RRset if it doesn't exist.
7922  */
7923 static isc_result_t
updatesecure(dns_db_t * db,dns_dbversion_t * version,dns_name_t * name,dns_ttl_t nsecttl,bool update_only,dns_diff_t * diff)7924 updatesecure(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
7925 	     dns_ttl_t nsecttl, bool update_only, dns_diff_t *diff) {
7926 	isc_result_t result;
7927 	dns_rdataset_t rdataset;
7928 	dns_dbnode_t *node = NULL;
7929 
7930 	CHECK(dns_db_getoriginnode(db, &node));
7931 	if (update_only) {
7932 		dns_rdataset_init(&rdataset);
7933 		result = dns_db_findrdataset(
7934 			db, node, version, dns_rdatatype_nsec,
7935 			dns_rdatatype_none, 0, &rdataset, NULL);
7936 		if (dns_rdataset_isassociated(&rdataset)) {
7937 			dns_rdataset_disassociate(&rdataset);
7938 		}
7939 		if (result == ISC_R_NOTFOUND) {
7940 			goto success;
7941 		}
7942 		if (result != ISC_R_SUCCESS) {
7943 			goto failure;
7944 		}
7945 	}
7946 	CHECK(delete_nsec(db, version, node, name, diff));
7947 	CHECK(add_nsec(db, version, name, node, nsecttl, false, diff));
7948 success:
7949 	result = ISC_R_SUCCESS;
7950 failure:
7951 	if (node != NULL) {
7952 		dns_db_detachnode(db, &node);
7953 	}
7954 	return (result);
7955 }
7956 
7957 static isc_result_t
updatesignwithkey(dns_zone_t * zone,dns_signing_t * signing,dns_dbversion_t * version,bool build_nsec3,dns_ttl_t nsecttl,dns_diff_t * diff)7958 updatesignwithkey(dns_zone_t *zone, dns_signing_t *signing,
7959 		  dns_dbversion_t *version, bool build_nsec3, dns_ttl_t nsecttl,
7960 		  dns_diff_t *diff) {
7961 	isc_result_t result;
7962 	dns_dbnode_t *node = NULL;
7963 	dns_rdataset_t rdataset;
7964 	dns_rdata_t rdata = DNS_RDATA_INIT;
7965 	unsigned char data[5];
7966 	bool seen_done = false;
7967 	bool have_rr = false;
7968 
7969 	dns_rdataset_init(&rdataset);
7970 	result = dns_db_getoriginnode(signing->db, &node);
7971 	if (result != ISC_R_SUCCESS) {
7972 		goto failure;
7973 	}
7974 
7975 	result = dns_db_findrdataset(signing->db, node, version,
7976 				     zone->privatetype, dns_rdatatype_none, 0,
7977 				     &rdataset, NULL);
7978 	if (result == ISC_R_NOTFOUND) {
7979 		INSIST(!dns_rdataset_isassociated(&rdataset));
7980 		result = ISC_R_SUCCESS;
7981 		goto failure;
7982 	}
7983 	if (result != ISC_R_SUCCESS) {
7984 		INSIST(!dns_rdataset_isassociated(&rdataset));
7985 		goto failure;
7986 	}
7987 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
7988 	     result = dns_rdataset_next(&rdataset))
7989 	{
7990 		dns_rdataset_current(&rdataset, &rdata);
7991 		/*
7992 		 * If we don't match the algorithm or keyid skip the record.
7993 		 */
7994 		if (rdata.length != 5 || rdata.data[0] != signing->algorithm ||
7995 		    rdata.data[1] != ((signing->keyid >> 8) & 0xff) ||
7996 		    rdata.data[2] != (signing->keyid & 0xff))
7997 		{
7998 			have_rr = true;
7999 			dns_rdata_reset(&rdata);
8000 			continue;
8001 		}
8002 		/*
8003 		 * We have a match.  If we were signing (!signing->deleteit)
8004 		 * and we already have a record indicating that we have
8005 		 * finished signing (rdata.data[4] != 0) then keep it.
8006 		 * Otherwise it needs to be deleted as we have removed all
8007 		 * the signatures (signing->deleteit), so any record indicating
8008 		 * completion is now out of date, or we have finished signing
8009 		 * with the new record so we no longer need to remember that
8010 		 * we need to sign the zone with the matching key across a
8011 		 * nameserver re-start.
8012 		 */
8013 		if (!signing->deleteit && rdata.data[4] != 0) {
8014 			seen_done = true;
8015 			have_rr = true;
8016 		} else {
8017 			CHECK(update_one_rr(signing->db, version, diff,
8018 					    DNS_DIFFOP_DEL, &zone->origin,
8019 					    rdataset.ttl, &rdata));
8020 		}
8021 		dns_rdata_reset(&rdata);
8022 	}
8023 	if (result == ISC_R_NOMORE) {
8024 		result = ISC_R_SUCCESS;
8025 	}
8026 	if (!signing->deleteit && !seen_done) {
8027 		/*
8028 		 * If we were signing then we need to indicate that we have
8029 		 * finished signing the zone with this key.  If it is already
8030 		 * there we don't need to add it a second time.
8031 		 */
8032 		data[0] = signing->algorithm;
8033 		data[1] = (signing->keyid >> 8) & 0xff;
8034 		data[2] = signing->keyid & 0xff;
8035 		data[3] = 0;
8036 		data[4] = 1;
8037 		rdata.length = sizeof(data);
8038 		rdata.data = data;
8039 		rdata.type = zone->privatetype;
8040 		rdata.rdclass = dns_db_class(signing->db);
8041 		CHECK(update_one_rr(signing->db, version, diff, DNS_DIFFOP_ADD,
8042 				    &zone->origin, rdataset.ttl, &rdata));
8043 	} else if (!have_rr) {
8044 		dns_name_t *origin = dns_db_origin(signing->db);
8045 		/*
8046 		 * Rebuild the NSEC/NSEC3 record for the origin as we no
8047 		 * longer have any private records.
8048 		 */
8049 		if (build_nsec3) {
8050 			CHECK(dns_nsec3_addnsec3s(signing->db, version, origin,
8051 						  nsecttl, false, diff));
8052 		}
8053 		CHECK(updatesecure(signing->db, version, origin, nsecttl, true,
8054 				   diff));
8055 	}
8056 
8057 failure:
8058 	if (dns_rdataset_isassociated(&rdataset)) {
8059 		dns_rdataset_disassociate(&rdataset);
8060 	}
8061 	if (node != NULL) {
8062 		dns_db_detachnode(signing->db, &node);
8063 	}
8064 	return (result);
8065 }
8066 
8067 /*
8068  * Called from zone_nsec3chain() in order to update zone records indicating
8069  * processing status of given NSEC3 chain:
8070  *
8071  *   - If the supplied dns_nsec3chain_t structure has been fully processed
8072  *     (which is indicated by "active" being set to false):
8073  *
8074  *       - remove all NSEC3PARAM records matching the relevant NSEC3 chain,
8075  *
8076  *       - remove all private-type records containing NSEC3PARAM RDATA matching
8077  *         the relevant NSEC3 chain.
8078  *
8079  *   - If the supplied dns_nsec3chain_t structure has not been fully processed
8080  *     (which is indicated by "active" being set to true), only remove the
8081  *     NSEC3PARAM record which matches the relevant NSEC3 chain and has the
8082  *     "flags" field set to 0.
8083  *
8084  *   - If given NSEC3 chain is being added, add an NSEC3PARAM record contained
8085  *     in the relevant private-type record, but with the "flags" field set to
8086  *     0, indicating that this NSEC3 chain is now complete for this zone.
8087  *
8088  * Note that this function is called at different processing stages for NSEC3
8089  * chain additions vs. removals and needs to handle all cases properly.
8090  */
8091 static isc_result_t
fixup_nsec3param(dns_db_t * db,dns_dbversion_t * ver,dns_nsec3chain_t * chain,bool active,dns_rdatatype_t privatetype,dns_diff_t * diff)8092 fixup_nsec3param(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3chain_t *chain,
8093 		 bool active, dns_rdatatype_t privatetype, dns_diff_t *diff) {
8094 	dns_dbnode_t *node = NULL;
8095 	dns_name_t *name = dns_db_origin(db);
8096 	dns_rdata_t rdata = DNS_RDATA_INIT;
8097 	dns_rdataset_t rdataset;
8098 	dns_rdata_nsec3param_t nsec3param;
8099 	isc_result_t result;
8100 	isc_buffer_t buffer;
8101 	unsigned char parambuf[DNS_NSEC3PARAM_BUFFERSIZE];
8102 	dns_ttl_t ttl = 0;
8103 	bool nseconly = false, nsec3ok = false;
8104 
8105 	dns_rdataset_init(&rdataset);
8106 
8107 	result = dns_db_getoriginnode(db, &node);
8108 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
8109 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param, 0,
8110 				     0, &rdataset, NULL);
8111 	if (result == ISC_R_NOTFOUND) {
8112 		goto try_private;
8113 	}
8114 	if (result != ISC_R_SUCCESS) {
8115 		goto failure;
8116 	}
8117 
8118 	/*
8119 	 * Preserve the existing ttl.
8120 	 */
8121 	ttl = rdataset.ttl;
8122 
8123 	/*
8124 	 * Delete all NSEC3PARAM records which match that in nsec3chain.
8125 	 */
8126 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
8127 	     result = dns_rdataset_next(&rdataset))
8128 	{
8129 		dns_rdataset_current(&rdataset, &rdata);
8130 		CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
8131 
8132 		if (nsec3param.hash != chain->nsec3param.hash ||
8133 		    (active && nsec3param.flags != 0) ||
8134 		    nsec3param.iterations != chain->nsec3param.iterations ||
8135 		    nsec3param.salt_length != chain->nsec3param.salt_length ||
8136 		    memcmp(nsec3param.salt, chain->nsec3param.salt,
8137 			   nsec3param.salt_length))
8138 		{
8139 			dns_rdata_reset(&rdata);
8140 			continue;
8141 		}
8142 
8143 		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
8144 				    rdataset.ttl, &rdata));
8145 		dns_rdata_reset(&rdata);
8146 	}
8147 	if (result != ISC_R_NOMORE) {
8148 		goto failure;
8149 	}
8150 
8151 	dns_rdataset_disassociate(&rdataset);
8152 
8153 try_private:
8154 
8155 	if (active) {
8156 		goto add;
8157 	}
8158 
8159 	result = dns_nsec_nseconly(db, ver, &nseconly);
8160 	nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
8161 
8162 	/*
8163 	 * Delete all private records which match that in nsec3chain.
8164 	 */
8165 	result = dns_db_findrdataset(db, node, ver, privatetype, 0, 0,
8166 				     &rdataset, NULL);
8167 	if (result == ISC_R_NOTFOUND) {
8168 		goto add;
8169 	}
8170 	if (result != ISC_R_SUCCESS) {
8171 		goto failure;
8172 	}
8173 
8174 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
8175 	     result = dns_rdataset_next(&rdataset))
8176 	{
8177 		dns_rdata_t private = DNS_RDATA_INIT;
8178 		unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
8179 
8180 		dns_rdataset_current(&rdataset, &private);
8181 		if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
8182 						sizeof(buf)))
8183 		{
8184 			continue;
8185 		}
8186 		CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
8187 
8188 		if ((!nsec3ok &&
8189 		     (nsec3param.flags & DNS_NSEC3FLAG_INITIAL) != 0) ||
8190 		    nsec3param.hash != chain->nsec3param.hash ||
8191 		    nsec3param.iterations != chain->nsec3param.iterations ||
8192 		    nsec3param.salt_length != chain->nsec3param.salt_length ||
8193 		    memcmp(nsec3param.salt, chain->nsec3param.salt,
8194 			   nsec3param.salt_length))
8195 		{
8196 			dns_rdata_reset(&rdata);
8197 			continue;
8198 		}
8199 
8200 		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
8201 				    rdataset.ttl, &private));
8202 		dns_rdata_reset(&rdata);
8203 	}
8204 	if (result != ISC_R_NOMORE) {
8205 		goto failure;
8206 	}
8207 
8208 add:
8209 	if ((chain->nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
8210 		result = ISC_R_SUCCESS;
8211 		goto failure;
8212 	}
8213 
8214 	/*
8215 	 * Add a NSEC3PARAM record which matches that in nsec3chain but
8216 	 * with all flags bits cleared.
8217 	 *
8218 	 * Note: we do not clear chain->nsec3param.flags as this change
8219 	 * may be reversed.
8220 	 */
8221 	isc_buffer_init(&buffer, &parambuf, sizeof(parambuf));
8222 	CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db),
8223 				   dns_rdatatype_nsec3param, &chain->nsec3param,
8224 				   &buffer));
8225 	rdata.data[1] = 0; /* Clear flag bits. */
8226 	CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, name, ttl, &rdata));
8227 
8228 failure:
8229 	dns_db_detachnode(db, &node);
8230 	if (dns_rdataset_isassociated(&rdataset)) {
8231 		dns_rdataset_disassociate(&rdataset);
8232 	}
8233 	return (result);
8234 }
8235 
8236 static isc_result_t
delete_nsec(dns_db_t * db,dns_dbversion_t * ver,dns_dbnode_t * node,dns_name_t * name,dns_diff_t * diff)8237 delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
8238 	    dns_name_t *name, dns_diff_t *diff) {
8239 	dns_rdataset_t rdataset;
8240 	isc_result_t result;
8241 
8242 	dns_rdataset_init(&rdataset);
8243 
8244 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec, 0, 0,
8245 				     &rdataset, NULL);
8246 	if (result == ISC_R_NOTFOUND) {
8247 		return (ISC_R_SUCCESS);
8248 	}
8249 	if (result != ISC_R_SUCCESS) {
8250 		return (result);
8251 	}
8252 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
8253 	     result = dns_rdataset_next(&rdataset))
8254 	{
8255 		dns_rdata_t rdata = DNS_RDATA_INIT;
8256 
8257 		dns_rdataset_current(&rdataset, &rdata);
8258 		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
8259 				    rdataset.ttl, &rdata));
8260 	}
8261 	if (result == ISC_R_NOMORE) {
8262 		result = ISC_R_SUCCESS;
8263 	}
8264 failure:
8265 	dns_rdataset_disassociate(&rdataset);
8266 	return (result);
8267 }
8268 
8269 static isc_result_t
deletematchingnsec3(dns_db_t * db,dns_dbversion_t * ver,dns_dbnode_t * node,dns_name_t * name,const dns_rdata_nsec3param_t * param,dns_diff_t * diff)8270 deletematchingnsec3(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
8271 		    dns_name_t *name, const dns_rdata_nsec3param_t *param,
8272 		    dns_diff_t *diff) {
8273 	dns_rdataset_t rdataset;
8274 	dns_rdata_nsec3_t nsec3;
8275 	isc_result_t result;
8276 
8277 	dns_rdataset_init(&rdataset);
8278 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3, 0, 0,
8279 				     &rdataset, NULL);
8280 	if (result == ISC_R_NOTFOUND) {
8281 		return (ISC_R_SUCCESS);
8282 	}
8283 	if (result != ISC_R_SUCCESS) {
8284 		return (result);
8285 	}
8286 
8287 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
8288 	     result = dns_rdataset_next(&rdataset))
8289 	{
8290 		dns_rdata_t rdata = DNS_RDATA_INIT;
8291 
8292 		dns_rdataset_current(&rdataset, &rdata);
8293 		CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
8294 		if (nsec3.hash != param->hash ||
8295 		    nsec3.iterations != param->iterations ||
8296 		    nsec3.salt_length != param->salt_length ||
8297 		    memcmp(nsec3.salt, param->salt, nsec3.salt_length))
8298 		{
8299 			continue;
8300 		}
8301 		CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
8302 				    rdataset.ttl, &rdata));
8303 	}
8304 	if (result == ISC_R_NOMORE) {
8305 		result = ISC_R_SUCCESS;
8306 	}
8307 failure:
8308 	dns_rdataset_disassociate(&rdataset);
8309 	return (result);
8310 }
8311 
8312 static isc_result_t
need_nsec_chain(dns_db_t * db,dns_dbversion_t * ver,const dns_rdata_nsec3param_t * param,bool * answer)8313 need_nsec_chain(dns_db_t *db, dns_dbversion_t *ver,
8314 		const dns_rdata_nsec3param_t *param, bool *answer) {
8315 	dns_dbnode_t *node = NULL;
8316 	dns_rdata_t rdata = DNS_RDATA_INIT;
8317 	dns_rdata_nsec3param_t myparam;
8318 	dns_rdataset_t rdataset;
8319 	isc_result_t result;
8320 
8321 	*answer = false;
8322 
8323 	result = dns_db_getoriginnode(db, &node);
8324 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
8325 
8326 	dns_rdataset_init(&rdataset);
8327 
8328 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec, 0, 0,
8329 				     &rdataset, NULL);
8330 	if (result == ISC_R_SUCCESS) {
8331 		dns_rdataset_disassociate(&rdataset);
8332 		dns_db_detachnode(db, &node);
8333 		return (result);
8334 	}
8335 	if (result != ISC_R_NOTFOUND) {
8336 		dns_db_detachnode(db, &node);
8337 		return (result);
8338 	}
8339 
8340 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param, 0,
8341 				     0, &rdataset, NULL);
8342 	if (result == ISC_R_NOTFOUND) {
8343 		*answer = true;
8344 		dns_db_detachnode(db, &node);
8345 		return (ISC_R_SUCCESS);
8346 	}
8347 	if (result != ISC_R_SUCCESS) {
8348 		dns_db_detachnode(db, &node);
8349 		return (result);
8350 	}
8351 
8352 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
8353 	     result = dns_rdataset_next(&rdataset))
8354 	{
8355 		dns_rdataset_current(&rdataset, &rdata);
8356 		CHECK(dns_rdata_tostruct(&rdata, &myparam, NULL));
8357 		dns_rdata_reset(&rdata);
8358 		/*
8359 		 * Ignore any NSEC3PARAM removals.
8360 		 */
8361 		if (NSEC3REMOVE(myparam.flags)) {
8362 			continue;
8363 		}
8364 		/*
8365 		 * Ignore the chain that we are in the process of deleting.
8366 		 */
8367 		if (myparam.hash == param->hash &&
8368 		    myparam.iterations == param->iterations &&
8369 		    myparam.salt_length == param->salt_length &&
8370 		    !memcmp(myparam.salt, param->salt, myparam.salt_length))
8371 		{
8372 			continue;
8373 		}
8374 		/*
8375 		 * Found an active NSEC3 chain.
8376 		 */
8377 		break;
8378 	}
8379 	if (result == ISC_R_NOMORE) {
8380 		*answer = true;
8381 		result = ISC_R_SUCCESS;
8382 	}
8383 
8384 failure:
8385 	if (dns_rdataset_isassociated(&rdataset)) {
8386 		dns_rdataset_disassociate(&rdataset);
8387 	}
8388 	dns_db_detachnode(db, &node);
8389 	return (result);
8390 }
8391 
8392 /*%
8393  * Given a tuple which is part of a diff, return a pointer to the next tuple in
8394  * that diff which has the same name and type (or NULL if no such tuple is
8395  * found).
8396  */
8397 static dns_difftuple_t *
find_next_matching_tuple(dns_difftuple_t * cur)8398 find_next_matching_tuple(dns_difftuple_t *cur) {
8399 	dns_difftuple_t *next = cur;
8400 
8401 	while ((next = ISC_LIST_NEXT(next, link)) != NULL) {
8402 		if (cur->rdata.type == next->rdata.type &&
8403 		    dns_name_equal(&cur->name, &next->name))
8404 		{
8405 			return (next);
8406 		}
8407 	}
8408 
8409 	return (NULL);
8410 }
8411 
8412 /*%
8413  * Remove all tuples with the same name and type as 'cur' from 'src' and append
8414  * them to 'dst'.
8415  */
8416 static void
move_matching_tuples(dns_difftuple_t * cur,dns_diff_t * src,dns_diff_t * dst)8417 move_matching_tuples(dns_difftuple_t *cur, dns_diff_t *src, dns_diff_t *dst) {
8418 	do {
8419 		dns_difftuple_t *next = find_next_matching_tuple(cur);
8420 		ISC_LIST_UNLINK(src->tuples, cur, link);
8421 		dns_diff_appendminimal(dst, &cur);
8422 		cur = next;
8423 	} while (cur != NULL);
8424 }
8425 
8426 /*%
8427  * Add/remove DNSSEC signatures for the list of "raw" zone changes supplied in
8428  * 'diff'.  Gradually remove tuples from 'diff' and append them to 'zonediff'
8429  * along with tuples representing relevant signature changes.
8430  */
8431 isc_result_t
dns__zone_updatesigs(dns_diff_t * diff,dns_db_t * db,dns_dbversion_t * version,dst_key_t * zone_keys[],unsigned int nkeys,dns_zone_t * zone,isc_stdtime_t inception,isc_stdtime_t expire,isc_stdtime_t keyexpire,isc_stdtime_t now,bool check_ksk,bool keyset_kskonly,dns__zonediff_t * zonediff)8432 dns__zone_updatesigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version,
8433 		     dst_key_t *zone_keys[], unsigned int nkeys,
8434 		     dns_zone_t *zone, isc_stdtime_t inception,
8435 		     isc_stdtime_t expire, isc_stdtime_t keyexpire,
8436 		     isc_stdtime_t now, bool check_ksk, bool keyset_kskonly,
8437 		     dns__zonediff_t *zonediff) {
8438 	dns_difftuple_t *tuple;
8439 	isc_result_t result;
8440 
8441 	while ((tuple = ISC_LIST_HEAD(diff->tuples)) != NULL) {
8442 		isc_stdtime_t exp = expire;
8443 
8444 		if (keyexpire != 0 &&
8445 		    (tuple->rdata.type == dns_rdatatype_dnskey ||
8446 		     tuple->rdata.type == dns_rdatatype_cdnskey ||
8447 		     tuple->rdata.type == dns_rdatatype_cds))
8448 		{
8449 			exp = keyexpire;
8450 		}
8451 
8452 		result = del_sigs(zone, db, version, &tuple->name,
8453 				  tuple->rdata.type, zonediff, zone_keys, nkeys,
8454 				  now, false);
8455 		if (result != ISC_R_SUCCESS) {
8456 			dns_zone_log(zone, ISC_LOG_ERROR,
8457 				     "dns__zone_updatesigs:del_sigs -> %s",
8458 				     dns_result_totext(result));
8459 			return (result);
8460 		}
8461 		result = add_sigs(db, version, &tuple->name, zone,
8462 				  tuple->rdata.type, zonediff->diff, zone_keys,
8463 				  nkeys, zone->mctx, inception, exp, check_ksk,
8464 				  keyset_kskonly);
8465 		if (result != ISC_R_SUCCESS) {
8466 			dns_zone_log(zone, ISC_LOG_ERROR,
8467 				     "dns__zone_updatesigs:add_sigs -> %s",
8468 				     dns_result_totext(result));
8469 			return (result);
8470 		}
8471 
8472 		/*
8473 		 * Signature changes for all RRs with name tuple->name and type
8474 		 * tuple->rdata.type were appended to zonediff->diff.  Now we
8475 		 * remove all the "raw" changes with the same name and type
8476 		 * from diff (so that they are not processed by this loop
8477 		 * again) and append them to zonediff so that they get applied.
8478 		 */
8479 		move_matching_tuples(tuple, diff, zonediff->diff);
8480 	}
8481 	return (ISC_R_SUCCESS);
8482 }
8483 
8484 /*
8485  * Incrementally build and sign a new NSEC3 chain using the parameters
8486  * requested.
8487  */
8488 static void
zone_nsec3chain(dns_zone_t * zone)8489 zone_nsec3chain(dns_zone_t *zone) {
8490 	const char *me = "zone_nsec3chain";
8491 	dns_db_t *db = NULL;
8492 	dns_dbnode_t *node = NULL;
8493 	dns_dbversion_t *version = NULL;
8494 	dns_diff_t _sig_diff;
8495 	dns_diff_t nsec_diff;
8496 	dns_diff_t nsec3_diff;
8497 	dns_diff_t param_diff;
8498 	dns__zonediff_t zonediff;
8499 	dns_fixedname_t fixed;
8500 	dns_fixedname_t nextfixed;
8501 	dns_name_t *name, *nextname;
8502 	dns_rdataset_t rdataset;
8503 	dns_nsec3chain_t *nsec3chain = NULL, *nextnsec3chain;
8504 	dns_nsec3chainlist_t cleanup;
8505 	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
8506 	int32_t signatures;
8507 	bool check_ksk, keyset_kskonly;
8508 	bool delegation;
8509 	bool first;
8510 	isc_result_t result;
8511 	isc_stdtime_t now, inception, soaexpire, expire;
8512 	uint32_t jitter, sigvalidityinterval, expiryinterval;
8513 	unsigned int i;
8514 	unsigned int nkeys = 0;
8515 	uint32_t nodes;
8516 	bool unsecure = false;
8517 	bool seen_soa, seen_ns, seen_dname, seen_ds;
8518 	bool seen_nsec, seen_nsec3, seen_rr;
8519 	dns_rdatasetiter_t *iterator = NULL;
8520 	bool buildnsecchain;
8521 	bool updatensec = false;
8522 	dns_rdatatype_t privatetype = zone->privatetype;
8523 
8524 	ENTER;
8525 
8526 	dns_rdataset_init(&rdataset);
8527 	name = dns_fixedname_initname(&fixed);
8528 	nextname = dns_fixedname_initname(&nextfixed);
8529 	dns_diff_init(zone->mctx, &param_diff);
8530 	dns_diff_init(zone->mctx, &nsec3_diff);
8531 	dns_diff_init(zone->mctx, &nsec_diff);
8532 	dns_diff_init(zone->mctx, &_sig_diff);
8533 	zonediff_init(&zonediff, &_sig_diff);
8534 	ISC_LIST_INIT(cleanup);
8535 
8536 	/*
8537 	 * Updates are disabled.  Pause for 5 minutes.
8538 	 */
8539 	if (zone->update_disabled) {
8540 		result = ISC_R_FAILURE;
8541 		goto failure;
8542 	}
8543 
8544 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8545 	/*
8546 	 * This function is called when zone timer fires, after the latter gets
8547 	 * set by zone_addnsec3chain().  If the action triggering the call to
8548 	 * zone_addnsec3chain() is closely followed by a zone deletion request,
8549 	 * it might turn out that the timer thread will not be woken up until
8550 	 * after the zone is deleted by rmzone(), which calls dns_db_detach()
8551 	 * for zone->db, causing the latter to become NULL.  Return immediately
8552 	 * if that happens.
8553 	 */
8554 	if (zone->db != NULL) {
8555 		dns_db_attach(zone->db, &db);
8556 	}
8557 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8558 	if (db == NULL) {
8559 		return;
8560 	}
8561 
8562 	result = dns_db_newversion(db, &version);
8563 	if (result != ISC_R_SUCCESS) {
8564 		dnssec_log(zone, ISC_LOG_ERROR,
8565 			   "zone_nsec3chain:dns_db_newversion -> %s",
8566 			   dns_result_totext(result));
8567 		goto failure;
8568 	}
8569 
8570 	isc_stdtime_get(&now);
8571 
8572 	result = dns__zone_findkeys(zone, db, version, now, zone->mctx,
8573 				    DNS_MAXZONEKEYS, zone_keys, &nkeys);
8574 	if (result != ISC_R_SUCCESS) {
8575 		dnssec_log(zone, ISC_LOG_ERROR,
8576 			   "zone_nsec3chain:dns__zone_findkeys -> %s",
8577 			   dns_result_totext(result));
8578 		goto failure;
8579 	}
8580 
8581 	sigvalidityinterval = dns_zone_getsigvalidityinterval(zone);
8582 	inception = now - 3600; /* Allow for clock skew. */
8583 	soaexpire = now + sigvalidityinterval;
8584 	expiryinterval = dns_zone_getsigresigninginterval(zone);
8585 	if (expiryinterval > sigvalidityinterval) {
8586 		expiryinterval = sigvalidityinterval;
8587 	} else {
8588 		expiryinterval = sigvalidityinterval - expiryinterval;
8589 	}
8590 
8591 	/*
8592 	 * Spread out signatures over time if they happen to be
8593 	 * clumped.  We don't do this for each add_sigs() call as
8594 	 * we still want some clustering to occur.
8595 	 */
8596 	if (sigvalidityinterval >= 3600U) {
8597 		if (sigvalidityinterval > 7200U) {
8598 			jitter = isc_random_uniform(expiryinterval);
8599 		} else {
8600 			jitter = isc_random_uniform(1200);
8601 		}
8602 		expire = soaexpire - jitter - 1;
8603 	} else {
8604 		expire = soaexpire - 1;
8605 	}
8606 
8607 	check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
8608 	keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
8609 
8610 	/*
8611 	 * We keep pulling nodes off each iterator in turn until
8612 	 * we have no more nodes to pull off or we reach the limits
8613 	 * for this quantum.
8614 	 */
8615 	nodes = zone->nodes;
8616 	signatures = zone->signatures;
8617 	LOCK_ZONE(zone);
8618 	nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
8619 	UNLOCK_ZONE(zone);
8620 	first = true;
8621 
8622 	if (nsec3chain != NULL) {
8623 		nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
8624 	}
8625 	/*
8626 	 * Generate new NSEC3 chains first.
8627 	 *
8628 	 * The following while loop iterates over nodes in the zone database,
8629 	 * updating the NSEC3 chain by calling dns_nsec3_addnsec3() for each of
8630 	 * them.  Once all nodes are processed, the "delete_nsec" field is
8631 	 * consulted to check whether we are supposed to remove NSEC records
8632 	 * from the zone database; if so, the database iterator is reset to
8633 	 * point to the first node and the loop traverses all of them again,
8634 	 * this time removing NSEC records.  If we hit a node which is obscured
8635 	 * by a delegation or a DNAME, nodes are skipped over until we find one
8636 	 * that is not obscured by the same obscuring name and then normal
8637 	 * processing is resumed.
8638 	 *
8639 	 * The above is repeated until all requested NSEC3 chain changes are
8640 	 * applied or when we reach the limits for this quantum, whichever
8641 	 * happens first.
8642 	 *
8643 	 * Note that the "signatures" variable is only used here to limit the
8644 	 * amount of work performed.  Actual DNSSEC signatures are only
8645 	 * generated by dns__zone_updatesigs() calls later in this function.
8646 	 */
8647 	while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
8648 		dns_dbiterator_pause(nsec3chain->dbiterator);
8649 
8650 		LOCK_ZONE(zone);
8651 		nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
8652 
8653 		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8654 		if (nsec3chain->done || nsec3chain->db != zone->db) {
8655 			ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
8656 			ISC_LIST_APPEND(cleanup, nsec3chain, link);
8657 		}
8658 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8659 		UNLOCK_ZONE(zone);
8660 		if (ISC_LIST_TAIL(cleanup) == nsec3chain) {
8661 			goto next_addchain;
8662 		}
8663 
8664 		/*
8665 		 * Possible future db.
8666 		 */
8667 		if (nsec3chain->db != db) {
8668 			goto next_addchain;
8669 		}
8670 
8671 		if (NSEC3REMOVE(nsec3chain->nsec3param.flags)) {
8672 			goto next_addchain;
8673 		}
8674 
8675 		dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
8676 
8677 		if (nsec3chain->delete_nsec) {
8678 			delegation = false;
8679 			dns_dbiterator_pause(nsec3chain->dbiterator);
8680 			CHECK(delete_nsec(db, version, node, name, &nsec_diff));
8681 			goto next_addnode;
8682 		}
8683 		/*
8684 		 * On the first pass we need to check if the current node
8685 		 * has not been obscured.
8686 		 */
8687 		delegation = false;
8688 		unsecure = false;
8689 		if (first) {
8690 			dns_fixedname_t ffound;
8691 			dns_name_t *found;
8692 			found = dns_fixedname_initname(&ffound);
8693 			result = dns_db_find(
8694 				db, name, version, dns_rdatatype_soa,
8695 				DNS_DBFIND_NOWILD, 0, NULL, found, NULL, NULL);
8696 			if ((result == DNS_R_DELEGATION ||
8697 			     result == DNS_R_DNAME) &&
8698 			    !dns_name_equal(name, found))
8699 			{
8700 				/*
8701 				 * Remember the obscuring name so that
8702 				 * we skip all obscured names.
8703 				 */
8704 				dns_name_copynf(found, name);
8705 				delegation = true;
8706 				goto next_addnode;
8707 			}
8708 		}
8709 
8710 		/*
8711 		 * Check to see if this is a bottom of zone node.
8712 		 */
8713 		result = dns_db_allrdatasets(db, node, version, 0, 0,
8714 					     &iterator);
8715 		if (result == ISC_R_NOTFOUND) {
8716 			/* Empty node? */
8717 			goto next_addnode;
8718 		}
8719 		if (result != ISC_R_SUCCESS) {
8720 			goto failure;
8721 		}
8722 
8723 		seen_soa = seen_ns = seen_dname = seen_ds = seen_nsec = false;
8724 		for (result = dns_rdatasetiter_first(iterator);
8725 		     result == ISC_R_SUCCESS;
8726 		     result = dns_rdatasetiter_next(iterator))
8727 		{
8728 			dns_rdatasetiter_current(iterator, &rdataset);
8729 			INSIST(rdataset.type != dns_rdatatype_nsec3);
8730 			if (rdataset.type == dns_rdatatype_soa) {
8731 				seen_soa = true;
8732 			} else if (rdataset.type == dns_rdatatype_ns) {
8733 				seen_ns = true;
8734 			} else if (rdataset.type == dns_rdatatype_dname) {
8735 				seen_dname = true;
8736 			} else if (rdataset.type == dns_rdatatype_ds) {
8737 				seen_ds = true;
8738 			} else if (rdataset.type == dns_rdatatype_nsec) {
8739 				seen_nsec = true;
8740 			}
8741 			dns_rdataset_disassociate(&rdataset);
8742 		}
8743 		dns_rdatasetiter_destroy(&iterator);
8744 		/*
8745 		 * Is there a NSEC chain than needs to be cleaned up?
8746 		 */
8747 		if (seen_nsec) {
8748 			nsec3chain->seen_nsec = true;
8749 		}
8750 		if (seen_ns && !seen_soa && !seen_ds) {
8751 			unsecure = true;
8752 		}
8753 		if ((seen_ns && !seen_soa) || seen_dname) {
8754 			delegation = true;
8755 		}
8756 
8757 		/*
8758 		 * Process one node.
8759 		 */
8760 		dns_dbiterator_pause(nsec3chain->dbiterator);
8761 		result = dns_nsec3_addnsec3(
8762 			db, version, name, &nsec3chain->nsec3param,
8763 			zone_nsecttl(zone), unsecure, &nsec3_diff);
8764 		if (result != ISC_R_SUCCESS) {
8765 			dnssec_log(zone, ISC_LOG_ERROR,
8766 				   "zone_nsec3chain:"
8767 				   "dns_nsec3_addnsec3 -> %s",
8768 				   dns_result_totext(result));
8769 			goto failure;
8770 		}
8771 
8772 		/*
8773 		 * Treat each call to dns_nsec3_addnsec3() as if it's cost is
8774 		 * two signatures.  Additionally there will, in general, be
8775 		 * two signature generated below.
8776 		 *
8777 		 * If we are only changing the optout flag the cost is half
8778 		 * that of the cost of generating a completely new chain.
8779 		 */
8780 		signatures -= 4;
8781 
8782 		/*
8783 		 * Go onto next node.
8784 		 */
8785 	next_addnode:
8786 		first = false;
8787 		dns_db_detachnode(db, &node);
8788 		do {
8789 			result = dns_dbiterator_next(nsec3chain->dbiterator);
8790 
8791 			if (result == ISC_R_NOMORE && nsec3chain->delete_nsec) {
8792 				dns_dbiterator_pause(nsec3chain->dbiterator);
8793 				CHECK(fixup_nsec3param(db, version, nsec3chain,
8794 						       false, privatetype,
8795 						       &param_diff));
8796 				LOCK_ZONE(zone);
8797 				ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
8798 						link);
8799 				UNLOCK_ZONE(zone);
8800 				ISC_LIST_APPEND(cleanup, nsec3chain, link);
8801 				goto next_addchain;
8802 			}
8803 			if (result == ISC_R_NOMORE) {
8804 				dns_dbiterator_pause(nsec3chain->dbiterator);
8805 				if (nsec3chain->seen_nsec) {
8806 					CHECK(fixup_nsec3param(
8807 						db, version, nsec3chain, true,
8808 						privatetype, &param_diff));
8809 					nsec3chain->delete_nsec = true;
8810 					goto same_addchain;
8811 				}
8812 				CHECK(fixup_nsec3param(db, version, nsec3chain,
8813 						       false, privatetype,
8814 						       &param_diff));
8815 				LOCK_ZONE(zone);
8816 				ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
8817 						link);
8818 				UNLOCK_ZONE(zone);
8819 				ISC_LIST_APPEND(cleanup, nsec3chain, link);
8820 				goto next_addchain;
8821 			} else if (result != ISC_R_SUCCESS) {
8822 				dnssec_log(zone, ISC_LOG_ERROR,
8823 					   "zone_nsec3chain:"
8824 					   "dns_dbiterator_next -> %s",
8825 					   dns_result_totext(result));
8826 				goto failure;
8827 			} else if (delegation) {
8828 				dns_dbiterator_current(nsec3chain->dbiterator,
8829 						       &node, nextname);
8830 				dns_db_detachnode(db, &node);
8831 				if (!dns_name_issubdomain(nextname, name)) {
8832 					break;
8833 				}
8834 			} else {
8835 				break;
8836 			}
8837 		} while (1);
8838 		continue;
8839 
8840 	same_addchain:
8841 		CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
8842 		first = true;
8843 		continue;
8844 
8845 	next_addchain:
8846 		dns_dbiterator_pause(nsec3chain->dbiterator);
8847 		nsec3chain = nextnsec3chain;
8848 		first = true;
8849 		if (nsec3chain != NULL) {
8850 			nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
8851 		}
8852 	}
8853 
8854 	if (nsec3chain != NULL) {
8855 		goto skip_removals;
8856 	}
8857 
8858 	/*
8859 	 * Process removals.
8860 	 *
8861 	 * This is a counterpart of the above while loop which takes care of
8862 	 * removing an NSEC3 chain.  It starts with determining whether the
8863 	 * zone needs to switch from NSEC3 to NSEC; if so, it first builds an
8864 	 * NSEC chain by iterating over all nodes in the zone database and only
8865 	 * then goes on to remove NSEC3 records be iterating over all nodes
8866 	 * again and calling deletematchingnsec3() for each of them; otherwise,
8867 	 * it starts removing NSEC3 records immediately.  Rules for processing
8868 	 * obscured nodes and interrupting work are the same as for the while
8869 	 * loop above.
8870 	 */
8871 	LOCK_ZONE(zone);
8872 	nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
8873 	UNLOCK_ZONE(zone);
8874 	first = true;
8875 	buildnsecchain = false;
8876 	while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
8877 		dns_dbiterator_pause(nsec3chain->dbiterator);
8878 
8879 		LOCK_ZONE(zone);
8880 		nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
8881 		UNLOCK_ZONE(zone);
8882 
8883 		if (nsec3chain->db != db) {
8884 			goto next_removechain;
8885 		}
8886 
8887 		if (!NSEC3REMOVE(nsec3chain->nsec3param.flags)) {
8888 			goto next_removechain;
8889 		}
8890 
8891 		/*
8892 		 * Work out if we need to build a NSEC chain as a consequence
8893 		 * of removing this NSEC3 chain.
8894 		 */
8895 		if (first && !updatensec &&
8896 		    (nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_NONSEC) == 0)
8897 		{
8898 			result = need_nsec_chain(db, version,
8899 						 &nsec3chain->nsec3param,
8900 						 &buildnsecchain);
8901 			if (result != ISC_R_SUCCESS) {
8902 				dnssec_log(zone, ISC_LOG_ERROR,
8903 					   "zone_nsec3chain:"
8904 					   "need_nsec_chain -> %s",
8905 					   dns_result_totext(result));
8906 				goto failure;
8907 			}
8908 		}
8909 
8910 		if (first) {
8911 			dnssec_log(zone, ISC_LOG_DEBUG(3),
8912 				   "zone_nsec3chain:buildnsecchain = %u\n",
8913 				   buildnsecchain);
8914 		}
8915 
8916 		dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
8917 		dns_dbiterator_pause(nsec3chain->dbiterator);
8918 		delegation = false;
8919 
8920 		if (!buildnsecchain) {
8921 			/*
8922 			 * Delete the NSEC3PARAM record matching this chain.
8923 			 */
8924 			if (first) {
8925 				result = fixup_nsec3param(
8926 					db, version, nsec3chain, true,
8927 					privatetype, &param_diff);
8928 				if (result != ISC_R_SUCCESS) {
8929 					dnssec_log(zone, ISC_LOG_ERROR,
8930 						   "zone_nsec3chain:"
8931 						   "fixup_nsec3param -> %s",
8932 						   dns_result_totext(result));
8933 					goto failure;
8934 				}
8935 			}
8936 
8937 			/*
8938 			 * Delete the NSEC3 records.
8939 			 */
8940 			result = deletematchingnsec3(db, version, node, name,
8941 						     &nsec3chain->nsec3param,
8942 						     &nsec3_diff);
8943 			if (result != ISC_R_SUCCESS) {
8944 				dnssec_log(zone, ISC_LOG_ERROR,
8945 					   "zone_nsec3chain:"
8946 					   "deletematchingnsec3 -> %s",
8947 					   dns_result_totext(result));
8948 				goto failure;
8949 			}
8950 			goto next_removenode;
8951 		}
8952 
8953 		if (first) {
8954 			dns_fixedname_t ffound;
8955 			dns_name_t *found;
8956 			found = dns_fixedname_initname(&ffound);
8957 			result = dns_db_find(
8958 				db, name, version, dns_rdatatype_soa,
8959 				DNS_DBFIND_NOWILD, 0, NULL, found, NULL, NULL);
8960 			if ((result == DNS_R_DELEGATION ||
8961 			     result == DNS_R_DNAME) &&
8962 			    !dns_name_equal(name, found))
8963 			{
8964 				/*
8965 				 * Remember the obscuring name so that
8966 				 * we skip all obscured names.
8967 				 */
8968 				dns_name_copynf(found, name);
8969 				delegation = true;
8970 				goto next_removenode;
8971 			}
8972 		}
8973 
8974 		/*
8975 		 * Check to see if this is a bottom of zone node.
8976 		 */
8977 		result = dns_db_allrdatasets(db, node, version, 0, 0,
8978 					     &iterator);
8979 		if (result == ISC_R_NOTFOUND) {
8980 			/* Empty node? */
8981 			goto next_removenode;
8982 		}
8983 		if (result != ISC_R_SUCCESS) {
8984 			goto failure;
8985 		}
8986 
8987 		seen_soa = seen_ns = seen_dname = seen_nsec3 = seen_nsec =
8988 			seen_rr = false;
8989 		for (result = dns_rdatasetiter_first(iterator);
8990 		     result == ISC_R_SUCCESS;
8991 		     result = dns_rdatasetiter_next(iterator))
8992 		{
8993 			dns_rdatasetiter_current(iterator, &rdataset);
8994 			if (rdataset.type == dns_rdatatype_soa) {
8995 				seen_soa = true;
8996 			} else if (rdataset.type == dns_rdatatype_ns) {
8997 				seen_ns = true;
8998 			} else if (rdataset.type == dns_rdatatype_dname) {
8999 				seen_dname = true;
9000 			} else if (rdataset.type == dns_rdatatype_nsec) {
9001 				seen_nsec = true;
9002 			} else if (rdataset.type == dns_rdatatype_nsec3) {
9003 				seen_nsec3 = true;
9004 			} else if (rdataset.type != dns_rdatatype_rrsig) {
9005 				seen_rr = true;
9006 			}
9007 			dns_rdataset_disassociate(&rdataset);
9008 		}
9009 		dns_rdatasetiter_destroy(&iterator);
9010 
9011 		if (!seen_rr || seen_nsec3 || seen_nsec) {
9012 			goto next_removenode;
9013 		}
9014 		if ((seen_ns && !seen_soa) || seen_dname) {
9015 			delegation = true;
9016 		}
9017 
9018 		/*
9019 		 * Add a NSEC record except at the origin.
9020 		 */
9021 		if (!dns_name_equal(name, dns_db_origin(db))) {
9022 			dns_dbiterator_pause(nsec3chain->dbiterator);
9023 			CHECK(add_nsec(db, version, name, node,
9024 				       zone_nsecttl(zone), delegation,
9025 				       &nsec_diff));
9026 			signatures--;
9027 		}
9028 
9029 	next_removenode:
9030 		first = false;
9031 		dns_db_detachnode(db, &node);
9032 		do {
9033 			result = dns_dbiterator_next(nsec3chain->dbiterator);
9034 			if (result == ISC_R_NOMORE && buildnsecchain) {
9035 				/*
9036 				 * The NSEC chain should now be built.
9037 				 * We can now remove the NSEC3 chain.
9038 				 */
9039 				updatensec = true;
9040 				goto same_removechain;
9041 			}
9042 			if (result == ISC_R_NOMORE) {
9043 				dns_dbiterator_pause(nsec3chain->dbiterator);
9044 				LOCK_ZONE(zone);
9045 				ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
9046 						link);
9047 				UNLOCK_ZONE(zone);
9048 				ISC_LIST_APPEND(cleanup, nsec3chain, link);
9049 				result = fixup_nsec3param(
9050 					db, version, nsec3chain, false,
9051 					privatetype, &param_diff);
9052 				if (result != ISC_R_SUCCESS) {
9053 					dnssec_log(zone, ISC_LOG_ERROR,
9054 						   "zone_nsec3chain:"
9055 						   "fixup_nsec3param -> %s",
9056 						   dns_result_totext(result));
9057 					goto failure;
9058 				}
9059 				goto next_removechain;
9060 			} else if (result != ISC_R_SUCCESS) {
9061 				dnssec_log(zone, ISC_LOG_ERROR,
9062 					   "zone_nsec3chain:"
9063 					   "dns_dbiterator_next -> %s",
9064 					   dns_result_totext(result));
9065 				goto failure;
9066 			} else if (delegation) {
9067 				dns_dbiterator_current(nsec3chain->dbiterator,
9068 						       &node, nextname);
9069 				dns_db_detachnode(db, &node);
9070 				if (!dns_name_issubdomain(nextname, name)) {
9071 					break;
9072 				}
9073 			} else {
9074 				break;
9075 			}
9076 		} while (1);
9077 		continue;
9078 
9079 	same_removechain:
9080 		CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
9081 		buildnsecchain = false;
9082 		first = true;
9083 		continue;
9084 
9085 	next_removechain:
9086 		dns_dbiterator_pause(nsec3chain->dbiterator);
9087 		nsec3chain = nextnsec3chain;
9088 		first = true;
9089 	}
9090 
9091 skip_removals:
9092 	/*
9093 	 * We may need to update the NSEC/NSEC3 records for the zone apex.
9094 	 */
9095 	if (!ISC_LIST_EMPTY(param_diff.tuples)) {
9096 		bool rebuild_nsec = false, rebuild_nsec3 = false;
9097 		result = dns_db_getoriginnode(db, &node);
9098 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
9099 		result = dns_db_allrdatasets(db, node, version, 0, 0,
9100 					     &iterator);
9101 		if (result != ISC_R_SUCCESS) {
9102 			dnssec_log(zone, ISC_LOG_ERROR,
9103 				   "zone_nsec3chain:dns_db_allrdatasets -> %s",
9104 				   dns_result_totext(result));
9105 			goto failure;
9106 		}
9107 		for (result = dns_rdatasetiter_first(iterator);
9108 		     result == ISC_R_SUCCESS;
9109 		     result = dns_rdatasetiter_next(iterator))
9110 		{
9111 			dns_rdatasetiter_current(iterator, &rdataset);
9112 			if (rdataset.type == dns_rdatatype_nsec) {
9113 				rebuild_nsec = true;
9114 			} else if (rdataset.type == dns_rdatatype_nsec3param) {
9115 				rebuild_nsec3 = true;
9116 			}
9117 			dns_rdataset_disassociate(&rdataset);
9118 		}
9119 		dns_rdatasetiter_destroy(&iterator);
9120 		dns_db_detachnode(db, &node);
9121 
9122 		if (rebuild_nsec) {
9123 			if (nsec3chain != NULL) {
9124 				dns_dbiterator_pause(nsec3chain->dbiterator);
9125 			}
9126 
9127 			result = updatesecure(db, version, &zone->origin,
9128 					      zone_nsecttl(zone), true,
9129 					      &nsec_diff);
9130 			if (result != ISC_R_SUCCESS) {
9131 				dnssec_log(zone, ISC_LOG_ERROR,
9132 					   "zone_nsec3chain:updatesecure -> %s",
9133 					   dns_result_totext(result));
9134 				goto failure;
9135 			}
9136 		}
9137 
9138 		if (rebuild_nsec3) {
9139 			if (nsec3chain != NULL) {
9140 				dns_dbiterator_pause(nsec3chain->dbiterator);
9141 			}
9142 
9143 			result = dns_nsec3_addnsec3s(
9144 				db, version, dns_db_origin(db),
9145 				zone_nsecttl(zone), false, &nsec3_diff);
9146 			if (result != ISC_R_SUCCESS) {
9147 				dnssec_log(zone, ISC_LOG_ERROR,
9148 					   "zone_nsec3chain:"
9149 					   "dns_nsec3_addnsec3s -> %s",
9150 					   dns_result_totext(result));
9151 				goto failure;
9152 			}
9153 		}
9154 	}
9155 
9156 	/*
9157 	 * Add / update signatures for the NSEC3 records.
9158 	 */
9159 	if (nsec3chain != NULL) {
9160 		dns_dbiterator_pause(nsec3chain->dbiterator);
9161 	}
9162 	result = dns__zone_updatesigs(&nsec3_diff, db, version, zone_keys,
9163 				      nkeys, zone, inception, expire, 0, now,
9164 				      check_ksk, keyset_kskonly, &zonediff);
9165 	if (result != ISC_R_SUCCESS) {
9166 		dnssec_log(zone, ISC_LOG_ERROR,
9167 			   "zone_nsec3chain:dns__zone_updatesigs -> %s",
9168 			   dns_result_totext(result));
9169 		goto failure;
9170 	}
9171 
9172 	/*
9173 	 * We have changed the NSEC3PARAM or private RRsets
9174 	 * above so we need to update the signatures.
9175 	 */
9176 	result = dns__zone_updatesigs(&param_diff, db, version, zone_keys,
9177 				      nkeys, zone, inception, expire, 0, now,
9178 				      check_ksk, keyset_kskonly, &zonediff);
9179 	if (result != ISC_R_SUCCESS) {
9180 		dnssec_log(zone, ISC_LOG_ERROR,
9181 			   "zone_nsec3chain:dns__zone_updatesigs -> %s",
9182 			   dns_result_totext(result));
9183 		goto failure;
9184 	}
9185 
9186 	if (updatensec) {
9187 		result = updatesecure(db, version, &zone->origin,
9188 				      zone_nsecttl(zone), false, &nsec_diff);
9189 		if (result != ISC_R_SUCCESS) {
9190 			dnssec_log(zone, ISC_LOG_ERROR,
9191 				   "zone_nsec3chain:updatesecure -> %s",
9192 				   dns_result_totext(result));
9193 			goto failure;
9194 		}
9195 	}
9196 
9197 	result = dns__zone_updatesigs(&nsec_diff, db, version, zone_keys, nkeys,
9198 				      zone, inception, expire, 0, now,
9199 				      check_ksk, keyset_kskonly, &zonediff);
9200 	if (result != ISC_R_SUCCESS) {
9201 		dnssec_log(zone, ISC_LOG_ERROR,
9202 			   "zone_nsec3chain:dns__zone_updatesigs -> %s",
9203 			   dns_result_totext(result));
9204 		goto failure;
9205 	}
9206 
9207 	/*
9208 	 * If we made no effective changes to the zone then we can just
9209 	 * cleanup otherwise we need to increment the serial.
9210 	 */
9211 	if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
9212 		/*
9213 		 * No need to call dns_db_closeversion() here as it is
9214 		 * called with commit = true below.
9215 		 */
9216 		goto done;
9217 	}
9218 
9219 	result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
9220 			  &zonediff, zone_keys, nkeys, now, false);
9221 	if (result != ISC_R_SUCCESS) {
9222 		dnssec_log(zone, ISC_LOG_ERROR,
9223 			   "zone_nsec3chain:del_sigs -> %s",
9224 			   dns_result_totext(result));
9225 		goto failure;
9226 	}
9227 
9228 	result = update_soa_serial(zone, db, version, zonediff.diff, zone->mctx,
9229 				   zone->updatemethod);
9230 	if (result != ISC_R_SUCCESS) {
9231 		dnssec_log(zone, ISC_LOG_ERROR,
9232 			   "zone_nsec3chain:update_soa_serial -> %s",
9233 			   dns_result_totext(result));
9234 		goto failure;
9235 	}
9236 
9237 	result = add_sigs(db, version, &zone->origin, zone, dns_rdatatype_soa,
9238 			  zonediff.diff, zone_keys, nkeys, zone->mctx,
9239 			  inception, soaexpire, check_ksk, keyset_kskonly);
9240 	if (result != ISC_R_SUCCESS) {
9241 		dnssec_log(zone, ISC_LOG_ERROR,
9242 			   "zone_nsec3chain:add_sigs -> %s",
9243 			   dns_result_totext(result));
9244 		goto failure;
9245 	}
9246 
9247 	/* Write changes to journal file. */
9248 	CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_nsec3chain"));
9249 
9250 	LOCK_ZONE(zone);
9251 	zone_needdump(zone, DNS_DUMP_DELAY);
9252 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
9253 	UNLOCK_ZONE(zone);
9254 
9255 done:
9256 	/*
9257 	 * Pause all iterators so that dns_db_closeversion() can succeed.
9258 	 */
9259 	LOCK_ZONE(zone);
9260 	for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain); nsec3chain != NULL;
9261 	     nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
9262 	{
9263 		dns_dbiterator_pause(nsec3chain->dbiterator);
9264 	}
9265 	UNLOCK_ZONE(zone);
9266 
9267 	/*
9268 	 * Everything has succeeded. Commit the changes.
9269 	 * Unconditionally commit as zonediff.offline not checked above.
9270 	 */
9271 	dns_db_closeversion(db, &version, true);
9272 
9273 	/*
9274 	 * Everything succeeded so we can clean these up now.
9275 	 */
9276 	nsec3chain = ISC_LIST_HEAD(cleanup);
9277 	while (nsec3chain != NULL) {
9278 		ISC_LIST_UNLINK(cleanup, nsec3chain, link);
9279 		dns_db_detach(&nsec3chain->db);
9280 		dns_dbiterator_destroy(&nsec3chain->dbiterator);
9281 		isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
9282 		nsec3chain = ISC_LIST_HEAD(cleanup);
9283 	}
9284 
9285 	LOCK_ZONE(zone);
9286 	set_resigntime(zone);
9287 	UNLOCK_ZONE(zone);
9288 
9289 failure:
9290 	if (result != ISC_R_SUCCESS) {
9291 		dnssec_log(zone, ISC_LOG_ERROR, "zone_nsec3chain: %s",
9292 			   dns_result_totext(result));
9293 	}
9294 
9295 	/*
9296 	 * On error roll back the current nsec3chain.
9297 	 */
9298 	if (result != ISC_R_SUCCESS && nsec3chain != NULL) {
9299 		if (nsec3chain->done) {
9300 			dns_db_detach(&nsec3chain->db);
9301 			dns_dbiterator_destroy(&nsec3chain->dbiterator);
9302 			isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
9303 		} else {
9304 			result = dns_dbiterator_first(nsec3chain->dbiterator);
9305 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
9306 			dns_dbiterator_pause(nsec3chain->dbiterator);
9307 			nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
9308 		}
9309 	}
9310 
9311 	/*
9312 	 * Rollback the cleanup list.
9313 	 */
9314 	nsec3chain = ISC_LIST_TAIL(cleanup);
9315 	while (nsec3chain != NULL) {
9316 		ISC_LIST_UNLINK(cleanup, nsec3chain, link);
9317 		if (nsec3chain->done) {
9318 			dns_db_detach(&nsec3chain->db);
9319 			dns_dbiterator_destroy(&nsec3chain->dbiterator);
9320 			isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
9321 		} else {
9322 			LOCK_ZONE(zone);
9323 			ISC_LIST_PREPEND(zone->nsec3chain, nsec3chain, link);
9324 			UNLOCK_ZONE(zone);
9325 			result = dns_dbiterator_first(nsec3chain->dbiterator);
9326 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
9327 			dns_dbiterator_pause(nsec3chain->dbiterator);
9328 			nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
9329 		}
9330 		nsec3chain = ISC_LIST_TAIL(cleanup);
9331 	}
9332 
9333 	LOCK_ZONE(zone);
9334 	for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain); nsec3chain != NULL;
9335 	     nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
9336 	{
9337 		dns_dbiterator_pause(nsec3chain->dbiterator);
9338 	}
9339 	UNLOCK_ZONE(zone);
9340 
9341 	dns_diff_clear(&param_diff);
9342 	dns_diff_clear(&nsec3_diff);
9343 	dns_diff_clear(&nsec_diff);
9344 	dns_diff_clear(&_sig_diff);
9345 
9346 	if (iterator != NULL) {
9347 		dns_rdatasetiter_destroy(&iterator);
9348 	}
9349 
9350 	for (i = 0; i < nkeys; i++) {
9351 		dst_key_free(&zone_keys[i]);
9352 	}
9353 
9354 	if (node != NULL) {
9355 		dns_db_detachnode(db, &node);
9356 	}
9357 	if (version != NULL) {
9358 		dns_db_closeversion(db, &version, false);
9359 		dns_db_detach(&db);
9360 	} else if (db != NULL) {
9361 		dns_db_detach(&db);
9362 	}
9363 
9364 	LOCK_ZONE(zone);
9365 	if (ISC_LIST_HEAD(zone->nsec3chain) != NULL) {
9366 		isc_interval_t interval;
9367 		if (zone->update_disabled || result != ISC_R_SUCCESS) {
9368 			isc_interval_set(&interval, 60, 0); /* 1 minute */
9369 		} else {
9370 			isc_interval_set(&interval, 0, 10000000); /* 10 ms */
9371 		}
9372 		isc_time_nowplusinterval(&zone->nsec3chaintime, &interval);
9373 	} else {
9374 		isc_time_settoepoch(&zone->nsec3chaintime);
9375 	}
9376 	UNLOCK_ZONE(zone);
9377 
9378 	INSIST(version == NULL);
9379 }
9380 
9381 /*%
9382  * Delete all RRSIG records with the given algorithm and keyid.
9383  * Remove the NSEC record and RRSIGs if nkeys is zero.
9384  * If all remaining RRsets are signed with the given algorithm
9385  * set *has_algp to true.
9386  */
9387 static isc_result_t
del_sig(dns_db_t * db,dns_dbversion_t * version,dns_name_t * name,dns_dbnode_t * node,unsigned int nkeys,dns_secalg_t algorithm,uint16_t keyid,bool * has_algp,dns_diff_t * diff)9388 del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
9389 	dns_dbnode_t *node, unsigned int nkeys, dns_secalg_t algorithm,
9390 	uint16_t keyid, bool *has_algp, dns_diff_t *diff) {
9391 	dns_rdata_rrsig_t rrsig;
9392 	dns_rdataset_t rdataset;
9393 	dns_rdatasetiter_t *iterator = NULL;
9394 	isc_result_t result;
9395 	bool alg_missed = false;
9396 	bool alg_found = false;
9397 
9398 	char namebuf[DNS_NAME_FORMATSIZE];
9399 	dns_name_format(name, namebuf, sizeof(namebuf));
9400 
9401 	result = dns_db_allrdatasets(db, node, version, 0, 0, &iterator);
9402 	if (result != ISC_R_SUCCESS) {
9403 		if (result == ISC_R_NOTFOUND) {
9404 			result = ISC_R_SUCCESS;
9405 		}
9406 		return (result);
9407 	}
9408 
9409 	dns_rdataset_init(&rdataset);
9410 	for (result = dns_rdatasetiter_first(iterator); result == ISC_R_SUCCESS;
9411 	     result = dns_rdatasetiter_next(iterator))
9412 	{
9413 		bool has_alg = false;
9414 		dns_rdatasetiter_current(iterator, &rdataset);
9415 		if (nkeys == 0 && rdataset.type == dns_rdatatype_nsec) {
9416 			for (result = dns_rdataset_first(&rdataset);
9417 			     result == ISC_R_SUCCESS;
9418 			     result = dns_rdataset_next(&rdataset))
9419 			{
9420 				dns_rdata_t rdata = DNS_RDATA_INIT;
9421 				dns_rdataset_current(&rdataset, &rdata);
9422 				CHECK(update_one_rr(db, version, diff,
9423 						    DNS_DIFFOP_DEL, name,
9424 						    rdataset.ttl, &rdata));
9425 			}
9426 			if (result != ISC_R_NOMORE) {
9427 				goto failure;
9428 			}
9429 			dns_rdataset_disassociate(&rdataset);
9430 			continue;
9431 		}
9432 		if (rdataset.type != dns_rdatatype_rrsig) {
9433 			dns_rdataset_disassociate(&rdataset);
9434 			continue;
9435 		}
9436 		for (result = dns_rdataset_first(&rdataset);
9437 		     result == ISC_R_SUCCESS;
9438 		     result = dns_rdataset_next(&rdataset))
9439 		{
9440 			dns_rdata_t rdata = DNS_RDATA_INIT;
9441 			dns_rdataset_current(&rdataset, &rdata);
9442 			CHECK(dns_rdata_tostruct(&rdata, &rrsig, NULL));
9443 			if (nkeys != 0 && (rrsig.algorithm != algorithm ||
9444 					   rrsig.keyid != keyid))
9445 			{
9446 				if (rrsig.algorithm == algorithm) {
9447 					has_alg = true;
9448 				}
9449 				continue;
9450 			}
9451 			CHECK(update_one_rr(db, version, diff,
9452 					    DNS_DIFFOP_DELRESIGN, name,
9453 					    rdataset.ttl, &rdata));
9454 		}
9455 		dns_rdataset_disassociate(&rdataset);
9456 		if (result != ISC_R_NOMORE) {
9457 			break;
9458 		}
9459 
9460 		/*
9461 		 * After deleting, if there's still a signature for
9462 		 * 'algorithm', set alg_found; if not, set alg_missed.
9463 		 */
9464 		if (has_alg) {
9465 			alg_found = true;
9466 		} else {
9467 			alg_missed = true;
9468 		}
9469 	}
9470 	if (result == ISC_R_NOMORE) {
9471 		result = ISC_R_SUCCESS;
9472 	}
9473 
9474 	/*
9475 	 * Set `has_algp` if the algorithm was found in every RRset:
9476 	 * i.e., found in at least one, and not missing from any.
9477 	 */
9478 	*has_algp = (alg_found && !alg_missed);
9479 failure:
9480 	if (dns_rdataset_isassociated(&rdataset)) {
9481 		dns_rdataset_disassociate(&rdataset);
9482 	}
9483 	dns_rdatasetiter_destroy(&iterator);
9484 	return (result);
9485 }
9486 
9487 /*
9488  * Incrementally sign the zone using the keys requested.
9489  * Builds the NSEC chain if required.
9490  */
9491 static void
zone_sign(dns_zone_t * zone)9492 zone_sign(dns_zone_t *zone) {
9493 	const char *me = "zone_sign";
9494 	dns_db_t *db = NULL;
9495 	dns_dbnode_t *node = NULL;
9496 	dns_dbversion_t *version = NULL;
9497 	dns_diff_t _sig_diff;
9498 	dns_diff_t post_diff;
9499 	dns__zonediff_t zonediff;
9500 	dns_fixedname_t fixed;
9501 	dns_fixedname_t nextfixed;
9502 	dns_kasp_t *kasp;
9503 	dns_name_t *name, *nextname;
9504 	dns_rdataset_t rdataset;
9505 	dns_signing_t *signing, *nextsigning;
9506 	dns_signinglist_t cleanup;
9507 	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
9508 	int32_t signatures;
9509 	bool check_ksk, keyset_kskonly, is_ksk, is_zsk;
9510 	bool with_ksk, with_zsk;
9511 	bool commit = false;
9512 	bool is_bottom_of_zone;
9513 	bool build_nsec = false;
9514 	bool build_nsec3 = false;
9515 	bool use_kasp = false;
9516 	bool first;
9517 	isc_result_t result;
9518 	isc_stdtime_t now, inception, soaexpire, expire;
9519 	uint32_t jitter, sigvalidityinterval, expiryinterval;
9520 	unsigned int i, j;
9521 	unsigned int nkeys = 0;
9522 	uint32_t nodes;
9523 
9524 	ENTER;
9525 
9526 	dns_rdataset_init(&rdataset);
9527 	name = dns_fixedname_initname(&fixed);
9528 	nextname = dns_fixedname_initname(&nextfixed);
9529 	dns_diff_init(zone->mctx, &_sig_diff);
9530 	dns_diff_init(zone->mctx, &post_diff);
9531 	zonediff_init(&zonediff, &_sig_diff);
9532 	ISC_LIST_INIT(cleanup);
9533 
9534 	/*
9535 	 * Updates are disabled.  Pause for 1 minute.
9536 	 */
9537 	if (zone->update_disabled) {
9538 		result = ISC_R_FAILURE;
9539 		goto cleanup;
9540 	}
9541 
9542 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9543 	if (zone->db != NULL) {
9544 		dns_db_attach(zone->db, &db);
9545 	}
9546 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9547 	if (db == NULL) {
9548 		result = ISC_R_FAILURE;
9549 		goto cleanup;
9550 	}
9551 
9552 	result = dns_db_newversion(db, &version);
9553 	if (result != ISC_R_SUCCESS) {
9554 		dnssec_log(zone, ISC_LOG_ERROR,
9555 			   "zone_sign:dns_db_newversion -> %s",
9556 			   dns_result_totext(result));
9557 		goto cleanup;
9558 	}
9559 
9560 	isc_stdtime_get(&now);
9561 
9562 	result = dns__zone_findkeys(zone, db, version, now, zone->mctx,
9563 				    DNS_MAXZONEKEYS, zone_keys, &nkeys);
9564 	if (result != ISC_R_SUCCESS) {
9565 		dnssec_log(zone, ISC_LOG_ERROR,
9566 			   "zone_sign:dns__zone_findkeys -> %s",
9567 			   dns_result_totext(result));
9568 		goto cleanup;
9569 	}
9570 
9571 	kasp = dns_zone_getkasp(zone);
9572 	sigvalidityinterval = dns_zone_getsigvalidityinterval(zone);
9573 	inception = now - 3600; /* Allow for clock skew. */
9574 	soaexpire = now + sigvalidityinterval;
9575 	expiryinterval = dns_zone_getsigresigninginterval(zone);
9576 	if (expiryinterval > sigvalidityinterval) {
9577 		expiryinterval = sigvalidityinterval;
9578 	} else {
9579 		expiryinterval = sigvalidityinterval - expiryinterval;
9580 	}
9581 
9582 	/*
9583 	 * Spread out signatures over time if they happen to be
9584 	 * clumped.  We don't do this for each add_sigs() call as
9585 	 * we still want some clustering to occur.
9586 	 */
9587 	if (sigvalidityinterval >= 3600U) {
9588 		if (sigvalidityinterval > 7200U) {
9589 			jitter = isc_random_uniform(expiryinterval);
9590 		} else {
9591 			jitter = isc_random_uniform(1200);
9592 		}
9593 		expire = soaexpire - jitter - 1;
9594 	} else {
9595 		expire = soaexpire - 1;
9596 	}
9597 
9598 	/*
9599 	 * We keep pulling nodes off each iterator in turn until
9600 	 * we have no more nodes to pull off or we reach the limits
9601 	 * for this quantum.
9602 	 */
9603 	nodes = zone->nodes;
9604 	signatures = zone->signatures;
9605 	signing = ISC_LIST_HEAD(zone->signing);
9606 	first = true;
9607 
9608 	if (dns_zone_getkasp(zone) != NULL) {
9609 		check_ksk = false;
9610 		keyset_kskonly = true;
9611 		use_kasp = true;
9612 	} else {
9613 		check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
9614 		keyset_kskonly = DNS_ZONE_OPTION(zone,
9615 						 DNS_ZONEOPT_DNSKEYKSKONLY);
9616 	}
9617 	dnssec_log(zone, ISC_LOG_DEBUG(3), "zone_sign:use kasp -> %s",
9618 		   use_kasp ? "yes" : "no");
9619 
9620 	/* Determine which type of chain to build */
9621 	CHECK(dns_private_chains(db, version, zone->privatetype, &build_nsec,
9622 				 &build_nsec3));
9623 	if (!build_nsec && !build_nsec3) {
9624 		if (use_kasp) {
9625 			build_nsec3 = dns_kasp_nsec3(kasp);
9626 			build_nsec = !build_nsec3;
9627 		} else {
9628 			/* If neither chain is found, default to NSEC */
9629 			build_nsec = true;
9630 		}
9631 	}
9632 
9633 	while (signing != NULL && nodes-- > 0 && signatures > 0) {
9634 		bool has_alg = false;
9635 
9636 		dns_dbiterator_pause(signing->dbiterator);
9637 		nextsigning = ISC_LIST_NEXT(signing, link);
9638 
9639 		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9640 		if (signing->done || signing->db != zone->db) {
9641 			/*
9642 			 * The zone has been reloaded.	We will have to
9643 			 * created new signings as part of the reload
9644 			 * process so we can destroy this one.
9645 			 */
9646 			ISC_LIST_UNLINK(zone->signing, signing, link);
9647 			ISC_LIST_APPEND(cleanup, signing, link);
9648 			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9649 			goto next_signing;
9650 		}
9651 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9652 
9653 		if (signing->db != db) {
9654 			goto next_signing;
9655 		}
9656 
9657 		is_bottom_of_zone = false;
9658 
9659 		if (first && signing->deleteit) {
9660 			/*
9661 			 * Remove the key we are deleting from consideration.
9662 			 */
9663 			for (i = 0, j = 0; i < nkeys; i++) {
9664 				/*
9665 				 * Find the key we want to remove.
9666 				 */
9667 				if (ALG(zone_keys[i]) == signing->algorithm &&
9668 				    dst_key_id(zone_keys[i]) == signing->keyid)
9669 				{
9670 					bool ksk = false;
9671 					isc_result_t ret = dst_key_getbool(
9672 						zone_keys[i], DST_BOOL_KSK,
9673 						&ksk);
9674 					if (ret != ISC_R_SUCCESS) {
9675 						ksk = KSK(zone_keys[i]);
9676 					}
9677 					if (ksk) {
9678 						dst_key_free(&zone_keys[i]);
9679 					}
9680 					continue;
9681 				}
9682 				zone_keys[j] = zone_keys[i];
9683 				j++;
9684 			}
9685 			for (i = j; i < nkeys; i++) {
9686 				zone_keys[i] = NULL;
9687 			}
9688 			nkeys = j;
9689 		}
9690 
9691 		dns_dbiterator_current(signing->dbiterator, &node, name);
9692 
9693 		if (signing->deleteit) {
9694 			dns_dbiterator_pause(signing->dbiterator);
9695 			CHECK(del_sig(db, version, name, node, nkeys,
9696 				      signing->algorithm, signing->keyid,
9697 				      &has_alg, zonediff.diff));
9698 		}
9699 
9700 		/*
9701 		 * On the first pass we need to check if the current node
9702 		 * has not been obscured.
9703 		 */
9704 		if (first) {
9705 			dns_fixedname_t ffound;
9706 			dns_name_t *found;
9707 			found = dns_fixedname_initname(&ffound);
9708 			result = dns_db_find(
9709 				db, name, version, dns_rdatatype_soa,
9710 				DNS_DBFIND_NOWILD, 0, NULL, found, NULL, NULL);
9711 			if ((result == DNS_R_DELEGATION ||
9712 			     result == DNS_R_DNAME) &&
9713 			    !dns_name_equal(name, found))
9714 			{
9715 				/*
9716 				 * Remember the obscuring name so that
9717 				 * we skip all obscured names.
9718 				 */
9719 				dns_name_copynf(found, name);
9720 				is_bottom_of_zone = true;
9721 				goto next_node;
9722 			}
9723 		}
9724 
9725 		/*
9726 		 * Process one node.
9727 		 */
9728 		with_ksk = false;
9729 		with_zsk = false;
9730 		dns_dbiterator_pause(signing->dbiterator);
9731 
9732 		CHECK(check_if_bottom_of_zone(db, node, version,
9733 					      &is_bottom_of_zone));
9734 
9735 		for (i = 0; !has_alg && i < nkeys; i++) {
9736 			bool both = false;
9737 
9738 			/*
9739 			 * Find the keys we want to sign with.
9740 			 */
9741 			if (!dst_key_isprivate(zone_keys[i])) {
9742 				continue;
9743 			}
9744 			if (dst_key_inactive(zone_keys[i])) {
9745 				continue;
9746 			}
9747 
9748 			/*
9749 			 * When adding look for the specific key.
9750 			 */
9751 			if (!signing->deleteit &&
9752 			    (dst_key_alg(zone_keys[i]) != signing->algorithm ||
9753 			     dst_key_id(zone_keys[i]) != signing->keyid))
9754 			{
9755 				continue;
9756 			}
9757 
9758 			/*
9759 			 * When deleting make sure we are properly signed
9760 			 * with the algorithm that was being removed.
9761 			 */
9762 			if (signing->deleteit &&
9763 			    ALG(zone_keys[i]) != signing->algorithm)
9764 			{
9765 				continue;
9766 			}
9767 
9768 			/*
9769 			 * Do we do KSK processing?
9770 			 */
9771 			if (check_ksk && !REVOKE(zone_keys[i])) {
9772 				bool have_ksk, have_nonksk;
9773 				if (KSK(zone_keys[i])) {
9774 					have_ksk = true;
9775 					have_nonksk = false;
9776 				} else {
9777 					have_ksk = false;
9778 					have_nonksk = true;
9779 				}
9780 				for (j = 0; j < nkeys; j++) {
9781 					if (j == i || (ALG(zone_keys[i]) !=
9782 						       ALG(zone_keys[j])))
9783 					{
9784 						continue;
9785 					}
9786 					/*
9787 					 * Don't consider inactive keys, however
9788 					 * the key may be temporary offline, so
9789 					 * do consider KSKs which private key
9790 					 * files are unavailable.
9791 					 */
9792 					if (dst_key_inactive(zone_keys[j])) {
9793 						continue;
9794 					}
9795 					if (REVOKE(zone_keys[j])) {
9796 						continue;
9797 					}
9798 					if (KSK(zone_keys[j])) {
9799 						have_ksk = true;
9800 					} else if (dst_key_isprivate(
9801 							   zone_keys[j]))
9802 					{
9803 						have_nonksk = true;
9804 					}
9805 					both = have_ksk && have_nonksk;
9806 					if (both) {
9807 						break;
9808 					}
9809 				}
9810 			}
9811 			if (use_kasp) {
9812 				/*
9813 				 * A dnssec-policy is found. Check what
9814 				 * RRsets this key can sign.
9815 				 */
9816 				isc_result_t kresult;
9817 				is_ksk = false;
9818 				kresult = dst_key_getbool(
9819 					zone_keys[i], DST_BOOL_KSK, &is_ksk);
9820 				if (kresult != ISC_R_SUCCESS) {
9821 					if (KSK(zone_keys[i])) {
9822 						is_ksk = true;
9823 					}
9824 				}
9825 
9826 				is_zsk = false;
9827 				kresult = dst_key_getbool(
9828 					zone_keys[i], DST_BOOL_ZSK, &is_zsk);
9829 				if (kresult != ISC_R_SUCCESS) {
9830 					if (!KSK(zone_keys[i])) {
9831 						is_zsk = true;
9832 					}
9833 				}
9834 				/* Treat as if we have both KSK and ZSK. */
9835 				both = true;
9836 			} else if (both || REVOKE(zone_keys[i])) {
9837 				is_ksk = KSK(zone_keys[i]);
9838 				is_zsk = !KSK(zone_keys[i]);
9839 			} else {
9840 				is_ksk = false;
9841 				is_zsk = true;
9842 			}
9843 
9844 			/*
9845 			 * If deleting signatures, we need to ensure that
9846 			 * the RRset is still signed at least once by a
9847 			 * KSK and a ZSK.
9848 			 */
9849 			if (signing->deleteit && is_zsk && with_zsk) {
9850 				continue;
9851 			}
9852 
9853 			if (signing->deleteit && is_ksk && with_ksk) {
9854 				continue;
9855 			}
9856 
9857 			CHECK(sign_a_node(
9858 				db, zone, name, node, version, build_nsec3,
9859 				build_nsec, zone_keys[i], inception, expire,
9860 				zone_nsecttl(zone), is_ksk, is_zsk,
9861 				(both && keyset_kskonly), is_bottom_of_zone,
9862 				zonediff.diff, &signatures, zone->mctx));
9863 			/*
9864 			 * If we are adding we are done.  Look for other keys
9865 			 * of the same algorithm if deleting.
9866 			 */
9867 			if (!signing->deleteit) {
9868 				break;
9869 			}
9870 			if (is_zsk) {
9871 				with_zsk = true;
9872 			}
9873 			if (is_ksk) {
9874 				with_ksk = true;
9875 			}
9876 		}
9877 
9878 		/*
9879 		 * Go onto next node.
9880 		 */
9881 	next_node:
9882 		first = false;
9883 		dns_db_detachnode(db, &node);
9884 		do {
9885 			result = dns_dbiterator_next(signing->dbiterator);
9886 			if (result == ISC_R_NOMORE) {
9887 				ISC_LIST_UNLINK(zone->signing, signing, link);
9888 				ISC_LIST_APPEND(cleanup, signing, link);
9889 				dns_dbiterator_pause(signing->dbiterator);
9890 				if (nkeys != 0 && build_nsec) {
9891 					/*
9892 					 * We have finished regenerating the
9893 					 * zone with a zone signing key.
9894 					 * The NSEC chain is now complete and
9895 					 * there is a full set of signatures
9896 					 * for the zone.  We can now clear the
9897 					 * OPT bit from the NSEC record.
9898 					 */
9899 					result = updatesecure(
9900 						db, version, &zone->origin,
9901 						zone_nsecttl(zone), false,
9902 						&post_diff);
9903 					if (result != ISC_R_SUCCESS) {
9904 						dnssec_log(zone, ISC_LOG_ERROR,
9905 							   "updatesecure -> %s",
9906 							   dns_result_totext(
9907 								   result));
9908 						goto cleanup;
9909 					}
9910 				}
9911 				result = updatesignwithkey(
9912 					zone, signing, version, build_nsec3,
9913 					zone_nsecttl(zone), &post_diff);
9914 				if (result != ISC_R_SUCCESS) {
9915 					dnssec_log(zone, ISC_LOG_ERROR,
9916 						   "updatesignwithkey -> %s",
9917 						   dns_result_totext(result));
9918 					goto cleanup;
9919 				}
9920 				build_nsec = false;
9921 				goto next_signing;
9922 			} else if (result != ISC_R_SUCCESS) {
9923 				dnssec_log(zone, ISC_LOG_ERROR,
9924 					   "zone_sign:"
9925 					   "dns_dbiterator_next -> %s",
9926 					   dns_result_totext(result));
9927 				goto cleanup;
9928 			} else if (is_bottom_of_zone) {
9929 				dns_dbiterator_current(signing->dbiterator,
9930 						       &node, nextname);
9931 				dns_db_detachnode(db, &node);
9932 				if (!dns_name_issubdomain(nextname, name)) {
9933 					break;
9934 				}
9935 			} else {
9936 				break;
9937 			}
9938 		} while (1);
9939 		continue;
9940 
9941 	next_signing:
9942 		dns_dbiterator_pause(signing->dbiterator);
9943 		signing = nextsigning;
9944 		first = true;
9945 	}
9946 
9947 	if (ISC_LIST_HEAD(post_diff.tuples) != NULL) {
9948 		result = dns__zone_updatesigs(&post_diff, db, version,
9949 					      zone_keys, nkeys, zone, inception,
9950 					      expire, 0, now, check_ksk,
9951 					      keyset_kskonly, &zonediff);
9952 		if (result != ISC_R_SUCCESS) {
9953 			dnssec_log(zone, ISC_LOG_ERROR,
9954 				   "zone_sign:dns__zone_updatesigs -> %s",
9955 				   dns_result_totext(result));
9956 			goto cleanup;
9957 		}
9958 	}
9959 
9960 	/*
9961 	 * Have we changed anything?
9962 	 */
9963 	if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
9964 		if (zonediff.offline) {
9965 			commit = true;
9966 		}
9967 		result = ISC_R_SUCCESS;
9968 		goto pauseall;
9969 	}
9970 
9971 	commit = true;
9972 
9973 	result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
9974 			  &zonediff, zone_keys, nkeys, now, false);
9975 	if (result != ISC_R_SUCCESS) {
9976 		dnssec_log(zone, ISC_LOG_ERROR, "zone_sign:del_sigs -> %s",
9977 			   dns_result_totext(result));
9978 		goto cleanup;
9979 	}
9980 
9981 	result = update_soa_serial(zone, db, version, zonediff.diff, zone->mctx,
9982 				   zone->updatemethod);
9983 	if (result != ISC_R_SUCCESS) {
9984 		dnssec_log(zone, ISC_LOG_ERROR,
9985 			   "zone_sign:update_soa_serial -> %s",
9986 			   dns_result_totext(result));
9987 		goto cleanup;
9988 	}
9989 
9990 	/*
9991 	 * Generate maximum life time signatures so that the above loop
9992 	 * termination is sensible.
9993 	 */
9994 	result = add_sigs(db, version, &zone->origin, zone, dns_rdatatype_soa,
9995 			  zonediff.diff, zone_keys, nkeys, zone->mctx,
9996 			  inception, soaexpire, check_ksk, keyset_kskonly);
9997 	if (result != ISC_R_SUCCESS) {
9998 		dnssec_log(zone, ISC_LOG_ERROR, "zone_sign:add_sigs -> %s",
9999 			   dns_result_totext(result));
10000 		goto cleanup;
10001 	}
10002 
10003 	/*
10004 	 * Write changes to journal file.
10005 	 */
10006 	CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_sign"));
10007 
10008 pauseall:
10009 	/*
10010 	 * Pause all iterators so that dns_db_closeversion() can succeed.
10011 	 */
10012 	for (signing = ISC_LIST_HEAD(zone->signing); signing != NULL;
10013 	     signing = ISC_LIST_NEXT(signing, link))
10014 	{
10015 		dns_dbiterator_pause(signing->dbiterator);
10016 	}
10017 
10018 	for (signing = ISC_LIST_HEAD(cleanup); signing != NULL;
10019 	     signing = ISC_LIST_NEXT(signing, link))
10020 	{
10021 		dns_dbiterator_pause(signing->dbiterator);
10022 	}
10023 
10024 	/*
10025 	 * Everything has succeeded. Commit the changes.
10026 	 */
10027 	dns_db_closeversion(db, &version, commit);
10028 
10029 	/*
10030 	 * Everything succeeded so we can clean these up now.
10031 	 */
10032 	signing = ISC_LIST_HEAD(cleanup);
10033 	while (signing != NULL) {
10034 		ISC_LIST_UNLINK(cleanup, signing, link);
10035 		dns_db_detach(&signing->db);
10036 		dns_dbiterator_destroy(&signing->dbiterator);
10037 		isc_mem_put(zone->mctx, signing, sizeof *signing);
10038 		signing = ISC_LIST_HEAD(cleanup);
10039 	}
10040 
10041 	LOCK_ZONE(zone);
10042 	set_resigntime(zone);
10043 	if (commit) {
10044 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
10045 		zone_needdump(zone, DNS_DUMP_DELAY);
10046 	}
10047 	UNLOCK_ZONE(zone);
10048 
10049 failure:
10050 	if (result != ISC_R_SUCCESS) {
10051 		dnssec_log(zone, ISC_LOG_ERROR, "zone_sign: failed: %s",
10052 			   dns_result_totext(result));
10053 	}
10054 
10055 cleanup:
10056 	/*
10057 	 * Pause all dbiterators.
10058 	 */
10059 	for (signing = ISC_LIST_HEAD(zone->signing); signing != NULL;
10060 	     signing = ISC_LIST_NEXT(signing, link))
10061 	{
10062 		dns_dbiterator_pause(signing->dbiterator);
10063 	}
10064 
10065 	/*
10066 	 * Rollback the cleanup list.
10067 	 */
10068 	signing = ISC_LIST_HEAD(cleanup);
10069 	while (signing != NULL) {
10070 		ISC_LIST_UNLINK(cleanup, signing, link);
10071 		ISC_LIST_PREPEND(zone->signing, signing, link);
10072 		dns_dbiterator_first(signing->dbiterator);
10073 		dns_dbiterator_pause(signing->dbiterator);
10074 		signing = ISC_LIST_HEAD(cleanup);
10075 	}
10076 
10077 	dns_diff_clear(&_sig_diff);
10078 
10079 	for (i = 0; i < nkeys; i++) {
10080 		dst_key_free(&zone_keys[i]);
10081 	}
10082 
10083 	if (node != NULL) {
10084 		dns_db_detachnode(db, &node);
10085 	}
10086 
10087 	if (version != NULL) {
10088 		dns_db_closeversion(db, &version, false);
10089 		dns_db_detach(&db);
10090 	} else if (db != NULL) {
10091 		dns_db_detach(&db);
10092 	}
10093 
10094 	LOCK_ZONE(zone);
10095 	if (ISC_LIST_HEAD(zone->signing) != NULL) {
10096 		isc_interval_t interval;
10097 		if (zone->update_disabled || result != ISC_R_SUCCESS) {
10098 			isc_interval_set(&interval, 60, 0); /* 1 minute */
10099 		} else {
10100 			isc_interval_set(&interval, 0, 10000000); /* 10 ms */
10101 		}
10102 		isc_time_nowplusinterval(&zone->signingtime, &interval);
10103 	} else {
10104 		isc_time_settoepoch(&zone->signingtime);
10105 	}
10106 	UNLOCK_ZONE(zone);
10107 
10108 	INSIST(version == NULL);
10109 }
10110 
10111 static isc_result_t
normalize_key(dns_rdata_t * rr,dns_rdata_t * target,unsigned char * data,int size)10112 normalize_key(dns_rdata_t *rr, dns_rdata_t *target, unsigned char *data,
10113 	      int size) {
10114 	dns_rdata_dnskey_t dnskey;
10115 	dns_rdata_keydata_t keydata;
10116 	isc_buffer_t buf;
10117 	isc_result_t result;
10118 
10119 	dns_rdata_reset(target);
10120 	isc_buffer_init(&buf, data, size);
10121 
10122 	switch (rr->type) {
10123 	case dns_rdatatype_dnskey:
10124 		result = dns_rdata_tostruct(rr, &dnskey, NULL);
10125 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
10126 		dnskey.flags &= ~DNS_KEYFLAG_REVOKE;
10127 		dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
10128 				     &dnskey, &buf);
10129 		break;
10130 	case dns_rdatatype_keydata:
10131 		result = dns_rdata_tostruct(rr, &keydata, NULL);
10132 		if (result == ISC_R_UNEXPECTEDEND) {
10133 			return (result);
10134 		}
10135 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
10136 		dns_keydata_todnskey(&keydata, &dnskey, NULL);
10137 		dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
10138 				     &dnskey, &buf);
10139 		break;
10140 	default:
10141 		UNREACHABLE();
10142 	}
10143 	return (ISC_R_SUCCESS);
10144 }
10145 
10146 /*
10147  * 'rdset' contains either a DNSKEY rdataset from the zone apex, or
10148  * a KEYDATA rdataset from the key zone.
10149  *
10150  * 'rr' contains either a DNSKEY record, or a KEYDATA record
10151  *
10152  * After normalizing keys to the same format (DNSKEY, with revoke bit
10153  * cleared), return true if a key that matches 'rr' is found in
10154  * 'rdset', or false if not.
10155  */
10156 
10157 static bool
matchkey(dns_rdataset_t * rdset,dns_rdata_t * rr)10158 matchkey(dns_rdataset_t *rdset, dns_rdata_t *rr) {
10159 	unsigned char data1[4096], data2[4096];
10160 	dns_rdata_t rdata, rdata1, rdata2;
10161 	isc_result_t result;
10162 
10163 	dns_rdata_init(&rdata);
10164 	dns_rdata_init(&rdata1);
10165 	dns_rdata_init(&rdata2);
10166 
10167 	result = normalize_key(rr, &rdata1, data1, sizeof(data1));
10168 	if (result != ISC_R_SUCCESS) {
10169 		return (false);
10170 	}
10171 
10172 	for (result = dns_rdataset_first(rdset); result == ISC_R_SUCCESS;
10173 	     result = dns_rdataset_next(rdset))
10174 	{
10175 		dns_rdata_reset(&rdata);
10176 		dns_rdataset_current(rdset, &rdata);
10177 		result = normalize_key(&rdata, &rdata2, data2, sizeof(data2));
10178 		if (result != ISC_R_SUCCESS) {
10179 			continue;
10180 		}
10181 		if (dns_rdata_compare(&rdata1, &rdata2) == 0) {
10182 			return (true);
10183 		}
10184 	}
10185 
10186 	return (false);
10187 }
10188 
10189 /*
10190  * Calculate the refresh interval for a keydata zone, per
10191  * RFC5011: MAX(1 hr,
10192  *		MIN(15 days,
10193  *		    1/2 * OrigTTL,
10194  *		    1/2 * RRSigExpirationInterval))
10195  * or for retries: MAX(1 hr,
10196  *		       MIN(1 day,
10197  *			   1/10 * OrigTTL,
10198  *			   1/10 * RRSigExpirationInterval))
10199  */
10200 static isc_stdtime_t
refresh_time(dns_keyfetch_t * kfetch,bool retry)10201 refresh_time(dns_keyfetch_t *kfetch, bool retry) {
10202 	isc_result_t result;
10203 	uint32_t t;
10204 	dns_rdataset_t *rdset;
10205 	dns_rdata_t sigrr = DNS_RDATA_INIT;
10206 	dns_rdata_sig_t sig;
10207 	isc_stdtime_t now;
10208 
10209 	isc_stdtime_get(&now);
10210 
10211 	if (dns_rdataset_isassociated(&kfetch->dnskeysigset)) {
10212 		rdset = &kfetch->dnskeysigset;
10213 	} else {
10214 		return (now + dns_zone_mkey_hour);
10215 	}
10216 
10217 	result = dns_rdataset_first(rdset);
10218 	if (result != ISC_R_SUCCESS) {
10219 		return (now + dns_zone_mkey_hour);
10220 	}
10221 
10222 	dns_rdataset_current(rdset, &sigrr);
10223 	result = dns_rdata_tostruct(&sigrr, &sig, NULL);
10224 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
10225 
10226 	if (!retry) {
10227 		t = sig.originalttl / 2;
10228 
10229 		if (isc_serial_gt(sig.timeexpire, now)) {
10230 			uint32_t exp = (sig.timeexpire - now) / 2;
10231 			if (t > exp) {
10232 				t = exp;
10233 			}
10234 		}
10235 
10236 		if (t > (15 * dns_zone_mkey_day)) {
10237 			t = (15 * dns_zone_mkey_day);
10238 		}
10239 
10240 		if (t < dns_zone_mkey_hour) {
10241 			t = dns_zone_mkey_hour;
10242 		}
10243 	} else {
10244 		t = sig.originalttl / 10;
10245 
10246 		if (isc_serial_gt(sig.timeexpire, now)) {
10247 			uint32_t exp = (sig.timeexpire - now) / 10;
10248 			if (t > exp) {
10249 				t = exp;
10250 			}
10251 		}
10252 
10253 		if (t > dns_zone_mkey_day) {
10254 			t = dns_zone_mkey_day;
10255 		}
10256 
10257 		if (t < dns_zone_mkey_hour) {
10258 			t = dns_zone_mkey_hour;
10259 		}
10260 	}
10261 
10262 	return (now + t);
10263 }
10264 
10265 /*
10266  * This routine is called when no changes are needed in a KEYDATA
10267  * record except to simply update the refresh timer.  Caller should
10268  * hold zone lock.
10269  */
10270 static isc_result_t
minimal_update(dns_keyfetch_t * kfetch,dns_dbversion_t * ver,dns_diff_t * diff)10271 minimal_update(dns_keyfetch_t *kfetch, dns_dbversion_t *ver, dns_diff_t *diff) {
10272 	isc_result_t result;
10273 	isc_buffer_t keyb;
10274 	unsigned char key_buf[4096];
10275 	dns_rdata_t rdata = DNS_RDATA_INIT;
10276 	dns_rdata_keydata_t keydata;
10277 	dns_name_t *name;
10278 	dns_zone_t *zone = kfetch->zone;
10279 	isc_stdtime_t now;
10280 
10281 	name = dns_fixedname_name(&kfetch->name);
10282 	isc_stdtime_get(&now);
10283 
10284 	for (result = dns_rdataset_first(&kfetch->keydataset);
10285 	     result == ISC_R_SUCCESS;
10286 	     result = dns_rdataset_next(&kfetch->keydataset))
10287 	{
10288 		dns_rdata_reset(&rdata);
10289 		dns_rdataset_current(&kfetch->keydataset, &rdata);
10290 
10291 		/* Delete old version */
10292 		CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_DEL, name,
10293 				    0, &rdata));
10294 
10295 		/* Update refresh timer */
10296 		result = dns_rdata_tostruct(&rdata, &keydata, NULL);
10297 		if (result == ISC_R_UNEXPECTEDEND) {
10298 			continue;
10299 		}
10300 		if (result != ISC_R_SUCCESS) {
10301 			goto failure;
10302 		}
10303 		keydata.refresh = refresh_time(kfetch, true);
10304 		set_refreshkeytimer(zone, &keydata, now, false);
10305 
10306 		dns_rdata_reset(&rdata);
10307 		isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10308 		CHECK(dns_rdata_fromstruct(&rdata, zone->rdclass,
10309 					   dns_rdatatype_keydata, &keydata,
10310 					   &keyb));
10311 
10312 		/* Insert updated version */
10313 		CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_ADD, name,
10314 				    0, &rdata));
10315 	}
10316 	result = ISC_R_SUCCESS;
10317 failure:
10318 	return (result);
10319 }
10320 
10321 /*
10322  * Verify that DNSKEY set is signed by the key specified in 'keydata'.
10323  */
10324 static bool
revocable(dns_keyfetch_t * kfetch,dns_rdata_keydata_t * keydata)10325 revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) {
10326 	isc_result_t result;
10327 	dns_name_t *keyname;
10328 	isc_mem_t *mctx;
10329 	dns_rdata_t sigrr = DNS_RDATA_INIT;
10330 	dns_rdata_t rr = DNS_RDATA_INIT;
10331 	dns_rdata_rrsig_t sig;
10332 	dns_rdata_dnskey_t dnskey;
10333 	dst_key_t *dstkey = NULL;
10334 	unsigned char key_buf[4096];
10335 	isc_buffer_t keyb;
10336 	bool answer = false;
10337 
10338 	REQUIRE(kfetch != NULL && keydata != NULL);
10339 	REQUIRE(dns_rdataset_isassociated(&kfetch->dnskeysigset));
10340 
10341 	keyname = dns_fixedname_name(&kfetch->name);
10342 	mctx = kfetch->zone->view->mctx;
10343 
10344 	/* Generate a key from keydata */
10345 	isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10346 	dns_keydata_todnskey(keydata, &dnskey, NULL);
10347 	dns_rdata_fromstruct(&rr, keydata->common.rdclass, dns_rdatatype_dnskey,
10348 			     &dnskey, &keyb);
10349 	result = dns_dnssec_keyfromrdata(keyname, &rr, mctx, &dstkey);
10350 	if (result != ISC_R_SUCCESS) {
10351 		return (false);
10352 	}
10353 
10354 	/* See if that key generated any of the signatures */
10355 	for (result = dns_rdataset_first(&kfetch->dnskeysigset);
10356 	     result == ISC_R_SUCCESS;
10357 	     result = dns_rdataset_next(&kfetch->dnskeysigset))
10358 	{
10359 		dns_fixedname_t fixed;
10360 		dns_fixedname_init(&fixed);
10361 
10362 		dns_rdata_reset(&sigrr);
10363 		dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
10364 		result = dns_rdata_tostruct(&sigrr, &sig, NULL);
10365 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
10366 
10367 		if (dst_key_alg(dstkey) == sig.algorithm &&
10368 		    dst_key_rid(dstkey) == sig.keyid)
10369 		{
10370 			result = dns_dnssec_verify(
10371 				keyname, &kfetch->dnskeyset, dstkey, false, 0,
10372 				mctx, &sigrr, dns_fixedname_name(&fixed));
10373 
10374 			dnssec_log(kfetch->zone, ISC_LOG_DEBUG(3),
10375 				   "Confirm revoked DNSKEY is self-signed: %s",
10376 				   dns_result_totext(result));
10377 
10378 			if (result == ISC_R_SUCCESS) {
10379 				answer = true;
10380 				break;
10381 			}
10382 		}
10383 	}
10384 
10385 	dst_key_free(&dstkey);
10386 	return (answer);
10387 }
10388 
10389 /*
10390  * A DNSKEY set has been fetched from the zone apex of a zone whose trust
10391  * anchors are being managed; scan the keyset, and update the key zone and the
10392  * local trust anchors according to RFC5011.
10393  */
10394 static void
keyfetch_done(isc_task_t * task,isc_event_t * event)10395 keyfetch_done(isc_task_t *task, isc_event_t *event) {
10396 	isc_result_t result, eresult;
10397 	dns_fetchevent_t *devent;
10398 	dns_keyfetch_t *kfetch;
10399 	dns_zone_t *zone;
10400 	isc_mem_t *mctx = NULL;
10401 	dns_keytable_t *secroots = NULL;
10402 	dns_dbversion_t *ver = NULL;
10403 	dns_diff_t diff;
10404 	bool alldone = false;
10405 	bool commit = false;
10406 	dns_name_t *keyname = NULL;
10407 	dns_rdata_t sigrr = DNS_RDATA_INIT;
10408 	dns_rdata_t dnskeyrr = DNS_RDATA_INIT;
10409 	dns_rdata_t keydatarr = DNS_RDATA_INIT;
10410 	dns_rdata_rrsig_t sig;
10411 	dns_rdata_dnskey_t dnskey;
10412 	dns_rdata_keydata_t keydata;
10413 	bool initializing;
10414 	char namebuf[DNS_NAME_FORMATSIZE];
10415 	unsigned char key_buf[4096];
10416 	isc_buffer_t keyb;
10417 	dst_key_t *dstkey = NULL;
10418 	isc_stdtime_t now;
10419 	int pending = 0;
10420 	bool secure = false, initial = false;
10421 	bool free_needed;
10422 	dns_keynode_t *keynode = NULL;
10423 	dns_rdataset_t *dnskeys = NULL, *dnskeysigs = NULL;
10424 	dns_rdataset_t *keydataset = NULL, dsset;
10425 
10426 	UNUSED(task);
10427 	INSIST(event != NULL && event->ev_type == DNS_EVENT_FETCHDONE);
10428 	INSIST(event->ev_arg != NULL);
10429 
10430 	kfetch = event->ev_arg;
10431 	zone = kfetch->zone;
10432 	mctx = kfetch->mctx;
10433 	keyname = dns_fixedname_name(&kfetch->name);
10434 	dnskeys = &kfetch->dnskeyset;
10435 	dnskeysigs = &kfetch->dnskeysigset;
10436 	keydataset = &kfetch->keydataset;
10437 
10438 	devent = (dns_fetchevent_t *)event;
10439 	eresult = devent->result;
10440 
10441 	/* Free resources which are not of interest */
10442 	if (devent->node != NULL) {
10443 		dns_db_detachnode(devent->db, &devent->node);
10444 	}
10445 	if (devent->db != NULL) {
10446 		dns_db_detach(&devent->db);
10447 	}
10448 	isc_event_free(&event);
10449 	dns_resolver_destroyfetch(&kfetch->fetch);
10450 
10451 	LOCK_ZONE(zone);
10452 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || zone->view == NULL) {
10453 		goto cleanup;
10454 	}
10455 
10456 	isc_stdtime_get(&now);
10457 	dns_name_format(keyname, namebuf, sizeof(namebuf));
10458 
10459 	result = dns_view_getsecroots(zone->view, &secroots);
10460 	INSIST(result == ISC_R_SUCCESS);
10461 
10462 	dns_diff_init(mctx, &diff);
10463 
10464 	CHECK(dns_db_newversion(kfetch->db, &ver));
10465 
10466 	zone->refreshkeycount--;
10467 	alldone = (zone->refreshkeycount == 0);
10468 
10469 	if (alldone) {
10470 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
10471 	}
10472 
10473 	dnssec_log(zone, ISC_LOG_DEBUG(3),
10474 		   "Returned from key fetch in keyfetch_done() for '%s': %s",
10475 		   namebuf, dns_result_totext(eresult));
10476 
10477 	/* Fetch failed */
10478 	if (eresult != ISC_R_SUCCESS || !dns_rdataset_isassociated(dnskeys)) {
10479 		dnssec_log(zone, ISC_LOG_WARNING,
10480 			   "Unable to fetch DNSKEY set '%s': %s", namebuf,
10481 			   dns_result_totext(eresult));
10482 		CHECK(minimal_update(kfetch, ver, &diff));
10483 		goto done;
10484 	}
10485 
10486 	/* No RRSIGs found */
10487 	if (!dns_rdataset_isassociated(dnskeysigs)) {
10488 		dnssec_log(zone, ISC_LOG_WARNING,
10489 			   "No DNSKEY RRSIGs found for '%s': %s", namebuf,
10490 			   dns_result_totext(eresult));
10491 		CHECK(minimal_update(kfetch, ver, &diff));
10492 		goto done;
10493 	}
10494 
10495 	/*
10496 	 * Clear any cached trust level, as we need to run validation
10497 	 * over again; trusted keys might have changed.
10498 	 */
10499 	dnskeys->trust = dnskeysigs->trust = dns_trust_none;
10500 
10501 	/* Look up the trust anchor */
10502 	result = dns_keytable_find(secroots, keyname, &keynode);
10503 	if (result != ISC_R_SUCCESS) {
10504 		goto anchors_done;
10505 	}
10506 
10507 	/*
10508 	 * If the keynode has a DS trust anchor, use it for verification.
10509 	 */
10510 	dns_rdataset_init(&dsset);
10511 	if (dns_keynode_dsset(keynode, &dsset)) {
10512 		for (result = dns_rdataset_first(dnskeysigs);
10513 		     result == ISC_R_SUCCESS;
10514 		     result = dns_rdataset_next(dnskeysigs))
10515 		{
10516 			isc_result_t tresult;
10517 			dns_rdata_t keyrdata = DNS_RDATA_INIT;
10518 
10519 			dns_rdata_reset(&sigrr);
10520 			dns_rdataset_current(dnskeysigs, &sigrr);
10521 			result = dns_rdata_tostruct(&sigrr, &sig, NULL);
10522 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
10523 
10524 			for (tresult = dns_rdataset_first(&dsset);
10525 			     tresult == ISC_R_SUCCESS;
10526 			     tresult = dns_rdataset_next(&dsset))
10527 			{
10528 				dns_rdata_t dsrdata = DNS_RDATA_INIT;
10529 				dns_rdata_ds_t ds;
10530 
10531 				dns_rdata_reset(&dsrdata);
10532 				dns_rdataset_current(&dsset, &dsrdata);
10533 				tresult = dns_rdata_tostruct(&dsrdata, &ds,
10534 							     NULL);
10535 				RUNTIME_CHECK(tresult == ISC_R_SUCCESS);
10536 
10537 				if (ds.key_tag != sig.keyid ||
10538 				    ds.algorithm != sig.algorithm)
10539 				{
10540 					continue;
10541 				}
10542 
10543 				result = dns_dnssec_matchdskey(
10544 					keyname, &dsrdata, dnskeys, &keyrdata);
10545 				if (result == ISC_R_SUCCESS) {
10546 					break;
10547 				}
10548 			}
10549 
10550 			if (tresult == ISC_R_NOMORE) {
10551 				continue;
10552 			}
10553 
10554 			result = dns_dnssec_keyfromrdata(keyname, &keyrdata,
10555 							 mctx, &dstkey);
10556 			if (result != ISC_R_SUCCESS) {
10557 				continue;
10558 			}
10559 
10560 			result = dns_dnssec_verify(keyname, dnskeys, dstkey,
10561 						   false, 0, mctx, &sigrr,
10562 						   NULL);
10563 			dst_key_free(&dstkey);
10564 
10565 			dnssec_log(zone, ISC_LOG_DEBUG(3),
10566 				   "Verifying DNSKEY set for zone "
10567 				   "'%s' using DS %d/%d: %s",
10568 				   namebuf, sig.keyid, sig.algorithm,
10569 				   dns_result_totext(result));
10570 
10571 			if (result == ISC_R_SUCCESS) {
10572 				dnskeys->trust = dns_trust_secure;
10573 				dnskeysigs->trust = dns_trust_secure;
10574 				initial = dns_keynode_initial(keynode);
10575 				dns_keynode_trust(keynode);
10576 				secure = true;
10577 				break;
10578 			}
10579 		}
10580 		dns_rdataset_disassociate(&dsset);
10581 	}
10582 
10583 anchors_done:
10584 	if (keynode != NULL) {
10585 		dns_keytable_detachkeynode(secroots, &keynode);
10586 	}
10587 
10588 	/*
10589 	 * If we were not able to verify the answer using the current
10590 	 * trusted keys then all we can do is look at any revoked keys.
10591 	 */
10592 	if (!secure) {
10593 		dnssec_log(zone, ISC_LOG_INFO,
10594 			   "DNSKEY set for zone '%s' could not be verified "
10595 			   "with current keys",
10596 			   namebuf);
10597 	}
10598 
10599 	/*
10600 	 * First scan keydataset to find keys that are not in dnskeyset
10601 	 *   - Missing keys which are not scheduled for removal,
10602 	 *     log a warning
10603 	 *   - Missing keys which are scheduled for removal and
10604 	 *     the remove hold-down timer has completed should
10605 	 *     be removed from the key zone
10606 	 *   - Missing keys whose acceptance timers have not yet
10607 	 *     completed, log a warning and reset the acceptance
10608 	 *     timer to 30 days in the future
10609 	 *   - All keys not being removed have their refresh timers
10610 	 *     updated
10611 	 */
10612 	initializing = true;
10613 	for (result = dns_rdataset_first(keydataset); result == ISC_R_SUCCESS;
10614 	     result = dns_rdataset_next(keydataset))
10615 	{
10616 		dns_keytag_t keytag;
10617 
10618 		dns_rdata_reset(&keydatarr);
10619 		dns_rdataset_current(keydataset, &keydatarr);
10620 		result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
10621 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
10622 
10623 		dns_keydata_todnskey(&keydata, &dnskey, NULL);
10624 		result = compute_tag(keyname, &dnskey, mctx, &keytag);
10625 		if (result != ISC_R_SUCCESS) {
10626 			/*
10627 			 * Skip if we cannot compute the key tag.
10628 			 * This may happen if the algorithm is unsupported
10629 			 */
10630 			dns_zone_log(zone, ISC_LOG_ERROR,
10631 				     "Cannot compute tag for key in zone %s: "
10632 				     "%s "
10633 				     "(skipping)",
10634 				     namebuf, dns_result_totext(result));
10635 			continue;
10636 		}
10637 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
10638 
10639 		/*
10640 		 * If any keydata record has a nonzero add holddown, then
10641 		 * there was a pre-existing trust anchor for this domain;
10642 		 * that means we are *not* initializing it and shouldn't
10643 		 * automatically trust all the keys we find at the zone apex.
10644 		 */
10645 		initializing = initializing && (keydata.addhd == 0);
10646 
10647 		if (!matchkey(dnskeys, &keydatarr)) {
10648 			bool deletekey = false;
10649 
10650 			if (!secure) {
10651 				if (keydata.removehd != 0 &&
10652 				    keydata.removehd <= now)
10653 				{
10654 					deletekey = true;
10655 				}
10656 			} else if (keydata.addhd == 0) {
10657 				deletekey = true;
10658 			} else if (keydata.addhd > now) {
10659 				dnssec_log(zone, ISC_LOG_INFO,
10660 					   "Pending key %d for zone %s "
10661 					   "unexpectedly missing "
10662 					   "restarting 30-day acceptance "
10663 					   "timer",
10664 					   keytag, namebuf);
10665 				if (keydata.addhd < now + dns_zone_mkey_month) {
10666 					keydata.addhd = now +
10667 							dns_zone_mkey_month;
10668 				}
10669 				keydata.refresh = refresh_time(kfetch, false);
10670 			} else if (keydata.removehd == 0) {
10671 				dnssec_log(zone, ISC_LOG_INFO,
10672 					   "Active key %d for zone %s "
10673 					   "unexpectedly missing",
10674 					   keytag, namebuf);
10675 				keydata.refresh = now + dns_zone_mkey_hour;
10676 			} else if (keydata.removehd <= now) {
10677 				deletekey = true;
10678 				dnssec_log(zone, ISC_LOG_INFO,
10679 					   "Revoked key %d for zone %s "
10680 					   "missing: deleting from "
10681 					   "managed keys database",
10682 					   keytag, namebuf);
10683 			} else {
10684 				keydata.refresh = refresh_time(kfetch, false);
10685 			}
10686 
10687 			if (secure || deletekey) {
10688 				/* Delete old version */
10689 				CHECK(update_one_rr(kfetch->db, ver, &diff,
10690 						    DNS_DIFFOP_DEL, keyname, 0,
10691 						    &keydatarr));
10692 			}
10693 
10694 			if (!secure || deletekey) {
10695 				continue;
10696 			}
10697 
10698 			dns_rdata_reset(&keydatarr);
10699 			isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10700 			dns_rdata_fromstruct(&keydatarr, zone->rdclass,
10701 					     dns_rdatatype_keydata, &keydata,
10702 					     &keyb);
10703 
10704 			/* Insert updated version */
10705 			CHECK(update_one_rr(kfetch->db, ver, &diff,
10706 					    DNS_DIFFOP_ADD, keyname, 0,
10707 					    &keydatarr));
10708 
10709 			set_refreshkeytimer(zone, &keydata, now, false);
10710 		}
10711 	}
10712 
10713 	/*
10714 	 * Next scan dnskeyset:
10715 	 *   - If new keys are found (i.e., lacking a match in keydataset)
10716 	 *     add them to the key zone and set the acceptance timer
10717 	 *     to 30 days in the future (or to immediately if we've
10718 	 *     determined that we're initializing the zone for the
10719 	 *     first time)
10720 	 *   - Previously-known keys that have been revoked
10721 	 *     must be scheduled for removal from the key zone (or,
10722 	 *     if they hadn't been accepted as trust anchors yet
10723 	 *     anyway, removed at once)
10724 	 *   - Previously-known unrevoked keys whose acceptance timers
10725 	 *     have completed are promoted to trust anchors
10726 	 *   - All keys not being removed have their refresh
10727 	 *     timers updated
10728 	 */
10729 	for (result = dns_rdataset_first(dnskeys); result == ISC_R_SUCCESS;
10730 	     result = dns_rdataset_next(dnskeys))
10731 	{
10732 		bool revoked = false;
10733 		bool newkey = false;
10734 		bool updatekey = false;
10735 		bool deletekey = false;
10736 		bool trustkey = false;
10737 		dns_keytag_t keytag;
10738 
10739 		dns_rdata_reset(&dnskeyrr);
10740 		dns_rdataset_current(dnskeys, &dnskeyrr);
10741 		result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
10742 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
10743 
10744 		/* Skip ZSK's */
10745 		if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0) {
10746 			continue;
10747 		}
10748 
10749 		result = compute_tag(keyname, &dnskey, mctx, &keytag);
10750 		if (result != ISC_R_SUCCESS) {
10751 			/*
10752 			 * Skip if we cannot compute the key tag.
10753 			 * This may happen if the algorithm is unsupported
10754 			 */
10755 			dns_zone_log(zone, ISC_LOG_ERROR,
10756 				     "Cannot compute tag for key in zone %s: "
10757 				     "%s "
10758 				     "(skipping)",
10759 				     namebuf, dns_result_totext(result));
10760 			continue;
10761 		}
10762 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
10763 
10764 		revoked = ((dnskey.flags & DNS_KEYFLAG_REVOKE) != 0);
10765 
10766 		if (matchkey(keydataset, &dnskeyrr)) {
10767 			dns_rdata_reset(&keydatarr);
10768 			dns_rdataset_current(keydataset, &keydatarr);
10769 			result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
10770 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
10771 
10772 			if (revoked && revocable(kfetch, &keydata)) {
10773 				if (keydata.addhd > now) {
10774 					/*
10775 					 * Key wasn't trusted yet, and now
10776 					 * it's been revoked?  Just remove it
10777 					 */
10778 					deletekey = true;
10779 					dnssec_log(zone, ISC_LOG_INFO,
10780 						   "Pending key %d for "
10781 						   "zone %s is now revoked: "
10782 						   "deleting from the "
10783 						   "managed keys database",
10784 						   keytag, namebuf);
10785 				} else if (keydata.removehd == 0) {
10786 					/*
10787 					 * Remove key from secroots.
10788 					 */
10789 					dns_view_untrust(zone->view, keyname,
10790 							 &dnskey);
10791 
10792 					/* If initializing, delete now */
10793 					if (keydata.addhd == 0) {
10794 						deletekey = true;
10795 					} else {
10796 						keydata.removehd =
10797 							now +
10798 							dns_zone_mkey_month;
10799 						keydata.flags |=
10800 							DNS_KEYFLAG_REVOKE;
10801 					}
10802 
10803 					dnssec_log(zone, ISC_LOG_INFO,
10804 						   "Trusted key %d for "
10805 						   "zone %s is now revoked",
10806 						   keytag, namebuf);
10807 				} else if (keydata.removehd < now) {
10808 					/* Scheduled for removal */
10809 					deletekey = true;
10810 
10811 					dnssec_log(zone, ISC_LOG_INFO,
10812 						   "Revoked key %d for "
10813 						   "zone %s removal timer "
10814 						   "complete: deleting from "
10815 						   "the managed keys database",
10816 						   keytag, namebuf);
10817 				}
10818 			} else if (revoked && keydata.removehd == 0) {
10819 				dnssec_log(zone, ISC_LOG_WARNING,
10820 					   "Active key %d for zone "
10821 					   "%s is revoked but "
10822 					   "did not self-sign; "
10823 					   "ignoring",
10824 					   keytag, namebuf);
10825 				continue;
10826 			} else if (secure) {
10827 				if (keydata.removehd != 0) {
10828 					/*
10829 					 * Key isn't revoked--but it
10830 					 * seems it used to be.
10831 					 * Remove it now and add it
10832 					 * back as if it were a fresh key,
10833 					 * with a 30-day acceptance timer.
10834 					 */
10835 					deletekey = true;
10836 					newkey = true;
10837 					keydata.removehd = 0;
10838 					keydata.addhd = now +
10839 							dns_zone_mkey_month;
10840 
10841 					dnssec_log(zone, ISC_LOG_INFO,
10842 						   "Revoked key %d for "
10843 						   "zone %s has returned: "
10844 						   "starting 30-day "
10845 						   "acceptance timer",
10846 						   keytag, namebuf);
10847 				} else if (keydata.addhd > now) {
10848 					pending++;
10849 				} else if (keydata.addhd == 0) {
10850 					keydata.addhd = now;
10851 				}
10852 
10853 				if (keydata.addhd <= now) {
10854 					trustkey = true;
10855 					dnssec_log(zone, ISC_LOG_INFO,
10856 						   "Key %d for zone %s "
10857 						   "is now trusted (%s)",
10858 						   keytag, namebuf,
10859 						   initial ? "initializing key "
10860 							     "verified"
10861 							   : "acceptance timer "
10862 							     "complete");
10863 				}
10864 			} else if (keydata.addhd > now) {
10865 				/*
10866 				 * Not secure, and key is pending:
10867 				 * reset the acceptance timer
10868 				 */
10869 				pending++;
10870 				keydata.addhd = now + dns_zone_mkey_month;
10871 				dnssec_log(zone, ISC_LOG_INFO,
10872 					   "Pending key %d "
10873 					   "for zone %s was "
10874 					   "not validated: restarting "
10875 					   "30-day acceptance timer",
10876 					   keytag, namebuf);
10877 			}
10878 
10879 			if (!deletekey && !newkey) {
10880 				updatekey = true;
10881 			}
10882 		} else if (secure) {
10883 			/*
10884 			 * Key wasn't in the key zone but it's
10885 			 * revoked now anyway, so just skip it
10886 			 */
10887 			if (revoked) {
10888 				continue;
10889 			}
10890 
10891 			/* Key wasn't in the key zone: add it */
10892 			newkey = true;
10893 
10894 			if (initializing) {
10895 				dnssec_log(zone, ISC_LOG_WARNING,
10896 					   "Initializing automatic trust "
10897 					   "anchor management for zone '%s'; "
10898 					   "DNSKEY ID %d is now trusted, "
10899 					   "waiving the normal 30-day "
10900 					   "waiting period.",
10901 					   namebuf, keytag);
10902 				trustkey = true;
10903 			} else {
10904 				dnssec_log(zone, ISC_LOG_INFO,
10905 					   "New key %d observed "
10906 					   "for zone '%s': "
10907 					   "starting 30-day "
10908 					   "acceptance timer",
10909 					   keytag, namebuf);
10910 			}
10911 		} else {
10912 			/*
10913 			 * No previously known key, and the key is not
10914 			 * secure, so skip it.
10915 			 */
10916 			continue;
10917 		}
10918 
10919 		/* Delete old version */
10920 		if (deletekey || !newkey) {
10921 			CHECK(update_one_rr(kfetch->db, ver, &diff,
10922 					    DNS_DIFFOP_DEL, keyname, 0,
10923 					    &keydatarr));
10924 		}
10925 
10926 		if (updatekey) {
10927 			/* Set refresh timer */
10928 			keydata.refresh = refresh_time(kfetch, false);
10929 			dns_rdata_reset(&keydatarr);
10930 			isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10931 			dns_rdata_fromstruct(&keydatarr, zone->rdclass,
10932 					     dns_rdatatype_keydata, &keydata,
10933 					     &keyb);
10934 
10935 			/* Insert updated version */
10936 			CHECK(update_one_rr(kfetch->db, ver, &diff,
10937 					    DNS_DIFFOP_ADD, keyname, 0,
10938 					    &keydatarr));
10939 		} else if (newkey) {
10940 			/* Convert DNSKEY to KEYDATA */
10941 			result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
10942 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
10943 			dns_keydata_fromdnskey(&keydata, &dnskey, 0, 0, 0,
10944 					       NULL);
10945 			keydata.addhd = initializing
10946 						? now
10947 						: now + dns_zone_mkey_month;
10948 			keydata.refresh = refresh_time(kfetch, false);
10949 			dns_rdata_reset(&keydatarr);
10950 			isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10951 			dns_rdata_fromstruct(&keydatarr, zone->rdclass,
10952 					     dns_rdatatype_keydata, &keydata,
10953 					     &keyb);
10954 
10955 			/* Insert into key zone */
10956 			CHECK(update_one_rr(kfetch->db, ver, &diff,
10957 					    DNS_DIFFOP_ADD, keyname, 0,
10958 					    &keydatarr));
10959 		}
10960 
10961 		if (trustkey) {
10962 			/* Trust this key. */
10963 			result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
10964 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
10965 			trust_key(zone, keyname, &dnskey, false);
10966 		}
10967 
10968 		if (secure && !deletekey) {
10969 			INSIST(newkey || updatekey);
10970 			set_refreshkeytimer(zone, &keydata, now, false);
10971 		}
10972 	}
10973 
10974 	/*
10975 	 * RFC5011 says, "A trust point that has all of its trust anchors
10976 	 * revoked is considered deleted and is treated as if the trust
10977 	 * point was never configured."  But if someone revoked their
10978 	 * active key before the standby was trusted, that would mean the
10979 	 * zone would suddenly be nonsecured.  We avoid this by checking to
10980 	 * see if there's pending keydata.  If so, we put a null key in
10981 	 * the security roots; then all queries to the zone will fail.
10982 	 */
10983 	if (pending != 0) {
10984 		fail_secure(zone, keyname);
10985 	}
10986 
10987 done:
10988 	if (!ISC_LIST_EMPTY(diff.tuples)) {
10989 		/* Write changes to journal file. */
10990 		CHECK(update_soa_serial(zone, kfetch->db, ver, &diff, mctx,
10991 					zone->updatemethod));
10992 		CHECK(zone_journal(zone, &diff, NULL, "keyfetch_done"));
10993 		commit = true;
10994 
10995 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
10996 		zone_needdump(zone, 30);
10997 	} else if (result == ISC_R_NOMORE) {
10998 		/*
10999 		 * If "updatekey" was true for all keys found in the DNSKEY
11000 		 * response and the previous update of those keys happened
11001 		 * during the same second (only possible if a key refresh was
11002 		 * externally triggered), it may happen that all relevant
11003 		 * update_one_rr() calls will return ISC_R_SUCCESS, but
11004 		 * diff.tuples will remain empty.  Reset result to
11005 		 * ISC_R_SUCCESS to prevent a bogus warning from being logged.
11006 		 */
11007 		result = ISC_R_SUCCESS;
11008 	}
11009 
11010 failure:
11011 	if (result != ISC_R_SUCCESS) {
11012 		dnssec_log(zone, ISC_LOG_ERROR,
11013 			   "error during managed-keys processing (%s): "
11014 			   "DNSSEC validation may be at risk",
11015 			   isc_result_totext(result));
11016 	}
11017 	dns_diff_clear(&diff);
11018 	if (ver != NULL) {
11019 		dns_db_closeversion(kfetch->db, &ver, commit);
11020 	}
11021 
11022 cleanup:
11023 	dns_db_detach(&kfetch->db);
11024 
11025 	/* The zone must be managed */
11026 	INSIST(kfetch->zone->task != NULL);
11027 	isc_refcount_decrement(&zone->irefs);
11028 
11029 	if (dns_rdataset_isassociated(keydataset)) {
11030 		dns_rdataset_disassociate(keydataset);
11031 	}
11032 	if (dns_rdataset_isassociated(dnskeys)) {
11033 		dns_rdataset_disassociate(dnskeys);
11034 	}
11035 	if (dns_rdataset_isassociated(dnskeysigs)) {
11036 		dns_rdataset_disassociate(dnskeysigs);
11037 	}
11038 
11039 	dns_name_free(keyname, mctx);
11040 	isc_mem_putanddetach(&kfetch->mctx, kfetch, sizeof(dns_keyfetch_t));
11041 
11042 	if (secroots != NULL) {
11043 		dns_keytable_detach(&secroots);
11044 	}
11045 
11046 	free_needed = exit_check(zone);
11047 	UNLOCK_ZONE(zone);
11048 
11049 	if (free_needed) {
11050 		zone_free(zone);
11051 	}
11052 
11053 	INSIST(ver == NULL);
11054 }
11055 
11056 static void
retry_keyfetch(dns_keyfetch_t * kfetch,dns_name_t * kname)11057 retry_keyfetch(dns_keyfetch_t *kfetch, dns_name_t *kname) {
11058 	isc_time_t timenow, timethen;
11059 	dns_zone_t *zone = kfetch->zone;
11060 	bool free_needed;
11061 	char namebuf[DNS_NAME_FORMATSIZE];
11062 
11063 	dns_name_format(kname, namebuf, sizeof(namebuf));
11064 	dnssec_log(zone, ISC_LOG_WARNING,
11065 		   "Failed to create fetch for %s DNSKEY update", namebuf);
11066 
11067 	/*
11068 	 * Error during a key fetch; cancel and retry in an hour.
11069 	 */
11070 	LOCK_ZONE(zone);
11071 	zone->refreshkeycount--;
11072 	isc_refcount_decrement(&zone->irefs);
11073 	dns_db_detach(&kfetch->db);
11074 	dns_rdataset_disassociate(&kfetch->keydataset);
11075 	dns_name_free(kname, zone->mctx);
11076 	isc_mem_putanddetach(&kfetch->mctx, kfetch, sizeof(*kfetch));
11077 
11078 	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
11079 		/* Don't really retry if we are exiting */
11080 		char timebuf[80];
11081 
11082 		TIME_NOW(&timenow);
11083 		DNS_ZONE_TIME_ADD(&timenow, dns_zone_mkey_hour, &timethen);
11084 		zone->refreshkeytime = timethen;
11085 		zone_settimer(zone, &timenow);
11086 
11087 		isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
11088 		dnssec_log(zone, ISC_LOG_DEBUG(1), "retry key refresh: %s",
11089 			   timebuf);
11090 	}
11091 
11092 	free_needed = exit_check(zone);
11093 	UNLOCK_ZONE(zone);
11094 
11095 	if (free_needed) {
11096 		zone_free(zone);
11097 	}
11098 }
11099 
11100 static void
do_keyfetch(isc_task_t * task,isc_event_t * event)11101 do_keyfetch(isc_task_t *task, isc_event_t *event) {
11102 	isc_result_t result;
11103 	dns_keyfetch_t *kfetch = (dns_keyfetch_t *)event->ev_arg;
11104 	dns_name_t *kname = dns_fixedname_name(&kfetch->name);
11105 	dns_zone_t *zone = kfetch->zone;
11106 
11107 	UNUSED(task);
11108 
11109 	isc_event_free(&event);
11110 
11111 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
11112 		retry_keyfetch(kfetch, kname);
11113 		return;
11114 	}
11115 
11116 	/*
11117 	 * Use of DNS_FETCHOPT_NOCACHED is essential here.  If it is not
11118 	 * set and the cache still holds a non-expired, validated version
11119 	 * of the RRset being queried for by the time the response is
11120 	 * received, the cached RRset will be passed to keyfetch_done()
11121 	 * instead of the one received in the response as the latter will
11122 	 * have a lower trust level due to not being validated until
11123 	 * keyfetch_done() is called.
11124 	 */
11125 	result = dns_resolver_createfetch(
11126 		zone->view->resolver, kname, dns_rdatatype_dnskey, NULL, NULL,
11127 		NULL, NULL, 0,
11128 		DNS_FETCHOPT_NOVALIDATE | DNS_FETCHOPT_UNSHARED |
11129 			DNS_FETCHOPT_NOCACHED,
11130 		0, NULL, zone->task, keyfetch_done, kfetch, &kfetch->dnskeyset,
11131 		&kfetch->dnskeysigset, &kfetch->fetch);
11132 
11133 	if (result != ISC_R_SUCCESS) {
11134 		retry_keyfetch(kfetch, kname);
11135 	}
11136 }
11137 
11138 /*
11139  * Refresh the data in the key zone.  Initiate a fetch to look up
11140  * DNSKEY records at the trust anchor name.
11141  */
11142 static void
zone_refreshkeys(dns_zone_t * zone)11143 zone_refreshkeys(dns_zone_t *zone) {
11144 	const char me[] = "zone_refreshkeys";
11145 	isc_result_t result;
11146 	dns_rriterator_t rrit;
11147 	dns_db_t *db = NULL;
11148 	dns_dbversion_t *ver = NULL;
11149 	dns_diff_t diff;
11150 	dns_rdata_t rdata = DNS_RDATA_INIT;
11151 	dns_rdata_keydata_t kd;
11152 	isc_stdtime_t now;
11153 	bool commit = false;
11154 	bool fetching = false;
11155 	bool timerset = false;
11156 
11157 	ENTER;
11158 	REQUIRE(zone->db != NULL);
11159 
11160 	isc_stdtime_get(&now);
11161 
11162 	LOCK_ZONE(zone);
11163 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
11164 		isc_time_settoepoch(&zone->refreshkeytime);
11165 		UNLOCK_ZONE(zone);
11166 		return;
11167 	}
11168 
11169 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11170 	dns_db_attach(zone->db, &db);
11171 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11172 
11173 	dns_diff_init(zone->mctx, &diff);
11174 
11175 	CHECK(dns_db_newversion(db, &ver));
11176 
11177 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESHING);
11178 
11179 	dns_rriterator_init(&rrit, db, ver, 0);
11180 	for (result = dns_rriterator_first(&rrit); result == ISC_R_SUCCESS;
11181 	     result = dns_rriterator_nextrrset(&rrit))
11182 	{
11183 		isc_stdtime_t timer = 0xffffffff;
11184 		dns_name_t *name = NULL, *kname = NULL;
11185 		dns_rdataset_t *kdset = NULL;
11186 		uint32_t ttl;
11187 
11188 		dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL);
11189 		if (kdset == NULL || kdset->type != dns_rdatatype_keydata ||
11190 		    !dns_rdataset_isassociated(kdset))
11191 		{
11192 			continue;
11193 		}
11194 
11195 		/*
11196 		 * Scan the stored keys looking for ones that need
11197 		 * removal or refreshing
11198 		 */
11199 		for (result = dns_rdataset_first(kdset);
11200 		     result == ISC_R_SUCCESS; result = dns_rdataset_next(kdset))
11201 		{
11202 			dns_rdata_reset(&rdata);
11203 			dns_rdataset_current(kdset, &rdata);
11204 			result = dns_rdata_tostruct(&rdata, &kd, NULL);
11205 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
11206 
11207 			/* Removal timer expired? */
11208 			if (kd.removehd != 0 && kd.removehd < now) {
11209 				dns_rriterator_pause(&rrit);
11210 				CHECK(update_one_rr(db, ver, &diff,
11211 						    DNS_DIFFOP_DEL, name, ttl,
11212 						    &rdata));
11213 				continue;
11214 			}
11215 
11216 			/* Acceptance timer expired? */
11217 			if (kd.addhd <= now) {
11218 				timer = kd.addhd;
11219 			}
11220 
11221 			/* Or do we just need to refresh the keyset? */
11222 			if (timer > kd.refresh) {
11223 				timer = kd.refresh;
11224 			}
11225 
11226 			dns_rriterator_pause(&rrit);
11227 			set_refreshkeytimer(zone, &kd, now, false);
11228 			timerset = true;
11229 		}
11230 
11231 		if (timer > now) {
11232 			continue;
11233 		}
11234 
11235 		dns_rriterator_pause(&rrit);
11236 
11237 #ifdef ENABLE_AFL
11238 		if (!dns_fuzzing_resolver) {
11239 #endif /* ifdef ENABLE_AFL */
11240 			dns_keyfetch_t *kfetch = NULL;
11241 			isc_event_t *e;
11242 
11243 			kfetch = isc_mem_get(zone->mctx,
11244 					     sizeof(dns_keyfetch_t));
11245 			*kfetch = (dns_keyfetch_t){ .zone = zone };
11246 			isc_mem_attach(zone->mctx, &kfetch->mctx);
11247 
11248 			zone->refreshkeycount++;
11249 			isc_refcount_increment0(&zone->irefs);
11250 			kname = dns_fixedname_initname(&kfetch->name);
11251 			dns_name_dup(name, zone->mctx, kname);
11252 			dns_rdataset_init(&kfetch->dnskeyset);
11253 			dns_rdataset_init(&kfetch->dnskeysigset);
11254 			dns_rdataset_init(&kfetch->keydataset);
11255 			dns_rdataset_clone(kdset, &kfetch->keydataset);
11256 			dns_db_attach(db, &kfetch->db);
11257 
11258 			if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
11259 				char namebuf[DNS_NAME_FORMATSIZE];
11260 				dns_name_format(kname, namebuf,
11261 						sizeof(namebuf));
11262 				dnssec_log(zone, ISC_LOG_DEBUG(3),
11263 					   "Creating key fetch in "
11264 					   "zone_refreshkeys() for '%s'",
11265 					   namebuf);
11266 			}
11267 
11268 			e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE,
11269 					       do_keyfetch, kfetch,
11270 					       sizeof(isc_event_t));
11271 			isc_task_send(zone->task, &e);
11272 			fetching = true;
11273 #ifdef ENABLE_AFL
11274 		}
11275 #endif /* ifdef ENABLE_AFL */
11276 	}
11277 	if (!ISC_LIST_EMPTY(diff.tuples)) {
11278 		CHECK(update_soa_serial(zone, db, ver, &diff, zone->mctx,
11279 					zone->updatemethod));
11280 		CHECK(zone_journal(zone, &diff, NULL, "zone_refreshkeys"));
11281 		commit = true;
11282 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
11283 		zone_needdump(zone, 30);
11284 	}
11285 
11286 failure:
11287 	if (!timerset) {
11288 		isc_time_settoepoch(&zone->refreshkeytime);
11289 	}
11290 
11291 	if (!fetching) {
11292 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
11293 	}
11294 
11295 	dns_diff_clear(&diff);
11296 	if (ver != NULL) {
11297 		dns_rriterator_destroy(&rrit);
11298 		dns_db_closeversion(db, &ver, commit);
11299 	}
11300 	dns_db_detach(&db);
11301 
11302 	UNLOCK_ZONE(zone);
11303 
11304 	INSIST(ver == NULL);
11305 }
11306 
11307 static void
zone_maintenance(dns_zone_t * zone)11308 zone_maintenance(dns_zone_t *zone) {
11309 	const char me[] = "zone_maintenance";
11310 	isc_time_t now;
11311 	isc_result_t result;
11312 	bool dumping, load_pending, exiting, viewok;
11313 	bool need_notify;
11314 
11315 	REQUIRE(DNS_ZONE_VALID(zone));
11316 	ENTER;
11317 
11318 	/*
11319 	 * Are we pending load/reload, exiting, or unconfigured
11320 	 * (e.g. because of a syntax failure in the config file)?
11321 	 * If so, don't attempt maintenance.
11322 	 */
11323 	LOCK_ZONE(zone);
11324 	load_pending = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING);
11325 	exiting = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING);
11326 	viewok = (zone->view != NULL && zone->view->adb != NULL);
11327 	UNLOCK_ZONE(zone);
11328 
11329 	if (load_pending || exiting || !viewok) {
11330 		return;
11331 	}
11332 
11333 	TIME_NOW(&now);
11334 
11335 	/*
11336 	 * Expire check.
11337 	 */
11338 	switch (zone->type) {
11339 	case dns_zone_redirect:
11340 		if (zone->masters == NULL) {
11341 			break;
11342 		}
11343 		FALLTHROUGH;
11344 	case dns_zone_secondary:
11345 	case dns_zone_mirror:
11346 	case dns_zone_stub:
11347 		LOCK_ZONE(zone);
11348 		if (isc_time_compare(&now, &zone->expiretime) >= 0 &&
11349 		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
11350 		{
11351 			zone_expire(zone);
11352 			zone->refreshtime = now;
11353 		}
11354 		UNLOCK_ZONE(zone);
11355 		break;
11356 	default:
11357 		break;
11358 	}
11359 
11360 	/*
11361 	 * Up to date check.
11362 	 */
11363 	switch (zone->type) {
11364 	case dns_zone_redirect:
11365 		if (zone->masters == NULL) {
11366 			break;
11367 		}
11368 		FALLTHROUGH;
11369 	case dns_zone_secondary:
11370 	case dns_zone_mirror:
11371 	case dns_zone_stub:
11372 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
11373 		    isc_time_compare(&now, &zone->refreshtime) >= 0)
11374 		{
11375 			dns_zone_refresh(zone);
11376 		}
11377 		break;
11378 	default:
11379 		break;
11380 	}
11381 
11382 	/*
11383 	 * Secondaries send notifies before backing up to disk,
11384 	 * primaries after.
11385 	 */
11386 	LOCK_ZONE(zone);
11387 	need_notify = (zone->type == dns_zone_secondary ||
11388 		       zone->type == dns_zone_mirror) &&
11389 		      (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
11390 		       DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY)) &&
11391 		      (isc_time_compare(&now, &zone->notifytime) >= 0);
11392 	UNLOCK_ZONE(zone);
11393 
11394 	if (need_notify) {
11395 		zone_notify(zone, &now);
11396 	}
11397 
11398 	/*
11399 	 * Do we need to consolidate the backing store?
11400 	 */
11401 	switch (zone->type) {
11402 	case dns_zone_primary:
11403 	case dns_zone_secondary:
11404 	case dns_zone_mirror:
11405 	case dns_zone_key:
11406 	case dns_zone_redirect:
11407 	case dns_zone_stub:
11408 		LOCK_ZONE(zone);
11409 		if (zone->masterfile != NULL &&
11410 		    isc_time_compare(&now, &zone->dumptime) >= 0 &&
11411 		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
11412 		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP))
11413 		{
11414 			dumping = was_dumping(zone);
11415 		} else {
11416 			dumping = true;
11417 		}
11418 		UNLOCK_ZONE(zone);
11419 		if (!dumping) {
11420 			result = zone_dump(zone, true); /* task locked */
11421 			if (result != ISC_R_SUCCESS) {
11422 				dns_zone_log(zone, ISC_LOG_WARNING,
11423 					     "dump failed: %s",
11424 					     dns_result_totext(result));
11425 			}
11426 		}
11427 		break;
11428 	default:
11429 		break;
11430 	}
11431 
11432 	/*
11433 	 * Master/redirect zones send notifies now, if needed
11434 	 */
11435 	switch (zone->type) {
11436 	case dns_zone_primary:
11437 	case dns_zone_redirect:
11438 		if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
11439 		     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY)) &&
11440 		    isc_time_compare(&now, &zone->notifytime) >= 0)
11441 		{
11442 			zone_notify(zone, &now);
11443 		}
11444 	default:
11445 		break;
11446 	}
11447 
11448 	/*
11449 	 * Do we need to refresh keys?
11450 	 */
11451 	switch (zone->type) {
11452 	case dns_zone_key:
11453 		if (isc_time_compare(&now, &zone->refreshkeytime) >= 0) {
11454 			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
11455 			    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING))
11456 			{
11457 				zone_refreshkeys(zone);
11458 			}
11459 		}
11460 		break;
11461 	case dns_zone_primary:
11462 		if (!isc_time_isepoch(&zone->refreshkeytime) &&
11463 		    isc_time_compare(&now, &zone->refreshkeytime) >= 0 &&
11464 		    zone->rss_event == NULL)
11465 		{
11466 			zone_rekey(zone);
11467 		}
11468 	default:
11469 		break;
11470 	}
11471 
11472 	switch (zone->type) {
11473 	case dns_zone_primary:
11474 	case dns_zone_redirect:
11475 	case dns_zone_secondary:
11476 		/*
11477 		 * Do we need to sign/resign some RRsets?
11478 		 */
11479 		if (zone->rss_event != NULL) {
11480 			break;
11481 		}
11482 		if (!isc_time_isepoch(&zone->signingtime) &&
11483 		    isc_time_compare(&now, &zone->signingtime) >= 0)
11484 		{
11485 			zone_sign(zone);
11486 		} else if (!isc_time_isepoch(&zone->resigntime) &&
11487 			   isc_time_compare(&now, &zone->resigntime) >= 0)
11488 		{
11489 			zone_resigninc(zone);
11490 		} else if (!isc_time_isepoch(&zone->nsec3chaintime) &&
11491 			   isc_time_compare(&now, &zone->nsec3chaintime) >= 0)
11492 		{
11493 			zone_nsec3chain(zone);
11494 		}
11495 		/*
11496 		 * Do we need to issue a key expiry warning?
11497 		 */
11498 		if (!isc_time_isepoch(&zone->keywarntime) &&
11499 		    isc_time_compare(&now, &zone->keywarntime) >= 0)
11500 		{
11501 			set_key_expiry_warning(zone, zone->key_expiry,
11502 					       isc_time_seconds(&now));
11503 		}
11504 		break;
11505 
11506 	default:
11507 		break;
11508 	}
11509 	LOCK_ZONE(zone);
11510 	zone_settimer(zone, &now);
11511 	UNLOCK_ZONE(zone);
11512 }
11513 
11514 void
dns_zone_markdirty(dns_zone_t * zone)11515 dns_zone_markdirty(dns_zone_t *zone) {
11516 	uint32_t serial;
11517 	isc_result_t result = ISC_R_SUCCESS;
11518 	dns_zone_t *secure = NULL;
11519 
11520 	/*
11521 	 * Obtaining a lock on the zone->secure (see zone_send_secureserial)
11522 	 * could result in a deadlock due to a LOR so we will spin if we
11523 	 * can't obtain the both locks.
11524 	 */
11525 again:
11526 	LOCK_ZONE(zone);
11527 	if (zone->type == dns_zone_primary) {
11528 		if (inline_raw(zone)) {
11529 			unsigned int soacount;
11530 			secure = zone->secure;
11531 			INSIST(secure != zone);
11532 			TRYLOCK_ZONE(result, secure);
11533 			if (result != ISC_R_SUCCESS) {
11534 				UNLOCK_ZONE(zone);
11535 				secure = NULL;
11536 				isc_thread_yield();
11537 				goto again;
11538 			}
11539 
11540 			ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11541 			if (zone->db != NULL) {
11542 				result = zone_get_from_db(
11543 					zone, zone->db, NULL, &soacount, NULL,
11544 					&serial, NULL, NULL, NULL, NULL, NULL);
11545 			} else {
11546 				result = DNS_R_NOTLOADED;
11547 			}
11548 			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11549 			if (result == ISC_R_SUCCESS && soacount > 0U) {
11550 				zone_send_secureserial(zone, serial);
11551 			}
11552 		}
11553 
11554 		/* XXXMPA make separate call back */
11555 		if (result == ISC_R_SUCCESS) {
11556 			set_resigntime(zone);
11557 			if (zone->task != NULL) {
11558 				isc_time_t now;
11559 				TIME_NOW(&now);
11560 				zone_settimer(zone, &now);
11561 			}
11562 		}
11563 	}
11564 	if (secure != NULL) {
11565 		UNLOCK_ZONE(secure);
11566 	}
11567 	zone_needdump(zone, DNS_DUMP_DELAY);
11568 	UNLOCK_ZONE(zone);
11569 }
11570 
11571 void
dns_zone_expire(dns_zone_t * zone)11572 dns_zone_expire(dns_zone_t *zone) {
11573 	REQUIRE(DNS_ZONE_VALID(zone));
11574 
11575 	LOCK_ZONE(zone);
11576 	zone_expire(zone);
11577 	UNLOCK_ZONE(zone);
11578 }
11579 
11580 static void
zone_expire(dns_zone_t * zone)11581 zone_expire(dns_zone_t *zone) {
11582 	dns_db_t *db = NULL;
11583 
11584 	/*
11585 	 * 'zone' locked by caller.
11586 	 */
11587 
11588 	REQUIRE(LOCKED_ZONE(zone));
11589 
11590 	dns_zone_log(zone, ISC_LOG_WARNING, "expired");
11591 
11592 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXPIRED);
11593 	zone->refresh = DNS_ZONE_DEFAULTREFRESH;
11594 	zone->retry = DNS_ZONE_DEFAULTRETRY;
11595 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
11596 
11597 	/*
11598 	 * An RPZ zone has expired; before unloading it, we must
11599 	 * first remove it from the RPZ summary database. The
11600 	 * easiest way to do this is "update" it with an empty
11601 	 * database so that the update callback synchronizes
11602 	 * the diff automatically.
11603 	 */
11604 	if (zone->rpzs != NULL && zone->rpz_num != DNS_RPZ_INVALID_NUM) {
11605 		isc_result_t result;
11606 		dns_rpz_zone_t *rpz = zone->rpzs->zones[zone->rpz_num];
11607 
11608 		CHECK(dns_db_create(zone->mctx, "rbt", &zone->origin,
11609 				    dns_dbtype_zone, zone->rdclass, 0, NULL,
11610 				    &db));
11611 		CHECK(dns_rpz_dbupdate_callback(db, rpz));
11612 		dns_zone_log(zone, ISC_LOG_WARNING,
11613 			     "response-policy zone expired; "
11614 			     "policies unloaded");
11615 	}
11616 
11617 failure:
11618 	if (db != NULL) {
11619 		dns_db_detach(&db);
11620 	}
11621 
11622 	zone_unload(zone);
11623 }
11624 
11625 void
dns_zone_refresh(dns_zone_t * zone)11626 dns_zone_refresh(dns_zone_t *zone) {
11627 	isc_interval_t i;
11628 	uint32_t oldflags;
11629 	unsigned int j;
11630 	isc_result_t result;
11631 
11632 	REQUIRE(DNS_ZONE_VALID(zone));
11633 
11634 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
11635 		return;
11636 	}
11637 
11638 	/*
11639 	 * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation
11640 	 * in progress at a time.
11641 	 */
11642 
11643 	LOCK_ZONE(zone);
11644 	oldflags = atomic_load(&zone->flags);
11645 	if (zone->masterscnt == 0) {
11646 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOMASTERS);
11647 		if ((oldflags & DNS_ZONEFLG_NOMASTERS) == 0) {
11648 			dns_zone_log(zone, ISC_LOG_ERROR,
11649 				     "cannot refresh: no primaries");
11650 		}
11651 		goto unlock;
11652 	}
11653 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
11654 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
11655 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
11656 	if ((oldflags & (DNS_ZONEFLG_REFRESH | DNS_ZONEFLG_LOADING)) != 0) {
11657 		goto unlock;
11658 	}
11659 
11660 	/*
11661 	 * Set the next refresh time as if refresh check has failed.
11662 	 * Setting this to the retry time will do that.  XXXMLG
11663 	 * If we are successful it will be reset using zone->refresh.
11664 	 */
11665 	isc_interval_set(&i, zone->retry - isc_random_uniform(zone->retry / 4),
11666 			 0);
11667 	result = isc_time_nowplusinterval(&zone->refreshtime, &i);
11668 	if (result != ISC_R_SUCCESS) {
11669 		dns_zone_log(zone, ISC_LOG_WARNING,
11670 			     "isc_time_nowplusinterval() failed: %s",
11671 			     dns_result_totext(result));
11672 	}
11673 
11674 	/*
11675 	 * When lacking user-specified timer values from the SOA,
11676 	 * do exponential backoff of the retry time up to a
11677 	 * maximum of six hours.
11678 	 */
11679 	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS)) {
11680 		zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
11681 	}
11682 
11683 	zone->curmaster = 0;
11684 	for (j = 0; j < zone->masterscnt; j++) {
11685 		zone->mastersok[j] = false;
11686 	}
11687 	/* initiate soa query */
11688 	queue_soa_query(zone);
11689 unlock:
11690 	UNLOCK_ZONE(zone);
11691 }
11692 
11693 static isc_result_t
zone_journal_rollforward(dns_zone_t * zone,dns_db_t * db,bool * needdump,bool * fixjournal)11694 zone_journal_rollforward(dns_zone_t *zone, dns_db_t *db, bool *needdump,
11695 			 bool *fixjournal) {
11696 	dns_journal_t *journal = NULL;
11697 	unsigned int options;
11698 	isc_result_t result;
11699 
11700 	if (zone->type == dns_zone_primary &&
11701 	    (inline_secure(zone) ||
11702 	     (zone->update_acl != NULL || zone->ssutable != NULL)))
11703 	{
11704 		options = DNS_JOURNALOPT_RESIGN;
11705 	} else {
11706 		options = 0;
11707 	}
11708 
11709 	result = dns_journal_open(zone->mctx, zone->journal, DNS_JOURNAL_READ,
11710 				  &journal);
11711 	if (result == ISC_R_NOTFOUND) {
11712 		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(3),
11713 			      "no journal file, but that's OK ");
11714 		return (ISC_R_SUCCESS);
11715 	} else if (result != ISC_R_SUCCESS) {
11716 		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
11717 			      "journal open failed: %s",
11718 			      dns_result_totext(result));
11719 		return (result);
11720 	}
11721 
11722 	if (dns_journal_empty(journal)) {
11723 		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
11724 			      "journal empty");
11725 		dns_journal_destroy(&journal);
11726 		return (ISC_R_SUCCESS);
11727 	}
11728 
11729 	result = dns_journal_rollforward(journal, db, options);
11730 	switch (result) {
11731 	case ISC_R_SUCCESS:
11732 		*needdump = true;
11733 		FALLTHROUGH;
11734 	case DNS_R_UPTODATE:
11735 		if (dns_journal_recovered(journal)) {
11736 			*fixjournal = true;
11737 			dns_zone_logc(
11738 				zone, DNS_LOGCATEGORY_ZONELOAD,
11739 				ISC_LOG_DEBUG(1),
11740 				"journal rollforward completed successfully "
11741 				"using old journal format: %s",
11742 				dns_result_totext(result));
11743 		} else {
11744 			dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
11745 				      ISC_LOG_DEBUG(1),
11746 				      "journal rollforward completed "
11747 				      "successfully: %s",
11748 				      dns_result_totext(result));
11749 		}
11750 
11751 		dns_journal_destroy(&journal);
11752 		return (ISC_R_SUCCESS);
11753 	case ISC_R_NOTFOUND:
11754 	case ISC_R_RANGE:
11755 		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
11756 			      "journal rollforward failed: journal out of sync "
11757 			      "with zone");
11758 		dns_journal_destroy(&journal);
11759 		return (result);
11760 	default:
11761 		dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
11762 			      "journal rollforward failed: %s",
11763 			      dns_result_totext(result));
11764 		dns_journal_destroy(&journal);
11765 		return (result);
11766 	}
11767 }
11768 
11769 static void
zone_journal_compact(dns_zone_t * zone,dns_db_t * db,uint32_t serial)11770 zone_journal_compact(dns_zone_t *zone, dns_db_t *db, uint32_t serial) {
11771 	isc_result_t result;
11772 	int32_t journalsize;
11773 	dns_dbversion_t *ver = NULL;
11774 	uint64_t dbsize;
11775 	uint32_t options = 0;
11776 
11777 	INSIST(LOCKED_ZONE(zone));
11778 	if (inline_raw(zone)) {
11779 		INSIST(LOCKED_ZONE(zone->secure));
11780 	}
11781 
11782 	journalsize = zone->journalsize;
11783 	if (journalsize == -1) {
11784 		journalsize = DNS_JOURNAL_SIZE_MAX;
11785 		dns_db_currentversion(db, &ver);
11786 		result = dns_db_getsize(db, ver, NULL, &dbsize);
11787 		dns_db_closeversion(db, &ver, false);
11788 		if (result != ISC_R_SUCCESS) {
11789 			dns_zone_log(zone, ISC_LOG_ERROR,
11790 				     "zone_journal_compact: "
11791 				     "could not get zone size: %s",
11792 				     isc_result_totext(result));
11793 		} else if (dbsize < DNS_JOURNAL_SIZE_MAX / 2) {
11794 			journalsize = (int32_t)dbsize * 2;
11795 		}
11796 	}
11797 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FIXJOURNAL)) {
11798 		options |= DNS_JOURNAL_COMPACTALL;
11799 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FIXJOURNAL);
11800 		zone_debuglog(zone, "zone_journal_compact", 1,
11801 			      "repair full journal");
11802 	} else {
11803 		zone_debuglog(zone, "zone_journal_compact", 1,
11804 			      "target journal size %d", journalsize);
11805 	}
11806 	result = dns_journal_compact(zone->mctx, zone->journal, serial, options,
11807 				     journalsize);
11808 	switch (result) {
11809 	case ISC_R_SUCCESS:
11810 	case ISC_R_NOSPACE:
11811 	case ISC_R_NOTFOUND:
11812 		dns_zone_log(zone, ISC_LOG_DEBUG(3), "dns_journal_compact: %s",
11813 			     dns_result_totext(result));
11814 		break;
11815 	default:
11816 		dns_zone_log(zone, ISC_LOG_ERROR,
11817 			     "dns_journal_compact failed: %s",
11818 			     dns_result_totext(result));
11819 		break;
11820 	}
11821 }
11822 
11823 isc_result_t
dns_zone_flush(dns_zone_t * zone)11824 dns_zone_flush(dns_zone_t *zone) {
11825 	isc_result_t result = ISC_R_SUCCESS;
11826 	bool dumping;
11827 
11828 	REQUIRE(DNS_ZONE_VALID(zone));
11829 
11830 	LOCK_ZONE(zone);
11831 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FLUSH);
11832 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
11833 	    zone->masterfile != NULL)
11834 	{
11835 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
11836 		result = ISC_R_ALREADYRUNNING;
11837 		dumping = was_dumping(zone);
11838 	} else {
11839 		dumping = true;
11840 	}
11841 	UNLOCK_ZONE(zone);
11842 	if (!dumping) {
11843 		result = zone_dump(zone, true); /* Unknown task. */
11844 	}
11845 	return (result);
11846 }
11847 
11848 isc_result_t
dns_zone_dump(dns_zone_t * zone)11849 dns_zone_dump(dns_zone_t *zone) {
11850 	isc_result_t result = ISC_R_ALREADYRUNNING;
11851 	bool dumping;
11852 
11853 	REQUIRE(DNS_ZONE_VALID(zone));
11854 
11855 	LOCK_ZONE(zone);
11856 	dumping = was_dumping(zone);
11857 	UNLOCK_ZONE(zone);
11858 	if (!dumping) {
11859 		result = zone_dump(zone, false); /* Unknown task. */
11860 	}
11861 	return (result);
11862 }
11863 
11864 static void
zone_needdump(dns_zone_t * zone,unsigned int delay)11865 zone_needdump(dns_zone_t *zone, unsigned int delay) {
11866 	const char me[] = "zone_needdump";
11867 	isc_time_t dumptime;
11868 	isc_time_t now;
11869 
11870 	/*
11871 	 * 'zone' locked by caller
11872 	 */
11873 
11874 	REQUIRE(DNS_ZONE_VALID(zone));
11875 	REQUIRE(LOCKED_ZONE(zone));
11876 	ENTER;
11877 
11878 	/*
11879 	 * Do we have a place to dump to and are we loaded?
11880 	 */
11881 	if (zone->masterfile == NULL ||
11882 	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
11883 	{
11884 		return;
11885 	}
11886 
11887 	TIME_NOW(&now);
11888 	/* add some noise */
11889 	DNS_ZONE_JITTER_ADD(&now, delay, &dumptime);
11890 
11891 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
11892 	if (isc_time_isepoch(&zone->dumptime) ||
11893 	    isc_time_compare(&zone->dumptime, &dumptime) > 0)
11894 	{
11895 		zone->dumptime = dumptime;
11896 	}
11897 	if (zone->task != NULL) {
11898 		zone_settimer(zone, &now);
11899 	}
11900 }
11901 
11902 static void
dump_done(void * arg,isc_result_t result)11903 dump_done(void *arg, isc_result_t result) {
11904 	const char me[] = "dump_done";
11905 	dns_zone_t *zone = arg;
11906 	dns_zone_t *secure = NULL;
11907 	dns_db_t *db;
11908 	dns_dbversion_t *version;
11909 	bool again = false;
11910 	bool compact = false;
11911 	uint32_t serial;
11912 	isc_result_t tresult;
11913 
11914 	REQUIRE(DNS_ZONE_VALID(zone));
11915 
11916 	ENTER;
11917 
11918 	if (result == ISC_R_SUCCESS && zone->journal != NULL) {
11919 		/*
11920 		 * We don't own these, zone->dctx must stay valid.
11921 		 */
11922 		db = dns_dumpctx_db(zone->dctx);
11923 		version = dns_dumpctx_version(zone->dctx);
11924 		tresult = dns_db_getsoaserial(db, version, &serial);
11925 
11926 		/*
11927 		 * Handle lock order inversion.
11928 		 */
11929 	again:
11930 		LOCK_ZONE(zone);
11931 		if (inline_raw(zone)) {
11932 			secure = zone->secure;
11933 			INSIST(secure != zone);
11934 			TRYLOCK_ZONE(result, secure);
11935 			if (result != ISC_R_SUCCESS) {
11936 				UNLOCK_ZONE(zone);
11937 				secure = NULL;
11938 				isc_thread_yield();
11939 				goto again;
11940 			}
11941 		}
11942 
11943 		/*
11944 		 * If there is a secure version of this zone
11945 		 * use its serial if it is less than ours.
11946 		 */
11947 		if (tresult == ISC_R_SUCCESS && secure != NULL) {
11948 			uint32_t sserial;
11949 			isc_result_t mresult;
11950 
11951 			ZONEDB_LOCK(&secure->dblock, isc_rwlocktype_read);
11952 			if (secure->db != NULL) {
11953 				mresult = dns_db_getsoaserial(zone->secure->db,
11954 							      NULL, &sserial);
11955 				if (mresult == ISC_R_SUCCESS &&
11956 				    isc_serial_lt(sserial, serial))
11957 				{
11958 					serial = sserial;
11959 				}
11960 			}
11961 			ZONEDB_UNLOCK(&secure->dblock, isc_rwlocktype_read);
11962 		}
11963 		if (tresult == ISC_R_SUCCESS && zone->xfr == NULL) {
11964 			dns_db_t *zdb = NULL;
11965 			if (dns_zone_getdb(zone, &zdb) == ISC_R_SUCCESS) {
11966 				zone_journal_compact(zone, zdb, serial);
11967 				dns_db_detach(&zdb);
11968 			}
11969 		} else if (tresult == ISC_R_SUCCESS) {
11970 			compact = true;
11971 			zone->compact_serial = serial;
11972 		}
11973 		if (secure != NULL) {
11974 			UNLOCK_ZONE(secure);
11975 		}
11976 		UNLOCK_ZONE(zone);
11977 	}
11978 
11979 	LOCK_ZONE(zone);
11980 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
11981 	if (compact) {
11982 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
11983 	}
11984 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN)) {
11985 		/*
11986 		 * If DNS_ZONEFLG_SHUTDOWN is set, all external references to
11987 		 * the zone are gone, which means it is in the process of being
11988 		 * cleaned up, so do not reschedule dumping.
11989 		 *
11990 		 * Detach from the raw version of the zone in case this
11991 		 * operation has been deferred in zone_shutdown().
11992 		 */
11993 		if (zone->raw != NULL) {
11994 			dns_zone_detach(&zone->raw);
11995 		}
11996 		if (result == ISC_R_SUCCESS) {
11997 			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
11998 		}
11999 	} else if (result != ISC_R_SUCCESS && result != ISC_R_CANCELED) {
12000 		/*
12001 		 * Try again in a short while.
12002 		 */
12003 		zone_needdump(zone, DNS_DUMP_DELAY);
12004 	} else if (result == ISC_R_SUCCESS &&
12005 		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
12006 		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
12007 		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
12008 	{
12009 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
12010 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
12011 		isc_time_settoepoch(&zone->dumptime);
12012 		again = true;
12013 	} else if (result == ISC_R_SUCCESS) {
12014 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
12015 	}
12016 
12017 	if (zone->dctx != NULL) {
12018 		dns_dumpctx_detach(&zone->dctx);
12019 	}
12020 	zonemgr_putio(&zone->writeio);
12021 	UNLOCK_ZONE(zone);
12022 	if (again) {
12023 		(void)zone_dump(zone, false);
12024 	}
12025 	dns_zone_idetach(&zone);
12026 }
12027 
12028 static isc_result_t
zone_dump(dns_zone_t * zone,bool compact)12029 zone_dump(dns_zone_t *zone, bool compact) {
12030 	const char me[] = "zone_dump";
12031 	isc_result_t result;
12032 	dns_dbversion_t *version = NULL;
12033 	bool again;
12034 	dns_db_t *db = NULL;
12035 	char *masterfile = NULL;
12036 	dns_masterformat_t masterformat = dns_masterformat_none;
12037 
12038 	/*
12039 	 * 'compact' MUST only be set if we are task locked.
12040 	 */
12041 
12042 	REQUIRE(DNS_ZONE_VALID(zone));
12043 	ENTER;
12044 
12045 redo:
12046 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
12047 	if (zone->db != NULL) {
12048 		dns_db_attach(zone->db, &db);
12049 	}
12050 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12051 	LOCK_ZONE(zone);
12052 	if (zone->masterfile != NULL) {
12053 		masterfile = isc_mem_strdup(zone->mctx, zone->masterfile);
12054 		masterformat = zone->masterformat;
12055 	}
12056 	UNLOCK_ZONE(zone);
12057 	if (db == NULL) {
12058 		result = DNS_R_NOTLOADED;
12059 		goto fail;
12060 	}
12061 	if (masterfile == NULL) {
12062 		result = DNS_R_NOMASTERFILE;
12063 		goto fail;
12064 	}
12065 
12066 	if (compact && zone->type != dns_zone_stub) {
12067 		dns_zone_t *dummy = NULL;
12068 		LOCK_ZONE(zone);
12069 		zone_iattach(zone, &dummy);
12070 		result = zonemgr_getio(zone->zmgr, false, zone->task,
12071 				       zone_gotwritehandle, zone,
12072 				       &zone->writeio);
12073 		if (result != ISC_R_SUCCESS) {
12074 			zone_idetach(&dummy);
12075 		} else {
12076 			result = DNS_R_CONTINUE;
12077 		}
12078 		UNLOCK_ZONE(zone);
12079 	} else {
12080 		const dns_master_style_t *output_style;
12081 
12082 		dns_masterrawheader_t rawdata;
12083 		dns_db_currentversion(db, &version);
12084 		dns_master_initrawheader(&rawdata);
12085 		if (inline_secure(zone)) {
12086 			get_raw_serial(zone->raw, &rawdata);
12087 		}
12088 		if (zone->type == dns_zone_key) {
12089 			output_style = &dns_master_style_keyzone;
12090 		} else {
12091 			output_style = &dns_master_style_default;
12092 		}
12093 		result = dns_master_dump(zone->mctx, db, version, output_style,
12094 					 masterfile, masterformat, &rawdata);
12095 		dns_db_closeversion(db, &version, false);
12096 	}
12097 fail:
12098 	if (db != NULL) {
12099 		dns_db_detach(&db);
12100 	}
12101 	if (masterfile != NULL) {
12102 		isc_mem_free(zone->mctx, masterfile);
12103 	}
12104 	masterfile = NULL;
12105 
12106 	if (result == DNS_R_CONTINUE) {
12107 		return (ISC_R_SUCCESS); /* XXXMPA */
12108 	}
12109 
12110 	again = false;
12111 	LOCK_ZONE(zone);
12112 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
12113 	if (result != ISC_R_SUCCESS) {
12114 		/*
12115 		 * Try again in a short while.
12116 		 */
12117 		zone_needdump(zone, DNS_DUMP_DELAY);
12118 	} else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
12119 		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
12120 		   DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
12121 	{
12122 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
12123 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
12124 		isc_time_settoepoch(&zone->dumptime);
12125 		again = true;
12126 	} else {
12127 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
12128 	}
12129 	UNLOCK_ZONE(zone);
12130 	if (again) {
12131 		goto redo;
12132 	}
12133 
12134 	return (result);
12135 }
12136 
12137 static isc_result_t
dumptostream(dns_zone_t * zone,FILE * fd,const dns_master_style_t * style,dns_masterformat_t format,const uint32_t rawversion)12138 dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style,
12139 	     dns_masterformat_t format, const uint32_t rawversion) {
12140 	isc_result_t result;
12141 	dns_dbversion_t *version = NULL;
12142 	dns_db_t *db = NULL;
12143 	dns_masterrawheader_t rawdata;
12144 
12145 	REQUIRE(DNS_ZONE_VALID(zone));
12146 
12147 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
12148 	if (zone->db != NULL) {
12149 		dns_db_attach(zone->db, &db);
12150 	}
12151 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12152 	if (db == NULL) {
12153 		return (DNS_R_NOTLOADED);
12154 	}
12155 
12156 	dns_db_currentversion(db, &version);
12157 	dns_master_initrawheader(&rawdata);
12158 	if (rawversion == 0) {
12159 		rawdata.flags |= DNS_MASTERRAW_COMPAT;
12160 	} else if (inline_secure(zone)) {
12161 		get_raw_serial(zone->raw, &rawdata);
12162 	} else if (zone->sourceserialset) {
12163 		rawdata.flags = DNS_MASTERRAW_SOURCESERIALSET;
12164 		rawdata.sourceserial = zone->sourceserial;
12165 	}
12166 	result = dns_master_dumptostream(zone->mctx, db, version, style, format,
12167 					 &rawdata, fd);
12168 	dns_db_closeversion(db, &version, false);
12169 	dns_db_detach(&db);
12170 	return (result);
12171 }
12172 
12173 isc_result_t
dns_zone_dumptostream(dns_zone_t * zone,FILE * fd,dns_masterformat_t format,const dns_master_style_t * style,const uint32_t rawversion)12174 dns_zone_dumptostream(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
12175 		      const dns_master_style_t *style,
12176 		      const uint32_t rawversion) {
12177 	return (dumptostream(zone, fd, style, format, rawversion));
12178 }
12179 
12180 void
dns_zone_unload(dns_zone_t * zone)12181 dns_zone_unload(dns_zone_t *zone) {
12182 	REQUIRE(DNS_ZONE_VALID(zone));
12183 
12184 	LOCK_ZONE(zone);
12185 	zone_unload(zone);
12186 	UNLOCK_ZONE(zone);
12187 }
12188 
12189 static void
notify_cancel(dns_zone_t * zone)12190 notify_cancel(dns_zone_t *zone) {
12191 	dns_notify_t *notify;
12192 
12193 	/*
12194 	 * 'zone' locked by caller.
12195 	 */
12196 
12197 	REQUIRE(LOCKED_ZONE(zone));
12198 
12199 	for (notify = ISC_LIST_HEAD(zone->notifies); notify != NULL;
12200 	     notify = ISC_LIST_NEXT(notify, link))
12201 	{
12202 		if (notify->find != NULL) {
12203 			dns_adb_cancelfind(notify->find);
12204 		}
12205 		if (notify->request != NULL) {
12206 			dns_request_cancel(notify->request);
12207 		}
12208 	}
12209 }
12210 
12211 static void
checkds_cancel(dns_zone_t * zone)12212 checkds_cancel(dns_zone_t *zone) {
12213 	dns_checkds_t *checkds;
12214 
12215 	/*
12216 	 * 'zone' locked by caller.
12217 	 */
12218 
12219 	REQUIRE(LOCKED_ZONE(zone));
12220 
12221 	for (checkds = ISC_LIST_HEAD(zone->checkds_requests); checkds != NULL;
12222 	     checkds = ISC_LIST_NEXT(checkds, link))
12223 	{
12224 		if (checkds->request != NULL) {
12225 			dns_request_cancel(checkds->request);
12226 		}
12227 	}
12228 }
12229 
12230 static void
forward_cancel(dns_zone_t * zone)12231 forward_cancel(dns_zone_t *zone) {
12232 	dns_forward_t *forward;
12233 
12234 	/*
12235 	 * 'zone' locked by caller.
12236 	 */
12237 
12238 	REQUIRE(LOCKED_ZONE(zone));
12239 
12240 	for (forward = ISC_LIST_HEAD(zone->forwards); forward != NULL;
12241 	     forward = ISC_LIST_NEXT(forward, link))
12242 	{
12243 		if (forward->request != NULL) {
12244 			dns_request_cancel(forward->request);
12245 		}
12246 	}
12247 }
12248 
12249 static void
zone_unload(dns_zone_t * zone)12250 zone_unload(dns_zone_t *zone) {
12251 	/*
12252 	 * 'zone' locked by caller.
12253 	 */
12254 
12255 	REQUIRE(LOCKED_ZONE(zone));
12256 
12257 	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
12258 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
12259 	{
12260 		if (zone->writeio != NULL) {
12261 			zonemgr_cancelio(zone->writeio);
12262 		}
12263 
12264 		if (zone->dctx != NULL) {
12265 			dns_dumpctx_cancel(zone->dctx);
12266 		}
12267 	}
12268 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
12269 	zone_detachdb(zone);
12270 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
12271 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
12272 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
12273 
12274 	if (zone->type == dns_zone_mirror) {
12275 		dns_zone_log(zone, ISC_LOG_INFO,
12276 			     "mirror zone is no longer in use; "
12277 			     "reverting to normal recursion");
12278 	}
12279 }
12280 
12281 void
dns_zone_setminrefreshtime(dns_zone_t * zone,uint32_t val)12282 dns_zone_setminrefreshtime(dns_zone_t *zone, uint32_t val) {
12283 	REQUIRE(DNS_ZONE_VALID(zone));
12284 	REQUIRE(val > 0);
12285 
12286 	zone->minrefresh = val;
12287 }
12288 
12289 void
dns_zone_setmaxrefreshtime(dns_zone_t * zone,uint32_t val)12290 dns_zone_setmaxrefreshtime(dns_zone_t *zone, uint32_t val) {
12291 	REQUIRE(DNS_ZONE_VALID(zone));
12292 	REQUIRE(val > 0);
12293 
12294 	zone->maxrefresh = val;
12295 }
12296 
12297 void
dns_zone_setminretrytime(dns_zone_t * zone,uint32_t val)12298 dns_zone_setminretrytime(dns_zone_t *zone, uint32_t val) {
12299 	REQUIRE(DNS_ZONE_VALID(zone));
12300 	REQUIRE(val > 0);
12301 
12302 	zone->minretry = val;
12303 }
12304 
12305 void
dns_zone_setmaxretrytime(dns_zone_t * zone,uint32_t val)12306 dns_zone_setmaxretrytime(dns_zone_t *zone, uint32_t val) {
12307 	REQUIRE(DNS_ZONE_VALID(zone));
12308 	REQUIRE(val > 0);
12309 
12310 	zone->maxretry = val;
12311 }
12312 
12313 uint32_t
dns_zone_getmaxrecords(dns_zone_t * zone)12314 dns_zone_getmaxrecords(dns_zone_t *zone) {
12315 	REQUIRE(DNS_ZONE_VALID(zone));
12316 
12317 	return (zone->maxrecords);
12318 }
12319 
12320 void
dns_zone_setmaxrecords(dns_zone_t * zone,uint32_t val)12321 dns_zone_setmaxrecords(dns_zone_t *zone, uint32_t val) {
12322 	REQUIRE(DNS_ZONE_VALID(zone));
12323 
12324 	zone->maxrecords = val;
12325 }
12326 
12327 static bool
notify_isqueued(dns_zone_t * zone,unsigned int flags,dns_name_t * name,isc_sockaddr_t * addr,dns_tsigkey_t * key)12328 notify_isqueued(dns_zone_t *zone, unsigned int flags, dns_name_t *name,
12329 		isc_sockaddr_t *addr, dns_tsigkey_t *key) {
12330 	dns_notify_t *notify;
12331 	dns_zonemgr_t *zmgr;
12332 	isc_result_t result;
12333 
12334 	for (notify = ISC_LIST_HEAD(zone->notifies); notify != NULL;
12335 	     notify = ISC_LIST_NEXT(notify, link))
12336 	{
12337 		if (notify->request != NULL) {
12338 			continue;
12339 		}
12340 		if (name != NULL && dns_name_dynamic(&notify->ns) &&
12341 		    dns_name_equal(name, &notify->ns))
12342 		{
12343 			goto requeue;
12344 		}
12345 		if (addr != NULL && isc_sockaddr_equal(addr, &notify->dst) &&
12346 		    notify->key == key)
12347 		{
12348 			goto requeue;
12349 		}
12350 	}
12351 	return (false);
12352 
12353 requeue:
12354 	/*
12355 	 * If we are enqueued on the startup ratelimiter and this is
12356 	 * not a startup notify, re-enqueue on the normal notify
12357 	 * ratelimiter.
12358 	 */
12359 	if (notify->event != NULL && (flags & DNS_NOTIFY_STARTUP) == 0 &&
12360 	    (notify->flags & DNS_NOTIFY_STARTUP) != 0)
12361 	{
12362 		zmgr = notify->zone->zmgr;
12363 		result = isc_ratelimiter_dequeue(zmgr->startupnotifyrl,
12364 						 notify->event);
12365 		if (result != ISC_R_SUCCESS) {
12366 			return (true);
12367 		}
12368 
12369 		notify->flags &= ~DNS_NOTIFY_STARTUP;
12370 		result = isc_ratelimiter_enqueue(notify->zone->zmgr->notifyrl,
12371 						 notify->zone->task,
12372 						 &notify->event);
12373 		if (result != ISC_R_SUCCESS) {
12374 			isc_event_free(&notify->event);
12375 			return (false);
12376 		}
12377 	}
12378 
12379 	return (true);
12380 }
12381 
12382 static bool
notify_isself(dns_zone_t * zone,isc_sockaddr_t * dst)12383 notify_isself(dns_zone_t *zone, isc_sockaddr_t *dst) {
12384 	dns_tsigkey_t *key = NULL;
12385 	isc_sockaddr_t src;
12386 	isc_sockaddr_t any;
12387 	bool isself;
12388 	isc_netaddr_t dstaddr;
12389 	isc_result_t result;
12390 
12391 	if (zone->view == NULL || zone->isself == NULL) {
12392 		return (false);
12393 	}
12394 
12395 	switch (isc_sockaddr_pf(dst)) {
12396 	case PF_INET:
12397 		src = zone->notifysrc4;
12398 		isc_sockaddr_any(&any);
12399 		break;
12400 	case PF_INET6:
12401 		src = zone->notifysrc6;
12402 		isc_sockaddr_any6(&any);
12403 		break;
12404 	default:
12405 		return (false);
12406 	}
12407 
12408 	/*
12409 	 * When sending from any the kernel will assign a source address
12410 	 * that matches the destination address.
12411 	 */
12412 	if (isc_sockaddr_eqaddr(&any, &src)) {
12413 		src = *dst;
12414 	}
12415 
12416 	isc_netaddr_fromsockaddr(&dstaddr, dst);
12417 	result = dns_view_getpeertsig(zone->view, &dstaddr, &key);
12418 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
12419 		return (false);
12420 	}
12421 	isself = (zone->isself)(zone->view, key, &src, dst, zone->rdclass,
12422 				zone->isselfarg);
12423 	if (key != NULL) {
12424 		dns_tsigkey_detach(&key);
12425 	}
12426 	return (isself);
12427 }
12428 
12429 static void
notify_destroy(dns_notify_t * notify,bool locked)12430 notify_destroy(dns_notify_t *notify, bool locked) {
12431 	isc_mem_t *mctx;
12432 
12433 	REQUIRE(DNS_NOTIFY_VALID(notify));
12434 
12435 	if (notify->zone != NULL) {
12436 		if (!locked) {
12437 			LOCK_ZONE(notify->zone);
12438 		}
12439 		REQUIRE(LOCKED_ZONE(notify->zone));
12440 		if (ISC_LINK_LINKED(notify, link)) {
12441 			ISC_LIST_UNLINK(notify->zone->notifies, notify, link);
12442 		}
12443 		if (!locked) {
12444 			UNLOCK_ZONE(notify->zone);
12445 		}
12446 		if (locked) {
12447 			zone_idetach(&notify->zone);
12448 		} else {
12449 			dns_zone_idetach(&notify->zone);
12450 		}
12451 	}
12452 	if (notify->find != NULL) {
12453 		dns_adb_destroyfind(&notify->find);
12454 	}
12455 	if (notify->request != NULL) {
12456 		dns_request_destroy(&notify->request);
12457 	}
12458 	if (dns_name_dynamic(&notify->ns)) {
12459 		dns_name_free(&notify->ns, notify->mctx);
12460 	}
12461 	if (notify->key != NULL) {
12462 		dns_tsigkey_detach(&notify->key);
12463 	}
12464 	mctx = notify->mctx;
12465 	isc_mem_put(notify->mctx, notify, sizeof(*notify));
12466 	isc_mem_detach(&mctx);
12467 }
12468 
12469 static isc_result_t
notify_create(isc_mem_t * mctx,unsigned int flags,dns_notify_t ** notifyp)12470 notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
12471 	dns_notify_t *notify;
12472 
12473 	REQUIRE(notifyp != NULL && *notifyp == NULL);
12474 
12475 	notify = isc_mem_get(mctx, sizeof(*notify));
12476 
12477 	notify->mctx = NULL;
12478 	isc_mem_attach(mctx, &notify->mctx);
12479 	notify->flags = flags;
12480 	notify->zone = NULL;
12481 	notify->find = NULL;
12482 	notify->request = NULL;
12483 	notify->key = NULL;
12484 	notify->event = NULL;
12485 	isc_sockaddr_any(&notify->dst);
12486 	dns_name_init(&notify->ns, NULL);
12487 	ISC_LINK_INIT(notify, link);
12488 	notify->magic = NOTIFY_MAGIC;
12489 	*notifyp = notify;
12490 	return (ISC_R_SUCCESS);
12491 }
12492 
12493 /*
12494  * XXXAG should check for DNS_ZONEFLG_EXITING
12495  */
12496 static void
process_adb_event(isc_task_t * task,isc_event_t * ev)12497 process_adb_event(isc_task_t *task, isc_event_t *ev) {
12498 	dns_notify_t *notify;
12499 	isc_eventtype_t result;
12500 
12501 	UNUSED(task);
12502 
12503 	notify = ev->ev_arg;
12504 	REQUIRE(DNS_NOTIFY_VALID(notify));
12505 	INSIST(task == notify->zone->task);
12506 	result = ev->ev_type;
12507 	isc_event_free(&ev);
12508 	if (result == DNS_EVENT_ADBMOREADDRESSES) {
12509 		dns_adb_destroyfind(&notify->find);
12510 		notify_find_address(notify);
12511 		return;
12512 	}
12513 	if (result == DNS_EVENT_ADBNOMOREADDRESSES) {
12514 		LOCK_ZONE(notify->zone);
12515 		notify_send(notify);
12516 		UNLOCK_ZONE(notify->zone);
12517 	}
12518 	notify_destroy(notify, false);
12519 }
12520 
12521 static void
notify_find_address(dns_notify_t * notify)12522 notify_find_address(dns_notify_t *notify) {
12523 	isc_result_t result;
12524 	unsigned int options;
12525 
12526 	REQUIRE(DNS_NOTIFY_VALID(notify));
12527 	options = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_INET | DNS_ADBFIND_INET6 |
12528 		  DNS_ADBFIND_RETURNLAME;
12529 
12530 	if (notify->zone->view->adb == NULL) {
12531 		goto destroy;
12532 	}
12533 
12534 	result = dns_adb_createfind(
12535 		notify->zone->view->adb, notify->zone->task, process_adb_event,
12536 		notify, &notify->ns, dns_rootname, 0, options, 0, NULL,
12537 		notify->zone->view->dstport, 0, NULL, &notify->find);
12538 
12539 	/* Something failed? */
12540 	if (result != ISC_R_SUCCESS) {
12541 		goto destroy;
12542 	}
12543 
12544 	/* More addresses pending? */
12545 	if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0) {
12546 		return;
12547 	}
12548 
12549 	/* We have as many addresses as we can get. */
12550 	LOCK_ZONE(notify->zone);
12551 	notify_send(notify);
12552 	UNLOCK_ZONE(notify->zone);
12553 
12554 destroy:
12555 	notify_destroy(notify, false);
12556 }
12557 
12558 static isc_result_t
notify_send_queue(dns_notify_t * notify,bool startup)12559 notify_send_queue(dns_notify_t *notify, bool startup) {
12560 	isc_event_t *e;
12561 	isc_result_t result;
12562 
12563 	INSIST(notify->event == NULL);
12564 	e = isc_event_allocate(notify->mctx, NULL, DNS_EVENT_NOTIFYSENDTOADDR,
12565 			       notify_send_toaddr, notify, sizeof(isc_event_t));
12566 	if (startup) {
12567 		notify->event = e;
12568 	}
12569 	e->ev_arg = notify;
12570 	e->ev_sender = NULL;
12571 	result = isc_ratelimiter_enqueue(
12572 		startup ? notify->zone->zmgr->startupnotifyrl
12573 			: notify->zone->zmgr->notifyrl,
12574 		notify->zone->task, &e);
12575 	if (result != ISC_R_SUCCESS) {
12576 		isc_event_free(&e);
12577 		notify->event = NULL;
12578 	}
12579 	return (result);
12580 }
12581 
12582 static void
notify_send_toaddr(isc_task_t * task,isc_event_t * event)12583 notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
12584 	dns_notify_t *notify;
12585 	isc_result_t result;
12586 	dns_message_t *message = NULL;
12587 	isc_netaddr_t dstip;
12588 	dns_tsigkey_t *key = NULL;
12589 	char addrbuf[ISC_SOCKADDR_FORMATSIZE];
12590 	isc_sockaddr_t src;
12591 	unsigned int options, timeout;
12592 	bool have_notifysource = false;
12593 	bool have_notifydscp = false;
12594 	isc_dscp_t dscp = -1;
12595 
12596 	notify = event->ev_arg;
12597 	REQUIRE(DNS_NOTIFY_VALID(notify));
12598 
12599 	UNUSED(task);
12600 
12601 	LOCK_ZONE(notify->zone);
12602 
12603 	notify->event = NULL;
12604 
12605 	if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0) {
12606 		result = ISC_R_CANCELED;
12607 		goto cleanup;
12608 	}
12609 
12610 	if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
12611 	    DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) ||
12612 	    notify->zone->view->requestmgr == NULL || notify->zone->db == NULL)
12613 	{
12614 		result = ISC_R_CANCELED;
12615 		goto cleanup;
12616 	}
12617 
12618 	/*
12619 	 * The raw IPv4 address should also exist.  Don't send to the
12620 	 * mapped form.
12621 	 */
12622 	if (isc_sockaddr_pf(&notify->dst) == PF_INET6 &&
12623 	    IN6_IS_ADDR_V4MAPPED(&notify->dst.type.sin6.sin6_addr))
12624 	{
12625 		isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
12626 		notify_log(notify->zone, ISC_LOG_DEBUG(3),
12627 			   "notify: ignoring IPv6 mapped IPV4 address: %s",
12628 			   addrbuf);
12629 		result = ISC_R_CANCELED;
12630 		goto cleanup;
12631 	}
12632 
12633 	result = notify_createmessage(notify->zone, notify->flags, &message);
12634 	if (result != ISC_R_SUCCESS) {
12635 		goto cleanup;
12636 	}
12637 
12638 	isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
12639 	if (notify->key != NULL) {
12640 		/* Transfer ownership of key */
12641 		key = notify->key;
12642 		notify->key = NULL;
12643 	} else {
12644 		isc_netaddr_fromsockaddr(&dstip, &notify->dst);
12645 		result = dns_view_getpeertsig(notify->zone->view, &dstip, &key);
12646 		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
12647 			notify_log(notify->zone, ISC_LOG_ERROR,
12648 				   "NOTIFY to %s not sent. "
12649 				   "Peer TSIG key lookup failure.",
12650 				   addrbuf);
12651 			goto cleanup_message;
12652 		}
12653 	}
12654 
12655 	if (key != NULL) {
12656 		char namebuf[DNS_NAME_FORMATSIZE];
12657 
12658 		dns_name_format(&key->name, namebuf, sizeof(namebuf));
12659 		notify_log(notify->zone, ISC_LOG_DEBUG(3),
12660 			   "sending notify to %s : TSIG (%s)", addrbuf,
12661 			   namebuf);
12662 	} else {
12663 		notify_log(notify->zone, ISC_LOG_DEBUG(3),
12664 			   "sending notify to %s", addrbuf);
12665 	}
12666 	options = 0;
12667 	if (notify->zone->view->peers != NULL) {
12668 		dns_peer_t *peer = NULL;
12669 		bool usetcp = false;
12670 		result = dns_peerlist_peerbyaddr(notify->zone->view->peers,
12671 						 &dstip, &peer);
12672 		if (result == ISC_R_SUCCESS) {
12673 			result = dns_peer_getnotifysource(peer, &src);
12674 			if (result == ISC_R_SUCCESS) {
12675 				have_notifysource = true;
12676 			}
12677 			dns_peer_getnotifydscp(peer, &dscp);
12678 			if (dscp != -1) {
12679 				have_notifydscp = true;
12680 			}
12681 			result = dns_peer_getforcetcp(peer, &usetcp);
12682 			if (result == ISC_R_SUCCESS && usetcp) {
12683 				options |= DNS_FETCHOPT_TCP;
12684 			}
12685 		}
12686 	}
12687 	switch (isc_sockaddr_pf(&notify->dst)) {
12688 	case PF_INET:
12689 		if (!have_notifysource) {
12690 			src = notify->zone->notifysrc4;
12691 		}
12692 		if (!have_notifydscp) {
12693 			dscp = notify->zone->notifysrc4dscp;
12694 		}
12695 		break;
12696 	case PF_INET6:
12697 		if (!have_notifysource) {
12698 			src = notify->zone->notifysrc6;
12699 		}
12700 		if (!have_notifydscp) {
12701 			dscp = notify->zone->notifysrc6dscp;
12702 		}
12703 		break;
12704 	default:
12705 		result = ISC_R_NOTIMPLEMENTED;
12706 		goto cleanup_key;
12707 	}
12708 	timeout = 15;
12709 	if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY)) {
12710 		timeout = 30;
12711 	}
12712 	result = dns_request_createvia(
12713 		notify->zone->view->requestmgr, message, &src, &notify->dst,
12714 		dscp, options, key, timeout * 3, timeout, 0, notify->zone->task,
12715 		notify_done, notify, &notify->request);
12716 	if (result == ISC_R_SUCCESS) {
12717 		if (isc_sockaddr_pf(&notify->dst) == AF_INET) {
12718 			inc_stats(notify->zone,
12719 				  dns_zonestatscounter_notifyoutv4);
12720 		} else {
12721 			inc_stats(notify->zone,
12722 				  dns_zonestatscounter_notifyoutv6);
12723 		}
12724 	}
12725 
12726 cleanup_key:
12727 	if (key != NULL) {
12728 		dns_tsigkey_detach(&key);
12729 	}
12730 cleanup_message:
12731 	dns_message_detach(&message);
12732 cleanup:
12733 	UNLOCK_ZONE(notify->zone);
12734 	isc_event_free(&event);
12735 	if (result != ISC_R_SUCCESS) {
12736 		notify_destroy(notify, false);
12737 	}
12738 }
12739 
12740 static void
notify_send(dns_notify_t * notify)12741 notify_send(dns_notify_t *notify) {
12742 	dns_adbaddrinfo_t *ai;
12743 	isc_sockaddr_t dst;
12744 	isc_result_t result;
12745 	dns_notify_t *newnotify = NULL;
12746 	unsigned int flags;
12747 	bool startup;
12748 
12749 	/*
12750 	 * Zone lock held by caller.
12751 	 */
12752 	REQUIRE(DNS_NOTIFY_VALID(notify));
12753 	REQUIRE(LOCKED_ZONE(notify->zone));
12754 
12755 	if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING)) {
12756 		return;
12757 	}
12758 
12759 	for (ai = ISC_LIST_HEAD(notify->find->list); ai != NULL;
12760 	     ai = ISC_LIST_NEXT(ai, publink))
12761 	{
12762 		dst = ai->sockaddr;
12763 		if (notify_isqueued(notify->zone, notify->flags, NULL, &dst,
12764 				    NULL))
12765 		{
12766 			continue;
12767 		}
12768 		if (notify_isself(notify->zone, &dst)) {
12769 			continue;
12770 		}
12771 		newnotify = NULL;
12772 		flags = notify->flags & DNS_NOTIFY_NOSOA;
12773 		result = notify_create(notify->mctx, flags, &newnotify);
12774 		if (result != ISC_R_SUCCESS) {
12775 			goto cleanup;
12776 		}
12777 		zone_iattach(notify->zone, &newnotify->zone);
12778 		ISC_LIST_APPEND(newnotify->zone->notifies, newnotify, link);
12779 		newnotify->dst = dst;
12780 		startup = ((notify->flags & DNS_NOTIFY_STARTUP) != 0);
12781 		result = notify_send_queue(newnotify, startup);
12782 		if (result != ISC_R_SUCCESS) {
12783 			goto cleanup;
12784 		}
12785 		newnotify = NULL;
12786 	}
12787 
12788 cleanup:
12789 	if (newnotify != NULL) {
12790 		notify_destroy(newnotify, true);
12791 	}
12792 }
12793 
12794 void
dns_zone_notify(dns_zone_t * zone)12795 dns_zone_notify(dns_zone_t *zone) {
12796 	isc_time_t now;
12797 
12798 	REQUIRE(DNS_ZONE_VALID(zone));
12799 
12800 	LOCK_ZONE(zone);
12801 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
12802 
12803 	TIME_NOW(&now);
12804 	zone_settimer(zone, &now);
12805 	UNLOCK_ZONE(zone);
12806 }
12807 
12808 static void
zone_notify(dns_zone_t * zone,isc_time_t * now)12809 zone_notify(dns_zone_t *zone, isc_time_t *now) {
12810 	dns_dbnode_t *node = NULL;
12811 	dns_db_t *zonedb = NULL;
12812 	dns_dbversion_t *version = NULL;
12813 	dns_name_t *origin = NULL;
12814 	dns_name_t master;
12815 	dns_rdata_ns_t ns;
12816 	dns_rdata_soa_t soa;
12817 	uint32_t serial;
12818 	dns_rdata_t rdata = DNS_RDATA_INIT;
12819 	dns_rdataset_t nsrdset;
12820 	dns_rdataset_t soardset;
12821 	isc_result_t result;
12822 	unsigned int i;
12823 	isc_sockaddr_t dst;
12824 	bool isqueued;
12825 	dns_notifytype_t notifytype;
12826 	unsigned int flags = 0;
12827 	bool loggednotify = false;
12828 	bool startup;
12829 
12830 	REQUIRE(DNS_ZONE_VALID(zone));
12831 
12832 	LOCK_ZONE(zone);
12833 	startup = !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
12834 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
12835 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY);
12836 	notifytype = zone->notifytype;
12837 	DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime);
12838 	UNLOCK_ZONE(zone);
12839 
12840 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
12841 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
12842 	{
12843 		return;
12844 	}
12845 
12846 	if (notifytype == dns_notifytype_no) {
12847 		return;
12848 	}
12849 
12850 	if (notifytype == dns_notifytype_masteronly &&
12851 	    zone->type != dns_zone_primary)
12852 	{
12853 		return;
12854 	}
12855 
12856 	origin = &zone->origin;
12857 
12858 	/*
12859 	 * If the zone is dialup we are done as we don't want to send
12860 	 * the current soa so as to force a refresh query.
12861 	 */
12862 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY)) {
12863 		flags |= DNS_NOTIFY_NOSOA;
12864 	}
12865 
12866 	/*
12867 	 * Record that this was a notify due to starting up.
12868 	 */
12869 	if (startup) {
12870 		flags |= DNS_NOTIFY_STARTUP;
12871 	}
12872 
12873 	/*
12874 	 * Get SOA RRset.
12875 	 */
12876 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
12877 	if (zone->db != NULL) {
12878 		dns_db_attach(zone->db, &zonedb);
12879 	}
12880 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12881 	if (zonedb == NULL) {
12882 		return;
12883 	}
12884 	dns_db_currentversion(zonedb, &version);
12885 	result = dns_db_findnode(zonedb, origin, false, &node);
12886 	if (result != ISC_R_SUCCESS) {
12887 		goto cleanup1;
12888 	}
12889 
12890 	dns_rdataset_init(&soardset);
12891 	result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
12892 				     dns_rdatatype_none, 0, &soardset, NULL);
12893 	if (result != ISC_R_SUCCESS) {
12894 		goto cleanup2;
12895 	}
12896 
12897 	/*
12898 	 * Find serial and master server's name.
12899 	 */
12900 	dns_name_init(&master, NULL);
12901 	result = dns_rdataset_first(&soardset);
12902 	if (result != ISC_R_SUCCESS) {
12903 		goto cleanup3;
12904 	}
12905 	dns_rdataset_current(&soardset, &rdata);
12906 	result = dns_rdata_tostruct(&rdata, &soa, NULL);
12907 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
12908 	dns_rdata_reset(&rdata);
12909 	dns_name_dup(&soa.origin, zone->mctx, &master);
12910 	serial = soa.serial;
12911 	dns_rdataset_disassociate(&soardset);
12912 
12913 	/*
12914 	 * Enqueue notify requests for 'also-notify' servers.
12915 	 */
12916 	LOCK_ZONE(zone);
12917 	for (i = 0; i < zone->notifycnt; i++) {
12918 		dns_tsigkey_t *key = NULL;
12919 		dns_notify_t *notify = NULL;
12920 
12921 		if ((zone->notifykeynames != NULL) &&
12922 		    (zone->notifykeynames[i] != NULL))
12923 		{
12924 			dns_view_t *view = dns_zone_getview(zone);
12925 			dns_name_t *keyname = zone->notifykeynames[i];
12926 			(void)dns_view_gettsig(view, keyname, &key);
12927 		}
12928 
12929 		dst = zone->notify[i];
12930 		if (notify_isqueued(zone, flags, NULL, &dst, key)) {
12931 			if (key != NULL) {
12932 				dns_tsigkey_detach(&key);
12933 			}
12934 			continue;
12935 		}
12936 
12937 		result = notify_create(zone->mctx, flags, &notify);
12938 		if (result != ISC_R_SUCCESS) {
12939 			if (key != NULL) {
12940 				dns_tsigkey_detach(&key);
12941 			}
12942 			continue;
12943 		}
12944 
12945 		zone_iattach(zone, &notify->zone);
12946 		notify->dst = dst;
12947 
12948 		INSIST(notify->key == NULL);
12949 
12950 		if (key != NULL) {
12951 			notify->key = key;
12952 			key = NULL;
12953 		}
12954 
12955 		ISC_LIST_APPEND(zone->notifies, notify, link);
12956 		result = notify_send_queue(notify, startup);
12957 		if (result != ISC_R_SUCCESS) {
12958 			notify_destroy(notify, true);
12959 		}
12960 		if (!loggednotify) {
12961 			notify_log(zone, ISC_LOG_INFO,
12962 				   "sending notifies (serial %u)", serial);
12963 			loggednotify = true;
12964 		}
12965 	}
12966 	UNLOCK_ZONE(zone);
12967 
12968 	if (notifytype == dns_notifytype_explicit) {
12969 		goto cleanup3;
12970 	}
12971 
12972 	/*
12973 	 * Process NS RRset to generate notifies.
12974 	 */
12975 
12976 	dns_rdataset_init(&nsrdset);
12977 	result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_ns,
12978 				     dns_rdatatype_none, 0, &nsrdset, NULL);
12979 	if (result != ISC_R_SUCCESS) {
12980 		goto cleanup3;
12981 	}
12982 
12983 	result = dns_rdataset_first(&nsrdset);
12984 	while (result == ISC_R_SUCCESS) {
12985 		dns_notify_t *notify = NULL;
12986 
12987 		dns_rdataset_current(&nsrdset, &rdata);
12988 		result = dns_rdata_tostruct(&rdata, &ns, NULL);
12989 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
12990 		dns_rdata_reset(&rdata);
12991 		/*
12992 		 * Don't notify the master server unless explicitly
12993 		 * configured to do so.
12994 		 */
12995 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOTIFYTOSOA) &&
12996 		    dns_name_compare(&master, &ns.name) == 0)
12997 		{
12998 			result = dns_rdataset_next(&nsrdset);
12999 			continue;
13000 		}
13001 
13002 		if (!loggednotify) {
13003 			notify_log(zone, ISC_LOG_INFO,
13004 				   "sending notifies (serial %u)", serial);
13005 			loggednotify = true;
13006 		}
13007 
13008 		LOCK_ZONE(zone);
13009 		isqueued = notify_isqueued(zone, flags, &ns.name, NULL, NULL);
13010 		UNLOCK_ZONE(zone);
13011 		if (isqueued) {
13012 			result = dns_rdataset_next(&nsrdset);
13013 			continue;
13014 		}
13015 		result = notify_create(zone->mctx, flags, &notify);
13016 		if (result != ISC_R_SUCCESS) {
13017 			continue;
13018 		}
13019 		dns_zone_iattach(zone, &notify->zone);
13020 		dns_name_dup(&ns.name, zone->mctx, &notify->ns);
13021 		LOCK_ZONE(zone);
13022 		ISC_LIST_APPEND(zone->notifies, notify, link);
13023 		UNLOCK_ZONE(zone);
13024 		notify_find_address(notify);
13025 		result = dns_rdataset_next(&nsrdset);
13026 	}
13027 	dns_rdataset_disassociate(&nsrdset);
13028 
13029 cleanup3:
13030 	if (dns_name_dynamic(&master)) {
13031 		dns_name_free(&master, zone->mctx);
13032 	}
13033 cleanup2:
13034 	dns_db_detachnode(zonedb, &node);
13035 cleanup1:
13036 	dns_db_closeversion(zonedb, &version, false);
13037 	dns_db_detach(&zonedb);
13038 }
13039 
13040 /***
13041  *** Private
13042  ***/
13043 static isc_result_t
create_query(dns_zone_t * zone,dns_rdatatype_t rdtype,dns_name_t * name,dns_message_t ** messagep)13044 create_query(dns_zone_t *zone, dns_rdatatype_t rdtype, dns_name_t *name,
13045 	     dns_message_t **messagep) {
13046 	dns_message_t *message = NULL;
13047 	dns_name_t *qname = NULL;
13048 	dns_rdataset_t *qrdataset = NULL;
13049 	isc_result_t result;
13050 
13051 	dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER, &message);
13052 
13053 	message->opcode = dns_opcode_query;
13054 	message->rdclass = zone->rdclass;
13055 
13056 	result = dns_message_gettempname(message, &qname);
13057 	if (result != ISC_R_SUCCESS) {
13058 		goto cleanup;
13059 	}
13060 
13061 	result = dns_message_gettemprdataset(message, &qrdataset);
13062 	if (result != ISC_R_SUCCESS) {
13063 		goto cleanup;
13064 	}
13065 
13066 	/*
13067 	 * Make question.
13068 	 */
13069 	dns_name_clone(name, qname);
13070 	dns_rdataset_makequestion(qrdataset, zone->rdclass, rdtype);
13071 	ISC_LIST_APPEND(qname->list, qrdataset, link);
13072 	dns_message_addname(message, qname, DNS_SECTION_QUESTION);
13073 
13074 	*messagep = message;
13075 	return (ISC_R_SUCCESS);
13076 
13077 cleanup:
13078 	if (qname != NULL) {
13079 		dns_message_puttempname(message, &qname);
13080 	}
13081 	if (qrdataset != NULL) {
13082 		dns_message_puttemprdataset(message, &qrdataset);
13083 	}
13084 	dns_message_detach(&message);
13085 	return (result);
13086 }
13087 
13088 static isc_result_t
add_opt(dns_message_t * message,uint16_t udpsize,bool reqnsid,bool reqexpire)13089 add_opt(dns_message_t *message, uint16_t udpsize, bool reqnsid,
13090 	bool reqexpire) {
13091 	isc_result_t result;
13092 	dns_rdataset_t *rdataset = NULL;
13093 	dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS];
13094 	int count = 0;
13095 
13096 	/* Set EDNS options if applicable. */
13097 	if (reqnsid) {
13098 		INSIST(count < DNS_EDNSOPTIONS);
13099 		ednsopts[count].code = DNS_OPT_NSID;
13100 		ednsopts[count].length = 0;
13101 		ednsopts[count].value = NULL;
13102 		count++;
13103 	}
13104 	if (reqexpire) {
13105 		INSIST(count < DNS_EDNSOPTIONS);
13106 		ednsopts[count].code = DNS_OPT_EXPIRE;
13107 		ednsopts[count].length = 0;
13108 		ednsopts[count].value = NULL;
13109 		count++;
13110 	}
13111 	result = dns_message_buildopt(message, &rdataset, 0, udpsize, 0,
13112 				      ednsopts, count);
13113 	if (result != ISC_R_SUCCESS) {
13114 		return (result);
13115 	}
13116 
13117 	return (dns_message_setopt(message, rdataset));
13118 }
13119 
13120 /*
13121  * Called when stub zone update is finished.
13122  * Update zone refresh, retry, expire values accordingly with
13123  * SOA received from master, sync database to file, restart
13124  * zone management timer.
13125  */
13126 static void
stub_finish_zone_update(dns_stub_t * stub,isc_time_t now)13127 stub_finish_zone_update(dns_stub_t *stub, isc_time_t now) {
13128 	uint32_t refresh, retry, expire;
13129 	isc_result_t result;
13130 	isc_interval_t i;
13131 	unsigned int soacount;
13132 	dns_zone_t *zone = stub->zone;
13133 
13134 	/*
13135 	 * Tidy up.
13136 	 */
13137 	dns_db_closeversion(stub->db, &stub->version, true);
13138 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
13139 	if (zone->db == NULL) {
13140 		zone_attachdb(zone, stub->db);
13141 	}
13142 	result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL, NULL,
13143 				  &refresh, &retry, &expire, NULL, NULL);
13144 	if (result == ISC_R_SUCCESS && soacount > 0U) {
13145 		zone->refresh = RANGE(refresh, zone->minrefresh,
13146 				      zone->maxrefresh);
13147 		zone->retry = RANGE(retry, zone->minretry, zone->maxretry);
13148 		zone->expire = RANGE(expire, zone->refresh + zone->retry,
13149 				     DNS_MAX_EXPIRE);
13150 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
13151 	}
13152 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
13153 	dns_db_detach(&stub->db);
13154 
13155 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
13156 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
13157 	DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
13158 	isc_interval_set(&i, zone->expire, 0);
13159 	DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
13160 
13161 	if (zone->masterfile != NULL) {
13162 		zone_needdump(zone, 0);
13163 	}
13164 
13165 	zone_settimer(zone, &now);
13166 }
13167 
13168 /*
13169  * Process answers for A and AAAA queries when
13170  * resolving nameserver addresses for which glue
13171  * was missing in a previous answer for a NS query.
13172  */
13173 static void
stub_glue_response_cb(isc_task_t * task,isc_event_t * event)13174 stub_glue_response_cb(isc_task_t *task, isc_event_t *event) {
13175 	const char me[] = "stub_glue_response_cb";
13176 	dns_requestevent_t *revent = (dns_requestevent_t *)event;
13177 	dns_stub_t *stub = NULL;
13178 	dns_message_t *msg = NULL;
13179 	dns_zone_t *zone = NULL;
13180 	char master[ISC_SOCKADDR_FORMATSIZE];
13181 	char source[ISC_SOCKADDR_FORMATSIZE];
13182 	uint32_t addr_count, cnamecnt;
13183 	isc_result_t result;
13184 	isc_time_t now;
13185 	struct stub_glue_request *request;
13186 	struct stub_cb_args *cb_args;
13187 	dns_rdataset_t *addr_rdataset = NULL;
13188 	dns_dbnode_t *node = NULL;
13189 
13190 	UNUSED(task);
13191 
13192 	request = revent->ev_arg;
13193 	cb_args = request->args;
13194 	stub = cb_args->stub;
13195 	INSIST(DNS_STUB_VALID(stub));
13196 
13197 	zone = stub->zone;
13198 
13199 	ENTER;
13200 
13201 	TIME_NOW(&now);
13202 
13203 	LOCK_ZONE(zone);
13204 
13205 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
13206 		zone_debuglog(zone, me, 1, "exiting");
13207 		goto cleanup;
13208 	}
13209 
13210 	isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
13211 	isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
13212 
13213 	if (revent->result != ISC_R_SUCCESS) {
13214 		dns_zonemgr_unreachableadd(zone->zmgr, &zone->masteraddr,
13215 					   &zone->sourceaddr, &now);
13216 		dns_zone_log(zone, ISC_LOG_INFO,
13217 			     "could not refresh stub from master %s"
13218 			     " (source %s): %s",
13219 			     master, source, dns_result_totext(revent->result));
13220 		goto cleanup;
13221 	}
13222 
13223 	dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
13224 	result = dns_request_getresponse(revent->request, msg, 0);
13225 	if (result != ISC_R_SUCCESS) {
13226 		dns_zone_log(zone, ISC_LOG_INFO,
13227 			     "refreshing stub: unable to parse response (%s)",
13228 			     isc_result_totext(result));
13229 		goto cleanup;
13230 	}
13231 
13232 	/*
13233 	 * Unexpected opcode.
13234 	 */
13235 	if (msg->opcode != dns_opcode_query) {
13236 		char opcode[128];
13237 		isc_buffer_t rb;
13238 
13239 		isc_buffer_init(&rb, opcode, sizeof(opcode));
13240 		(void)dns_opcode_totext(msg->opcode, &rb);
13241 
13242 		dns_zone_log(zone, ISC_LOG_INFO,
13243 			     "refreshing stub: "
13244 			     "unexpected opcode (%.*s) from %s (source %s)",
13245 			     (int)rb.used, opcode, master, source);
13246 		goto cleanup;
13247 	}
13248 
13249 	/*
13250 	 * Unexpected rcode.
13251 	 */
13252 	if (msg->rcode != dns_rcode_noerror) {
13253 		char rcode[128];
13254 		isc_buffer_t rb;
13255 
13256 		isc_buffer_init(&rb, rcode, sizeof(rcode));
13257 		(void)dns_rcode_totext(msg->rcode, &rb);
13258 
13259 		dns_zone_log(zone, ISC_LOG_INFO,
13260 			     "refreshing stub: "
13261 			     "unexpected rcode (%.*s) from %s (source %s)",
13262 			     (int)rb.used, rcode, master, source);
13263 		goto cleanup;
13264 	}
13265 
13266 	/*
13267 	 * We need complete messages.
13268 	 */
13269 	if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
13270 		if (dns_request_usedtcp(revent->request)) {
13271 			dns_zone_log(zone, ISC_LOG_INFO,
13272 				     "refreshing stub: truncated TCP "
13273 				     "response from master %s (source %s)",
13274 				     master, source);
13275 		}
13276 		goto cleanup;
13277 	}
13278 
13279 	/*
13280 	 * If non-auth log.
13281 	 */
13282 	if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
13283 		dns_zone_log(zone, ISC_LOG_INFO,
13284 			     "refreshing stub: "
13285 			     "non-authoritative answer from "
13286 			     "master %s (source %s)",
13287 			     master, source);
13288 		goto cleanup;
13289 	}
13290 
13291 	/*
13292 	 * Sanity checks.
13293 	 */
13294 	cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
13295 	addr_count = message_count(msg, DNS_SECTION_ANSWER,
13296 				   request->ipv4 ? dns_rdatatype_a
13297 						 : dns_rdatatype_aaaa);
13298 
13299 	if (cnamecnt != 0) {
13300 		dns_zone_log(zone, ISC_LOG_INFO,
13301 			     "refreshing stub: unexpected CNAME response "
13302 			     "from master %s (source %s)",
13303 			     master, source);
13304 		goto cleanup;
13305 	}
13306 
13307 	if (addr_count == 0) {
13308 		dns_zone_log(zone, ISC_LOG_INFO,
13309 			     "refreshing stub: no %s records in response "
13310 			     "from master %s (source %s)",
13311 			     request->ipv4 ? "A" : "AAAA", master, source);
13312 		goto cleanup;
13313 	}
13314 	/*
13315 	 * Extract A or AAAA RRset from message.
13316 	 */
13317 	result = dns_message_findname(msg, DNS_SECTION_ANSWER, &request->name,
13318 				      request->ipv4 ? dns_rdatatype_a
13319 						    : dns_rdatatype_aaaa,
13320 				      dns_rdatatype_none, NULL, &addr_rdataset);
13321 	if (result != ISC_R_SUCCESS) {
13322 		if (result != DNS_R_NXDOMAIN && result != DNS_R_NXRRSET) {
13323 			char namebuf[DNS_NAME_FORMATSIZE];
13324 			dns_name_format(&request->name, namebuf,
13325 					sizeof(namebuf));
13326 			dns_zone_log(
13327 				zone, ISC_LOG_INFO,
13328 				"refreshing stub: dns_message_findname(%s/%s) "
13329 				"failed (%s)",
13330 				namebuf, request->ipv4 ? "A" : "AAAA",
13331 				isc_result_totext(result));
13332 		}
13333 		goto cleanup;
13334 	}
13335 
13336 	result = dns_db_findnode(stub->db, &request->name, true, &node);
13337 	if (result != ISC_R_SUCCESS) {
13338 		dns_zone_log(zone, ISC_LOG_INFO,
13339 			     "refreshing stub: "
13340 			     "dns_db_findnode() failed: %s",
13341 			     dns_result_totext(result));
13342 		goto cleanup;
13343 	}
13344 
13345 	result = dns_db_addrdataset(stub->db, node, stub->version, 0,
13346 				    addr_rdataset, 0, NULL);
13347 	if (result != ISC_R_SUCCESS) {
13348 		dns_zone_log(zone, ISC_LOG_INFO,
13349 			     "refreshing stub: "
13350 			     "dns_db_addrdataset() failed: %s",
13351 			     dns_result_totext(result));
13352 	}
13353 	dns_db_detachnode(stub->db, &node);
13354 
13355 cleanup:
13356 	if (msg != NULL) {
13357 		dns_message_detach(&msg);
13358 	}
13359 	isc_event_free(&event);
13360 	dns_name_free(&request->name, zone->mctx);
13361 	dns_request_destroy(&request->request);
13362 	isc_mem_put(zone->mctx, request, sizeof(*request));
13363 
13364 	/* If last request, release all related resources */
13365 	if (atomic_fetch_sub_release(&stub->pending_requests, 1) == 1) {
13366 		isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
13367 		stub_finish_zone_update(stub, now);
13368 		UNLOCK_ZONE(zone);
13369 		stub->magic = 0;
13370 		dns_zone_idetach(&stub->zone);
13371 		INSIST(stub->db == NULL);
13372 		INSIST(stub->version == NULL);
13373 		isc_mem_put(stub->mctx, stub, sizeof(*stub));
13374 	} else {
13375 		UNLOCK_ZONE(zone);
13376 	}
13377 }
13378 
13379 /*
13380  * Create and send an A or AAAA query to the master
13381  * server of the stub zone given.
13382  */
13383 static isc_result_t
stub_request_nameserver_address(struct stub_cb_args * args,bool ipv4,const dns_name_t * name)13384 stub_request_nameserver_address(struct stub_cb_args *args, bool ipv4,
13385 				const dns_name_t *name) {
13386 	dns_message_t *message = NULL;
13387 	dns_zone_t *zone;
13388 	isc_result_t result;
13389 	struct stub_glue_request *request;
13390 
13391 	zone = args->stub->zone;
13392 	request = isc_mem_get(zone->mctx, sizeof(*request));
13393 	request->request = NULL;
13394 	request->args = args;
13395 	request->name = (dns_name_t)DNS_NAME_INITEMPTY;
13396 	request->ipv4 = ipv4;
13397 	dns_name_dup(name, zone->mctx, &request->name);
13398 
13399 	result = create_query(zone, ipv4 ? dns_rdatatype_a : dns_rdatatype_aaaa,
13400 			      &request->name, &message);
13401 	INSIST(result == ISC_R_SUCCESS);
13402 
13403 	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
13404 		result = add_opt(message, args->udpsize, args->reqnsid, false);
13405 		if (result != ISC_R_SUCCESS) {
13406 			zone_debuglog(zone, "stub_send_query", 1,
13407 				      "unable to add opt record: %s",
13408 				      dns_result_totext(result));
13409 			goto fail;
13410 		}
13411 	}
13412 
13413 	atomic_fetch_add_release(&args->stub->pending_requests, 1);
13414 
13415 	result = dns_request_createvia(
13416 		zone->view->requestmgr, message, &zone->sourceaddr,
13417 		&zone->masteraddr, args->dscp, DNS_REQUESTOPT_TCP,
13418 		args->tsig_key, args->timeout * 3, args->timeout, 0, zone->task,
13419 		stub_glue_response_cb, request, &request->request);
13420 
13421 	if (result != ISC_R_SUCCESS) {
13422 		INSIST(atomic_fetch_sub_release(&args->stub->pending_requests,
13423 						1) > 1);
13424 		zone_debuglog(zone, "stub_send_query", 1,
13425 			      "dns_request_createvia() failed: %s",
13426 			      dns_result_totext(result));
13427 		goto fail;
13428 	}
13429 
13430 	dns_message_detach(&message);
13431 
13432 	return (ISC_R_SUCCESS);
13433 
13434 fail:
13435 	dns_name_free(&request->name, zone->mctx);
13436 	isc_mem_put(zone->mctx, request, sizeof(*request));
13437 
13438 	if (message != NULL) {
13439 		dns_message_detach(&message);
13440 	}
13441 
13442 	return (result);
13443 }
13444 
13445 static isc_result_t
save_nsrrset(dns_message_t * message,dns_name_t * name,struct stub_cb_args * cb_args,dns_db_t * db,dns_dbversion_t * version)13446 save_nsrrset(dns_message_t *message, dns_name_t *name,
13447 	     struct stub_cb_args *cb_args, dns_db_t *db,
13448 	     dns_dbversion_t *version) {
13449 	dns_rdataset_t *nsrdataset = NULL;
13450 	dns_rdataset_t *rdataset = NULL;
13451 	dns_dbnode_t *node = NULL;
13452 	dns_rdata_ns_t ns;
13453 	isc_result_t result;
13454 	dns_rdata_t rdata = DNS_RDATA_INIT;
13455 	bool has_glue = false;
13456 	dns_name_t *ns_name;
13457 	/*
13458 	 * List of NS entries in answer, keep names that will be used
13459 	 * to resolve missing A/AAAA glue for each entry.
13460 	 */
13461 	dns_namelist_t ns_list;
13462 	ISC_LIST_INIT(ns_list);
13463 
13464 	/*
13465 	 * Extract NS RRset from message.
13466 	 */
13467 	result = dns_message_findname(message, DNS_SECTION_ANSWER, name,
13468 				      dns_rdatatype_ns, dns_rdatatype_none,
13469 				      NULL, &nsrdataset);
13470 	if (result != ISC_R_SUCCESS) {
13471 		goto done;
13472 	}
13473 
13474 	/*
13475 	 * Add NS rdataset.
13476 	 */
13477 	result = dns_db_findnode(db, name, true, &node);
13478 	if (result != ISC_R_SUCCESS) {
13479 		goto done;
13480 	}
13481 	result = dns_db_addrdataset(db, node, version, 0, nsrdataset, 0, NULL);
13482 	dns_db_detachnode(db, &node);
13483 	if (result != ISC_R_SUCCESS) {
13484 		goto done;
13485 	}
13486 	/*
13487 	 * Add glue rdatasets.
13488 	 */
13489 	for (result = dns_rdataset_first(nsrdataset); result == ISC_R_SUCCESS;
13490 	     result = dns_rdataset_next(nsrdataset))
13491 	{
13492 		dns_rdataset_current(nsrdataset, &rdata);
13493 		result = dns_rdata_tostruct(&rdata, &ns, NULL);
13494 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
13495 		dns_rdata_reset(&rdata);
13496 
13497 		if (!dns_name_issubdomain(&ns.name, name)) {
13498 			continue;
13499 		}
13500 		rdataset = NULL;
13501 		result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
13502 					      &ns.name, dns_rdatatype_aaaa,
13503 					      dns_rdatatype_none, NULL,
13504 					      &rdataset);
13505 		if (result == ISC_R_SUCCESS) {
13506 			has_glue = true;
13507 			result = dns_db_findnode(db, &ns.name, true, &node);
13508 			if (result != ISC_R_SUCCESS) {
13509 				goto done;
13510 			}
13511 			result = dns_db_addrdataset(db, node, version, 0,
13512 						    rdataset, 0, NULL);
13513 			dns_db_detachnode(db, &node);
13514 			if (result != ISC_R_SUCCESS) {
13515 				goto done;
13516 			}
13517 		}
13518 
13519 		rdataset = NULL;
13520 		result = dns_message_findname(
13521 			message, DNS_SECTION_ADDITIONAL, &ns.name,
13522 			dns_rdatatype_a, dns_rdatatype_none, NULL, &rdataset);
13523 		if (result == ISC_R_SUCCESS) {
13524 			has_glue = true;
13525 			result = dns_db_findnode(db, &ns.name, true, &node);
13526 			if (result != ISC_R_SUCCESS) {
13527 				goto done;
13528 			}
13529 			result = dns_db_addrdataset(db, node, version, 0,
13530 						    rdataset, 0, NULL);
13531 			dns_db_detachnode(db, &node);
13532 			if (result != ISC_R_SUCCESS) {
13533 				goto done;
13534 			}
13535 		}
13536 
13537 		/*
13538 		 * If no glue is found so far, we add the name to the list to
13539 		 * resolve the A/AAAA glue later. If any glue is found in any
13540 		 * iteration step, this list will be discarded and only the glue
13541 		 * provided in this message will be used.
13542 		 */
13543 		if (!has_glue && dns_name_issubdomain(&ns.name, name)) {
13544 			dns_name_t *tmp_name;
13545 			tmp_name = isc_mem_get(cb_args->stub->mctx,
13546 					       sizeof(*tmp_name));
13547 			dns_name_init(tmp_name, NULL);
13548 			dns_name_dup(&ns.name, cb_args->stub->mctx, tmp_name);
13549 			ISC_LIST_APPEND(ns_list, tmp_name, link);
13550 		}
13551 	}
13552 
13553 	if (result != ISC_R_NOMORE) {
13554 		goto done;
13555 	}
13556 
13557 	/*
13558 	 * If no glue records were found, we attempt to resolve A/AAAA
13559 	 * for each NS entry found in the answer.
13560 	 */
13561 	if (!has_glue) {
13562 		for (ns_name = ISC_LIST_HEAD(ns_list); ns_name != NULL;
13563 		     ns_name = ISC_LIST_NEXT(ns_name, link))
13564 		{
13565 			/*
13566 			 * Resolve NS IPv4 address/A.
13567 			 */
13568 			result = stub_request_nameserver_address(cb_args, true,
13569 								 ns_name);
13570 			if (result != ISC_R_SUCCESS) {
13571 				goto done;
13572 			}
13573 			/*
13574 			 * Resolve NS IPv6 address/AAAA.
13575 			 */
13576 			result = stub_request_nameserver_address(cb_args, false,
13577 								 ns_name);
13578 			if (result != ISC_R_SUCCESS) {
13579 				goto done;
13580 			}
13581 		}
13582 	}
13583 
13584 	result = ISC_R_SUCCESS;
13585 
13586 done:
13587 	while ((ns_name = ISC_LIST_HEAD(ns_list)) != NULL) {
13588 		ISC_LIST_UNLINK(ns_list, ns_name, link);
13589 		dns_name_free(ns_name, cb_args->stub->mctx);
13590 		isc_mem_put(cb_args->stub->mctx, ns_name, sizeof(*ns_name));
13591 	}
13592 	return (result);
13593 }
13594 
13595 static void
stub_callback(isc_task_t * task,isc_event_t * event)13596 stub_callback(isc_task_t *task, isc_event_t *event) {
13597 	const char me[] = "stub_callback";
13598 	dns_requestevent_t *revent = (dns_requestevent_t *)event;
13599 	dns_stub_t *stub = NULL;
13600 	dns_message_t *msg = NULL;
13601 	dns_zone_t *zone = NULL;
13602 	char master[ISC_SOCKADDR_FORMATSIZE];
13603 	char source[ISC_SOCKADDR_FORMATSIZE];
13604 	uint32_t nscnt, cnamecnt;
13605 	isc_result_t result;
13606 	isc_time_t now;
13607 	bool exiting = false;
13608 	unsigned int j;
13609 	struct stub_cb_args *cb_args;
13610 
13611 	cb_args = revent->ev_arg;
13612 	stub = cb_args->stub;
13613 	INSIST(DNS_STUB_VALID(stub));
13614 
13615 	UNUSED(task);
13616 
13617 	zone = stub->zone;
13618 
13619 	ENTER;
13620 
13621 	TIME_NOW(&now);
13622 
13623 	LOCK_ZONE(zone);
13624 
13625 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
13626 		zone_debuglog(zone, me, 1, "exiting");
13627 		exiting = true;
13628 		goto next_master;
13629 	}
13630 
13631 	isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
13632 	isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
13633 
13634 	if (revent->result != ISC_R_SUCCESS) {
13635 		if (revent->result == ISC_R_TIMEDOUT &&
13636 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS))
13637 		{
13638 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
13639 			dns_zone_log(zone, ISC_LOG_DEBUG(1),
13640 				     "refreshing stub: timeout retrying "
13641 				     " without EDNS master %s (source %s)",
13642 				     master, source);
13643 			goto same_master;
13644 		}
13645 		dns_zonemgr_unreachableadd(zone->zmgr, &zone->masteraddr,
13646 					   &zone->sourceaddr, &now);
13647 		dns_zone_log(zone, ISC_LOG_INFO,
13648 			     "could not refresh stub from master %s"
13649 			     " (source %s): %s",
13650 			     master, source, dns_result_totext(revent->result));
13651 		goto next_master;
13652 	}
13653 
13654 	dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
13655 
13656 	result = dns_request_getresponse(revent->request, msg, 0);
13657 	if (result != ISC_R_SUCCESS) {
13658 		goto next_master;
13659 	}
13660 
13661 	/*
13662 	 * Unexpected opcode.
13663 	 */
13664 	if (msg->opcode != dns_opcode_query) {
13665 		char opcode[128];
13666 		isc_buffer_t rb;
13667 
13668 		isc_buffer_init(&rb, opcode, sizeof(opcode));
13669 		(void)dns_opcode_totext(msg->opcode, &rb);
13670 
13671 		dns_zone_log(zone, ISC_LOG_INFO,
13672 			     "refreshing stub: "
13673 			     "unexpected opcode (%.*s) from %s (source %s)",
13674 			     (int)rb.used, opcode, master, source);
13675 		goto next_master;
13676 	}
13677 
13678 	/*
13679 	 * Unexpected rcode.
13680 	 */
13681 	if (msg->rcode != dns_rcode_noerror) {
13682 		char rcode[128];
13683 		isc_buffer_t rb;
13684 
13685 		isc_buffer_init(&rb, rcode, sizeof(rcode));
13686 		(void)dns_rcode_totext(msg->rcode, &rb);
13687 
13688 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
13689 		    (msg->rcode == dns_rcode_servfail ||
13690 		     msg->rcode == dns_rcode_notimp ||
13691 		     msg->rcode == dns_rcode_formerr))
13692 		{
13693 			dns_zone_log(zone, ISC_LOG_DEBUG(1),
13694 				     "refreshing stub: rcode (%.*s) retrying "
13695 				     "without EDNS master %s (source %s)",
13696 				     (int)rb.used, rcode, master, source);
13697 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
13698 			goto same_master;
13699 		}
13700 
13701 		dns_zone_log(zone, ISC_LOG_INFO,
13702 			     "refreshing stub: "
13703 			     "unexpected rcode (%.*s) from %s (source %s)",
13704 			     (int)rb.used, rcode, master, source);
13705 		goto next_master;
13706 	}
13707 
13708 	/*
13709 	 * We need complete messages.
13710 	 */
13711 	if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
13712 		if (dns_request_usedtcp(revent->request)) {
13713 			dns_zone_log(zone, ISC_LOG_INFO,
13714 				     "refreshing stub: truncated TCP "
13715 				     "response from master %s (source %s)",
13716 				     master, source);
13717 			goto next_master;
13718 		}
13719 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
13720 		goto same_master;
13721 	}
13722 
13723 	/*
13724 	 * If non-auth log and next master.
13725 	 */
13726 	if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
13727 		dns_zone_log(zone, ISC_LOG_INFO,
13728 			     "refreshing stub: "
13729 			     "non-authoritative answer from "
13730 			     "master %s (source %s)",
13731 			     master, source);
13732 		goto next_master;
13733 	}
13734 
13735 	/*
13736 	 * Sanity checks.
13737 	 */
13738 	cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
13739 	nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns);
13740 
13741 	if (cnamecnt != 0) {
13742 		dns_zone_log(zone, ISC_LOG_INFO,
13743 			     "refreshing stub: unexpected CNAME response "
13744 			     "from master %s (source %s)",
13745 			     master, source);
13746 		goto next_master;
13747 	}
13748 
13749 	if (nscnt == 0) {
13750 		dns_zone_log(zone, ISC_LOG_INFO,
13751 			     "refreshing stub: no NS records in response "
13752 			     "from master %s (source %s)",
13753 			     master, source);
13754 		goto next_master;
13755 	}
13756 
13757 	atomic_fetch_add(&stub->pending_requests, 1);
13758 
13759 	/*
13760 	 * Save answer.
13761 	 */
13762 	result = save_nsrrset(msg, &zone->origin, cb_args, stub->db,
13763 			      stub->version);
13764 	if (result != ISC_R_SUCCESS) {
13765 		dns_zone_log(zone, ISC_LOG_INFO,
13766 			     "refreshing stub: unable to save NS records "
13767 			     "from master %s (source %s)",
13768 			     master, source);
13769 		goto next_master;
13770 	}
13771 
13772 	dns_message_detach(&msg);
13773 	isc_event_free(&event);
13774 	dns_request_destroy(&zone->request);
13775 
13776 	/*
13777 	 * Check to see if there are no outstanding requests and
13778 	 * finish off if that is so.
13779 	 */
13780 	if (atomic_fetch_sub(&stub->pending_requests, 1) == 1) {
13781 		isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
13782 		stub_finish_zone_update(stub, now);
13783 		goto free_stub;
13784 	}
13785 
13786 	UNLOCK_ZONE(zone);
13787 	return;
13788 
13789 next_master:
13790 	isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
13791 	if (stub->version != NULL) {
13792 		dns_db_closeversion(stub->db, &stub->version, false);
13793 	}
13794 	if (stub->db != NULL) {
13795 		dns_db_detach(&stub->db);
13796 	}
13797 	if (msg != NULL) {
13798 		dns_message_detach(&msg);
13799 	}
13800 	isc_event_free(&event);
13801 	dns_request_destroy(&zone->request);
13802 	/*
13803 	 * Skip to next failed / untried master.
13804 	 */
13805 	do {
13806 		zone->curmaster++;
13807 	} while (zone->curmaster < zone->masterscnt &&
13808 		 zone->mastersok[zone->curmaster]);
13809 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
13810 	if (exiting || zone->curmaster >= zone->masterscnt) {
13811 		bool done = true;
13812 		if (!exiting &&
13813 		    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
13814 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
13815 		{
13816 			/*
13817 			 * Did we get a good answer from all the primaries?
13818 			 */
13819 			for (j = 0; j < zone->masterscnt; j++) {
13820 				if (!zone->mastersok[j]) {
13821 					{
13822 						done = false;
13823 						break;
13824 					}
13825 				}
13826 			}
13827 		} else {
13828 			done = true;
13829 		}
13830 		if (!done) {
13831 			zone->curmaster = 0;
13832 			/*
13833 			 * Find the next failed master.
13834 			 */
13835 			while (zone->curmaster < zone->masterscnt &&
13836 			       zone->mastersok[zone->curmaster])
13837 			{
13838 				zone->curmaster++;
13839 			}
13840 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
13841 		} else {
13842 			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
13843 
13844 			zone_settimer(zone, &now);
13845 			goto free_stub;
13846 		}
13847 	}
13848 	queue_soa_query(zone);
13849 	goto free_stub;
13850 
13851 same_master:
13852 	isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
13853 	if (msg != NULL) {
13854 		dns_message_detach(&msg);
13855 	}
13856 	isc_event_free(&event);
13857 	dns_request_destroy(&zone->request);
13858 	ns_query(zone, NULL, stub);
13859 	UNLOCK_ZONE(zone);
13860 	goto done;
13861 
13862 free_stub:
13863 	UNLOCK_ZONE(zone);
13864 	stub->magic = 0;
13865 	dns_zone_idetach(&stub->zone);
13866 	INSIST(stub->db == NULL);
13867 	INSIST(stub->version == NULL);
13868 	isc_mem_put(stub->mctx, stub, sizeof(*stub));
13869 
13870 done:
13871 	INSIST(event == NULL);
13872 	return;
13873 }
13874 
13875 /*
13876  * Get the EDNS EXPIRE option from the response and if it exists trim
13877  * expire to be not more than it.
13878  */
13879 static void
get_edns_expire(dns_zone_t * zone,dns_message_t * message,uint32_t * expirep)13880 get_edns_expire(dns_zone_t *zone, dns_message_t *message, uint32_t *expirep) {
13881 	isc_result_t result;
13882 	uint32_t expire;
13883 	dns_rdata_t rdata = DNS_RDATA_INIT;
13884 	isc_buffer_t optbuf;
13885 	uint16_t optcode;
13886 	uint16_t optlen;
13887 
13888 	REQUIRE(expirep != NULL);
13889 	REQUIRE(message != NULL);
13890 
13891 	if (message->opt == NULL) {
13892 		return;
13893 	}
13894 
13895 	result = dns_rdataset_first(message->opt);
13896 	if (result == ISC_R_SUCCESS) {
13897 		dns_rdataset_current(message->opt, &rdata);
13898 		isc_buffer_init(&optbuf, rdata.data, rdata.length);
13899 		isc_buffer_add(&optbuf, rdata.length);
13900 		while (isc_buffer_remaininglength(&optbuf) >= 4) {
13901 			optcode = isc_buffer_getuint16(&optbuf);
13902 			optlen = isc_buffer_getuint16(&optbuf);
13903 			/*
13904 			 * A EDNS EXPIRE response has a length of 4.
13905 			 */
13906 			if (optcode != DNS_OPT_EXPIRE || optlen != 4) {
13907 				isc_buffer_forward(&optbuf, optlen);
13908 				continue;
13909 			}
13910 			expire = isc_buffer_getuint32(&optbuf);
13911 			dns_zone_log(zone, ISC_LOG_DEBUG(1),
13912 				     "got EDNS EXPIRE of %u", expire);
13913 			/*
13914 			 * Trim *expirep?
13915 			 */
13916 			if (expire < *expirep) {
13917 				*expirep = expire;
13918 			}
13919 			break;
13920 		}
13921 	}
13922 }
13923 
13924 /*
13925  * Set the file modification time zone->expire seconds before expiretime.
13926  */
13927 static void
setmodtime(dns_zone_t * zone,isc_time_t * expiretime)13928 setmodtime(dns_zone_t *zone, isc_time_t *expiretime) {
13929 	isc_result_t result;
13930 	isc_time_t when;
13931 	isc_interval_t i;
13932 
13933 	isc_interval_set(&i, zone->expire, 0);
13934 	result = isc_time_subtract(expiretime, &i, &when);
13935 	if (result != ISC_R_SUCCESS) {
13936 		return;
13937 	}
13938 
13939 	result = ISC_R_FAILURE;
13940 	if (zone->journal != NULL) {
13941 		result = isc_file_settime(zone->journal, &when);
13942 	}
13943 	if (result == ISC_R_SUCCESS &&
13944 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
13945 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
13946 	{
13947 		result = isc_file_settime(zone->masterfile, &when);
13948 	} else if (result != ISC_R_SUCCESS) {
13949 		result = isc_file_settime(zone->masterfile, &when);
13950 	}
13951 
13952 	/*
13953 	 * Someone removed the file from underneath us!
13954 	 */
13955 	if (result == ISC_R_FILENOTFOUND) {
13956 		zone_needdump(zone, DNS_DUMP_DELAY);
13957 	} else if (result != ISC_R_SUCCESS) {
13958 		dns_zone_log(zone, ISC_LOG_ERROR,
13959 			     "refresh: could not set "
13960 			     "file modification time of '%s': %s",
13961 			     zone->masterfile, dns_result_totext(result));
13962 	}
13963 }
13964 
13965 /*
13966  * An SOA query has finished (successfully or not).
13967  */
13968 static void
refresh_callback(isc_task_t * task,isc_event_t * event)13969 refresh_callback(isc_task_t *task, isc_event_t *event) {
13970 	const char me[] = "refresh_callback";
13971 	dns_requestevent_t *revent = (dns_requestevent_t *)event;
13972 	dns_zone_t *zone;
13973 	dns_message_t *msg = NULL;
13974 	uint32_t soacnt, cnamecnt, soacount, nscount;
13975 	isc_time_t now;
13976 	char master[ISC_SOCKADDR_FORMATSIZE];
13977 	char source[ISC_SOCKADDR_FORMATSIZE];
13978 	dns_rdataset_t *rdataset = NULL;
13979 	dns_rdata_t rdata = DNS_RDATA_INIT;
13980 	dns_rdata_soa_t soa;
13981 	isc_result_t result;
13982 	uint32_t serial, oldserial = 0;
13983 	unsigned int j;
13984 	bool do_queue_xfrin = false;
13985 
13986 	zone = revent->ev_arg;
13987 	INSIST(DNS_ZONE_VALID(zone));
13988 
13989 	UNUSED(task);
13990 
13991 	ENTER;
13992 
13993 	TIME_NOW(&now);
13994 
13995 	LOCK_ZONE(zone);
13996 
13997 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
13998 		isc_event_free(&event);
13999 		dns_request_destroy(&zone->request);
14000 		goto detach;
14001 	}
14002 
14003 	/*
14004 	 * if timeout log and next master;
14005 	 */
14006 
14007 	isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
14008 	isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
14009 
14010 	if (revent->result != ISC_R_SUCCESS) {
14011 		if (revent->result == ISC_R_TIMEDOUT &&
14012 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS))
14013 		{
14014 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
14015 			dns_zone_log(zone, ISC_LOG_DEBUG(1),
14016 				     "refresh: timeout retrying without EDNS "
14017 				     "master %s (source %s)",
14018 				     master, source);
14019 			goto same_master;
14020 		}
14021 		if (revent->result == ISC_R_TIMEDOUT &&
14022 		    !dns_request_usedtcp(revent->request))
14023 		{
14024 			dns_zone_log(zone, ISC_LOG_INFO,
14025 				     "refresh: retry limit for "
14026 				     "master %s exceeded (source %s)",
14027 				     master, source);
14028 			/* Try with slave with TCP. */
14029 			if ((zone->type == dns_zone_secondary ||
14030 			     zone->type == dns_zone_mirror ||
14031 			     zone->type == dns_zone_redirect) &&
14032 			    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH))
14033 			{
14034 				if (!dns_zonemgr_unreachable(
14035 					    zone->zmgr, &zone->masteraddr,
14036 					    &zone->sourceaddr, &now))
14037 				{
14038 					DNS_ZONE_SETFLAG(
14039 						zone,
14040 						DNS_ZONEFLG_SOABEFOREAXFR);
14041 					goto tcp_transfer;
14042 				}
14043 				dns_zone_log(zone, ISC_LOG_DEBUG(1),
14044 					     "refresh: skipped tcp fallback "
14045 					     "as master %s (source %s) is "
14046 					     "unreachable (cached)",
14047 					     master, source);
14048 			}
14049 		} else {
14050 			dns_zone_log(zone, ISC_LOG_INFO,
14051 				     "refresh: failure trying master "
14052 				     "%s (source %s): %s",
14053 				     master, source,
14054 				     dns_result_totext(revent->result));
14055 		}
14056 		goto next_master;
14057 	}
14058 
14059 	dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
14060 	result = dns_request_getresponse(revent->request, msg, 0);
14061 	if (result != ISC_R_SUCCESS) {
14062 		dns_zone_log(zone, ISC_LOG_INFO,
14063 			     "refresh: failure trying master "
14064 			     "%s (source %s): %s",
14065 			     master, source, dns_result_totext(result));
14066 		goto next_master;
14067 	}
14068 
14069 	/*
14070 	 * Unexpected opcode.
14071 	 */
14072 	if (msg->opcode != dns_opcode_query) {
14073 		char opcode[128];
14074 		isc_buffer_t rb;
14075 
14076 		isc_buffer_init(&rb, opcode, sizeof(opcode));
14077 		(void)dns_opcode_totext(msg->opcode, &rb);
14078 
14079 		dns_zone_log(zone, ISC_LOG_INFO,
14080 			     "refresh: "
14081 			     "unexpected opcode (%.*s) from %s (source %s)",
14082 			     (int)rb.used, opcode, master, source);
14083 		goto next_master;
14084 	}
14085 
14086 	/*
14087 	 * Unexpected rcode.
14088 	 */
14089 	if (msg->rcode != dns_rcode_noerror) {
14090 		char rcode[128];
14091 		isc_buffer_t rb;
14092 
14093 		isc_buffer_init(&rb, rcode, sizeof(rcode));
14094 		(void)dns_rcode_totext(msg->rcode, &rb);
14095 
14096 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
14097 		    (msg->rcode == dns_rcode_servfail ||
14098 		     msg->rcode == dns_rcode_notimp ||
14099 		     msg->rcode == dns_rcode_formerr))
14100 		{
14101 			dns_zone_log(zone, ISC_LOG_DEBUG(1),
14102 				     "refresh: rcode (%.*s) retrying without "
14103 				     "EDNS master %s (source %s)",
14104 				     (int)rb.used, rcode, master, source);
14105 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
14106 			goto same_master;
14107 		}
14108 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
14109 		    msg->rcode == dns_rcode_badvers)
14110 		{
14111 			dns_zone_log(zone, ISC_LOG_DEBUG(1),
14112 				     "refresh: rcode (%.*s) retrying without "
14113 				     "EDNS EXPIRE OPTION master %s (source %s)",
14114 				     (int)rb.used, rcode, master, source);
14115 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
14116 			goto same_master;
14117 		}
14118 		dns_zone_log(zone, ISC_LOG_INFO,
14119 			     "refresh: unexpected rcode (%.*s) from "
14120 			     "master %s (source %s)",
14121 			     (int)rb.used, rcode, master, source);
14122 		/*
14123 		 * Perhaps AXFR/IXFR is allowed even if SOA queries aren't.
14124 		 */
14125 		if (msg->rcode == dns_rcode_refused &&
14126 		    (zone->type == dns_zone_secondary ||
14127 		     zone->type == dns_zone_mirror ||
14128 		     zone->type == dns_zone_redirect))
14129 		{
14130 			goto tcp_transfer;
14131 		}
14132 		goto next_master;
14133 	}
14134 
14135 	/*
14136 	 * If truncated punt to zone transfer which will query again.
14137 	 */
14138 	if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
14139 		if (zone->type == dns_zone_secondary ||
14140 		    zone->type == dns_zone_mirror ||
14141 		    zone->type == dns_zone_redirect)
14142 		{
14143 			dns_zone_log(zone, ISC_LOG_INFO,
14144 				     "refresh: truncated UDP answer, "
14145 				     "initiating TCP zone xfer "
14146 				     "for master %s (source %s)",
14147 				     master, source);
14148 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
14149 			goto tcp_transfer;
14150 		} else {
14151 			INSIST(zone->type == dns_zone_stub);
14152 			if (dns_request_usedtcp(revent->request)) {
14153 				dns_zone_log(zone, ISC_LOG_INFO,
14154 					     "refresh: truncated TCP response "
14155 					     "from master %s (source %s)",
14156 					     master, source);
14157 				goto next_master;
14158 			}
14159 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
14160 			goto same_master;
14161 		}
14162 	}
14163 
14164 	/*
14165 	 * if non-auth log and next master;
14166 	 */
14167 	if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
14168 		dns_zone_log(zone, ISC_LOG_INFO,
14169 			     "refresh: non-authoritative answer from "
14170 			     "master %s (source %s)",
14171 			     master, source);
14172 		goto next_master;
14173 	}
14174 
14175 	cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
14176 	soacnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_soa);
14177 	nscount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_ns);
14178 	soacount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_soa);
14179 
14180 	/*
14181 	 * There should not be a CNAME record at top of zone.
14182 	 */
14183 	if (cnamecnt != 0) {
14184 		dns_zone_log(zone, ISC_LOG_INFO,
14185 			     "refresh: CNAME at top of zone "
14186 			     "in master %s (source %s)",
14187 			     master, source);
14188 		goto next_master;
14189 	}
14190 
14191 	/*
14192 	 * if referral log and next master;
14193 	 */
14194 	if (soacnt == 0 && soacount == 0 && nscount != 0) {
14195 		dns_zone_log(zone, ISC_LOG_INFO,
14196 			     "refresh: referral response "
14197 			     "from master %s (source %s)",
14198 			     master, source);
14199 		goto next_master;
14200 	}
14201 
14202 	/*
14203 	 * if nodata log and next master;
14204 	 */
14205 	if (soacnt == 0 && (nscount == 0 || soacount != 0)) {
14206 		dns_zone_log(zone, ISC_LOG_INFO,
14207 			     "refresh: NODATA response "
14208 			     "from master %s (source %s)",
14209 			     master, source);
14210 		goto next_master;
14211 	}
14212 
14213 	/*
14214 	 * Only one soa at top of zone.
14215 	 */
14216 	if (soacnt != 1) {
14217 		dns_zone_log(zone, ISC_LOG_INFO,
14218 			     "refresh: answer SOA count (%d) != 1 "
14219 			     "from master %s (source %s)",
14220 			     soacnt, master, source);
14221 		goto next_master;
14222 	}
14223 
14224 	/*
14225 	 * Extract serial
14226 	 */
14227 	rdataset = NULL;
14228 	result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin,
14229 				      dns_rdatatype_soa, dns_rdatatype_none,
14230 				      NULL, &rdataset);
14231 	if (result != ISC_R_SUCCESS) {
14232 		dns_zone_log(zone, ISC_LOG_INFO,
14233 			     "refresh: unable to get SOA record "
14234 			     "from master %s (source %s)",
14235 			     master, source);
14236 		goto next_master;
14237 	}
14238 
14239 	result = dns_rdataset_first(rdataset);
14240 	if (result != ISC_R_SUCCESS) {
14241 		dns_zone_log(zone, ISC_LOG_INFO,
14242 			     "refresh: dns_rdataset_first() failed");
14243 		goto next_master;
14244 	}
14245 
14246 	dns_rdataset_current(rdataset, &rdata);
14247 	result = dns_rdata_tostruct(&rdata, &soa, NULL);
14248 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
14249 
14250 	serial = soa.serial;
14251 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
14252 		unsigned int dbsoacount;
14253 		result = zone_get_from_db(zone, zone->db, NULL, &dbsoacount,
14254 					  NULL, &oldserial, NULL, NULL, NULL,
14255 					  NULL, NULL);
14256 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
14257 		RUNTIME_CHECK(dbsoacount > 0U);
14258 		zone_debuglog(zone, me, 1, "serial: new %u, old %u", serial,
14259 			      oldserial);
14260 	} else {
14261 		zone_debuglog(zone, me, 1, "serial: new %u, old not loaded",
14262 			      serial);
14263 	}
14264 
14265 	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
14266 	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
14267 	    isc_serial_gt(serial, oldserial))
14268 	{
14269 		if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
14270 					    &zone->sourceaddr, &now))
14271 		{
14272 			dns_zone_log(zone, ISC_LOG_INFO,
14273 				     "refresh: skipping %s as master %s "
14274 				     "(source %s) is unreachable (cached)",
14275 				     (zone->type == dns_zone_secondary ||
14276 				      zone->type == dns_zone_mirror ||
14277 				      zone->type == dns_zone_redirect)
14278 					     ? "zone transfer"
14279 					     : "NS query",
14280 				     master, source);
14281 			goto next_master;
14282 		}
14283 	tcp_transfer:
14284 		isc_event_free(&event);
14285 		dns_request_destroy(&zone->request);
14286 		if (zone->type == dns_zone_secondary ||
14287 		    zone->type == dns_zone_mirror ||
14288 		    zone->type == dns_zone_redirect)
14289 		{
14290 			do_queue_xfrin = true;
14291 		} else {
14292 			INSIST(zone->type == dns_zone_stub);
14293 			ns_query(zone, rdataset, NULL);
14294 		}
14295 		if (msg != NULL) {
14296 			dns_message_detach(&msg);
14297 		}
14298 	} else if (isc_serial_eq(soa.serial, oldserial)) {
14299 		isc_time_t expiretime;
14300 		uint32_t expire;
14301 
14302 		/*
14303 		 * Compute the new expire time based on this response.
14304 		 */
14305 		expire = zone->expire;
14306 		get_edns_expire(zone, msg, &expire);
14307 		DNS_ZONE_TIME_ADD(&now, expire, &expiretime);
14308 
14309 		/*
14310 		 * Has the expire time improved?
14311 		 */
14312 		if (isc_time_compare(&expiretime, &zone->expiretime) > 0) {
14313 			zone->expiretime = expiretime;
14314 			if (zone->masterfile != NULL) {
14315 				setmodtime(zone, &expiretime);
14316 			}
14317 		}
14318 
14319 		DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
14320 		zone->mastersok[zone->curmaster] = true;
14321 		goto next_master;
14322 	} else {
14323 		if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER)) {
14324 			dns_zone_log(zone, ISC_LOG_INFO,
14325 				     "serial number (%u) "
14326 				     "received from master %s < ours (%u)",
14327 				     soa.serial, master, oldserial);
14328 		} else {
14329 			zone_debuglog(zone, me, 1, "ahead");
14330 		}
14331 		zone->mastersok[zone->curmaster] = true;
14332 		goto next_master;
14333 	}
14334 	if (msg != NULL) {
14335 		dns_message_detach(&msg);
14336 	}
14337 	goto detach;
14338 
14339 next_master:
14340 	if (msg != NULL) {
14341 		dns_message_detach(&msg);
14342 	}
14343 	isc_event_free(&event);
14344 	dns_request_destroy(&zone->request);
14345 	/*
14346 	 * Skip to next failed / untried master.
14347 	 */
14348 	do {
14349 		zone->curmaster++;
14350 	} while (zone->curmaster < zone->masterscnt &&
14351 		 zone->mastersok[zone->curmaster]);
14352 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
14353 	if (zone->curmaster >= zone->masterscnt) {
14354 		bool done = true;
14355 		if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
14356 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
14357 		{
14358 			/*
14359 			 * Did we get a good answer from all the primaries?
14360 			 */
14361 			for (j = 0; j < zone->masterscnt; j++) {
14362 				if (!zone->mastersok[j]) {
14363 					{
14364 						done = false;
14365 						break;
14366 					}
14367 				}
14368 			}
14369 		} else {
14370 			done = true;
14371 		}
14372 		if (!done) {
14373 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
14374 			zone->curmaster = 0;
14375 			/*
14376 			 * Find the next failed master.
14377 			 */
14378 			while (zone->curmaster < zone->masterscnt &&
14379 			       zone->mastersok[zone->curmaster])
14380 			{
14381 				zone->curmaster++;
14382 			}
14383 			goto requeue;
14384 		}
14385 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
14386 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
14387 			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
14388 			zone->refreshtime = now;
14389 		}
14390 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
14391 		zone_settimer(zone, &now);
14392 		goto detach;
14393 	}
14394 
14395 requeue:
14396 	queue_soa_query(zone);
14397 	goto detach;
14398 
14399 same_master:
14400 	if (msg != NULL) {
14401 		dns_message_detach(&msg);
14402 	}
14403 	isc_event_free(&event);
14404 	dns_request_destroy(&zone->request);
14405 	queue_soa_query(zone);
14406 
14407 detach:
14408 	UNLOCK_ZONE(zone);
14409 	if (do_queue_xfrin) {
14410 		queue_xfrin(zone);
14411 	}
14412 	dns_zone_idetach(&zone);
14413 	return;
14414 }
14415 
14416 static void
queue_soa_query(dns_zone_t * zone)14417 queue_soa_query(dns_zone_t *zone) {
14418 	const char me[] = "queue_soa_query";
14419 	isc_event_t *e;
14420 	dns_zone_t *dummy = NULL;
14421 	isc_result_t result;
14422 
14423 	ENTER;
14424 	/*
14425 	 * Locked by caller
14426 	 */
14427 	REQUIRE(LOCKED_ZONE(zone));
14428 
14429 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
14430 		cancel_refresh(zone);
14431 		return;
14432 	}
14433 
14434 	e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE, soa_query,
14435 			       zone, sizeof(isc_event_t));
14436 
14437 	/*
14438 	 * Attach so that we won't clean up
14439 	 * until the event is delivered.
14440 	 */
14441 	zone_iattach(zone, &dummy);
14442 
14443 	e->ev_arg = zone;
14444 	e->ev_sender = NULL;
14445 	result = isc_ratelimiter_enqueue(zone->zmgr->refreshrl, zone->task, &e);
14446 	if (result != ISC_R_SUCCESS) {
14447 		zone_idetach(&dummy);
14448 		isc_event_free(&e);
14449 		cancel_refresh(zone);
14450 	}
14451 }
14452 
14453 static void
soa_query(isc_task_t * task,isc_event_t * event)14454 soa_query(isc_task_t *task, isc_event_t *event) {
14455 	const char me[] = "soa_query";
14456 	isc_result_t result = ISC_R_FAILURE;
14457 	dns_message_t *message = NULL;
14458 	dns_zone_t *zone = event->ev_arg;
14459 	dns_zone_t *dummy = NULL;
14460 	isc_netaddr_t masterip;
14461 	dns_tsigkey_t *key = NULL;
14462 	uint32_t options;
14463 	bool cancel = true;
14464 	int timeout;
14465 	bool have_xfrsource, have_xfrdscp, reqnsid, reqexpire;
14466 	uint16_t udpsize = SEND_BUFFER_SIZE;
14467 	isc_dscp_t dscp = -1;
14468 
14469 	REQUIRE(DNS_ZONE_VALID(zone));
14470 
14471 	UNUSED(task);
14472 
14473 	ENTER;
14474 
14475 	LOCK_ZONE(zone);
14476 	if (((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) ||
14477 	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
14478 	    zone->view->requestmgr == NULL)
14479 	{
14480 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
14481 			cancel = false;
14482 		}
14483 		goto cleanup;
14484 	}
14485 
14486 again:
14487 	result = create_query(zone, dns_rdatatype_soa, &zone->origin, &message);
14488 	if (result != ISC_R_SUCCESS) {
14489 		goto cleanup;
14490 	}
14491 
14492 	INSIST(zone->masterscnt > 0);
14493 	INSIST(zone->curmaster < zone->masterscnt);
14494 
14495 	zone->masteraddr = zone->masters[zone->curmaster];
14496 
14497 	isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
14498 	/*
14499 	 * First, look for a tsig key in the master statement, then
14500 	 * try for a server key.
14501 	 */
14502 	if ((zone->masterkeynames != NULL) &&
14503 	    (zone->masterkeynames[zone->curmaster] != NULL))
14504 	{
14505 		dns_view_t *view = dns_zone_getview(zone);
14506 		dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
14507 		result = dns_view_gettsig(view, keyname, &key);
14508 		if (result != ISC_R_SUCCESS) {
14509 			char namebuf[DNS_NAME_FORMATSIZE];
14510 			dns_name_format(keyname, namebuf, sizeof(namebuf));
14511 			dns_zone_log(zone, ISC_LOG_ERROR,
14512 				     "unable to find key: %s", namebuf);
14513 			goto skip_master;
14514 		}
14515 	}
14516 	if (key == NULL) {
14517 		result = dns_view_getpeertsig(zone->view, &masterip, &key);
14518 		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
14519 			char addrbuf[ISC_NETADDR_FORMATSIZE];
14520 			isc_netaddr_format(&masterip, addrbuf, sizeof(addrbuf));
14521 			dns_zone_log(zone, ISC_LOG_ERROR,
14522 				     "unable to find TSIG key for %s", addrbuf);
14523 			goto skip_master;
14524 		}
14525 	}
14526 
14527 	options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ? DNS_REQUESTOPT_TCP
14528 							 : 0;
14529 	have_xfrsource = have_xfrdscp = false;
14530 	reqnsid = zone->view->requestnsid;
14531 	reqexpire = zone->requestexpire;
14532 	if (zone->view->peers != NULL) {
14533 		dns_peer_t *peer = NULL;
14534 		bool edns, usetcp;
14535 		result = dns_peerlist_peerbyaddr(zone->view->peers, &masterip,
14536 						 &peer);
14537 		if (result == ISC_R_SUCCESS) {
14538 			result = dns_peer_getsupportedns(peer, &edns);
14539 			if (result == ISC_R_SUCCESS && !edns) {
14540 				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
14541 			}
14542 			result = dns_peer_gettransfersource(peer,
14543 							    &zone->sourceaddr);
14544 			if (result == ISC_R_SUCCESS) {
14545 				have_xfrsource = true;
14546 			}
14547 			(void)dns_peer_gettransferdscp(peer, &dscp);
14548 			if (dscp != -1) {
14549 				have_xfrdscp = true;
14550 			}
14551 			if (zone->view->resolver != NULL) {
14552 				udpsize = dns_resolver_getudpsize(
14553 					zone->view->resolver);
14554 			}
14555 			(void)dns_peer_getudpsize(peer, &udpsize);
14556 			(void)dns_peer_getrequestnsid(peer, &reqnsid);
14557 			(void)dns_peer_getrequestexpire(peer, &reqexpire);
14558 			result = dns_peer_getforcetcp(peer, &usetcp);
14559 			if (result == ISC_R_SUCCESS && usetcp) {
14560 				options |= DNS_REQUESTOPT_TCP;
14561 			}
14562 		}
14563 	}
14564 
14565 	switch (isc_sockaddr_pf(&zone->masteraddr)) {
14566 	case PF_INET:
14567 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
14568 			if (isc_sockaddr_equal(&zone->altxfrsource4,
14569 					       &zone->xfrsource4))
14570 			{
14571 				goto skip_master;
14572 			}
14573 			zone->sourceaddr = zone->altxfrsource4;
14574 			if (!have_xfrdscp) {
14575 				dscp = zone->altxfrsource4dscp;
14576 			}
14577 		} else if (!have_xfrsource) {
14578 			zone->sourceaddr = zone->xfrsource4;
14579 			if (!have_xfrdscp) {
14580 				dscp = zone->xfrsource4dscp;
14581 			}
14582 		}
14583 		break;
14584 	case PF_INET6:
14585 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
14586 			if (isc_sockaddr_equal(&zone->altxfrsource6,
14587 					       &zone->xfrsource6))
14588 			{
14589 				goto skip_master;
14590 			}
14591 			zone->sourceaddr = zone->altxfrsource6;
14592 			if (!have_xfrdscp) {
14593 				dscp = zone->altxfrsource6dscp;
14594 			}
14595 		} else if (!have_xfrsource) {
14596 			zone->sourceaddr = zone->xfrsource6;
14597 			if (!have_xfrdscp) {
14598 				dscp = zone->xfrsource6dscp;
14599 			}
14600 		}
14601 		break;
14602 	default:
14603 		result = ISC_R_NOTIMPLEMENTED;
14604 		goto cleanup;
14605 	}
14606 
14607 	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
14608 		result = add_opt(message, udpsize, reqnsid, reqexpire);
14609 		if (result != ISC_R_SUCCESS) {
14610 			zone_debuglog(zone, me, 1,
14611 				      "unable to add opt record: %s",
14612 				      dns_result_totext(result));
14613 		}
14614 	}
14615 
14616 	zone_iattach(zone, &dummy);
14617 	timeout = 15;
14618 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH)) {
14619 		timeout = 30;
14620 	}
14621 	result = dns_request_createvia(
14622 		zone->view->requestmgr, message, &zone->sourceaddr,
14623 		&zone->masteraddr, dscp, options, key, timeout * 3, timeout, 0,
14624 		zone->task, refresh_callback, zone, &zone->request);
14625 	if (result != ISC_R_SUCCESS) {
14626 		zone_idetach(&dummy);
14627 		zone_debuglog(zone, me, 1,
14628 			      "dns_request_createvia4() failed: %s",
14629 			      dns_result_totext(result));
14630 		goto skip_master;
14631 	} else {
14632 		if (isc_sockaddr_pf(&zone->masteraddr) == PF_INET) {
14633 			inc_stats(zone, dns_zonestatscounter_soaoutv4);
14634 		} else {
14635 			inc_stats(zone, dns_zonestatscounter_soaoutv6);
14636 		}
14637 	}
14638 	cancel = false;
14639 
14640 cleanup:
14641 	if (key != NULL) {
14642 		dns_tsigkey_detach(&key);
14643 	}
14644 	if (result != ISC_R_SUCCESS) {
14645 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
14646 	}
14647 	if (message != NULL) {
14648 		dns_message_detach(&message);
14649 	}
14650 	if (cancel) {
14651 		cancel_refresh(zone);
14652 	}
14653 	isc_event_free(&event);
14654 	UNLOCK_ZONE(zone);
14655 	dns_zone_idetach(&zone);
14656 	return;
14657 
14658 skip_master:
14659 	if (key != NULL) {
14660 		dns_tsigkey_detach(&key);
14661 	}
14662 	dns_message_detach(&message);
14663 	/*
14664 	 * Skip to next failed / untried master.
14665 	 */
14666 	do {
14667 		zone->curmaster++;
14668 	} while (zone->curmaster < zone->masterscnt &&
14669 		 zone->mastersok[zone->curmaster]);
14670 	if (zone->curmaster < zone->masterscnt) {
14671 		goto again;
14672 	}
14673 	zone->curmaster = 0;
14674 	goto cleanup;
14675 }
14676 
14677 static void
ns_query(dns_zone_t * zone,dns_rdataset_t * soardataset,dns_stub_t * stub)14678 ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
14679 	const char me[] = "ns_query";
14680 	isc_result_t result;
14681 	dns_message_t *message = NULL;
14682 	isc_netaddr_t masterip;
14683 	dns_tsigkey_t *key = NULL;
14684 	dns_dbnode_t *node = NULL;
14685 	int timeout;
14686 	bool have_xfrsource = false, have_xfrdscp = false;
14687 	bool reqnsid;
14688 	uint16_t udpsize = SEND_BUFFER_SIZE;
14689 	isc_dscp_t dscp = -1;
14690 	struct stub_cb_args *cb_args;
14691 
14692 	REQUIRE(DNS_ZONE_VALID(zone));
14693 	REQUIRE(LOCKED_ZONE(zone));
14694 	REQUIRE((soardataset != NULL && stub == NULL) ||
14695 		(soardataset == NULL && stub != NULL));
14696 	REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
14697 
14698 	ENTER;
14699 
14700 	if (stub == NULL) {
14701 		stub = isc_mem_get(zone->mctx, sizeof(*stub));
14702 		stub->magic = STUB_MAGIC;
14703 		stub->mctx = zone->mctx;
14704 		stub->zone = NULL;
14705 		stub->db = NULL;
14706 		stub->version = NULL;
14707 		atomic_init(&stub->pending_requests, 0);
14708 
14709 		/*
14710 		 * Attach so that the zone won't disappear from under us.
14711 		 */
14712 		zone_iattach(zone, &stub->zone);
14713 
14714 		/*
14715 		 * If a db exists we will update it, otherwise we create a
14716 		 * new one and attach it to the zone once we have the NS
14717 		 * RRset and glue.
14718 		 */
14719 		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
14720 		if (zone->db != NULL) {
14721 			dns_db_attach(zone->db, &stub->db);
14722 			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
14723 		} else {
14724 			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
14725 
14726 			INSIST(zone->db_argc >= 1);
14727 			result = dns_db_create(zone->mctx, zone->db_argv[0],
14728 					       &zone->origin, dns_dbtype_stub,
14729 					       zone->rdclass, zone->db_argc - 1,
14730 					       zone->db_argv + 1, &stub->db);
14731 			if (result != ISC_R_SUCCESS) {
14732 				dns_zone_log(zone, ISC_LOG_ERROR,
14733 					     "refreshing stub: "
14734 					     "could not create "
14735 					     "database: %s",
14736 					     dns_result_totext(result));
14737 				goto cleanup;
14738 			}
14739 			dns_db_settask(stub->db, zone->task);
14740 		}
14741 
14742 		result = dns_db_newversion(stub->db, &stub->version);
14743 		if (result != ISC_R_SUCCESS) {
14744 			dns_zone_log(zone, ISC_LOG_INFO,
14745 				     "refreshing stub: "
14746 				     "dns_db_newversion() failed: %s",
14747 				     dns_result_totext(result));
14748 			goto cleanup;
14749 		}
14750 
14751 		/*
14752 		 * Update SOA record.
14753 		 */
14754 		result = dns_db_findnode(stub->db, &zone->origin, true, &node);
14755 		if (result != ISC_R_SUCCESS) {
14756 			dns_zone_log(zone, ISC_LOG_INFO,
14757 				     "refreshing stub: "
14758 				     "dns_db_findnode() failed: %s",
14759 				     dns_result_totext(result));
14760 			goto cleanup;
14761 		}
14762 
14763 		result = dns_db_addrdataset(stub->db, node, stub->version, 0,
14764 					    soardataset, 0, NULL);
14765 		dns_db_detachnode(stub->db, &node);
14766 		if (result != ISC_R_SUCCESS) {
14767 			dns_zone_log(zone, ISC_LOG_INFO,
14768 				     "refreshing stub: "
14769 				     "dns_db_addrdataset() failed: %s",
14770 				     dns_result_totext(result));
14771 			goto cleanup;
14772 		}
14773 	}
14774 
14775 	/*
14776 	 * XXX Optimisation: Create message when zone is setup and reuse.
14777 	 */
14778 	result = create_query(zone, dns_rdatatype_ns, &zone->origin, &message);
14779 	INSIST(result == ISC_R_SUCCESS);
14780 
14781 	INSIST(zone->masterscnt > 0);
14782 	INSIST(zone->curmaster < zone->masterscnt);
14783 	zone->masteraddr = zone->masters[zone->curmaster];
14784 
14785 	isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
14786 	/*
14787 	 * First, look for a tsig key in the master statement, then
14788 	 * try for a server key.
14789 	 */
14790 	if ((zone->masterkeynames != NULL) &&
14791 	    (zone->masterkeynames[zone->curmaster] != NULL))
14792 	{
14793 		dns_view_t *view = dns_zone_getview(zone);
14794 		dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
14795 		result = dns_view_gettsig(view, keyname, &key);
14796 		if (result != ISC_R_SUCCESS) {
14797 			char namebuf[DNS_NAME_FORMATSIZE];
14798 			dns_name_format(keyname, namebuf, sizeof(namebuf));
14799 			dns_zone_log(zone, ISC_LOG_ERROR,
14800 				     "unable to find key: %s", namebuf);
14801 		}
14802 	}
14803 	if (key == NULL) {
14804 		(void)dns_view_getpeertsig(zone->view, &masterip, &key);
14805 	}
14806 
14807 	reqnsid = zone->view->requestnsid;
14808 	if (zone->view->peers != NULL) {
14809 		dns_peer_t *peer = NULL;
14810 		bool edns;
14811 		result = dns_peerlist_peerbyaddr(zone->view->peers, &masterip,
14812 						 &peer);
14813 		if (result == ISC_R_SUCCESS) {
14814 			result = dns_peer_getsupportedns(peer, &edns);
14815 			if (result == ISC_R_SUCCESS && !edns) {
14816 				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
14817 			}
14818 			result = dns_peer_gettransfersource(peer,
14819 							    &zone->sourceaddr);
14820 			if (result == ISC_R_SUCCESS) {
14821 				have_xfrsource = true;
14822 			}
14823 			result = dns_peer_gettransferdscp(peer, &dscp);
14824 			if (result == ISC_R_SUCCESS && dscp != -1) {
14825 				have_xfrdscp = true;
14826 			}
14827 			if (zone->view->resolver != NULL) {
14828 				udpsize = dns_resolver_getudpsize(
14829 					zone->view->resolver);
14830 			}
14831 			(void)dns_peer_getudpsize(peer, &udpsize);
14832 			(void)dns_peer_getrequestnsid(peer, &reqnsid);
14833 		}
14834 	}
14835 	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
14836 		result = add_opt(message, udpsize, reqnsid, false);
14837 		if (result != ISC_R_SUCCESS) {
14838 			zone_debuglog(zone, me, 1,
14839 				      "unable to add opt record: %s",
14840 				      dns_result_totext(result));
14841 		}
14842 	}
14843 
14844 	/*
14845 	 * Always use TCP so that we shouldn't truncate in additional section.
14846 	 */
14847 	switch (isc_sockaddr_pf(&zone->masteraddr)) {
14848 	case PF_INET:
14849 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
14850 			zone->sourceaddr = zone->altxfrsource4;
14851 			if (!have_xfrdscp) {
14852 				dscp = zone->altxfrsource4dscp;
14853 			}
14854 		} else if (!have_xfrsource) {
14855 			zone->sourceaddr = zone->xfrsource4;
14856 			if (!have_xfrdscp) {
14857 				dscp = zone->xfrsource4dscp;
14858 			}
14859 		}
14860 		break;
14861 	case PF_INET6:
14862 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
14863 			zone->sourceaddr = zone->altxfrsource6;
14864 			if (!have_xfrdscp) {
14865 				dscp = zone->altxfrsource6dscp;
14866 			}
14867 		} else if (!have_xfrsource) {
14868 			zone->sourceaddr = zone->xfrsource6;
14869 			if (!have_xfrdscp) {
14870 				dscp = zone->xfrsource6dscp;
14871 			}
14872 		}
14873 		break;
14874 	default:
14875 		result = ISC_R_NOTIMPLEMENTED;
14876 		POST(result);
14877 		goto cleanup;
14878 	}
14879 	timeout = 15;
14880 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH)) {
14881 		timeout = 30;
14882 	}
14883 
14884 	/*
14885 	 * Save request parameters so we can reuse them later on
14886 	 * for resolving missing glue A/AAAA records.
14887 	 */
14888 	cb_args = isc_mem_get(zone->mctx, sizeof(*cb_args));
14889 	cb_args->stub = stub;
14890 	cb_args->tsig_key = key;
14891 	cb_args->dscp = dscp;
14892 	cb_args->udpsize = udpsize;
14893 	cb_args->timeout = timeout;
14894 	cb_args->reqnsid = reqnsid;
14895 
14896 	result = dns_request_createvia(
14897 		zone->view->requestmgr, message, &zone->sourceaddr,
14898 		&zone->masteraddr, dscp, DNS_REQUESTOPT_TCP, key, timeout * 3,
14899 		timeout, 0, zone->task, stub_callback, cb_args, &zone->request);
14900 	if (result != ISC_R_SUCCESS) {
14901 		zone_debuglog(zone, me, 1, "dns_request_createvia() failed: %s",
14902 			      dns_result_totext(result));
14903 		goto cleanup;
14904 	}
14905 	dns_message_detach(&message);
14906 	goto unlock;
14907 
14908 cleanup:
14909 	cancel_refresh(zone);
14910 	stub->magic = 0;
14911 	if (stub->version != NULL) {
14912 		dns_db_closeversion(stub->db, &stub->version, false);
14913 	}
14914 	if (stub->db != NULL) {
14915 		dns_db_detach(&stub->db);
14916 	}
14917 	if (stub->zone != NULL) {
14918 		zone_idetach(&stub->zone);
14919 	}
14920 	isc_mem_put(stub->mctx, stub, sizeof(*stub));
14921 	if (message != NULL) {
14922 		dns_message_detach(&message);
14923 	}
14924 unlock:
14925 	if (key != NULL) {
14926 		dns_tsigkey_detach(&key);
14927 	}
14928 	return;
14929 }
14930 
14931 /*
14932  * Shut the zone down.
14933  */
14934 static void
zone_shutdown(isc_task_t * task,isc_event_t * event)14935 zone_shutdown(isc_task_t *task, isc_event_t *event) {
14936 	dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
14937 	bool free_needed, linked = false;
14938 	dns_zone_t *raw = NULL, *secure = NULL;
14939 	dns_view_t *view = NULL, *prev_view = NULL;
14940 
14941 	UNUSED(task);
14942 	REQUIRE(DNS_ZONE_VALID(zone));
14943 	INSIST(event->ev_type == DNS_EVENT_ZONECONTROL);
14944 	INSIST(isc_refcount_current(&zone->erefs) == 0);
14945 
14946 	zone_debuglog(zone, "zone_shutdown", 3, "shutting down");
14947 
14948 	/*
14949 	 * If we were waiting for xfrin quota, step out of
14950 	 * the queue.
14951 	 * If there's no zone manager, we can't be waiting for the
14952 	 * xfrin quota
14953 	 */
14954 	if (zone->zmgr != NULL) {
14955 		RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
14956 		if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
14957 			ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone,
14958 					statelink);
14959 			linked = true;
14960 			zone->statelist = NULL;
14961 		}
14962 		if (zone->statelist == &zone->zmgr->xfrin_in_progress) {
14963 			ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone,
14964 					statelink);
14965 			zone->statelist = NULL;
14966 			zmgr_resume_xfrs(zone->zmgr, false);
14967 		}
14968 		RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
14969 	}
14970 
14971 	/*
14972 	 * In task context, no locking required.  See zone_xfrdone().
14973 	 */
14974 	if (zone->xfr != NULL) {
14975 		dns_xfrin_shutdown(zone->xfr);
14976 	}
14977 
14978 	/* Safe to release the zone now */
14979 	if (zone->zmgr != NULL) {
14980 		dns_zonemgr_releasezone(zone->zmgr, zone);
14981 	}
14982 
14983 	LOCK_ZONE(zone);
14984 	INSIST(zone != zone->raw);
14985 
14986 	/*
14987 	 * Detach the views early, we don't need them anymore.  However, we need
14988 	 * to detach them outside of the zone lock to break the lock loop
14989 	 * between view, adb and zone locks.
14990 	 */
14991 	view = zone->view;
14992 	zone->view = NULL;
14993 	prev_view = zone->prev_view;
14994 	zone->prev_view = NULL;
14995 
14996 	if (linked) {
14997 		isc_refcount_decrement(&zone->irefs);
14998 	}
14999 	if (zone->request != NULL) {
15000 		dns_request_cancel(zone->request);
15001 	}
15002 
15003 	if (zone->readio != NULL) {
15004 		zonemgr_cancelio(zone->readio);
15005 	}
15006 
15007 	if (zone->lctx != NULL) {
15008 		dns_loadctx_cancel(zone->lctx);
15009 	}
15010 
15011 	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
15012 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
15013 	{
15014 		if (zone->writeio != NULL) {
15015 			zonemgr_cancelio(zone->writeio);
15016 		}
15017 
15018 		if (zone->dctx != NULL) {
15019 			dns_dumpctx_cancel(zone->dctx);
15020 		}
15021 	}
15022 
15023 	checkds_cancel(zone);
15024 
15025 	notify_cancel(zone);
15026 
15027 	forward_cancel(zone);
15028 
15029 	if (zone->timer != NULL) {
15030 		isc_timer_destroy(&zone->timer);
15031 		isc_refcount_decrement(&zone->irefs);
15032 	}
15033 
15034 	/*
15035 	 * We have now canceled everything set the flag to allow exit_check()
15036 	 * to succeed.	We must not unlock between setting this flag and
15037 	 * calling exit_check().
15038 	 */
15039 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN);
15040 	free_needed = exit_check(zone);
15041 	/*
15042 	 * If a dump is in progress for the secure zone, defer detaching from
15043 	 * the raw zone as it may prevent the unsigned serial number from being
15044 	 * stored in the raw-format dump of the secure zone.  In this scenario,
15045 	 * dump_done() takes care of cleaning up the zone->raw reference.
15046 	 */
15047 	if (inline_secure(zone) && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
15048 		raw = zone->raw;
15049 		zone->raw = NULL;
15050 	}
15051 	if (inline_raw(zone)) {
15052 		secure = zone->secure;
15053 		zone->secure = NULL;
15054 	}
15055 	UNLOCK_ZONE(zone);
15056 
15057 	if (view != NULL) {
15058 		dns_view_weakdetach(&view);
15059 	}
15060 	if (prev_view != NULL) {
15061 		dns_view_weakdetach(&prev_view);
15062 	}
15063 
15064 	if (raw != NULL) {
15065 		dns_zone_detach(&raw);
15066 	}
15067 	if (secure != NULL) {
15068 		dns_zone_idetach(&secure);
15069 	}
15070 	if (free_needed) {
15071 		zone_free(zone);
15072 	}
15073 }
15074 
15075 static void
zone_timer(isc_task_t * task,isc_event_t * event)15076 zone_timer(isc_task_t *task, isc_event_t *event) {
15077 	const char me[] = "zone_timer";
15078 	dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
15079 
15080 	UNUSED(task);
15081 	REQUIRE(DNS_ZONE_VALID(zone));
15082 
15083 	ENTER;
15084 
15085 	zone_maintenance(zone);
15086 
15087 	isc_event_free(&event);
15088 }
15089 
15090 static void
zone_settimer(dns_zone_t * zone,isc_time_t * now)15091 zone_settimer(dns_zone_t *zone, isc_time_t *now) {
15092 	const char me[] = "zone_settimer";
15093 	isc_time_t next;
15094 	isc_result_t result;
15095 
15096 	REQUIRE(DNS_ZONE_VALID(zone));
15097 	REQUIRE(LOCKED_ZONE(zone));
15098 	ENTER;
15099 
15100 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
15101 		return;
15102 	}
15103 
15104 	isc_time_settoepoch(&next);
15105 
15106 	switch (zone->type) {
15107 	case dns_zone_redirect:
15108 		if (zone->masters != NULL) {
15109 			goto treat_as_slave;
15110 		}
15111 		FALLTHROUGH;
15112 	case dns_zone_primary:
15113 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
15114 		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))
15115 		{
15116 			next = zone->notifytime;
15117 		}
15118 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
15119 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
15120 		{
15121 			INSIST(!isc_time_isepoch(&zone->dumptime));
15122 			if (isc_time_isepoch(&next) ||
15123 			    isc_time_compare(&zone->dumptime, &next) < 0)
15124 			{
15125 				next = zone->dumptime;
15126 			}
15127 		}
15128 		if (zone->type == dns_zone_redirect) {
15129 			break;
15130 		}
15131 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING) &&
15132 		    !isc_time_isepoch(&zone->refreshkeytime))
15133 		{
15134 			if (isc_time_isepoch(&next) ||
15135 			    isc_time_compare(&zone->refreshkeytime, &next) < 0)
15136 			{
15137 				next = zone->refreshkeytime;
15138 			}
15139 		}
15140 		if (!isc_time_isepoch(&zone->resigntime)) {
15141 			if (isc_time_isepoch(&next) ||
15142 			    isc_time_compare(&zone->resigntime, &next) < 0)
15143 			{
15144 				next = zone->resigntime;
15145 			}
15146 		}
15147 		if (!isc_time_isepoch(&zone->keywarntime)) {
15148 			if (isc_time_isepoch(&next) ||
15149 			    isc_time_compare(&zone->keywarntime, &next) < 0)
15150 			{
15151 				next = zone->keywarntime;
15152 			}
15153 		}
15154 		if (!isc_time_isepoch(&zone->signingtime)) {
15155 			if (isc_time_isepoch(&next) ||
15156 			    isc_time_compare(&zone->signingtime, &next) < 0)
15157 			{
15158 				next = zone->signingtime;
15159 			}
15160 		}
15161 		if (!isc_time_isepoch(&zone->nsec3chaintime)) {
15162 			if (isc_time_isepoch(&next) ||
15163 			    isc_time_compare(&zone->nsec3chaintime, &next) < 0)
15164 			{
15165 				next = zone->nsec3chaintime;
15166 			}
15167 		}
15168 		break;
15169 
15170 	case dns_zone_secondary:
15171 	case dns_zone_mirror:
15172 	treat_as_slave:
15173 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
15174 		    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))
15175 		{
15176 			next = zone->notifytime;
15177 		}
15178 		FALLTHROUGH;
15179 	case dns_zone_stub:
15180 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) &&
15181 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOMASTERS) &&
15182 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH) &&
15183 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING) &&
15184 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING) &&
15185 		    !isc_time_isepoch(&zone->refreshtime) &&
15186 		    (isc_time_isepoch(&next) ||
15187 		     isc_time_compare(&zone->refreshtime, &next) < 0))
15188 		{
15189 			next = zone->refreshtime;
15190 		}
15191 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
15192 		    !isc_time_isepoch(&zone->expiretime))
15193 		{
15194 			if (isc_time_isepoch(&next) ||
15195 			    isc_time_compare(&zone->expiretime, &next) < 0)
15196 			{
15197 				next = zone->expiretime;
15198 			}
15199 		}
15200 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
15201 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
15202 		{
15203 			INSIST(!isc_time_isepoch(&zone->dumptime));
15204 			if (isc_time_isepoch(&next) ||
15205 			    isc_time_compare(&zone->dumptime, &next) < 0)
15206 			{
15207 				next = zone->dumptime;
15208 			}
15209 		}
15210 		break;
15211 
15212 	case dns_zone_key:
15213 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
15214 		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
15215 		{
15216 			INSIST(!isc_time_isepoch(&zone->dumptime));
15217 			if (isc_time_isepoch(&next) ||
15218 			    isc_time_compare(&zone->dumptime, &next) < 0)
15219 			{
15220 				next = zone->dumptime;
15221 			}
15222 		}
15223 		if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
15224 			if (isc_time_isepoch(&next) ||
15225 			    (!isc_time_isepoch(&zone->refreshkeytime) &&
15226 			     isc_time_compare(&zone->refreshkeytime, &next) <
15227 				     0))
15228 			{
15229 				next = zone->refreshkeytime;
15230 			}
15231 		}
15232 		break;
15233 
15234 	default:
15235 		break;
15236 	}
15237 
15238 	if (isc_time_isepoch(&next)) {
15239 		zone_debuglog(zone, me, 10, "settimer inactive");
15240 		result = isc_timer_reset(zone->timer, isc_timertype_inactive,
15241 					 NULL, NULL, true);
15242 		if (result != ISC_R_SUCCESS) {
15243 			dns_zone_log(zone, ISC_LOG_ERROR,
15244 				     "could not deactivate zone timer: %s",
15245 				     isc_result_totext(result));
15246 		}
15247 	} else {
15248 		if (isc_time_compare(&next, now) <= 0) {
15249 			next = *now;
15250 		}
15251 		result = isc_timer_reset(zone->timer, isc_timertype_once, &next,
15252 					 NULL, true);
15253 		if (result != ISC_R_SUCCESS) {
15254 			dns_zone_log(zone, ISC_LOG_ERROR,
15255 				     "could not reset zone timer: %s",
15256 				     isc_result_totext(result));
15257 		}
15258 	}
15259 }
15260 
15261 static void
cancel_refresh(dns_zone_t * zone)15262 cancel_refresh(dns_zone_t *zone) {
15263 	const char me[] = "cancel_refresh";
15264 	isc_time_t now;
15265 
15266 	/*
15267 	 * 'zone' locked by caller.
15268 	 */
15269 
15270 	REQUIRE(DNS_ZONE_VALID(zone));
15271 	REQUIRE(LOCKED_ZONE(zone));
15272 
15273 	ENTER;
15274 
15275 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
15276 	TIME_NOW(&now);
15277 	zone_settimer(zone, &now);
15278 }
15279 
15280 static isc_result_t
notify_createmessage(dns_zone_t * zone,unsigned int flags,dns_message_t ** messagep)15281 notify_createmessage(dns_zone_t *zone, unsigned int flags,
15282 		     dns_message_t **messagep) {
15283 	dns_db_t *zonedb = NULL;
15284 	dns_dbnode_t *node = NULL;
15285 	dns_dbversion_t *version = NULL;
15286 	dns_message_t *message = NULL;
15287 	dns_rdataset_t rdataset;
15288 	dns_rdata_t rdata = DNS_RDATA_INIT;
15289 
15290 	dns_name_t *tempname = NULL;
15291 	dns_rdata_t *temprdata = NULL;
15292 	dns_rdatalist_t *temprdatalist = NULL;
15293 	dns_rdataset_t *temprdataset = NULL;
15294 
15295 	isc_result_t result;
15296 	isc_region_t r;
15297 	isc_buffer_t *b = NULL;
15298 
15299 	REQUIRE(DNS_ZONE_VALID(zone));
15300 	REQUIRE(messagep != NULL && *messagep == NULL);
15301 
15302 	dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER, &message);
15303 
15304 	message->opcode = dns_opcode_notify;
15305 	message->flags |= DNS_MESSAGEFLAG_AA;
15306 	message->rdclass = zone->rdclass;
15307 
15308 	result = dns_message_gettempname(message, &tempname);
15309 	if (result != ISC_R_SUCCESS) {
15310 		goto cleanup;
15311 	}
15312 
15313 	result = dns_message_gettemprdataset(message, &temprdataset);
15314 	if (result != ISC_R_SUCCESS) {
15315 		goto cleanup;
15316 	}
15317 
15318 	/*
15319 	 * Make question.
15320 	 */
15321 	dns_name_clone(&zone->origin, tempname);
15322 	dns_rdataset_makequestion(temprdataset, zone->rdclass,
15323 				  dns_rdatatype_soa);
15324 	ISC_LIST_APPEND(tempname->list, temprdataset, link);
15325 	dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
15326 	tempname = NULL;
15327 	temprdataset = NULL;
15328 
15329 	if ((flags & DNS_NOTIFY_NOSOA) != 0) {
15330 		goto done;
15331 	}
15332 
15333 	result = dns_message_gettempname(message, &tempname);
15334 	if (result != ISC_R_SUCCESS) {
15335 		goto soa_cleanup;
15336 	}
15337 	result = dns_message_gettemprdata(message, &temprdata);
15338 	if (result != ISC_R_SUCCESS) {
15339 		goto soa_cleanup;
15340 	}
15341 	result = dns_message_gettemprdataset(message, &temprdataset);
15342 	if (result != ISC_R_SUCCESS) {
15343 		goto soa_cleanup;
15344 	}
15345 	result = dns_message_gettemprdatalist(message, &temprdatalist);
15346 	if (result != ISC_R_SUCCESS) {
15347 		goto soa_cleanup;
15348 	}
15349 
15350 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
15351 	INSIST(zone->db != NULL); /* XXXJT: is this assumption correct? */
15352 	dns_db_attach(zone->db, &zonedb);
15353 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
15354 
15355 	dns_name_clone(&zone->origin, tempname);
15356 	dns_db_currentversion(zonedb, &version);
15357 	result = dns_db_findnode(zonedb, tempname, false, &node);
15358 	if (result != ISC_R_SUCCESS) {
15359 		goto soa_cleanup;
15360 	}
15361 
15362 	dns_rdataset_init(&rdataset);
15363 	result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
15364 				     dns_rdatatype_none, 0, &rdataset, NULL);
15365 	if (result != ISC_R_SUCCESS) {
15366 		goto soa_cleanup;
15367 	}
15368 	result = dns_rdataset_first(&rdataset);
15369 	if (result != ISC_R_SUCCESS) {
15370 		goto soa_cleanup;
15371 	}
15372 	dns_rdataset_current(&rdataset, &rdata);
15373 	dns_rdata_toregion(&rdata, &r);
15374 	isc_buffer_allocate(zone->mctx, &b, r.length);
15375 	isc_buffer_putmem(b, r.base, r.length);
15376 	isc_buffer_usedregion(b, &r);
15377 	dns_rdata_init(temprdata);
15378 	dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r);
15379 	dns_message_takebuffer(message, &b);
15380 	result = dns_rdataset_next(&rdataset);
15381 	dns_rdataset_disassociate(&rdataset);
15382 	if (result != ISC_R_NOMORE) {
15383 		goto soa_cleanup;
15384 	}
15385 	temprdatalist->rdclass = rdata.rdclass;
15386 	temprdatalist->type = rdata.type;
15387 	temprdatalist->ttl = rdataset.ttl;
15388 	ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link);
15389 
15390 	result = dns_rdatalist_tordataset(temprdatalist, temprdataset);
15391 	if (result != ISC_R_SUCCESS) {
15392 		goto soa_cleanup;
15393 	}
15394 
15395 	ISC_LIST_APPEND(tempname->list, temprdataset, link);
15396 	dns_message_addname(message, tempname, DNS_SECTION_ANSWER);
15397 	temprdatalist = NULL;
15398 	temprdataset = NULL;
15399 	temprdata = NULL;
15400 	tempname = NULL;
15401 
15402 soa_cleanup:
15403 	if (node != NULL) {
15404 		dns_db_detachnode(zonedb, &node);
15405 	}
15406 	if (version != NULL) {
15407 		dns_db_closeversion(zonedb, &version, false);
15408 	}
15409 	if (zonedb != NULL) {
15410 		dns_db_detach(&zonedb);
15411 	}
15412 	if (tempname != NULL) {
15413 		dns_message_puttempname(message, &tempname);
15414 	}
15415 	if (temprdata != NULL) {
15416 		dns_message_puttemprdata(message, &temprdata);
15417 	}
15418 	if (temprdataset != NULL) {
15419 		dns_message_puttemprdataset(message, &temprdataset);
15420 	}
15421 	if (temprdatalist != NULL) {
15422 		dns_message_puttemprdatalist(message, &temprdatalist);
15423 	}
15424 
15425 done:
15426 	*messagep = message;
15427 	return (ISC_R_SUCCESS);
15428 
15429 cleanup:
15430 	if (tempname != NULL) {
15431 		dns_message_puttempname(message, &tempname);
15432 	}
15433 	if (temprdataset != NULL) {
15434 		dns_message_puttemprdataset(message, &temprdataset);
15435 	}
15436 	dns_message_detach(&message);
15437 	return (result);
15438 }
15439 
15440 isc_result_t
dns_zone_notifyreceive(dns_zone_t * zone,isc_sockaddr_t * from,isc_sockaddr_t * to,dns_message_t * msg)15441 dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
15442 		       isc_sockaddr_t *to, dns_message_t *msg) {
15443 	unsigned int i;
15444 	dns_rdata_soa_t soa;
15445 	dns_rdataset_t *rdataset = NULL;
15446 	dns_rdata_t rdata = DNS_RDATA_INIT;
15447 	isc_result_t result;
15448 	char fromtext[ISC_SOCKADDR_FORMATSIZE];
15449 	int match = 0;
15450 	isc_netaddr_t netaddr;
15451 	uint32_t serial = 0;
15452 	bool have_serial = false;
15453 	dns_tsigkey_t *tsigkey;
15454 	const dns_name_t *tsig;
15455 
15456 	REQUIRE(DNS_ZONE_VALID(zone));
15457 
15458 	/*
15459 	 * If type != T_SOA return DNS_R_NOTIMP.  We don't yet support
15460 	 * ROLLOVER.
15461 	 *
15462 	 * SOA:	RFC1996
15463 	 * Check that 'from' is a valid notify source, (zone->masters).
15464 	 *	Return DNS_R_REFUSED if not.
15465 	 *
15466 	 * If the notify message contains a serial number check it
15467 	 * against the zones serial and return if <= current serial
15468 	 *
15469 	 * If a refresh check is progress, if so just record the
15470 	 * fact we received a NOTIFY and from where and return.
15471 	 * We will perform a new refresh check when the current one
15472 	 * completes. Return ISC_R_SUCCESS.
15473 	 *
15474 	 * Otherwise initiate a refresh check using 'from' as the
15475 	 * first address to check.  Return ISC_R_SUCCESS.
15476 	 */
15477 
15478 	isc_sockaddr_format(from, fromtext, sizeof(fromtext));
15479 
15480 	/*
15481 	 * Notify messages are processed by the raw zone.
15482 	 */
15483 	LOCK_ZONE(zone);
15484 	INSIST(zone != zone->raw);
15485 	if (inline_secure(zone)) {
15486 		result = dns_zone_notifyreceive(zone->raw, from, to, msg);
15487 		UNLOCK_ZONE(zone);
15488 		return (result);
15489 	}
15490 	/*
15491 	 *  We only handle NOTIFY (SOA) at the present.
15492 	 */
15493 	if (isc_sockaddr_pf(from) == PF_INET) {
15494 		inc_stats(zone, dns_zonestatscounter_notifyinv4);
15495 	} else {
15496 		inc_stats(zone, dns_zonestatscounter_notifyinv6);
15497 	}
15498 	if (msg->counts[DNS_SECTION_QUESTION] == 0 ||
15499 	    dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin,
15500 				 dns_rdatatype_soa, dns_rdatatype_none, NULL,
15501 				 NULL) != ISC_R_SUCCESS)
15502 	{
15503 		UNLOCK_ZONE(zone);
15504 		if (msg->counts[DNS_SECTION_QUESTION] == 0) {
15505 			dns_zone_log(zone, ISC_LOG_NOTICE,
15506 				     "NOTIFY with no "
15507 				     "question section from: %s",
15508 				     fromtext);
15509 			return (DNS_R_FORMERR);
15510 		}
15511 		dns_zone_log(zone, ISC_LOG_NOTICE,
15512 			     "NOTIFY zone does not match");
15513 		return (DNS_R_NOTIMP);
15514 	}
15515 
15516 	/*
15517 	 * If we are a master zone just succeed.
15518 	 */
15519 	if (zone->type == dns_zone_primary) {
15520 		UNLOCK_ZONE(zone);
15521 		return (ISC_R_SUCCESS);
15522 	}
15523 
15524 	isc_netaddr_fromsockaddr(&netaddr, from);
15525 	for (i = 0; i < zone->masterscnt; i++) {
15526 		if (isc_sockaddr_eqaddr(from, &zone->masters[i])) {
15527 			break;
15528 		}
15529 		if (zone->view->aclenv.match_mapped &&
15530 		    IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) &&
15531 		    isc_sockaddr_pf(&zone->masters[i]) == AF_INET)
15532 		{
15533 			isc_netaddr_t na1, na2;
15534 			isc_netaddr_fromv4mapped(&na1, &netaddr);
15535 			isc_netaddr_fromsockaddr(&na2, &zone->masters[i]);
15536 			if (isc_netaddr_equal(&na1, &na2)) {
15537 				break;
15538 			}
15539 		}
15540 	}
15541 
15542 	/*
15543 	 * Accept notify requests from non masters if they are on
15544 	 * 'zone->notify_acl'.
15545 	 */
15546 	tsigkey = dns_message_gettsigkey(msg);
15547 	tsig = dns_tsigkey_identity(tsigkey);
15548 	if (i >= zone->masterscnt && zone->notify_acl != NULL &&
15549 	    (dns_acl_match(&netaddr, tsig, zone->notify_acl,
15550 			   &zone->view->aclenv, &match,
15551 			   NULL) == ISC_R_SUCCESS) &&
15552 	    match > 0)
15553 	{
15554 		/* Accept notify. */
15555 	} else if (i >= zone->masterscnt) {
15556 		UNLOCK_ZONE(zone);
15557 		dns_zone_log(zone, ISC_LOG_INFO,
15558 			     "refused notify from non-master: %s", fromtext);
15559 		inc_stats(zone, dns_zonestatscounter_notifyrej);
15560 		return (DNS_R_REFUSED);
15561 	}
15562 
15563 	/*
15564 	 * If the zone is loaded and there are answers check the serial
15565 	 * to see if we need to do a refresh.  Do not worry about this
15566 	 * check if we are a dialup zone as we use the notify request
15567 	 * to trigger a refresh check.
15568 	 */
15569 	if (msg->counts[DNS_SECTION_ANSWER] > 0 &&
15570 	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
15571 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH))
15572 	{
15573 		result = dns_message_findname(
15574 			msg, DNS_SECTION_ANSWER, &zone->origin,
15575 			dns_rdatatype_soa, dns_rdatatype_none, NULL, &rdataset);
15576 		if (result == ISC_R_SUCCESS) {
15577 			result = dns_rdataset_first(rdataset);
15578 		}
15579 		if (result == ISC_R_SUCCESS) {
15580 			uint32_t oldserial;
15581 			unsigned int soacount;
15582 
15583 			dns_rdataset_current(rdataset, &rdata);
15584 			result = dns_rdata_tostruct(&rdata, &soa, NULL);
15585 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
15586 			serial = soa.serial;
15587 			have_serial = true;
15588 			/*
15589 			 * The following should safely be performed without DB
15590 			 * lock and succeed in this context.
15591 			 */
15592 			result = zone_get_from_db(zone, zone->db, NULL,
15593 						  &soacount, NULL, &oldserial,
15594 						  NULL, NULL, NULL, NULL, NULL);
15595 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
15596 			RUNTIME_CHECK(soacount > 0U);
15597 			if (isc_serial_le(serial, oldserial)) {
15598 				dns_zone_log(zone, ISC_LOG_INFO,
15599 					     "notify from %s: "
15600 					     "zone is up to date",
15601 					     fromtext);
15602 				UNLOCK_ZONE(zone);
15603 				return (ISC_R_SUCCESS);
15604 			}
15605 		}
15606 	}
15607 
15608 	/*
15609 	 * If we got this far and there was a refresh in progress just
15610 	 * let it complete.  Record where we got the notify from so we
15611 	 * can perform a refresh check when the current one completes
15612 	 */
15613 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
15614 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
15615 		zone->notifyfrom = *from;
15616 		UNLOCK_ZONE(zone);
15617 		if (have_serial) {
15618 			dns_zone_log(zone, ISC_LOG_INFO,
15619 				     "notify from %s: serial %u: refresh in "
15620 				     "progress, refresh check queued",
15621 				     fromtext, serial);
15622 		} else {
15623 			dns_zone_log(zone, ISC_LOG_INFO,
15624 				     "notify from %s: refresh in progress, "
15625 				     "refresh check queued",
15626 				     fromtext);
15627 		}
15628 		return (ISC_R_SUCCESS);
15629 	}
15630 	if (have_serial) {
15631 		dns_zone_log(zone, ISC_LOG_INFO, "notify from %s: serial %u",
15632 			     fromtext, serial);
15633 	} else {
15634 		dns_zone_log(zone, ISC_LOG_INFO, "notify from %s: no serial",
15635 			     fromtext);
15636 	}
15637 	zone->notifyfrom = *from;
15638 	UNLOCK_ZONE(zone);
15639 
15640 	if (to != NULL) {
15641 		dns_zonemgr_unreachabledel(zone->zmgr, from, to);
15642 	}
15643 	dns_zone_refresh(zone);
15644 	return (ISC_R_SUCCESS);
15645 }
15646 
15647 void
dns_zone_setnotifyacl(dns_zone_t * zone,dns_acl_t * acl)15648 dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
15649 	REQUIRE(DNS_ZONE_VALID(zone));
15650 
15651 	LOCK_ZONE(zone);
15652 	if (zone->notify_acl != NULL) {
15653 		dns_acl_detach(&zone->notify_acl);
15654 	}
15655 	dns_acl_attach(acl, &zone->notify_acl);
15656 	UNLOCK_ZONE(zone);
15657 }
15658 
15659 void
dns_zone_setqueryacl(dns_zone_t * zone,dns_acl_t * acl)15660 dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
15661 	REQUIRE(DNS_ZONE_VALID(zone));
15662 
15663 	LOCK_ZONE(zone);
15664 	if (zone->query_acl != NULL) {
15665 		dns_acl_detach(&zone->query_acl);
15666 	}
15667 	dns_acl_attach(acl, &zone->query_acl);
15668 	UNLOCK_ZONE(zone);
15669 }
15670 
15671 void
dns_zone_setqueryonacl(dns_zone_t * zone,dns_acl_t * acl)15672 dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl) {
15673 	REQUIRE(DNS_ZONE_VALID(zone));
15674 
15675 	LOCK_ZONE(zone);
15676 	if (zone->queryon_acl != NULL) {
15677 		dns_acl_detach(&zone->queryon_acl);
15678 	}
15679 	dns_acl_attach(acl, &zone->queryon_acl);
15680 	UNLOCK_ZONE(zone);
15681 }
15682 
15683 void
dns_zone_setupdateacl(dns_zone_t * zone,dns_acl_t * acl)15684 dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
15685 	REQUIRE(DNS_ZONE_VALID(zone));
15686 
15687 	LOCK_ZONE(zone);
15688 	if (zone->update_acl != NULL) {
15689 		dns_acl_detach(&zone->update_acl);
15690 	}
15691 	dns_acl_attach(acl, &zone->update_acl);
15692 	UNLOCK_ZONE(zone);
15693 }
15694 
15695 void
dns_zone_setforwardacl(dns_zone_t * zone,dns_acl_t * acl)15696 dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
15697 	REQUIRE(DNS_ZONE_VALID(zone));
15698 
15699 	LOCK_ZONE(zone);
15700 	if (zone->forward_acl != NULL) {
15701 		dns_acl_detach(&zone->forward_acl);
15702 	}
15703 	dns_acl_attach(acl, &zone->forward_acl);
15704 	UNLOCK_ZONE(zone);
15705 }
15706 
15707 void
dns_zone_setxfracl(dns_zone_t * zone,dns_acl_t * acl)15708 dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
15709 	REQUIRE(DNS_ZONE_VALID(zone));
15710 
15711 	LOCK_ZONE(zone);
15712 	if (zone->xfr_acl != NULL) {
15713 		dns_acl_detach(&zone->xfr_acl);
15714 	}
15715 	dns_acl_attach(acl, &zone->xfr_acl);
15716 	UNLOCK_ZONE(zone);
15717 }
15718 
15719 dns_acl_t *
dns_zone_getnotifyacl(dns_zone_t * zone)15720 dns_zone_getnotifyacl(dns_zone_t *zone) {
15721 	REQUIRE(DNS_ZONE_VALID(zone));
15722 
15723 	return (zone->notify_acl);
15724 }
15725 
15726 dns_acl_t *
dns_zone_getqueryacl(dns_zone_t * zone)15727 dns_zone_getqueryacl(dns_zone_t *zone) {
15728 	REQUIRE(DNS_ZONE_VALID(zone));
15729 
15730 	return (zone->query_acl);
15731 }
15732 
15733 dns_acl_t *
dns_zone_getqueryonacl(dns_zone_t * zone)15734 dns_zone_getqueryonacl(dns_zone_t *zone) {
15735 	REQUIRE(DNS_ZONE_VALID(zone));
15736 
15737 	return (zone->queryon_acl);
15738 }
15739 
15740 dns_acl_t *
dns_zone_getupdateacl(dns_zone_t * zone)15741 dns_zone_getupdateacl(dns_zone_t *zone) {
15742 	REQUIRE(DNS_ZONE_VALID(zone));
15743 
15744 	return (zone->update_acl);
15745 }
15746 
15747 dns_acl_t *
dns_zone_getforwardacl(dns_zone_t * zone)15748 dns_zone_getforwardacl(dns_zone_t *zone) {
15749 	REQUIRE(DNS_ZONE_VALID(zone));
15750 
15751 	return (zone->forward_acl);
15752 }
15753 
15754 dns_acl_t *
dns_zone_getxfracl(dns_zone_t * zone)15755 dns_zone_getxfracl(dns_zone_t *zone) {
15756 	REQUIRE(DNS_ZONE_VALID(zone));
15757 
15758 	return (zone->xfr_acl);
15759 }
15760 
15761 void
dns_zone_clearupdateacl(dns_zone_t * zone)15762 dns_zone_clearupdateacl(dns_zone_t *zone) {
15763 	REQUIRE(DNS_ZONE_VALID(zone));
15764 
15765 	LOCK_ZONE(zone);
15766 	if (zone->update_acl != NULL) {
15767 		dns_acl_detach(&zone->update_acl);
15768 	}
15769 	UNLOCK_ZONE(zone);
15770 }
15771 
15772 void
dns_zone_clearforwardacl(dns_zone_t * zone)15773 dns_zone_clearforwardacl(dns_zone_t *zone) {
15774 	REQUIRE(DNS_ZONE_VALID(zone));
15775 
15776 	LOCK_ZONE(zone);
15777 	if (zone->forward_acl != NULL) {
15778 		dns_acl_detach(&zone->forward_acl);
15779 	}
15780 	UNLOCK_ZONE(zone);
15781 }
15782 
15783 void
dns_zone_clearnotifyacl(dns_zone_t * zone)15784 dns_zone_clearnotifyacl(dns_zone_t *zone) {
15785 	REQUIRE(DNS_ZONE_VALID(zone));
15786 
15787 	LOCK_ZONE(zone);
15788 	if (zone->notify_acl != NULL) {
15789 		dns_acl_detach(&zone->notify_acl);
15790 	}
15791 	UNLOCK_ZONE(zone);
15792 }
15793 
15794 void
dns_zone_clearqueryacl(dns_zone_t * zone)15795 dns_zone_clearqueryacl(dns_zone_t *zone) {
15796 	REQUIRE(DNS_ZONE_VALID(zone));
15797 
15798 	LOCK_ZONE(zone);
15799 	if (zone->query_acl != NULL) {
15800 		dns_acl_detach(&zone->query_acl);
15801 	}
15802 	UNLOCK_ZONE(zone);
15803 }
15804 
15805 void
dns_zone_clearqueryonacl(dns_zone_t * zone)15806 dns_zone_clearqueryonacl(dns_zone_t *zone) {
15807 	REQUIRE(DNS_ZONE_VALID(zone));
15808 
15809 	LOCK_ZONE(zone);
15810 	if (zone->queryon_acl != NULL) {
15811 		dns_acl_detach(&zone->queryon_acl);
15812 	}
15813 	UNLOCK_ZONE(zone);
15814 }
15815 
15816 void
dns_zone_clearxfracl(dns_zone_t * zone)15817 dns_zone_clearxfracl(dns_zone_t *zone) {
15818 	REQUIRE(DNS_ZONE_VALID(zone));
15819 
15820 	LOCK_ZONE(zone);
15821 	if (zone->xfr_acl != NULL) {
15822 		dns_acl_detach(&zone->xfr_acl);
15823 	}
15824 	UNLOCK_ZONE(zone);
15825 }
15826 
15827 bool
dns_zone_getupdatedisabled(dns_zone_t * zone)15828 dns_zone_getupdatedisabled(dns_zone_t *zone) {
15829 	REQUIRE(DNS_ZONE_VALID(zone));
15830 	return (zone->update_disabled);
15831 }
15832 
15833 void
dns_zone_setupdatedisabled(dns_zone_t * zone,bool state)15834 dns_zone_setupdatedisabled(dns_zone_t *zone, bool state) {
15835 	REQUIRE(DNS_ZONE_VALID(zone));
15836 	zone->update_disabled = state;
15837 }
15838 
15839 bool
dns_zone_getzeronosoattl(dns_zone_t * zone)15840 dns_zone_getzeronosoattl(dns_zone_t *zone) {
15841 	REQUIRE(DNS_ZONE_VALID(zone));
15842 	return (zone->zero_no_soa_ttl);
15843 }
15844 
15845 void
dns_zone_setzeronosoattl(dns_zone_t * zone,bool state)15846 dns_zone_setzeronosoattl(dns_zone_t *zone, bool state) {
15847 	REQUIRE(DNS_ZONE_VALID(zone));
15848 	zone->zero_no_soa_ttl = state;
15849 }
15850 
15851 void
dns_zone_setchecknames(dns_zone_t * zone,dns_severity_t severity)15852 dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
15853 	REQUIRE(DNS_ZONE_VALID(zone));
15854 
15855 	zone->check_names = severity;
15856 }
15857 
15858 dns_severity_t
dns_zone_getchecknames(dns_zone_t * zone)15859 dns_zone_getchecknames(dns_zone_t *zone) {
15860 	REQUIRE(DNS_ZONE_VALID(zone));
15861 
15862 	return (zone->check_names);
15863 }
15864 
15865 void
dns_zone_setjournalsize(dns_zone_t * zone,int32_t size)15866 dns_zone_setjournalsize(dns_zone_t *zone, int32_t size) {
15867 	REQUIRE(DNS_ZONE_VALID(zone));
15868 
15869 	zone->journalsize = size;
15870 }
15871 
15872 int32_t
dns_zone_getjournalsize(dns_zone_t * zone)15873 dns_zone_getjournalsize(dns_zone_t *zone) {
15874 	REQUIRE(DNS_ZONE_VALID(zone));
15875 
15876 	return (zone->journalsize);
15877 }
15878 
15879 static void
zone_namerd_tostr(dns_zone_t * zone,char * buf,size_t length)15880 zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) {
15881 	isc_result_t result = ISC_R_FAILURE;
15882 	isc_buffer_t buffer;
15883 
15884 	REQUIRE(buf != NULL);
15885 	REQUIRE(length > 1U);
15886 
15887 	/*
15888 	 * Leave space for terminating '\0'.
15889 	 */
15890 	isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
15891 	if (zone->type != dns_zone_redirect && zone->type != dns_zone_key) {
15892 		if (dns_name_dynamic(&zone->origin)) {
15893 			result = dns_name_totext(&zone->origin, true, &buffer);
15894 		}
15895 		if (result != ISC_R_SUCCESS &&
15896 		    isc_buffer_availablelength(&buffer) >=
15897 			    (sizeof("<UNKNOWN>") - 1))
15898 		{
15899 			isc_buffer_putstr(&buffer, "<UNKNOWN>");
15900 		}
15901 
15902 		if (isc_buffer_availablelength(&buffer) > 0) {
15903 			isc_buffer_putstr(&buffer, "/");
15904 		}
15905 		(void)dns_rdataclass_totext(zone->rdclass, &buffer);
15906 	}
15907 
15908 	if (zone->view != NULL && strcmp(zone->view->name, "_bind") != 0 &&
15909 	    strcmp(zone->view->name, "_default") != 0 &&
15910 	    strlen(zone->view->name) < isc_buffer_availablelength(&buffer))
15911 	{
15912 		isc_buffer_putstr(&buffer, "/");
15913 		isc_buffer_putstr(&buffer, zone->view->name);
15914 	}
15915 	if (inline_secure(zone) && 9U < isc_buffer_availablelength(&buffer)) {
15916 		isc_buffer_putstr(&buffer, " (signed)");
15917 	}
15918 	if (inline_raw(zone) && 11U < isc_buffer_availablelength(&buffer)) {
15919 		isc_buffer_putstr(&buffer, " (unsigned)");
15920 	}
15921 
15922 	buf[isc_buffer_usedlength(&buffer)] = '\0';
15923 }
15924 
15925 static void
zone_name_tostr(dns_zone_t * zone,char * buf,size_t length)15926 zone_name_tostr(dns_zone_t *zone, char *buf, size_t length) {
15927 	isc_result_t result = ISC_R_FAILURE;
15928 	isc_buffer_t buffer;
15929 
15930 	REQUIRE(buf != NULL);
15931 	REQUIRE(length > 1U);
15932 
15933 	/*
15934 	 * Leave space for terminating '\0'.
15935 	 */
15936 	isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
15937 	if (dns_name_dynamic(&zone->origin)) {
15938 		result = dns_name_totext(&zone->origin, true, &buffer);
15939 	}
15940 	if (result != ISC_R_SUCCESS &&
15941 	    isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
15942 	{
15943 		isc_buffer_putstr(&buffer, "<UNKNOWN>");
15944 	}
15945 
15946 	buf[isc_buffer_usedlength(&buffer)] = '\0';
15947 }
15948 
15949 static void
zone_rdclass_tostr(dns_zone_t * zone,char * buf,size_t length)15950 zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length) {
15951 	isc_buffer_t buffer;
15952 
15953 	REQUIRE(buf != NULL);
15954 	REQUIRE(length > 1U);
15955 
15956 	/*
15957 	 * Leave space for terminating '\0'.
15958 	 */
15959 	isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
15960 	(void)dns_rdataclass_totext(zone->rdclass, &buffer);
15961 
15962 	buf[isc_buffer_usedlength(&buffer)] = '\0';
15963 }
15964 
15965 static void
zone_viewname_tostr(dns_zone_t * zone,char * buf,size_t length)15966 zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length) {
15967 	isc_buffer_t buffer;
15968 
15969 	REQUIRE(buf != NULL);
15970 	REQUIRE(length > 1U);
15971 
15972 	/*
15973 	 * Leave space for terminating '\0'.
15974 	 */
15975 	isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
15976 
15977 	if (zone->view == NULL) {
15978 		isc_buffer_putstr(&buffer, "_none");
15979 	} else if (strlen(zone->view->name) <
15980 		   isc_buffer_availablelength(&buffer))
15981 	{
15982 		isc_buffer_putstr(&buffer, zone->view->name);
15983 	} else {
15984 		isc_buffer_putstr(&buffer, "_toolong");
15985 	}
15986 
15987 	buf[isc_buffer_usedlength(&buffer)] = '\0';
15988 }
15989 
15990 void
dns_zone_name(dns_zone_t * zone,char * buf,size_t length)15991 dns_zone_name(dns_zone_t *zone, char *buf, size_t length) {
15992 	REQUIRE(DNS_ZONE_VALID(zone));
15993 	REQUIRE(buf != NULL);
15994 
15995 	LOCK_ZONE(zone);
15996 	zone_namerd_tostr(zone, buf, length);
15997 	UNLOCK_ZONE(zone);
15998 }
15999 
16000 void
dns_zone_nameonly(dns_zone_t * zone,char * buf,size_t length)16001 dns_zone_nameonly(dns_zone_t *zone, char *buf, size_t length) {
16002 	REQUIRE(DNS_ZONE_VALID(zone));
16003 	REQUIRE(buf != NULL);
16004 	zone_name_tostr(zone, buf, length);
16005 }
16006 
16007 void
dns_zone_logv(dns_zone_t * zone,isc_logcategory_t * category,int level,const char * prefix,const char * fmt,va_list ap)16008 dns_zone_logv(dns_zone_t *zone, isc_logcategory_t *category, int level,
16009 	      const char *prefix, const char *fmt, va_list ap) {
16010 	char message[4096];
16011 	const char *zstr;
16012 
16013 	REQUIRE(DNS_ZONE_VALID(zone));
16014 
16015 	if (!isc_log_wouldlog(dns_lctx, level)) {
16016 		return;
16017 	}
16018 
16019 	vsnprintf(message, sizeof(message), fmt, ap);
16020 
16021 	switch (zone->type) {
16022 	case dns_zone_key:
16023 		zstr = "managed-keys-zone";
16024 		break;
16025 	case dns_zone_redirect:
16026 		zstr = "redirect-zone";
16027 		break;
16028 	default:
16029 		zstr = "zone ";
16030 	}
16031 
16032 	isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE, level,
16033 		      "%s%s%s%s: %s", (prefix != NULL ? prefix : ""),
16034 		      (prefix != NULL ? ": " : ""), zstr, zone->strnamerd,
16035 		      message);
16036 }
16037 
16038 static void
notify_log(dns_zone_t * zone,int level,const char * fmt,...)16039 notify_log(dns_zone_t *zone, int level, const char *fmt, ...) {
16040 	va_list ap;
16041 
16042 	va_start(ap, fmt);
16043 	dns_zone_logv(zone, DNS_LOGCATEGORY_NOTIFY, level, NULL, fmt, ap);
16044 	va_end(ap);
16045 }
16046 
16047 void
dns_zone_logc(dns_zone_t * zone,isc_logcategory_t * category,int level,const char * fmt,...)16048 dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category, int level,
16049 	      const char *fmt, ...) {
16050 	va_list ap;
16051 
16052 	va_start(ap, fmt);
16053 	dns_zone_logv(zone, category, level, NULL, fmt, ap);
16054 	va_end(ap);
16055 }
16056 
16057 void
dns_zone_log(dns_zone_t * zone,int level,const char * fmt,...)16058 dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) {
16059 	va_list ap;
16060 
16061 	va_start(ap, fmt);
16062 	dns_zone_logv(zone, DNS_LOGCATEGORY_GENERAL, level, NULL, fmt, ap);
16063 	va_end(ap);
16064 }
16065 
16066 static void
zone_debuglog(dns_zone_t * zone,const char * me,int debuglevel,const char * fmt,...)16067 zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel, const char *fmt,
16068 	      ...) {
16069 	int level = ISC_LOG_DEBUG(debuglevel);
16070 	va_list ap;
16071 
16072 	va_start(ap, fmt);
16073 	dns_zone_logv(zone, DNS_LOGCATEGORY_GENERAL, level, me, fmt, ap);
16074 	va_end(ap);
16075 }
16076 
16077 static void
dnssec_log(dns_zone_t * zone,int level,const char * fmt,...)16078 dnssec_log(dns_zone_t *zone, int level, const char *fmt, ...) {
16079 	va_list ap;
16080 
16081 	va_start(ap, fmt);
16082 	dns_zone_logv(zone, DNS_LOGCATEGORY_DNSSEC, level, NULL, fmt, ap);
16083 	va_end(ap);
16084 }
16085 
16086 static int
message_count(dns_message_t * msg,dns_section_t section,dns_rdatatype_t type)16087 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type) {
16088 	isc_result_t result;
16089 	dns_name_t *name;
16090 	dns_rdataset_t *curr;
16091 	int count = 0;
16092 
16093 	result = dns_message_firstname(msg, section);
16094 	while (result == ISC_R_SUCCESS) {
16095 		name = NULL;
16096 		dns_message_currentname(msg, section, &name);
16097 
16098 		for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
16099 		     curr = ISC_LIST_PREV(curr, link))
16100 		{
16101 			if (curr->type == type) {
16102 				count++;
16103 			}
16104 		}
16105 		result = dns_message_nextname(msg, section);
16106 	}
16107 
16108 	return (count);
16109 }
16110 
16111 void
dns_zone_setmaxxfrin(dns_zone_t * zone,uint32_t maxxfrin)16112 dns_zone_setmaxxfrin(dns_zone_t *zone, uint32_t maxxfrin) {
16113 	REQUIRE(DNS_ZONE_VALID(zone));
16114 
16115 	zone->maxxfrin = maxxfrin;
16116 }
16117 
16118 uint32_t
dns_zone_getmaxxfrin(dns_zone_t * zone)16119 dns_zone_getmaxxfrin(dns_zone_t *zone) {
16120 	REQUIRE(DNS_ZONE_VALID(zone));
16121 
16122 	return (zone->maxxfrin);
16123 }
16124 
16125 void
dns_zone_setmaxxfrout(dns_zone_t * zone,uint32_t maxxfrout)16126 dns_zone_setmaxxfrout(dns_zone_t *zone, uint32_t maxxfrout) {
16127 	REQUIRE(DNS_ZONE_VALID(zone));
16128 	zone->maxxfrout = maxxfrout;
16129 }
16130 
16131 uint32_t
dns_zone_getmaxxfrout(dns_zone_t * zone)16132 dns_zone_getmaxxfrout(dns_zone_t *zone) {
16133 	REQUIRE(DNS_ZONE_VALID(zone));
16134 
16135 	return (zone->maxxfrout);
16136 }
16137 
16138 dns_zonetype_t
dns_zone_gettype(dns_zone_t * zone)16139 dns_zone_gettype(dns_zone_t *zone) {
16140 	REQUIRE(DNS_ZONE_VALID(zone));
16141 
16142 	return (zone->type);
16143 }
16144 
16145 const char *
dns_zonetype_name(dns_zonetype_t type)16146 dns_zonetype_name(dns_zonetype_t type) {
16147 	switch (type) {
16148 	case dns_zone_none:
16149 		return ("none");
16150 	case dns_zone_primary:
16151 		return ("primary");
16152 	case dns_zone_secondary:
16153 		return ("secondary");
16154 	case dns_zone_mirror:
16155 		return ("mirror");
16156 	case dns_zone_stub:
16157 		return ("stub");
16158 	case dns_zone_staticstub:
16159 		return ("static-stub");
16160 	case dns_zone_key:
16161 		return ("key");
16162 	case dns_zone_dlz:
16163 		return ("dlz");
16164 	case dns_zone_redirect:
16165 		return ("redirect");
16166 	default:
16167 		return ("unknown");
16168 	}
16169 }
16170 
16171 dns_zonetype_t
dns_zone_getredirecttype(dns_zone_t * zone)16172 dns_zone_getredirecttype(dns_zone_t *zone) {
16173 	REQUIRE(DNS_ZONE_VALID(zone));
16174 	REQUIRE(zone->type == dns_zone_redirect);
16175 
16176 	return (zone->masters == NULL ? dns_zone_primary : dns_zone_secondary);
16177 }
16178 
16179 dns_name_t *
dns_zone_getorigin(dns_zone_t * zone)16180 dns_zone_getorigin(dns_zone_t *zone) {
16181 	REQUIRE(DNS_ZONE_VALID(zone));
16182 
16183 	return (&zone->origin);
16184 }
16185 
16186 void
dns_zone_settask(dns_zone_t * zone,isc_task_t * task)16187 dns_zone_settask(dns_zone_t *zone, isc_task_t *task) {
16188 	REQUIRE(DNS_ZONE_VALID(zone));
16189 
16190 	LOCK_ZONE(zone);
16191 	if (zone->task != NULL) {
16192 		isc_task_detach(&zone->task);
16193 	}
16194 	isc_task_attach(task, &zone->task);
16195 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
16196 	if (zone->db != NULL) {
16197 		dns_db_settask(zone->db, zone->task);
16198 	}
16199 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
16200 	UNLOCK_ZONE(zone);
16201 }
16202 
16203 void
dns_zone_gettask(dns_zone_t * zone,isc_task_t ** target)16204 dns_zone_gettask(dns_zone_t *zone, isc_task_t **target) {
16205 	REQUIRE(DNS_ZONE_VALID(zone));
16206 	isc_task_attach(zone->task, target);
16207 }
16208 
16209 void
dns_zone_setidlein(dns_zone_t * zone,uint32_t idlein)16210 dns_zone_setidlein(dns_zone_t *zone, uint32_t idlein) {
16211 	REQUIRE(DNS_ZONE_VALID(zone));
16212 
16213 	if (idlein == 0) {
16214 		idlein = DNS_DEFAULT_IDLEIN;
16215 	}
16216 	zone->idlein = idlein;
16217 }
16218 
16219 uint32_t
dns_zone_getidlein(dns_zone_t * zone)16220 dns_zone_getidlein(dns_zone_t *zone) {
16221 	REQUIRE(DNS_ZONE_VALID(zone));
16222 
16223 	return (zone->idlein);
16224 }
16225 
16226 void
dns_zone_setidleout(dns_zone_t * zone,uint32_t idleout)16227 dns_zone_setidleout(dns_zone_t *zone, uint32_t idleout) {
16228 	REQUIRE(DNS_ZONE_VALID(zone));
16229 
16230 	zone->idleout = idleout;
16231 }
16232 
16233 uint32_t
dns_zone_getidleout(dns_zone_t * zone)16234 dns_zone_getidleout(dns_zone_t *zone) {
16235 	REQUIRE(DNS_ZONE_VALID(zone));
16236 
16237 	return (zone->idleout);
16238 }
16239 
16240 static void
notify_done(isc_task_t * task,isc_event_t * event)16241 notify_done(isc_task_t *task, isc_event_t *event) {
16242 	dns_requestevent_t *revent = (dns_requestevent_t *)event;
16243 	dns_notify_t *notify;
16244 	isc_result_t result;
16245 	dns_message_t *message = NULL;
16246 	isc_buffer_t buf;
16247 	char rcode[128];
16248 	char addrbuf[ISC_SOCKADDR_FORMATSIZE];
16249 
16250 	UNUSED(task);
16251 
16252 	notify = event->ev_arg;
16253 	REQUIRE(DNS_NOTIFY_VALID(notify));
16254 	INSIST(task == notify->zone->task);
16255 
16256 	isc_buffer_init(&buf, rcode, sizeof(rcode));
16257 	isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
16258 	dns_message_create(notify->zone->mctx, DNS_MESSAGE_INTENTPARSE,
16259 			   &message);
16260 
16261 	result = revent->result;
16262 	if (result == ISC_R_SUCCESS) {
16263 		result =
16264 			dns_request_getresponse(revent->request, message,
16265 						DNS_MESSAGEPARSE_PRESERVEORDER);
16266 	}
16267 	if (result == ISC_R_SUCCESS) {
16268 		result = dns_rcode_totext(message->rcode, &buf);
16269 	}
16270 	if (result == ISC_R_SUCCESS) {
16271 		notify_log(notify->zone, ISC_LOG_DEBUG(3),
16272 			   "notify response from %s: %.*s", addrbuf,
16273 			   (int)buf.used, rcode);
16274 	} else {
16275 		notify_log(notify->zone, ISC_LOG_DEBUG(2),
16276 			   "notify to %s failed: %s", addrbuf,
16277 			   dns_result_totext(result));
16278 	}
16279 
16280 	/*
16281 	 * Old bind's return formerr if they see a soa record.	Retry w/o
16282 	 * the soa if we see a formerr and had sent a SOA.
16283 	 */
16284 	isc_event_free(&event);
16285 	if (message->rcode == dns_rcode_formerr &&
16286 	    (notify->flags & DNS_NOTIFY_NOSOA) == 0)
16287 	{
16288 		bool startup;
16289 
16290 		notify->flags |= DNS_NOTIFY_NOSOA;
16291 		dns_request_destroy(&notify->request);
16292 		startup = (notify->flags & DNS_NOTIFY_STARTUP);
16293 		result = notify_send_queue(notify, startup);
16294 		if (result != ISC_R_SUCCESS) {
16295 			notify_destroy(notify, false);
16296 		}
16297 	} else {
16298 		if (result == ISC_R_TIMEDOUT) {
16299 			notify_log(notify->zone, ISC_LOG_DEBUG(1),
16300 				   "notify to %s: retries exceeded", addrbuf);
16301 		}
16302 		notify_destroy(notify, false);
16303 	}
16304 	dns_message_detach(&message);
16305 }
16306 
16307 struct secure_event {
16308 	isc_event_t e;
16309 	dns_db_t *db;
16310 	uint32_t serial;
16311 };
16312 
16313 static void
update_log_cb(void * arg,dns_zone_t * zone,int level,const char * message)16314 update_log_cb(void *arg, dns_zone_t *zone, int level, const char *message) {
16315 	UNUSED(arg);
16316 	dns_zone_log(zone, level, "%s", message);
16317 }
16318 
16319 static isc_result_t
sync_secure_journal(dns_zone_t * zone,dns_zone_t * raw,dns_journal_t * journal,uint32_t start,uint32_t end,dns_difftuple_t ** soatuplep,dns_diff_t * diff)16320 sync_secure_journal(dns_zone_t *zone, dns_zone_t *raw, dns_journal_t *journal,
16321 		    uint32_t start, uint32_t end, dns_difftuple_t **soatuplep,
16322 		    dns_diff_t *diff) {
16323 	isc_result_t result;
16324 	dns_difftuple_t *tuple = NULL;
16325 	dns_diffop_t op = DNS_DIFFOP_ADD;
16326 	int n_soa = 0;
16327 
16328 	REQUIRE(soatuplep != NULL);
16329 
16330 	if (start == end) {
16331 		return (DNS_R_UNCHANGED);
16332 	}
16333 
16334 	CHECK(dns_journal_iter_init(journal, start, end, NULL));
16335 	for (result = dns_journal_first_rr(journal); result == ISC_R_SUCCESS;
16336 	     result = dns_journal_next_rr(journal))
16337 	{
16338 		dns_name_t *name = NULL;
16339 		uint32_t ttl;
16340 		dns_rdata_t *rdata = NULL;
16341 		dns_journal_current_rr(journal, &name, &ttl, &rdata);
16342 
16343 		if (rdata->type == dns_rdatatype_soa) {
16344 			n_soa++;
16345 			if (n_soa == 2) {
16346 				/*
16347 				 * Save the latest raw SOA record.
16348 				 */
16349 				if (*soatuplep != NULL) {
16350 					dns_difftuple_free(soatuplep);
16351 				}
16352 				CHECK(dns_difftuple_create(
16353 					diff->mctx, DNS_DIFFOP_ADD, name, ttl,
16354 					rdata, soatuplep));
16355 			}
16356 			if (n_soa == 3) {
16357 				n_soa = 1;
16358 			}
16359 			continue;
16360 		}
16361 
16362 		/* Sanity. */
16363 		if (n_soa == 0) {
16364 			dns_zone_log(raw, ISC_LOG_ERROR,
16365 				     "corrupt journal file: '%s'\n",
16366 				     raw->journal);
16367 			return (ISC_R_FAILURE);
16368 		}
16369 
16370 		if (zone->privatetype != 0 && rdata->type == zone->privatetype)
16371 		{
16372 			continue;
16373 		}
16374 
16375 		if (rdata->type == dns_rdatatype_nsec ||
16376 		    rdata->type == dns_rdatatype_rrsig ||
16377 		    rdata->type == dns_rdatatype_nsec3 ||
16378 		    rdata->type == dns_rdatatype_dnskey ||
16379 		    rdata->type == dns_rdatatype_nsec3param)
16380 		{
16381 			continue;
16382 		}
16383 
16384 		op = (n_soa == 1) ? DNS_DIFFOP_DEL : DNS_DIFFOP_ADD;
16385 
16386 		CHECK(dns_difftuple_create(diff->mctx, op, name, ttl, rdata,
16387 					   &tuple));
16388 		dns_diff_appendminimal(diff, &tuple);
16389 	}
16390 	if (result == ISC_R_NOMORE) {
16391 		result = ISC_R_SUCCESS;
16392 	}
16393 
16394 failure:
16395 	return (result);
16396 }
16397 
16398 static isc_result_t
sync_secure_db(dns_zone_t * seczone,dns_zone_t * raw,dns_db_t * secdb,dns_dbversion_t * secver,dns_difftuple_t ** soatuple,dns_diff_t * diff)16399 sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb,
16400 	       dns_dbversion_t *secver, dns_difftuple_t **soatuple,
16401 	       dns_diff_t *diff) {
16402 	isc_result_t result;
16403 	dns_db_t *rawdb = NULL;
16404 	dns_dbversion_t *rawver = NULL;
16405 	dns_difftuple_t *tuple = NULL, *next;
16406 	dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
16407 	dns_rdata_soa_t oldsoa, newsoa;
16408 
16409 	REQUIRE(DNS_ZONE_VALID(seczone));
16410 	REQUIRE(soatuple != NULL && *soatuple == NULL);
16411 
16412 	if (!seczone->sourceserialset) {
16413 		return (DNS_R_UNCHANGED);
16414 	}
16415 
16416 	dns_db_attach(raw->db, &rawdb);
16417 	dns_db_currentversion(rawdb, &rawver);
16418 	result = dns_db_diffx(diff, rawdb, rawver, secdb, secver, NULL);
16419 	dns_db_closeversion(rawdb, &rawver, false);
16420 	dns_db_detach(&rawdb);
16421 
16422 	if (result != ISC_R_SUCCESS) {
16423 		return (result);
16424 	}
16425 
16426 	for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL; tuple = next) {
16427 		next = ISC_LIST_NEXT(tuple, link);
16428 		if (tuple->rdata.type == dns_rdatatype_nsec ||
16429 		    tuple->rdata.type == dns_rdatatype_rrsig ||
16430 		    tuple->rdata.type == dns_rdatatype_dnskey ||
16431 		    tuple->rdata.type == dns_rdatatype_nsec3 ||
16432 		    tuple->rdata.type == dns_rdatatype_nsec3param)
16433 		{
16434 			ISC_LIST_UNLINK(diff->tuples, tuple, link);
16435 			dns_difftuple_free(&tuple);
16436 			continue;
16437 		}
16438 		if (tuple->rdata.type == dns_rdatatype_soa) {
16439 			if (tuple->op == DNS_DIFFOP_DEL) {
16440 				INSIST(oldtuple == NULL);
16441 				oldtuple = tuple;
16442 			}
16443 			if (tuple->op == DNS_DIFFOP_ADD) {
16444 				INSIST(newtuple == NULL);
16445 				newtuple = tuple;
16446 			}
16447 		}
16448 	}
16449 
16450 	if (oldtuple != NULL && newtuple != NULL) {
16451 		result = dns_rdata_tostruct(&oldtuple->rdata, &oldsoa, NULL);
16452 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
16453 
16454 		result = dns_rdata_tostruct(&newtuple->rdata, &newsoa, NULL);
16455 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
16456 
16457 		/*
16458 		 * If the SOA records are the same except for the serial
16459 		 * remove them from the diff.
16460 		 */
16461 		if (oldtuple->ttl == newtuple->ttl &&
16462 		    oldsoa.refresh == newsoa.refresh &&
16463 		    oldsoa.retry == newsoa.retry &&
16464 		    oldsoa.minimum == newsoa.minimum &&
16465 		    oldsoa.expire == newsoa.expire &&
16466 		    dns_name_equal(&oldsoa.origin, &newsoa.origin) &&
16467 		    dns_name_equal(&oldsoa.contact, &newsoa.contact))
16468 		{
16469 			ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
16470 			dns_difftuple_free(&oldtuple);
16471 			ISC_LIST_UNLINK(diff->tuples, newtuple, link);
16472 			dns_difftuple_free(&newtuple);
16473 		}
16474 	}
16475 
16476 	if (ISC_LIST_EMPTY(diff->tuples)) {
16477 		return (DNS_R_UNCHANGED);
16478 	}
16479 
16480 	/*
16481 	 * If there are still SOA records in the diff they can now be removed
16482 	 * saving the new SOA record.
16483 	 */
16484 	if (oldtuple != NULL) {
16485 		ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
16486 		dns_difftuple_free(&oldtuple);
16487 	}
16488 
16489 	if (newtuple != NULL) {
16490 		ISC_LIST_UNLINK(diff->tuples, newtuple, link);
16491 		*soatuple = newtuple;
16492 	}
16493 
16494 	return (ISC_R_SUCCESS);
16495 }
16496 
16497 static void
receive_secure_serial(isc_task_t * task,isc_event_t * event)16498 receive_secure_serial(isc_task_t *task, isc_event_t *event) {
16499 	static char me[] = "receive_secure_serial";
16500 	isc_result_t result = ISC_R_SUCCESS;
16501 	dns_journal_t *rjournal = NULL;
16502 	dns_journal_t *sjournal = NULL;
16503 	uint32_t start, end;
16504 	dns_zone_t *zone;
16505 	dns_difftuple_t *tuple = NULL, *soatuple = NULL;
16506 	dns_update_log_t log = { update_log_cb, NULL };
16507 	uint32_t newserial = 0, desired = 0;
16508 	isc_time_t timenow;
16509 	int level = ISC_LOG_ERROR;
16510 
16511 	UNUSED(task);
16512 
16513 	zone = event->ev_arg;
16514 	end = ((struct secure_event *)event)->serial;
16515 
16516 	ENTER;
16517 
16518 	LOCK_ZONE(zone);
16519 
16520 	/*
16521 	 * If we are already processing a receive secure serial event
16522 	 * for the zone, just queue the new one and exit.
16523 	 */
16524 	if (zone->rss_event != NULL && zone->rss_event != event) {
16525 		ISC_LIST_APPEND(zone->rss_events, event, ev_link);
16526 		UNLOCK_ZONE(zone);
16527 		return;
16528 	}
16529 
16530 nextevent:
16531 	if (zone->rss_event != NULL) {
16532 		INSIST(zone->rss_event == event);
16533 		UNLOCK_ZONE(zone);
16534 	} else {
16535 		zone->rss_event = event;
16536 		dns_diff_init(zone->mctx, &zone->rss_diff);
16537 
16538 		/*
16539 		 * zone->db may be NULL, if the load from disk failed.
16540 		 */
16541 		result = ISC_R_SUCCESS;
16542 		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
16543 		if (zone->db != NULL) {
16544 			dns_db_attach(zone->db, &zone->rss_db);
16545 		} else {
16546 			result = ISC_R_FAILURE;
16547 		}
16548 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
16549 
16550 		if (result == ISC_R_SUCCESS && zone->raw != NULL) {
16551 			dns_zone_attach(zone->raw, &zone->rss_raw);
16552 		} else {
16553 			result = ISC_R_FAILURE;
16554 		}
16555 
16556 		UNLOCK_ZONE(zone);
16557 
16558 		CHECK(result);
16559 
16560 		/*
16561 		 * We first attempt to sync the raw zone to the secure zone
16562 		 * by using the raw zone's journal, applying all the deltas
16563 		 * from the latest source-serial of the secure zone up to
16564 		 * the current serial number of the raw zone.
16565 		 *
16566 		 * If that fails, then we'll fall back to a direct comparison
16567 		 * between raw and secure zones.
16568 		 */
16569 		CHECK(dns_journal_open(zone->rss_raw->mctx,
16570 				       zone->rss_raw->journal,
16571 				       DNS_JOURNAL_WRITE, &rjournal));
16572 
16573 		result = dns_journal_open(zone->mctx, zone->journal,
16574 					  DNS_JOURNAL_READ, &sjournal);
16575 		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
16576 			goto failure;
16577 		}
16578 
16579 		if (!dns_journal_get_sourceserial(rjournal, &start)) {
16580 			start = dns_journal_first_serial(rjournal);
16581 			dns_journal_set_sourceserial(rjournal, start);
16582 		}
16583 		if (sjournal != NULL) {
16584 			uint32_t serial;
16585 			/*
16586 			 * We read the secure journal first, if that
16587 			 * exists use its value provided it is greater
16588 			 * that from the raw journal.
16589 			 */
16590 			if (dns_journal_get_sourceserial(sjournal, &serial)) {
16591 				if (isc_serial_gt(serial, start)) {
16592 					start = serial;
16593 				}
16594 			}
16595 			dns_journal_destroy(&sjournal);
16596 		}
16597 
16598 		dns_db_currentversion(zone->rss_db, &zone->rss_oldver);
16599 		CHECK(dns_db_newversion(zone->rss_db, &zone->rss_newver));
16600 
16601 		/*
16602 		 * Try to apply diffs from the raw zone's journal to the secure
16603 		 * zone.  If that fails, we recover by syncing up the databases
16604 		 * directly.
16605 		 */
16606 		result = sync_secure_journal(zone, zone->rss_raw, rjournal,
16607 					     start, end, &soatuple,
16608 					     &zone->rss_diff);
16609 		if (result == DNS_R_UNCHANGED) {
16610 			level = ISC_LOG_INFO;
16611 			goto failure;
16612 		} else if (result != ISC_R_SUCCESS) {
16613 			CHECK(sync_secure_db(zone, zone->rss_raw, zone->rss_db,
16614 					     zone->rss_oldver, &soatuple,
16615 					     &zone->rss_diff));
16616 		}
16617 
16618 		CHECK(dns_diff_apply(&zone->rss_diff, zone->rss_db,
16619 				     zone->rss_newver));
16620 
16621 		if (soatuple != NULL) {
16622 			uint32_t oldserial;
16623 
16624 			CHECK(dns_db_createsoatuple(
16625 				zone->rss_db, zone->rss_oldver,
16626 				zone->rss_diff.mctx, DNS_DIFFOP_DEL, &tuple));
16627 			oldserial = dns_soa_getserial(&tuple->rdata);
16628 			newserial = desired =
16629 				dns_soa_getserial(&soatuple->rdata);
16630 			if (!isc_serial_gt(newserial, oldserial)) {
16631 				newserial = oldserial + 1;
16632 				if (newserial == 0) {
16633 					newserial++;
16634 				}
16635 				dns_soa_setserial(newserial, &soatuple->rdata);
16636 			}
16637 			CHECK(do_one_tuple(&tuple, zone->rss_db,
16638 					   zone->rss_newver, &zone->rss_diff));
16639 			CHECK(do_one_tuple(&soatuple, zone->rss_db,
16640 					   zone->rss_newver, &zone->rss_diff));
16641 		} else {
16642 			CHECK(update_soa_serial(zone, zone->rss_db,
16643 						zone->rss_newver,
16644 						&zone->rss_diff, zone->mctx,
16645 						zone->updatemethod));
16646 		}
16647 	}
16648 	result = dns_update_signaturesinc(
16649 		&log, zone, zone->rss_db, zone->rss_oldver, zone->rss_newver,
16650 		&zone->rss_diff, zone->sigvalidityinterval, &zone->rss_state);
16651 	if (result == DNS_R_CONTINUE) {
16652 		if (rjournal != NULL) {
16653 			dns_journal_destroy(&rjournal);
16654 		}
16655 		isc_task_send(task, &event);
16656 		return;
16657 	}
16658 	/*
16659 	 * If something went wrong while trying to update the secure zone and
16660 	 * the latter was already signed before, do not apply raw zone deltas
16661 	 * to it as that would break existing DNSSEC signatures.  However, if
16662 	 * the secure zone was not yet signed (e.g. because no signing keys
16663 	 * were created for it), commence applying raw zone deltas to it so
16664 	 * that contents of the raw zone and the secure zone are kept in sync.
16665 	 */
16666 	if (result != ISC_R_SUCCESS && dns_db_issecure(zone->rss_db)) {
16667 		goto failure;
16668 	}
16669 
16670 	if (rjournal == NULL) {
16671 		CHECK(dns_journal_open(zone->rss_raw->mctx,
16672 				       zone->rss_raw->journal,
16673 				       DNS_JOURNAL_WRITE, &rjournal));
16674 	}
16675 	CHECK(zone_journal(zone, &zone->rss_diff, &end,
16676 			   "receive_secure_serial"));
16677 
16678 	dns_journal_set_sourceserial(rjournal, end);
16679 	dns_journal_commit(rjournal);
16680 
16681 	LOCK_ZONE(zone);
16682 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
16683 
16684 	zone->sourceserial = end;
16685 	zone->sourceserialset = true;
16686 	zone_needdump(zone, DNS_DUMP_DELAY);
16687 
16688 	/*
16689 	 * Set resign time to make sure it is set to the earliest
16690 	 * signature expiration.
16691 	 */
16692 	set_resigntime(zone);
16693 	TIME_NOW(&timenow);
16694 	zone_settimer(zone, &timenow);
16695 	UNLOCK_ZONE(zone);
16696 
16697 	dns_db_closeversion(zone->rss_db, &zone->rss_oldver, false);
16698 	dns_db_closeversion(zone->rss_db, &zone->rss_newver, true);
16699 
16700 	if (newserial != 0) {
16701 		dns_zone_log(zone, ISC_LOG_INFO, "serial %u (unsigned %u)",
16702 			     newserial, desired);
16703 	}
16704 
16705 failure:
16706 	isc_event_free(&zone->rss_event);
16707 	event = ISC_LIST_HEAD(zone->rss_events);
16708 
16709 	if (zone->rss_raw != NULL) {
16710 		dns_zone_detach(&zone->rss_raw);
16711 	}
16712 	if (result != ISC_R_SUCCESS) {
16713 		LOCK_ZONE(zone);
16714 		set_resigntime(zone);
16715 		TIME_NOW(&timenow);
16716 		zone_settimer(zone, &timenow);
16717 		UNLOCK_ZONE(zone);
16718 		dns_zone_log(zone, level, "receive_secure_serial: %s",
16719 			     dns_result_totext(result));
16720 	}
16721 	if (tuple != NULL) {
16722 		dns_difftuple_free(&tuple);
16723 	}
16724 	if (soatuple != NULL) {
16725 		dns_difftuple_free(&soatuple);
16726 	}
16727 	if (zone->rss_db != NULL) {
16728 		if (zone->rss_oldver != NULL) {
16729 			dns_db_closeversion(zone->rss_db, &zone->rss_oldver,
16730 					    false);
16731 		}
16732 		if (zone->rss_newver != NULL) {
16733 			dns_db_closeversion(zone->rss_db, &zone->rss_newver,
16734 					    false);
16735 		}
16736 		dns_db_detach(&zone->rss_db);
16737 	}
16738 	INSIST(zone->rss_oldver == NULL);
16739 	INSIST(zone->rss_newver == NULL);
16740 	if (rjournal != NULL) {
16741 		dns_journal_destroy(&rjournal);
16742 	}
16743 	dns_diff_clear(&zone->rss_diff);
16744 
16745 	if (event != NULL) {
16746 		LOCK_ZONE(zone);
16747 		isc_refcount_decrement(&zone->irefs);
16748 		ISC_LIST_UNLINK(zone->rss_events, event, ev_link);
16749 		goto nextevent;
16750 	}
16751 
16752 	event = ISC_LIST_HEAD(zone->rss_post);
16753 	while (event != NULL) {
16754 		ISC_LIST_UNLINK(zone->rss_post, event, ev_link);
16755 		rss_post(zone, event);
16756 		event = ISC_LIST_HEAD(zone->rss_post);
16757 	}
16758 
16759 	dns_zone_idetach(&zone);
16760 }
16761 
16762 static isc_result_t
zone_send_secureserial(dns_zone_t * zone,uint32_t serial)16763 zone_send_secureserial(dns_zone_t *zone, uint32_t serial) {
16764 	isc_event_t *e;
16765 	dns_zone_t *dummy = NULL;
16766 
16767 	e = isc_event_allocate(zone->secure->mctx, zone,
16768 			       DNS_EVENT_ZONESECURESERIAL,
16769 			       receive_secure_serial, zone->secure,
16770 			       sizeof(struct secure_event));
16771 	((struct secure_event *)e)->serial = serial;
16772 	INSIST(LOCKED_ZONE(zone->secure));
16773 	zone_iattach(zone->secure, &dummy);
16774 	isc_task_send(zone->secure->task, &e);
16775 
16776 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
16777 	return (ISC_R_SUCCESS);
16778 }
16779 
16780 static isc_result_t
checkandaddsoa(dns_db_t * db,dns_dbnode_t * node,dns_dbversion_t * version,dns_rdataset_t * rdataset,uint32_t oldserial)16781 checkandaddsoa(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
16782 	       dns_rdataset_t *rdataset, uint32_t oldserial) {
16783 	dns_rdata_soa_t soa;
16784 	dns_rdata_t rdata = DNS_RDATA_INIT;
16785 	dns_rdatalist_t temprdatalist;
16786 	dns_rdataset_t temprdataset;
16787 	isc_buffer_t b;
16788 	isc_result_t result;
16789 	unsigned char buf[DNS_SOA_BUFFERSIZE];
16790 	dns_fixedname_t fixed;
16791 	dns_name_t *name;
16792 
16793 	result = dns_rdataset_first(rdataset);
16794 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
16795 	dns_rdataset_current(rdataset, &rdata);
16796 	result = dns_rdata_tostruct(&rdata, &soa, NULL);
16797 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
16798 
16799 	if (isc_serial_gt(soa.serial, oldserial)) {
16800 		return (dns_db_addrdataset(db, node, version, 0, rdataset, 0,
16801 					   NULL));
16802 	}
16803 	/*
16804 	 * Always bump the serial.
16805 	 */
16806 	oldserial++;
16807 	if (oldserial == 0) {
16808 		oldserial++;
16809 	}
16810 	soa.serial = oldserial;
16811 
16812 	/*
16813 	 * Construct a replacement rdataset.
16814 	 */
16815 	dns_rdata_reset(&rdata);
16816 	isc_buffer_init(&b, buf, sizeof(buf));
16817 	result = dns_rdata_fromstruct(&rdata, rdataset->rdclass,
16818 				      dns_rdatatype_soa, &soa, &b);
16819 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
16820 	dns_rdatalist_init(&temprdatalist);
16821 	temprdatalist.rdclass = rdata.rdclass;
16822 	temprdatalist.type = rdata.type;
16823 	temprdatalist.ttl = rdataset->ttl;
16824 	ISC_LIST_APPEND(temprdatalist.rdata, &rdata, link);
16825 
16826 	dns_rdataset_init(&temprdataset);
16827 	result = dns_rdatalist_tordataset(&temprdatalist, &temprdataset);
16828 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
16829 
16830 	name = dns_fixedname_initname(&fixed);
16831 	result = dns_db_nodefullname(db, node, name);
16832 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
16833 	dns_rdataset_getownercase(rdataset, name);
16834 	dns_rdataset_setownercase(&temprdataset, name);
16835 	return (dns_db_addrdataset(db, node, version, 0, &temprdataset, 0,
16836 				   NULL));
16837 }
16838 
16839 /*
16840  * This function should populate an nsec3paramlist_t with the
16841  * nsecparam_t data from a zone.
16842  */
16843 static isc_result_t
save_nsec3param(dns_zone_t * zone,nsec3paramlist_t * nsec3list)16844 save_nsec3param(dns_zone_t *zone, nsec3paramlist_t *nsec3list) {
16845 	isc_result_t result;
16846 	dns_dbnode_t *node = NULL;
16847 	dns_rdataset_t rdataset, prdataset;
16848 	dns_dbversion_t *version = NULL;
16849 	nsec3param_t *nsec3param = NULL;
16850 	nsec3param_t *nsec3p = NULL;
16851 	nsec3param_t *next;
16852 	dns_db_t *db = NULL;
16853 	unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
16854 
16855 	REQUIRE(DNS_ZONE_VALID(zone));
16856 	REQUIRE(nsec3list != NULL);
16857 	REQUIRE(ISC_LIST_EMPTY(*nsec3list));
16858 
16859 	dns_rdataset_init(&rdataset);
16860 	dns_rdataset_init(&prdataset);
16861 
16862 	dns_db_attach(zone->db, &db);
16863 	CHECK(dns_db_getoriginnode(db, &node));
16864 
16865 	dns_db_currentversion(db, &version);
16866 	result = dns_db_findrdataset(db, node, version,
16867 				     dns_rdatatype_nsec3param,
16868 				     dns_rdatatype_none, 0, &rdataset, NULL);
16869 
16870 	if (result != ISC_R_SUCCESS) {
16871 		goto getprivate;
16872 	}
16873 
16874 	/*
16875 	 * Walk nsec3param rdataset making a list of parameters (note that
16876 	 * multiple simultaneous nsec3 chains are annoyingly legal -- this
16877 	 * is why we use an nsec3list, even though we will usually only
16878 	 * have one).
16879 	 */
16880 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
16881 	     result = dns_rdataset_next(&rdataset))
16882 	{
16883 		dns_rdata_t rdata = DNS_RDATA_INIT;
16884 		dns_rdata_t private = DNS_RDATA_INIT;
16885 
16886 		dns_rdataset_current(&rdataset, &rdata);
16887 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
16888 			      DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
16889 			      "looping through nsec3param data");
16890 		nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
16891 		ISC_LINK_INIT(nsec3param, link);
16892 
16893 		/*
16894 		 * now transfer the data from the rdata to
16895 		 * the nsec3param
16896 		 */
16897 		dns_nsec3param_toprivate(&rdata, &private, zone->privatetype,
16898 					 nsec3param->data,
16899 					 sizeof(nsec3param->data));
16900 		nsec3param->length = private.length;
16901 		ISC_LIST_APPEND(*nsec3list, nsec3param, link);
16902 	}
16903 
16904 getprivate:
16905 	result = dns_db_findrdataset(db, node, version, zone->privatetype,
16906 				     dns_rdatatype_none, 0, &prdataset, NULL);
16907 	if (result != ISC_R_SUCCESS) {
16908 		goto done;
16909 	}
16910 
16911 	/*
16912 	 * walk private type records, converting them to nsec3 parameters
16913 	 * using dns_nsec3param_fromprivate(), do the right thing based on
16914 	 * CREATE and REMOVE flags
16915 	 */
16916 	for (result = dns_rdataset_first(&prdataset); result == ISC_R_SUCCESS;
16917 	     result = dns_rdataset_next(&prdataset))
16918 	{
16919 		dns_rdata_t rdata = DNS_RDATA_INIT;
16920 		dns_rdata_t private = DNS_RDATA_INIT;
16921 
16922 		dns_rdataset_current(&prdataset, &private);
16923 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
16924 			      DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
16925 			      "looping through nsec3param private data");
16926 
16927 		/*
16928 		 * Do we have a valid private record?
16929 		 */
16930 		if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
16931 						sizeof(buf)))
16932 		{
16933 			continue;
16934 		}
16935 
16936 		/*
16937 		 * Remove any NSEC3PARAM records scheduled to be removed.
16938 		 */
16939 		if (NSEC3REMOVE(rdata.data[1])) {
16940 			/*
16941 			 * Zero out the flags.
16942 			 */
16943 			rdata.data[1] = 0;
16944 
16945 			for (nsec3p = ISC_LIST_HEAD(*nsec3list); nsec3p != NULL;
16946 			     nsec3p = next)
16947 			{
16948 				next = ISC_LIST_NEXT(nsec3p, link);
16949 
16950 				if (nsec3p->length == rdata.length + 1 &&
16951 				    memcmp(rdata.data, nsec3p->data + 1,
16952 					   nsec3p->length - 1) == 0)
16953 				{
16954 					ISC_LIST_UNLINK(*nsec3list, nsec3p,
16955 							link);
16956 					isc_mem_put(zone->mctx, nsec3p,
16957 						    sizeof(nsec3param_t));
16958 				}
16959 			}
16960 			continue;
16961 		}
16962 
16963 		nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
16964 		ISC_LINK_INIT(nsec3param, link);
16965 
16966 		/*
16967 		 * Copy the remaining private records so the nsec/nsec3
16968 		 * chain gets created.
16969 		 */
16970 		INSIST(private.length <= sizeof(nsec3param->data));
16971 		memmove(nsec3param->data, private.data, private.length);
16972 		nsec3param->length = private.length;
16973 		ISC_LIST_APPEND(*nsec3list, nsec3param, link);
16974 	}
16975 
16976 done:
16977 	if (result == ISC_R_NOMORE || result == ISC_R_NOTFOUND) {
16978 		result = ISC_R_SUCCESS;
16979 	}
16980 
16981 failure:
16982 	if (node != NULL) {
16983 		dns_db_detachnode(db, &node);
16984 	}
16985 	if (version != NULL) {
16986 		dns_db_closeversion(db, &version, false);
16987 	}
16988 	if (db != NULL) {
16989 		dns_db_detach(&db);
16990 	}
16991 	if (dns_rdataset_isassociated(&rdataset)) {
16992 		dns_rdataset_disassociate(&rdataset);
16993 	}
16994 	if (dns_rdataset_isassociated(&prdataset)) {
16995 		dns_rdataset_disassociate(&prdataset);
16996 	}
16997 	return (result);
16998 }
16999 
17000 /*
17001  * Populate new zone db with private type records found by save_nsec3param().
17002  */
17003 static isc_result_t
restore_nsec3param(dns_zone_t * zone,dns_db_t * db,dns_dbversion_t * version,nsec3paramlist_t * nsec3list)17004 restore_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
17005 		   nsec3paramlist_t *nsec3list) {
17006 	isc_result_t result = ISC_R_SUCCESS;
17007 	dns_diff_t diff;
17008 	dns_rdata_t rdata;
17009 	nsec3param_t *nsec3p = NULL;
17010 	nsec3param_t *next;
17011 
17012 	REQUIRE(DNS_ZONE_VALID(zone));
17013 	REQUIRE(!ISC_LIST_EMPTY(*nsec3list));
17014 
17015 	dns_diff_init(zone->mctx, &diff);
17016 
17017 	/*
17018 	 * Loop through the list of private-type records, set the INITIAL
17019 	 * and CREATE flags, and the add the record to the apex of the tree
17020 	 * in db.
17021 	 */
17022 	for (nsec3p = ISC_LIST_HEAD(*nsec3list); nsec3p != NULL; nsec3p = next)
17023 	{
17024 		next = ISC_LIST_NEXT(nsec3p, link);
17025 		dns_rdata_init(&rdata);
17026 		nsec3p->data[2] = DNS_NSEC3FLAG_CREATE | DNS_NSEC3FLAG_INITIAL;
17027 		rdata.length = nsec3p->length;
17028 		rdata.data = nsec3p->data;
17029 		rdata.type = zone->privatetype;
17030 		rdata.rdclass = zone->rdclass;
17031 		result = update_one_rr(db, version, &diff, DNS_DIFFOP_ADD,
17032 				       &zone->origin, 0, &rdata);
17033 		if (result != ISC_R_SUCCESS) {
17034 			break;
17035 		}
17036 	}
17037 
17038 	dns_diff_clear(&diff);
17039 	return (result);
17040 }
17041 
17042 static isc_result_t
copy_non_dnssec_records(dns_db_t * db,dns_db_t * version,dns_db_t * rawdb,dns_dbiterator_t * dbiterator,unsigned int * oldserial)17043 copy_non_dnssec_records(dns_db_t *db, dns_db_t *version, dns_db_t *rawdb,
17044 			dns_dbiterator_t *dbiterator, unsigned int *oldserial) {
17045 	dns_dbnode_t *rawnode = NULL, *node = NULL;
17046 	dns_fixedname_t fixed;
17047 	dns_name_t *name = dns_fixedname_initname(&fixed);
17048 	dns_rdataset_t rdataset;
17049 	dns_rdatasetiter_t *rdsit = NULL;
17050 	isc_result_t result;
17051 
17052 	result = dns_dbiterator_current(dbiterator, &rawnode, name);
17053 	if (result != ISC_R_SUCCESS) {
17054 		return (ISC_R_SUCCESS);
17055 	}
17056 
17057 	dns_dbiterator_pause(dbiterator);
17058 
17059 	result = dns_db_findnode(db, name, true, &node);
17060 	if (result != ISC_R_SUCCESS) {
17061 		goto cleanup;
17062 	}
17063 
17064 	result = dns_db_allrdatasets(rawdb, rawnode, NULL, 0, 0, &rdsit);
17065 	if (result != ISC_R_SUCCESS) {
17066 		goto cleanup;
17067 	}
17068 
17069 	dns_rdataset_init(&rdataset);
17070 
17071 	for (result = dns_rdatasetiter_first(rdsit); result == ISC_R_SUCCESS;
17072 	     result = dns_rdatasetiter_next(rdsit))
17073 	{
17074 		dns_rdatasetiter_current(rdsit, &rdataset);
17075 		if (rdataset.type == dns_rdatatype_nsec ||
17076 		    rdataset.type == dns_rdatatype_rrsig ||
17077 		    rdataset.type == dns_rdatatype_nsec3 ||
17078 		    rdataset.type == dns_rdatatype_dnskey ||
17079 		    rdataset.type == dns_rdatatype_nsec3param)
17080 		{
17081 			dns_rdataset_disassociate(&rdataset);
17082 			continue;
17083 		}
17084 		if (rdataset.type == dns_rdatatype_soa && oldserial != NULL) {
17085 			result = checkandaddsoa(db, node, version, &rdataset,
17086 						*oldserial);
17087 		} else {
17088 			result = dns_db_addrdataset(db, node, version, 0,
17089 						    &rdataset, 0, NULL);
17090 		}
17091 		dns_rdataset_disassociate(&rdataset);
17092 		if (result != ISC_R_SUCCESS) {
17093 			goto cleanup;
17094 		}
17095 	}
17096 	if (result == ISC_R_NOMORE) {
17097 		result = ISC_R_SUCCESS;
17098 	}
17099 
17100 cleanup:
17101 	if (rdsit != NULL) {
17102 		dns_rdatasetiter_destroy(&rdsit);
17103 	}
17104 	if (rawnode) {
17105 		dns_db_detachnode(rawdb, &rawnode);
17106 	}
17107 	if (node) {
17108 		dns_db_detachnode(db, &node);
17109 	}
17110 	return (result);
17111 }
17112 
17113 static void
receive_secure_db(isc_task_t * task,isc_event_t * event)17114 receive_secure_db(isc_task_t *task, isc_event_t *event) {
17115 	isc_result_t result;
17116 	dns_zone_t *zone;
17117 	dns_db_t *rawdb, *db = NULL;
17118 	dns_dbiterator_t *dbiterator = NULL;
17119 	dns_dbversion_t *version = NULL;
17120 	isc_time_t loadtime;
17121 	unsigned int oldserial = 0, *oldserialp = NULL;
17122 	nsec3paramlist_t nsec3list;
17123 	isc_event_t *setnsec3param_event;
17124 	dns_zone_t *dummy;
17125 
17126 	UNUSED(task);
17127 
17128 	ISC_LIST_INIT(nsec3list);
17129 
17130 	zone = event->ev_arg;
17131 	rawdb = ((struct secure_event *)event)->db;
17132 	isc_event_free(&event);
17133 
17134 	LOCK_ZONE(zone);
17135 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || !inline_secure(zone)) {
17136 		result = ISC_R_SHUTTINGDOWN;
17137 		goto failure;
17138 	}
17139 
17140 	TIME_NOW(&loadtime);
17141 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
17142 	if (zone->db != NULL) {
17143 		result = dns_db_getsoaserial(zone->db, NULL, &oldserial);
17144 		if (result == ISC_R_SUCCESS) {
17145 			oldserialp = &oldserial;
17146 		}
17147 
17148 		/*
17149 		 * assemble nsec3parameters from the old zone, and set a flag
17150 		 * if any are found
17151 		 */
17152 		result = save_nsec3param(zone, &nsec3list);
17153 		if (result != ISC_R_SUCCESS) {
17154 			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17155 			goto failure;
17156 		}
17157 	}
17158 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17159 
17160 	result = dns_db_create(zone->mctx, zone->db_argv[0], &zone->origin,
17161 			       dns_dbtype_zone, zone->rdclass,
17162 			       zone->db_argc - 1, zone->db_argv + 1, &db);
17163 	if (result != ISC_R_SUCCESS) {
17164 		goto failure;
17165 	}
17166 
17167 	result = dns_db_setgluecachestats(db, zone->gluecachestats);
17168 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) {
17169 		goto failure;
17170 	}
17171 
17172 	result = dns_db_newversion(db, &version);
17173 	if (result != ISC_R_SUCCESS) {
17174 		goto failure;
17175 	}
17176 
17177 	result = dns_db_createiterator(rawdb, 0, &dbiterator);
17178 	if (result != ISC_R_SUCCESS) {
17179 		goto failure;
17180 	}
17181 
17182 	for (result = dns_dbiterator_first(dbiterator); result == ISC_R_SUCCESS;
17183 	     result = dns_dbiterator_next(dbiterator))
17184 	{
17185 		result = copy_non_dnssec_records(db, version, rawdb, dbiterator,
17186 						 oldserialp);
17187 		if (result != ISC_R_SUCCESS) {
17188 			goto failure;
17189 		}
17190 	}
17191 	dns_dbiterator_destroy(&dbiterator);
17192 	if (result != ISC_R_NOMORE) {
17193 		goto failure;
17194 	}
17195 
17196 	/*
17197 	 * Call restore_nsec3param() to create private-type records from
17198 	 * the old nsec3 parameters and insert them into db
17199 	 */
17200 	if (!ISC_LIST_EMPTY(nsec3list)) {
17201 		result = restore_nsec3param(zone, db, version, &nsec3list);
17202 		if (result != ISC_R_SUCCESS) {
17203 			goto failure;
17204 		}
17205 	}
17206 
17207 	dns_db_closeversion(db, &version, true);
17208 
17209 	/*
17210 	 * Lock hierarchy: zmgr, zone, raw.
17211 	 */
17212 	INSIST(zone != zone->raw);
17213 	LOCK_ZONE(zone->raw);
17214 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
17215 	result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
17216 	zone_needdump(zone, 0); /* XXXMPA */
17217 	UNLOCK_ZONE(zone->raw);
17218 
17219 	/*
17220 	 * Process any queued NSEC3PARAM change requests.
17221 	 */
17222 	while (!ISC_LIST_EMPTY(zone->setnsec3param_queue)) {
17223 		setnsec3param_event = ISC_LIST_HEAD(zone->setnsec3param_queue);
17224 		ISC_LIST_UNLINK(zone->setnsec3param_queue, setnsec3param_event,
17225 				ev_link);
17226 		dummy = NULL;
17227 		zone_iattach(zone, &dummy);
17228 		isc_task_send(zone->task, &setnsec3param_event);
17229 	}
17230 
17231 failure:
17232 	UNLOCK_ZONE(zone);
17233 	if (dbiterator != NULL) {
17234 		dns_dbiterator_destroy(&dbiterator);
17235 	}
17236 	if (result != ISC_R_SUCCESS) {
17237 		dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_db: %s",
17238 			     dns_result_totext(result));
17239 	}
17240 
17241 	while (!ISC_LIST_EMPTY(nsec3list)) {
17242 		nsec3param_t *nsec3p;
17243 		nsec3p = ISC_LIST_HEAD(nsec3list);
17244 		ISC_LIST_UNLINK(nsec3list, nsec3p, link);
17245 		isc_mem_put(zone->mctx, nsec3p, sizeof(nsec3param_t));
17246 	}
17247 	if (db != NULL) {
17248 		if (version != NULL) {
17249 			dns_db_closeversion(db, &version, false);
17250 		}
17251 		dns_db_detach(&db);
17252 	}
17253 	dns_db_detach(&rawdb);
17254 	dns_zone_idetach(&zone);
17255 
17256 	INSIST(version == NULL);
17257 }
17258 
17259 static isc_result_t
zone_send_securedb(dns_zone_t * zone,dns_db_t * db)17260 zone_send_securedb(dns_zone_t *zone, dns_db_t *db) {
17261 	isc_event_t *e;
17262 	dns_db_t *dummy = NULL;
17263 	dns_zone_t *secure = NULL;
17264 
17265 	e = isc_event_allocate(zone->secure->mctx, zone, DNS_EVENT_ZONESECUREDB,
17266 			       receive_secure_db, zone->secure,
17267 			       sizeof(struct secure_event));
17268 	dns_db_attach(db, &dummy);
17269 	((struct secure_event *)e)->db = dummy;
17270 	INSIST(LOCKED_ZONE(zone->secure));
17271 	zone_iattach(zone->secure, &secure);
17272 	isc_task_send(zone->secure->task, &e);
17273 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
17274 	return (ISC_R_SUCCESS);
17275 }
17276 
17277 isc_result_t
dns_zone_replacedb(dns_zone_t * zone,dns_db_t * db,bool dump)17278 dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump) {
17279 	isc_result_t result;
17280 	dns_zone_t *secure = NULL;
17281 
17282 	REQUIRE(DNS_ZONE_VALID(zone));
17283 again:
17284 	LOCK_ZONE(zone);
17285 	if (inline_raw(zone)) {
17286 		secure = zone->secure;
17287 		INSIST(secure != zone);
17288 		TRYLOCK_ZONE(result, secure);
17289 		if (result != ISC_R_SUCCESS) {
17290 			UNLOCK_ZONE(zone);
17291 			secure = NULL;
17292 			isc_thread_yield();
17293 			goto again;
17294 		}
17295 	}
17296 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
17297 	result = zone_replacedb(zone, db, dump);
17298 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
17299 	if (secure != NULL) {
17300 		UNLOCK_ZONE(secure);
17301 	}
17302 	UNLOCK_ZONE(zone);
17303 	return (result);
17304 }
17305 
17306 static isc_result_t
zone_replacedb(dns_zone_t * zone,dns_db_t * db,bool dump)17307 zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump) {
17308 	dns_dbversion_t *ver;
17309 	isc_result_t result;
17310 	unsigned int soacount = 0;
17311 	unsigned int nscount = 0;
17312 
17313 	/*
17314 	 * 'zone' and 'zone->db' locked by caller.
17315 	 */
17316 	REQUIRE(DNS_ZONE_VALID(zone));
17317 	REQUIRE(LOCKED_ZONE(zone));
17318 	if (inline_raw(zone)) {
17319 		REQUIRE(LOCKED_ZONE(zone->secure));
17320 	}
17321 
17322 	result = zone_get_from_db(zone, db, &nscount, &soacount, NULL, NULL,
17323 				  NULL, NULL, NULL, NULL, NULL);
17324 	if (result == ISC_R_SUCCESS) {
17325 		if (soacount != 1) {
17326 			dns_zone_log(zone, ISC_LOG_ERROR, "has %d SOA records",
17327 				     soacount);
17328 			result = DNS_R_BADZONE;
17329 		}
17330 		if (nscount == 0 && zone->type != dns_zone_key) {
17331 			dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records");
17332 			result = DNS_R_BADZONE;
17333 		}
17334 		if (result != ISC_R_SUCCESS) {
17335 			return (result);
17336 		}
17337 	} else {
17338 		dns_zone_log(zone, ISC_LOG_ERROR,
17339 			     "retrieving SOA and NS records failed: %s",
17340 			     dns_result_totext(result));
17341 		return (result);
17342 	}
17343 
17344 	result = check_nsec3param(zone, db);
17345 	if (result != ISC_R_SUCCESS) {
17346 		return (result);
17347 	}
17348 
17349 	ver = NULL;
17350 	dns_db_currentversion(db, &ver);
17351 
17352 	/*
17353 	 * The initial version of a slave zone is always dumped;
17354 	 * subsequent versions may be journaled instead if this
17355 	 * is enabled in the configuration.
17356 	 */
17357 	if (zone->db != NULL && zone->journal != NULL &&
17358 	    DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
17359 	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER))
17360 	{
17361 		uint32_t serial, oldserial;
17362 
17363 		dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
17364 
17365 		result = dns_db_getsoaserial(db, ver, &serial);
17366 		if (result != ISC_R_SUCCESS) {
17367 			dns_zone_log(zone, ISC_LOG_ERROR,
17368 				     "ixfr-from-differences: unable to get "
17369 				     "new serial");
17370 			goto fail;
17371 		}
17372 
17373 		/*
17374 		 * This is checked in zone_postload() for master zones.
17375 		 */
17376 		result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL,
17377 					  &oldserial, NULL, NULL, NULL, NULL,
17378 					  NULL);
17379 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
17380 		RUNTIME_CHECK(soacount > 0U);
17381 		if ((zone->type == dns_zone_secondary ||
17382 		     (zone->type == dns_zone_redirect &&
17383 		      zone->masters != NULL)) &&
17384 		    !isc_serial_gt(serial, oldserial))
17385 		{
17386 			uint32_t serialmin, serialmax;
17387 			serialmin = (oldserial + 1) & 0xffffffffU;
17388 			serialmax = (oldserial + 0x7fffffffU) & 0xffffffffU;
17389 			dns_zone_log(zone, ISC_LOG_ERROR,
17390 				     "ixfr-from-differences: failed: "
17391 				     "new serial (%u) out of range [%u - %u]",
17392 				     serial, serialmin, serialmax);
17393 			result = ISC_R_RANGE;
17394 			goto fail;
17395 		}
17396 
17397 		result = dns_db_diff(zone->mctx, db, ver, zone->db, NULL,
17398 				     zone->journal);
17399 		if (result != ISC_R_SUCCESS) {
17400 			char strbuf[ISC_STRERRORSIZE];
17401 			strerror_r(errno, strbuf, sizeof(strbuf));
17402 			dns_zone_log(zone, ISC_LOG_ERROR,
17403 				     "ixfr-from-differences: failed: "
17404 				     "%s",
17405 				     strbuf);
17406 			goto fallback;
17407 		}
17408 		if (dump) {
17409 			zone_needdump(zone, DNS_DUMP_DELAY);
17410 		} else {
17411 			zone_journal_compact(zone, zone->db, serial);
17412 		}
17413 		if (zone->type == dns_zone_primary && inline_raw(zone)) {
17414 			zone_send_secureserial(zone, serial);
17415 		}
17416 	} else {
17417 	fallback:
17418 		if (dump && zone->masterfile != NULL) {
17419 			/*
17420 			 * If DNS_ZONEFLG_FORCEXFER was set we don't want
17421 			 * to keep the old masterfile.
17422 			 */
17423 			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) &&
17424 			    remove(zone->masterfile) < 0 && errno != ENOENT)
17425 			{
17426 				char strbuf[ISC_STRERRORSIZE];
17427 				strerror_r(errno, strbuf, sizeof(strbuf));
17428 				isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
17429 					      DNS_LOGMODULE_ZONE,
17430 					      ISC_LOG_WARNING,
17431 					      "unable to remove masterfile "
17432 					      "'%s': '%s'",
17433 					      zone->masterfile, strbuf);
17434 			}
17435 			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0) {
17436 				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NODELAY);
17437 			} else {
17438 				zone_needdump(zone, 0);
17439 			}
17440 		}
17441 		if (dump && zone->journal != NULL) {
17442 			/*
17443 			 * The in-memory database just changed, and
17444 			 * because 'dump' is set, it didn't change by
17445 			 * being loaded from disk.  Also, we have not
17446 			 * journaled diffs for this change.
17447 			 * Therefore, the on-disk journal is missing
17448 			 * the deltas for this change.	Since it can
17449 			 * no longer be used to bring the zone
17450 			 * up-to-date, it is useless and should be
17451 			 * removed.
17452 			 */
17453 			isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
17454 				      DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
17455 				      "removing journal file");
17456 			if (remove(zone->journal) < 0 && errno != ENOENT) {
17457 				char strbuf[ISC_STRERRORSIZE];
17458 				strerror_r(errno, strbuf, sizeof(strbuf));
17459 				isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
17460 					      DNS_LOGMODULE_ZONE,
17461 					      ISC_LOG_WARNING,
17462 					      "unable to remove journal "
17463 					      "'%s': '%s'",
17464 					      zone->journal, strbuf);
17465 			}
17466 		}
17467 
17468 		if (inline_raw(zone)) {
17469 			zone_send_securedb(zone, db);
17470 		}
17471 	}
17472 
17473 	dns_db_closeversion(db, &ver, false);
17474 
17475 	dns_zone_log(zone, ISC_LOG_DEBUG(3), "replacing zone database");
17476 
17477 	if (zone->db != NULL) {
17478 		zone_detachdb(zone);
17479 	}
17480 	zone_attachdb(zone, db);
17481 	dns_db_settask(zone->db, zone->task);
17482 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED | DNS_ZONEFLG_NEEDNOTIFY);
17483 	return (ISC_R_SUCCESS);
17484 
17485 fail:
17486 	dns_db_closeversion(db, &ver, false);
17487 	return (result);
17488 }
17489 
17490 /* The caller must hold the dblock as a writer. */
17491 static void
zone_attachdb(dns_zone_t * zone,dns_db_t * db)17492 zone_attachdb(dns_zone_t *zone, dns_db_t *db) {
17493 	REQUIRE(zone->db == NULL && db != NULL);
17494 
17495 	dns_db_attach(db, &zone->db);
17496 }
17497 
17498 /* The caller must hold the dblock as a writer. */
17499 static void
zone_detachdb(dns_zone_t * zone)17500 zone_detachdb(dns_zone_t *zone) {
17501 	REQUIRE(zone->db != NULL);
17502 
17503 	dns_zone_rpz_disable_db(zone, zone->db);
17504 	dns_zone_catz_disable_db(zone, zone->db);
17505 	dns_db_detach(&zone->db);
17506 }
17507 
17508 static void
zone_xfrdone(dns_zone_t * zone,isc_result_t result)17509 zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
17510 	isc_time_t now;
17511 	bool again = false;
17512 	unsigned int soacount;
17513 	unsigned int nscount;
17514 	uint32_t serial, refresh, retry, expire, minimum, soattl;
17515 	isc_result_t xfrresult = result;
17516 	bool free_needed;
17517 	dns_zone_t *secure = NULL;
17518 
17519 	REQUIRE(DNS_ZONE_VALID(zone));
17520 
17521 	dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(1),
17522 		      "zone transfer finished: %s", dns_result_totext(result));
17523 
17524 	/*
17525 	 * Obtaining a lock on the zone->secure (see zone_send_secureserial)
17526 	 * could result in a deadlock due to a LOR so we will spin if we
17527 	 * can't obtain the both locks.
17528 	 */
17529 again:
17530 	LOCK_ZONE(zone);
17531 	if (inline_raw(zone)) {
17532 		secure = zone->secure;
17533 		INSIST(secure != zone);
17534 		TRYLOCK_ZONE(result, secure);
17535 		if (result != ISC_R_SUCCESS) {
17536 			UNLOCK_ZONE(zone);
17537 			secure = NULL;
17538 			isc_thread_yield();
17539 			goto again;
17540 		}
17541 	}
17542 
17543 	INSIST(DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH));
17544 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
17545 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
17546 
17547 	TIME_NOW(&now);
17548 	switch (xfrresult) {
17549 	case ISC_R_SUCCESS:
17550 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
17551 		FALLTHROUGH;
17552 	case DNS_R_UPTODATE:
17553 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FORCEXFER);
17554 		/*
17555 		 * Has the zone expired underneath us?
17556 		 */
17557 		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
17558 		if (zone->db == NULL) {
17559 			ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17560 			goto same_master;
17561 		}
17562 
17563 		/*
17564 		 * Update the zone structure's data from the actual
17565 		 * SOA received.
17566 		 */
17567 		nscount = 0;
17568 		soacount = 0;
17569 		INSIST(zone->db != NULL);
17570 		result = zone_get_from_db(zone, zone->db, &nscount, &soacount,
17571 					  &soattl, &serial, &refresh, &retry,
17572 					  &expire, &minimum, NULL);
17573 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17574 		if (result == ISC_R_SUCCESS) {
17575 			if (soacount != 1) {
17576 				dns_zone_log(zone, ISC_LOG_ERROR,
17577 					     "transferred zone "
17578 					     "has %d SOA records",
17579 					     soacount);
17580 				if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
17581 				{
17582 					zone->refresh = DNS_ZONE_DEFAULTREFRESH;
17583 					zone->retry = DNS_ZONE_DEFAULTRETRY;
17584 				}
17585 				DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
17586 				zone_unload(zone);
17587 				goto next_master;
17588 			}
17589 			if (nscount == 0) {
17590 				dns_zone_log(zone, ISC_LOG_ERROR,
17591 					     "transferred zone "
17592 					     "has no NS records");
17593 				if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
17594 				{
17595 					zone->refresh = DNS_ZONE_DEFAULTREFRESH;
17596 					zone->retry = DNS_ZONE_DEFAULTRETRY;
17597 				}
17598 				DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
17599 				zone_unload(zone);
17600 				goto next_master;
17601 			}
17602 			zone->refresh = RANGE(refresh, zone->minrefresh,
17603 					      zone->maxrefresh);
17604 			zone->retry = RANGE(retry, zone->minretry,
17605 					    zone->maxretry);
17606 			zone->expire = RANGE(expire,
17607 					     zone->refresh + zone->retry,
17608 					     DNS_MAX_EXPIRE);
17609 			zone->soattl = soattl;
17610 			zone->minimum = minimum;
17611 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
17612 		}
17613 
17614 		/*
17615 		 * Set our next update/expire times.
17616 		 */
17617 		if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
17618 			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
17619 			zone->refreshtime = now;
17620 			DNS_ZONE_TIME_ADD(&now, zone->expire,
17621 					  &zone->expiretime);
17622 		} else {
17623 			DNS_ZONE_JITTER_ADD(&now, zone->refresh,
17624 					    &zone->refreshtime);
17625 			DNS_ZONE_TIME_ADD(&now, zone->expire,
17626 					  &zone->expiretime);
17627 		}
17628 		if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS) {
17629 			char buf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
17630 			if (zone->tsigkey != NULL) {
17631 				char namebuf[DNS_NAME_FORMATSIZE];
17632 				dns_name_format(&zone->tsigkey->name, namebuf,
17633 						sizeof(namebuf));
17634 				snprintf(buf, sizeof(buf), ": TSIG '%s'",
17635 					 namebuf);
17636 			} else {
17637 				buf[0] = '\0';
17638 			}
17639 			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
17640 				      ISC_LOG_INFO, "transferred serial %u%s",
17641 				      serial, buf);
17642 			if (inline_raw(zone)) {
17643 				zone_send_secureserial(zone, serial);
17644 			}
17645 		}
17646 
17647 		/*
17648 		 * This is not necessary if we just performed a AXFR
17649 		 * however it is necessary for an IXFR / UPTODATE and
17650 		 * won't hurt with an AXFR.
17651 		 */
17652 		if (zone->masterfile != NULL || zone->journal != NULL) {
17653 			unsigned int delay = DNS_DUMP_DELAY;
17654 
17655 			result = ISC_R_FAILURE;
17656 			if (zone->journal != NULL) {
17657 				result = isc_file_settime(zone->journal, &now);
17658 			}
17659 			if (result != ISC_R_SUCCESS && zone->masterfile != NULL)
17660 			{
17661 				result = isc_file_settime(zone->masterfile,
17662 							  &now);
17663 			}
17664 
17665 			if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NODELAY) != 0) ||
17666 			    result == ISC_R_FILENOTFOUND)
17667 			{
17668 				delay = 0;
17669 			}
17670 
17671 			if ((result == ISC_R_SUCCESS ||
17672 			     result == ISC_R_FILENOTFOUND) &&
17673 			    zone->masterfile != NULL)
17674 			{
17675 				zone_needdump(zone, delay);
17676 			} else if (result != ISC_R_SUCCESS) {
17677 				dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
17678 					      ISC_LOG_ERROR,
17679 					      "transfer: could not set file "
17680 					      "modification time of '%s': %s",
17681 					      zone->masterfile,
17682 					      dns_result_totext(result));
17683 			}
17684 		}
17685 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NODELAY);
17686 		inc_stats(zone, dns_zonestatscounter_xfrsuccess);
17687 		break;
17688 
17689 	case DNS_R_BADIXFR:
17690 		/* Force retry with AXFR. */
17691 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOIXFR);
17692 		goto same_master;
17693 
17694 	case DNS_R_TOOMANYRECORDS:
17695 	case DNS_R_VERIFYFAILURE:
17696 		DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
17697 		inc_stats(zone, dns_zonestatscounter_xfrfail);
17698 		break;
17699 
17700 	default:
17701 	next_master:
17702 		/*
17703 		 * Skip to next failed / untried master.
17704 		 */
17705 		do {
17706 			zone->curmaster++;
17707 		} while (zone->curmaster < zone->masterscnt &&
17708 			 zone->mastersok[zone->curmaster]);
17709 	same_master:
17710 		if (zone->curmaster >= zone->masterscnt) {
17711 			zone->curmaster = 0;
17712 			if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
17713 			    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
17714 			{
17715 				DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
17716 				DNS_ZONE_SETFLAG(zone,
17717 						 DNS_ZONEFLG_USEALTXFRSRC);
17718 				while (zone->curmaster < zone->masterscnt &&
17719 				       zone->mastersok[zone->curmaster])
17720 				{
17721 					zone->curmaster++;
17722 				}
17723 				again = true;
17724 			} else {
17725 				DNS_ZONE_CLRFLAG(zone,
17726 						 DNS_ZONEFLG_USEALTXFRSRC);
17727 			}
17728 		} else {
17729 			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
17730 			again = true;
17731 		}
17732 		inc_stats(zone, dns_zonestatscounter_xfrfail);
17733 		break;
17734 	}
17735 	zone_settimer(zone, &now);
17736 
17737 	/*
17738 	 * If creating the transfer object failed, zone->xfr is NULL.
17739 	 * Otherwise, we are called as the done callback of a zone
17740 	 * transfer object that just entered its shutting-down
17741 	 * state.  Since we are no longer responsible for shutting
17742 	 * it down, we can detach our reference.
17743 	 */
17744 	if (zone->xfr != NULL) {
17745 		dns_xfrin_detach(&zone->xfr);
17746 	}
17747 
17748 	if (zone->tsigkey != NULL) {
17749 		dns_tsigkey_detach(&zone->tsigkey);
17750 	}
17751 
17752 	/*
17753 	 * Handle any deferred journal compaction.
17754 	 */
17755 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDCOMPACT)) {
17756 		dns_db_t *db = NULL;
17757 		if (dns_zone_getdb(zone, &db) == ISC_R_SUCCESS) {
17758 			zone_journal_compact(zone, db, zone->compact_serial);
17759 			dns_db_detach(&db);
17760 			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
17761 		}
17762 	}
17763 
17764 	if (secure != NULL) {
17765 		UNLOCK_ZONE(secure);
17766 	}
17767 	/*
17768 	 * This transfer finishing freed up a transfer quota slot.
17769 	 * Let any other zones waiting for quota have it.
17770 	 */
17771 	if (zone->zmgr != NULL &&
17772 	    zone->statelist == &zone->zmgr->xfrin_in_progress)
17773 	{
17774 		UNLOCK_ZONE(zone);
17775 		RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
17776 		ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
17777 		zone->statelist = NULL;
17778 		zmgr_resume_xfrs(zone->zmgr, false);
17779 		RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
17780 		LOCK_ZONE(zone);
17781 	}
17782 
17783 	/*
17784 	 * Retry with a different server if necessary.
17785 	 */
17786 	if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
17787 		queue_soa_query(zone);
17788 	}
17789 
17790 	isc_refcount_decrement(&zone->irefs);
17791 	free_needed = exit_check(zone);
17792 	UNLOCK_ZONE(zone);
17793 	if (free_needed) {
17794 		zone_free(zone);
17795 	}
17796 }
17797 
17798 static void
zone_loaddone(void * arg,isc_result_t result)17799 zone_loaddone(void *arg, isc_result_t result) {
17800 	static char me[] = "zone_loaddone";
17801 	dns_load_t *load = arg;
17802 	dns_zone_t *zone;
17803 	isc_result_t tresult;
17804 	dns_zone_t *secure = NULL;
17805 
17806 	REQUIRE(DNS_LOAD_VALID(load));
17807 	zone = load->zone;
17808 
17809 	ENTER;
17810 
17811 	/*
17812 	 * If zone loading failed, remove the update db callbacks prior
17813 	 * to calling the list of callbacks in the zone load structure.
17814 	 */
17815 	if (result != ISC_R_SUCCESS) {
17816 		dns_zone_rpz_disable_db(zone, load->db);
17817 		dns_zone_catz_disable_db(zone, load->db);
17818 	}
17819 
17820 	tresult = dns_db_endload(load->db, &load->callbacks);
17821 	if (tresult != ISC_R_SUCCESS &&
17822 	    (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
17823 	{
17824 		result = tresult;
17825 	}
17826 
17827 	/*
17828 	 * Lock hierarchy: zmgr, zone, raw.
17829 	 */
17830 again:
17831 	LOCK_ZONE(zone);
17832 	INSIST(zone != zone->raw);
17833 	if (inline_secure(zone)) {
17834 		LOCK_ZONE(zone->raw);
17835 	} else if (inline_raw(zone)) {
17836 		secure = zone->secure;
17837 		TRYLOCK_ZONE(tresult, secure);
17838 		if (tresult != ISC_R_SUCCESS) {
17839 			UNLOCK_ZONE(zone);
17840 			secure = NULL;
17841 			isc_thread_yield();
17842 			goto again;
17843 		}
17844 	}
17845 	(void)zone_postload(zone, load->db, load->loadtime, result);
17846 	zonemgr_putio(&zone->readio);
17847 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADING);
17848 	zone_idetach(&load->callbacks.zone);
17849 	/*
17850 	 * Leave the zone frozen if the reload fails.
17851 	 */
17852 	if ((result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) &&
17853 	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_THAW))
17854 	{
17855 		zone->update_disabled = false;
17856 	}
17857 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_THAW);
17858 	if (inline_secure(zone)) {
17859 		UNLOCK_ZONE(zone->raw);
17860 	} else if (secure != NULL) {
17861 		UNLOCK_ZONE(secure);
17862 	}
17863 	UNLOCK_ZONE(zone);
17864 
17865 	load->magic = 0;
17866 	dns_db_detach(&load->db);
17867 	if (load->zone->lctx != NULL) {
17868 		dns_loadctx_detach(&load->zone->lctx);
17869 	}
17870 	dns_zone_idetach(&load->zone);
17871 	isc_mem_putanddetach(&load->mctx, load, sizeof(*load));
17872 }
17873 
17874 void
dns_zone_getssutable(dns_zone_t * zone,dns_ssutable_t ** table)17875 dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) {
17876 	REQUIRE(DNS_ZONE_VALID(zone));
17877 	REQUIRE(table != NULL);
17878 	REQUIRE(*table == NULL);
17879 
17880 	LOCK_ZONE(zone);
17881 	if (zone->ssutable != NULL) {
17882 		dns_ssutable_attach(zone->ssutable, table);
17883 	}
17884 	UNLOCK_ZONE(zone);
17885 }
17886 
17887 void
dns_zone_setssutable(dns_zone_t * zone,dns_ssutable_t * table)17888 dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
17889 	REQUIRE(DNS_ZONE_VALID(zone));
17890 
17891 	LOCK_ZONE(zone);
17892 	if (zone->ssutable != NULL) {
17893 		dns_ssutable_detach(&zone->ssutable);
17894 	}
17895 	if (table != NULL) {
17896 		dns_ssutable_attach(table, &zone->ssutable);
17897 	}
17898 	UNLOCK_ZONE(zone);
17899 }
17900 
17901 void
dns_zone_setsigvalidityinterval(dns_zone_t * zone,uint32_t interval)17902 dns_zone_setsigvalidityinterval(dns_zone_t *zone, uint32_t interval) {
17903 	REQUIRE(DNS_ZONE_VALID(zone));
17904 
17905 	zone->sigvalidityinterval = interval;
17906 }
17907 
17908 uint32_t
dns_zone_getsigvalidityinterval(dns_zone_t * zone)17909 dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
17910 	REQUIRE(DNS_ZONE_VALID(zone));
17911 
17912 	return (zone->sigvalidityinterval);
17913 }
17914 
17915 void
dns_zone_setkeyvalidityinterval(dns_zone_t * zone,uint32_t interval)17916 dns_zone_setkeyvalidityinterval(dns_zone_t *zone, uint32_t interval) {
17917 	REQUIRE(DNS_ZONE_VALID(zone));
17918 
17919 	zone->keyvalidityinterval = interval;
17920 }
17921 
17922 uint32_t
dns_zone_getkeyvalidityinterval(dns_zone_t * zone)17923 dns_zone_getkeyvalidityinterval(dns_zone_t *zone) {
17924 	REQUIRE(DNS_ZONE_VALID(zone));
17925 
17926 	return (zone->keyvalidityinterval);
17927 }
17928 
17929 void
dns_zone_setsigresigninginterval(dns_zone_t * zone,uint32_t interval)17930 dns_zone_setsigresigninginterval(dns_zone_t *zone, uint32_t interval) {
17931 	isc_time_t now;
17932 
17933 	REQUIRE(DNS_ZONE_VALID(zone));
17934 
17935 	LOCK_ZONE(zone);
17936 	zone->sigresigninginterval = interval;
17937 	set_resigntime(zone);
17938 	if (zone->task != NULL) {
17939 		TIME_NOW(&now);
17940 		zone_settimer(zone, &now);
17941 	}
17942 	UNLOCK_ZONE(zone);
17943 }
17944 
17945 uint32_t
dns_zone_getsigresigninginterval(dns_zone_t * zone)17946 dns_zone_getsigresigninginterval(dns_zone_t *zone) {
17947 	REQUIRE(DNS_ZONE_VALID(zone));
17948 
17949 	return (zone->sigresigninginterval);
17950 }
17951 
17952 static void
queue_xfrin(dns_zone_t * zone)17953 queue_xfrin(dns_zone_t *zone) {
17954 	const char me[] = "queue_xfrin";
17955 	isc_result_t result;
17956 	dns_zonemgr_t *zmgr = zone->zmgr;
17957 
17958 	ENTER;
17959 
17960 	INSIST(zone->statelist == NULL);
17961 
17962 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
17963 	ISC_LIST_APPEND(zmgr->waiting_for_xfrin, zone, statelink);
17964 	isc_refcount_increment0(&zone->irefs);
17965 	zone->statelist = &zmgr->waiting_for_xfrin;
17966 	result = zmgr_start_xfrin_ifquota(zmgr, zone);
17967 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
17968 
17969 	if (result == ISC_R_QUOTA) {
17970 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
17971 			      "zone transfer deferred due to quota");
17972 	} else if (result != ISC_R_SUCCESS) {
17973 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
17974 			      "starting zone transfer: %s",
17975 			      isc_result_totext(result));
17976 	}
17977 }
17978 
17979 /*
17980  * This event callback is called when a zone has received
17981  * any necessary zone transfer quota.  This is the time
17982  * to go ahead and start the transfer.
17983  */
17984 static void
got_transfer_quota(isc_task_t * task,isc_event_t * event)17985 got_transfer_quota(isc_task_t *task, isc_event_t *event) {
17986 	isc_result_t result = ISC_R_SUCCESS;
17987 	dns_peer_t *peer = NULL;
17988 	char master[ISC_SOCKADDR_FORMATSIZE];
17989 	char source[ISC_SOCKADDR_FORMATSIZE];
17990 	dns_rdatatype_t xfrtype;
17991 	dns_zone_t *zone = event->ev_arg;
17992 	isc_netaddr_t masterip;
17993 	isc_sockaddr_t sourceaddr;
17994 	isc_sockaddr_t masteraddr;
17995 	isc_time_t now;
17996 	const char *soa_before = "";
17997 	isc_dscp_t dscp = -1;
17998 	bool loaded;
17999 
18000 	UNUSED(task);
18001 
18002 	INSIST(task == zone->task);
18003 
18004 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
18005 		result = ISC_R_CANCELED;
18006 		goto cleanup;
18007 	}
18008 
18009 	TIME_NOW(&now);
18010 
18011 	isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
18012 	if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
18013 				    &zone->sourceaddr, &now))
18014 	{
18015 		isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
18016 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
18017 			      "got_transfer_quota: skipping zone transfer as "
18018 			      "master %s (source %s) is unreachable (cached)",
18019 			      master, source);
18020 		result = ISC_R_CANCELED;
18021 		goto cleanup;
18022 	}
18023 
18024 	isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
18025 	(void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
18026 
18027 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR)) {
18028 		soa_before = "SOA before ";
18029 	}
18030 	/*
18031 	 * Decide whether we should request IXFR or AXFR.
18032 	 */
18033 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
18034 	loaded = (zone->db != NULL);
18035 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
18036 
18037 	if (!loaded) {
18038 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(1),
18039 			      "no database exists yet, requesting AXFR of "
18040 			      "initial version from %s",
18041 			      master);
18042 		xfrtype = dns_rdatatype_axfr;
18043 	} else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
18044 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(1),
18045 			      "forced reload, requesting AXFR of "
18046 			      "initial version from %s",
18047 			      master);
18048 		xfrtype = dns_rdatatype_axfr;
18049 	} else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOIXFR)) {
18050 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(1),
18051 			      "retrying with AXFR from %s due to "
18052 			      "previous IXFR failure",
18053 			      master);
18054 		xfrtype = dns_rdatatype_axfr;
18055 		LOCK_ZONE(zone);
18056 		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOIXFR);
18057 		UNLOCK_ZONE(zone);
18058 	} else {
18059 		bool use_ixfr = true;
18060 		if (peer != NULL) {
18061 			result = dns_peer_getrequestixfr(peer, &use_ixfr);
18062 		}
18063 		if (peer == NULL || result != ISC_R_SUCCESS) {
18064 			use_ixfr = zone->requestixfr;
18065 		}
18066 		if (!use_ixfr) {
18067 			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
18068 				      ISC_LOG_DEBUG(1),
18069 				      "IXFR disabled, "
18070 				      "requesting %sAXFR from %s",
18071 				      soa_before, master);
18072 			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR)) {
18073 				xfrtype = dns_rdatatype_soa;
18074 			} else {
18075 				xfrtype = dns_rdatatype_axfr;
18076 			}
18077 		} else {
18078 			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
18079 				      ISC_LOG_DEBUG(1),
18080 				      "requesting IXFR from %s", master);
18081 			xfrtype = dns_rdatatype_ixfr;
18082 		}
18083 	}
18084 
18085 	/*
18086 	 * Determine if we should attempt to sign the request with TSIG.
18087 	 */
18088 	result = ISC_R_NOTFOUND;
18089 
18090 	/*
18091 	 * First, look for a tsig key in the master statement, then
18092 	 * try for a server key.
18093 	 */
18094 	if ((zone->masterkeynames != NULL) &&
18095 	    (zone->masterkeynames[zone->curmaster] != NULL))
18096 	{
18097 		dns_view_t *view = dns_zone_getview(zone);
18098 		dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
18099 		result = dns_view_gettsig(view, keyname, &zone->tsigkey);
18100 	}
18101 	if (zone->tsigkey == NULL) {
18102 		result = dns_view_getpeertsig(zone->view, &masterip,
18103 					      &zone->tsigkey);
18104 	}
18105 
18106 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
18107 		dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
18108 			      "could not get TSIG key for zone transfer: %s",
18109 			      isc_result_totext(result));
18110 	}
18111 
18112 	if (zone->masterdscps != NULL) {
18113 		dscp = zone->masterdscps[zone->curmaster];
18114 	}
18115 
18116 	LOCK_ZONE(zone);
18117 	masteraddr = zone->masteraddr;
18118 	sourceaddr = zone->sourceaddr;
18119 	switch (isc_sockaddr_pf(&masteraddr)) {
18120 	case PF_INET:
18121 		if (dscp == -1) {
18122 			dscp = zone->xfrsource4dscp;
18123 		}
18124 		break;
18125 	case PF_INET6:
18126 		if (dscp == -1) {
18127 			dscp = zone->xfrsource6dscp;
18128 		}
18129 		break;
18130 	default:
18131 		UNREACHABLE();
18132 	}
18133 	UNLOCK_ZONE(zone);
18134 	INSIST(isc_sockaddr_pf(&masteraddr) == isc_sockaddr_pf(&sourceaddr));
18135 	result = dns_xfrin_create(zone, xfrtype, &masteraddr, &sourceaddr, dscp,
18136 				  zone->tsigkey, zone->mctx,
18137 				  zone->zmgr->timermgr, zone->zmgr->socketmgr,
18138 				  zone->task, zone_xfrdone, &zone->xfr);
18139 	if (result == ISC_R_SUCCESS) {
18140 		LOCK_ZONE(zone);
18141 		if (xfrtype == dns_rdatatype_axfr) {
18142 			if (isc_sockaddr_pf(&masteraddr) == PF_INET) {
18143 				inc_stats(zone, dns_zonestatscounter_axfrreqv4);
18144 			} else {
18145 				inc_stats(zone, dns_zonestatscounter_axfrreqv6);
18146 			}
18147 		} else if (xfrtype == dns_rdatatype_ixfr) {
18148 			if (isc_sockaddr_pf(&masteraddr) == PF_INET) {
18149 				inc_stats(zone, dns_zonestatscounter_ixfrreqv4);
18150 			} else {
18151 				inc_stats(zone, dns_zonestatscounter_ixfrreqv6);
18152 			}
18153 		}
18154 		UNLOCK_ZONE(zone);
18155 	}
18156 cleanup:
18157 	/*
18158 	 * Any failure in this function is handled like a failed
18159 	 * zone transfer.  This ensures that we get removed from
18160 	 * zmgr->xfrin_in_progress.
18161 	 */
18162 	if (result != ISC_R_SUCCESS) {
18163 		zone_xfrdone(zone, result);
18164 	}
18165 
18166 	isc_event_free(&event);
18167 }
18168 
18169 /*
18170  * Update forwarding support.
18171  */
18172 
18173 static void
forward_destroy(dns_forward_t * forward)18174 forward_destroy(dns_forward_t *forward) {
18175 	forward->magic = 0;
18176 	if (forward->request != NULL) {
18177 		dns_request_destroy(&forward->request);
18178 	}
18179 	if (forward->msgbuf != NULL) {
18180 		isc_buffer_free(&forward->msgbuf);
18181 	}
18182 	if (forward->zone != NULL) {
18183 		LOCK(&forward->zone->lock);
18184 		if (ISC_LINK_LINKED(forward, link)) {
18185 			ISC_LIST_UNLINK(forward->zone->forwards, forward, link);
18186 		}
18187 		UNLOCK(&forward->zone->lock);
18188 		dns_zone_idetach(&forward->zone);
18189 	}
18190 	isc_mem_putanddetach(&forward->mctx, forward, sizeof(*forward));
18191 }
18192 
18193 static isc_result_t
sendtomaster(dns_forward_t * forward)18194 sendtomaster(dns_forward_t *forward) {
18195 	isc_result_t result;
18196 	isc_sockaddr_t src;
18197 	isc_dscp_t dscp = -1;
18198 
18199 	LOCK_ZONE(forward->zone);
18200 
18201 	if (DNS_ZONE_FLAG(forward->zone, DNS_ZONEFLG_EXITING)) {
18202 		UNLOCK_ZONE(forward->zone);
18203 		return (ISC_R_CANCELED);
18204 	}
18205 
18206 	if (forward->which >= forward->zone->masterscnt) {
18207 		UNLOCK_ZONE(forward->zone);
18208 		return (ISC_R_NOMORE);
18209 	}
18210 
18211 	forward->addr = forward->zone->masters[forward->which];
18212 	/*
18213 	 * Always use TCP regardless of whether the original update
18214 	 * used TCP.
18215 	 * XXX The timeout may but a bit small if we are far down a
18216 	 * transfer graph and the master has to try several masters.
18217 	 */
18218 	switch (isc_sockaddr_pf(&forward->addr)) {
18219 	case PF_INET:
18220 		src = forward->zone->xfrsource4;
18221 		dscp = forward->zone->xfrsource4dscp;
18222 		break;
18223 	case PF_INET6:
18224 		src = forward->zone->xfrsource6;
18225 		dscp = forward->zone->xfrsource6dscp;
18226 		break;
18227 	default:
18228 		result = ISC_R_NOTIMPLEMENTED;
18229 		goto unlock;
18230 	}
18231 	result = dns_request_createraw(forward->zone->view->requestmgr,
18232 				       forward->msgbuf, &src, &forward->addr,
18233 				       dscp, forward->options, 15 /* XXX */, 0,
18234 				       0, forward->zone->task, forward_callback,
18235 				       forward, &forward->request);
18236 	if (result == ISC_R_SUCCESS) {
18237 		if (!ISC_LINK_LINKED(forward, link)) {
18238 			ISC_LIST_APPEND(forward->zone->forwards, forward, link);
18239 		}
18240 	}
18241 
18242 unlock:
18243 	UNLOCK_ZONE(forward->zone);
18244 	return (result);
18245 }
18246 
18247 static void
forward_callback(isc_task_t * task,isc_event_t * event)18248 forward_callback(isc_task_t *task, isc_event_t *event) {
18249 	const char me[] = "forward_callback";
18250 	dns_requestevent_t *revent = (dns_requestevent_t *)event;
18251 	dns_message_t *msg = NULL;
18252 	char master[ISC_SOCKADDR_FORMATSIZE];
18253 	isc_result_t result;
18254 	dns_forward_t *forward;
18255 	dns_zone_t *zone;
18256 
18257 	UNUSED(task);
18258 
18259 	forward = revent->ev_arg;
18260 	INSIST(DNS_FORWARD_VALID(forward));
18261 	zone = forward->zone;
18262 	INSIST(DNS_ZONE_VALID(zone));
18263 
18264 	ENTER;
18265 
18266 	isc_sockaddr_format(&forward->addr, master, sizeof(master));
18267 
18268 	if (revent->result != ISC_R_SUCCESS) {
18269 		dns_zone_log(zone, ISC_LOG_INFO,
18270 			     "could not forward dynamic update to %s: %s",
18271 			     master, dns_result_totext(revent->result));
18272 		goto next_master;
18273 	}
18274 
18275 	dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
18276 
18277 	result = dns_request_getresponse(revent->request, msg,
18278 					 DNS_MESSAGEPARSE_PRESERVEORDER |
18279 						 DNS_MESSAGEPARSE_CLONEBUFFER);
18280 	if (result != ISC_R_SUCCESS) {
18281 		goto next_master;
18282 	}
18283 
18284 	/*
18285 	 * Unexpected opcode.
18286 	 */
18287 	if (msg->opcode != dns_opcode_update) {
18288 		char opcode[128];
18289 		isc_buffer_t rb;
18290 
18291 		isc_buffer_init(&rb, opcode, sizeof(opcode));
18292 		(void)dns_opcode_totext(msg->opcode, &rb);
18293 
18294 		dns_zone_log(zone, ISC_LOG_INFO,
18295 			     "forwarding dynamic update: "
18296 			     "unexpected opcode (%.*s) from %s",
18297 			     (int)rb.used, opcode, master);
18298 		goto next_master;
18299 	}
18300 
18301 	switch (msg->rcode) {
18302 	/*
18303 	 * Pass these rcodes back to client.
18304 	 */
18305 	case dns_rcode_noerror:
18306 	case dns_rcode_yxdomain:
18307 	case dns_rcode_yxrrset:
18308 	case dns_rcode_nxrrset:
18309 	case dns_rcode_refused:
18310 	case dns_rcode_nxdomain: {
18311 		char rcode[128];
18312 		isc_buffer_t rb;
18313 
18314 		isc_buffer_init(&rb, rcode, sizeof(rcode));
18315 		(void)dns_rcode_totext(msg->rcode, &rb);
18316 		dns_zone_log(zone, ISC_LOG_INFO,
18317 			     "forwarded dynamic update: "
18318 			     "master %s returned: %.*s",
18319 			     master, (int)rb.used, rcode);
18320 		break;
18321 	}
18322 
18323 	/* These should not occur if the primaries/zone are valid. */
18324 	case dns_rcode_notzone:
18325 	case dns_rcode_notauth: {
18326 		char rcode[128];
18327 		isc_buffer_t rb;
18328 
18329 		isc_buffer_init(&rb, rcode, sizeof(rcode));
18330 		(void)dns_rcode_totext(msg->rcode, &rb);
18331 		dns_zone_log(zone, ISC_LOG_WARNING,
18332 			     "forwarding dynamic update: "
18333 			     "unexpected response: master %s returned: %.*s",
18334 			     master, (int)rb.used, rcode);
18335 		goto next_master;
18336 	}
18337 
18338 	/* Try another server for these rcodes. */
18339 	case dns_rcode_formerr:
18340 	case dns_rcode_servfail:
18341 	case dns_rcode_notimp:
18342 	case dns_rcode_badvers:
18343 	default:
18344 		goto next_master;
18345 	}
18346 
18347 	/* call callback */
18348 	(forward->callback)(forward->callback_arg, ISC_R_SUCCESS, msg);
18349 	msg = NULL;
18350 	dns_request_destroy(&forward->request);
18351 	forward_destroy(forward);
18352 	isc_event_free(&event);
18353 	return;
18354 
18355 next_master:
18356 	if (msg != NULL) {
18357 		dns_message_detach(&msg);
18358 	}
18359 	isc_event_free(&event);
18360 	forward->which++;
18361 	dns_request_destroy(&forward->request);
18362 	result = sendtomaster(forward);
18363 	if (result != ISC_R_SUCCESS) {
18364 		/* call callback */
18365 		dns_zone_log(zone, ISC_LOG_DEBUG(3),
18366 			     "exhausted dynamic update forwarder list");
18367 		(forward->callback)(forward->callback_arg, result, NULL);
18368 		forward_destroy(forward);
18369 	}
18370 }
18371 
18372 isc_result_t
dns_zone_forwardupdate(dns_zone_t * zone,dns_message_t * msg,dns_updatecallback_t callback,void * callback_arg)18373 dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
18374 		       dns_updatecallback_t callback, void *callback_arg) {
18375 	dns_forward_t *forward;
18376 	isc_result_t result;
18377 	isc_region_t *mr;
18378 
18379 	REQUIRE(DNS_ZONE_VALID(zone));
18380 	REQUIRE(msg != NULL);
18381 	REQUIRE(callback != NULL);
18382 
18383 	forward = isc_mem_get(zone->mctx, sizeof(*forward));
18384 
18385 	forward->request = NULL;
18386 	forward->zone = NULL;
18387 	forward->msgbuf = NULL;
18388 	forward->which = 0;
18389 	forward->mctx = 0;
18390 	forward->callback = callback;
18391 	forward->callback_arg = callback_arg;
18392 	ISC_LINK_INIT(forward, link);
18393 	forward->magic = FORWARD_MAGIC;
18394 	forward->options = DNS_REQUESTOPT_TCP;
18395 	/*
18396 	 * If we have a SIG(0) signed message we need to preserve the
18397 	 * query id as that is included in the SIG(0) computation.
18398 	 */
18399 	if (msg->sig0 != NULL) {
18400 		forward->options |= DNS_REQUESTOPT_FIXEDID;
18401 	}
18402 
18403 	mr = dns_message_getrawmessage(msg);
18404 	if (mr == NULL) {
18405 		result = ISC_R_UNEXPECTEDEND;
18406 		goto cleanup;
18407 	}
18408 
18409 	isc_buffer_allocate(zone->mctx, &forward->msgbuf, mr->length);
18410 	result = isc_buffer_copyregion(forward->msgbuf, mr);
18411 	if (result != ISC_R_SUCCESS) {
18412 		goto cleanup;
18413 	}
18414 
18415 	isc_mem_attach(zone->mctx, &forward->mctx);
18416 	dns_zone_iattach(zone, &forward->zone);
18417 	result = sendtomaster(forward);
18418 
18419 cleanup:
18420 	if (result != ISC_R_SUCCESS) {
18421 		forward_destroy(forward);
18422 	}
18423 	return (result);
18424 }
18425 
18426 isc_result_t
dns_zone_next(dns_zone_t * zone,dns_zone_t ** next)18427 dns_zone_next(dns_zone_t *zone, dns_zone_t **next) {
18428 	REQUIRE(DNS_ZONE_VALID(zone));
18429 	REQUIRE(next != NULL && *next == NULL);
18430 
18431 	*next = ISC_LIST_NEXT(zone, link);
18432 	if (*next == NULL) {
18433 		return (ISC_R_NOMORE);
18434 	} else {
18435 		return (ISC_R_SUCCESS);
18436 	}
18437 }
18438 
18439 isc_result_t
dns_zone_first(dns_zonemgr_t * zmgr,dns_zone_t ** first)18440 dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) {
18441 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18442 	REQUIRE(first != NULL && *first == NULL);
18443 
18444 	*first = ISC_LIST_HEAD(zmgr->zones);
18445 	if (*first == NULL) {
18446 		return (ISC_R_NOMORE);
18447 	} else {
18448 		return (ISC_R_SUCCESS);
18449 	}
18450 }
18451 
18452 /***
18453  ***	Zone manager.
18454  ***/
18455 
18456 #define KEYMGMT_OVERCOMMIT 3
18457 #define KEYMGMT_BITS_MIN   2U
18458 #define KEYMGMT_BITS_MAX   32U
18459 
18460 /*
18461  * WMM: Static hash functions copied from lib/dns/rbtdb.c. Should be moved to
18462  * lib/isc/hash.c when we refactor the hash table code.
18463  */
18464 #define GOLDEN_RATIO_32 0x61C88647
18465 #define HASHSIZE(bits)	(UINT64_C(1) << (bits))
18466 
18467 static uint32_t
hash_index(uint32_t val,uint32_t bits)18468 hash_index(uint32_t val, uint32_t bits) {
18469 	return (val * GOLDEN_RATIO_32 >> (32 - bits));
18470 }
18471 
18472 static uint32_t
hash_bits_grow(uint32_t bits,uint32_t count)18473 hash_bits_grow(uint32_t bits, uint32_t count) {
18474 	uint32_t newbits = bits;
18475 	while (count >= HASHSIZE(newbits) && newbits < KEYMGMT_BITS_MAX) {
18476 		newbits++;
18477 	}
18478 	return (newbits);
18479 }
18480 
18481 static uint32_t
hash_bits_shrink(uint32_t bits,uint32_t count)18482 hash_bits_shrink(uint32_t bits, uint32_t count) {
18483 	uint32_t newbits = bits;
18484 	while (count <= HASHSIZE(newbits) && newbits > KEYMGMT_BITS_MIN) {
18485 		newbits--;
18486 	}
18487 	return (newbits);
18488 }
18489 
18490 static void
zonemgr_keymgmt_init(dns_zonemgr_t * zmgr)18491 zonemgr_keymgmt_init(dns_zonemgr_t *zmgr) {
18492 	dns_keymgmt_t *mgmt = isc_mem_get(zmgr->mctx, sizeof(*mgmt));
18493 	uint32_t size;
18494 
18495 	*mgmt = (dns_keymgmt_t){
18496 		.bits = KEYMGMT_BITS_MIN,
18497 	};
18498 	isc_mem_attach(zmgr->mctx, &mgmt->mctx);
18499 	isc_rwlock_init(&mgmt->lock, 0, 0);
18500 
18501 	size = HASHSIZE(mgmt->bits);
18502 	mgmt->table = isc_mem_get(mgmt->mctx, sizeof(*mgmt->table) * size);
18503 	memset(mgmt->table, 0, size * sizeof(mgmt->table[0]));
18504 
18505 	atomic_init(&mgmt->count, 0);
18506 	mgmt->magic = KEYMGMT_MAGIC;
18507 
18508 	zmgr->keymgmt = mgmt;
18509 }
18510 
18511 static void
zonemgr_keymgmt_destroy(dns_zonemgr_t * zmgr)18512 zonemgr_keymgmt_destroy(dns_zonemgr_t *zmgr) {
18513 	dns_keymgmt_t *mgmt = zmgr->keymgmt;
18514 	uint32_t size;
18515 
18516 	REQUIRE(DNS_KEYMGMT_VALID(mgmt));
18517 
18518 	size = HASHSIZE(mgmt->bits);
18519 
18520 	RWLOCK(&mgmt->lock, isc_rwlocktype_write);
18521 	INSIST(mgmt->count == 0);
18522 	RWUNLOCK(&mgmt->lock, isc_rwlocktype_write);
18523 
18524 	mgmt->magic = 0;
18525 	isc_rwlock_destroy(&mgmt->lock);
18526 	isc_mem_put(mgmt->mctx, mgmt->table, size * sizeof(mgmt->table[0]));
18527 	isc_mem_putanddetach(&mgmt->mctx, mgmt, sizeof(dns_keymgmt_t));
18528 }
18529 
18530 static void
zonemgr_keymgmt_resize(dns_zonemgr_t * zmgr)18531 zonemgr_keymgmt_resize(dns_zonemgr_t *zmgr) {
18532 	dns_keyfileio_t **newtable;
18533 	dns_keymgmt_t *mgmt = zmgr->keymgmt;
18534 	uint32_t bits, newbits, count, size, newsize;
18535 	bool grow;
18536 
18537 	REQUIRE(DNS_KEYMGMT_VALID(mgmt));
18538 
18539 	RWLOCK(&mgmt->lock, isc_rwlocktype_read);
18540 	count = atomic_load_relaxed(&mgmt->count);
18541 	bits = mgmt->bits;
18542 	RWUNLOCK(&mgmt->lock, isc_rwlocktype_read);
18543 
18544 	size = HASHSIZE(bits);
18545 	INSIST(size > 0);
18546 
18547 	if (count >= (size * KEYMGMT_OVERCOMMIT)) {
18548 		grow = true;
18549 	} else if (count < (size / 2)) {
18550 		grow = false;
18551 	} else {
18552 		/* No need to resize. */
18553 		return;
18554 	}
18555 
18556 	if (grow) {
18557 		newbits = hash_bits_grow(bits, count);
18558 	} else {
18559 		newbits = hash_bits_shrink(bits, count);
18560 	}
18561 
18562 	if (newbits == bits) {
18563 		/*
18564 		 * Bit values may stay the same if maximum or minimum is
18565 		 * reached.
18566 		 */
18567 		return;
18568 	}
18569 
18570 	newsize = HASHSIZE(newbits);
18571 	INSIST(newsize > 0);
18572 
18573 	RWLOCK(&mgmt->lock, isc_rwlocktype_write);
18574 
18575 	newtable = isc_mem_get(mgmt->mctx, sizeof(dns_keyfileio_t *) * newsize);
18576 	memset(newtable, 0, sizeof(dns_keyfileio_t *) * newsize);
18577 
18578 	for (unsigned int i = 0; i < size; i++) {
18579 		dns_keyfileio_t *kfio, *next;
18580 		for (kfio = mgmt->table[i]; kfio != NULL; kfio = next) {
18581 			uint32_t hash = hash_index(kfio->hashval, newbits);
18582 			next = kfio->next;
18583 			kfio->next = newtable[hash];
18584 			newtable[hash] = kfio;
18585 		}
18586 		mgmt->table[i] = NULL;
18587 	}
18588 
18589 	isc_mem_put(mgmt->mctx, mgmt->table, sizeof(*mgmt->table) * size);
18590 	mgmt->bits = newbits;
18591 	mgmt->table = newtable;
18592 
18593 	RWUNLOCK(&mgmt->lock, isc_rwlocktype_write);
18594 }
18595 
18596 static void
zonemgr_keymgmt_add(dns_zonemgr_t * zmgr,dns_zone_t * zone,dns_keyfileio_t ** added)18597 zonemgr_keymgmt_add(dns_zonemgr_t *zmgr, dns_zone_t *zone,
18598 		    dns_keyfileio_t **added) {
18599 	dns_keymgmt_t *mgmt = zmgr->keymgmt;
18600 	uint32_t hashval, hash;
18601 	dns_keyfileio_t *kfio, *next;
18602 
18603 	REQUIRE(DNS_KEYMGMT_VALID(mgmt));
18604 	REQUIRE(added != NULL && *added == NULL);
18605 
18606 	RWLOCK(&mgmt->lock, isc_rwlocktype_write);
18607 
18608 	hashval = dns_name_hash(&zone->origin, false);
18609 	hash = hash_index(hashval, mgmt->bits);
18610 
18611 	for (kfio = mgmt->table[hash]; kfio != NULL; kfio = next) {
18612 		next = kfio->next;
18613 		if (dns_name_equal(kfio->name, &zone->origin)) {
18614 			/* Already in table, increment the counter. */
18615 			isc_refcount_increment(&kfio->references);
18616 			break;
18617 		}
18618 	}
18619 
18620 	if (kfio == NULL) {
18621 		/* No entry found, add it. */
18622 		kfio = isc_mem_get(mgmt->mctx, sizeof(*kfio));
18623 		*kfio = (dns_keyfileio_t){
18624 			.hashval = hashval,
18625 			.next = mgmt->table[hash],
18626 			.magic = KEYFILEIO_MAGIC,
18627 		};
18628 
18629 		isc_refcount_init(&kfio->references, 1);
18630 
18631 		kfio->name = dns_fixedname_initname(&kfio->fname);
18632 		dns_name_copynf(&zone->origin, kfio->name);
18633 
18634 		isc_mutex_init(&kfio->lock);
18635 
18636 		mgmt->table[hash] = kfio;
18637 
18638 		atomic_fetch_add_relaxed(&mgmt->count, 1);
18639 	}
18640 
18641 	RWUNLOCK(&mgmt->lock, isc_rwlocktype_write);
18642 
18643 	*added = kfio;
18644 
18645 	/*
18646 	 * Call resize, that function will also check if resize is necessary.
18647 	 */
18648 	zonemgr_keymgmt_resize(zmgr);
18649 }
18650 
18651 static void
zonemgr_keymgmt_delete(dns_zonemgr_t * zmgr,dns_zone_t * zone,dns_keyfileio_t ** deleted)18652 zonemgr_keymgmt_delete(dns_zonemgr_t *zmgr, dns_zone_t *zone,
18653 		       dns_keyfileio_t **deleted) {
18654 	dns_keymgmt_t *mgmt = zmgr->keymgmt;
18655 	uint32_t hashval, hash;
18656 	dns_keyfileio_t *kfio, *prev, *next;
18657 
18658 	REQUIRE(DNS_KEYMGMT_VALID(mgmt));
18659 	REQUIRE(deleted != NULL && DNS_KEYFILEIO_VALID(*deleted));
18660 
18661 	RWLOCK(&mgmt->lock, isc_rwlocktype_write);
18662 
18663 	hashval = dns_name_hash(&zone->origin, false);
18664 	hash = hash_index(hashval, mgmt->bits);
18665 
18666 	prev = NULL;
18667 	for (kfio = mgmt->table[hash]; kfio != NULL; kfio = next) {
18668 		next = kfio->next;
18669 		if (dns_name_equal(kfio->name, &zone->origin)) {
18670 			INSIST(kfio == *deleted);
18671 			*deleted = NULL;
18672 
18673 			if (isc_refcount_decrement(&kfio->references) == 1) {
18674 				if (prev == NULL) {
18675 					mgmt->table[hash] = kfio->next;
18676 				} else {
18677 					prev->next = kfio->next;
18678 				}
18679 
18680 				isc_refcount_destroy(&kfio->references);
18681 				isc_mutex_destroy(&kfio->lock);
18682 				isc_mem_put(mgmt->mctx, kfio, sizeof(*kfio));
18683 
18684 				atomic_fetch_sub_relaxed(&mgmt->count, 1);
18685 			}
18686 			break;
18687 		}
18688 
18689 		prev = kfio;
18690 	}
18691 
18692 	RWUNLOCK(&mgmt->lock, isc_rwlocktype_write);
18693 
18694 	/*
18695 	 * Call resize, that function will also check if resize is necessary.
18696 	 */
18697 	zonemgr_keymgmt_resize(zmgr);
18698 }
18699 
18700 isc_result_t
dns_zonemgr_create(isc_mem_t * mctx,isc_taskmgr_t * taskmgr,isc_timermgr_t * timermgr,isc_socketmgr_t * socketmgr,dns_zonemgr_t ** zmgrp)18701 dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
18702 		   isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
18703 		   dns_zonemgr_t **zmgrp) {
18704 	dns_zonemgr_t *zmgr;
18705 	isc_result_t result;
18706 
18707 	zmgr = isc_mem_get(mctx, sizeof(*zmgr));
18708 	zmgr->mctx = NULL;
18709 	isc_refcount_init(&zmgr->refs, 1);
18710 	isc_mem_attach(mctx, &zmgr->mctx);
18711 	zmgr->taskmgr = taskmgr;
18712 	zmgr->timermgr = timermgr;
18713 	zmgr->socketmgr = socketmgr;
18714 	zmgr->zonetasks = NULL;
18715 	zmgr->loadtasks = NULL;
18716 	zmgr->mctxpool = NULL;
18717 	zmgr->task = NULL;
18718 	zmgr->checkdsrl = NULL;
18719 	zmgr->notifyrl = NULL;
18720 	zmgr->refreshrl = NULL;
18721 	zmgr->startupnotifyrl = NULL;
18722 	zmgr->startuprefreshrl = NULL;
18723 	ISC_LIST_INIT(zmgr->zones);
18724 	ISC_LIST_INIT(zmgr->waiting_for_xfrin);
18725 	ISC_LIST_INIT(zmgr->xfrin_in_progress);
18726 	memset(zmgr->unreachable, 0, sizeof(zmgr->unreachable));
18727 	for (size_t i = 0; i < UNREACH_CACHE_SIZE; i++) {
18728 		atomic_init(&zmgr->unreachable[i].expire, 0);
18729 	}
18730 	isc_rwlock_init(&zmgr->rwlock, 0, 0);
18731 
18732 	zmgr->transfersin = 10;
18733 	zmgr->transfersperns = 2;
18734 
18735 	/* Unreachable lock. */
18736 	isc_rwlock_init(&zmgr->urlock, 0, 0);
18737 
18738 	/* Create a single task for queueing of SOA queries. */
18739 	result = isc_task_create(taskmgr, 1, &zmgr->task);
18740 	if (result != ISC_R_SUCCESS) {
18741 		goto free_urlock;
18742 	}
18743 
18744 	isc_task_setname(zmgr->task, "zmgr", zmgr);
18745 	result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
18746 					&zmgr->checkdsrl);
18747 	if (result != ISC_R_SUCCESS) {
18748 		goto free_task;
18749 	}
18750 
18751 	result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
18752 					&zmgr->notifyrl);
18753 	if (result != ISC_R_SUCCESS) {
18754 		goto free_checkdsrl;
18755 	}
18756 
18757 	result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
18758 					&zmgr->refreshrl);
18759 	if (result != ISC_R_SUCCESS) {
18760 		goto free_notifyrl;
18761 	}
18762 
18763 	result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
18764 					&zmgr->startupnotifyrl);
18765 	if (result != ISC_R_SUCCESS) {
18766 		goto free_refreshrl;
18767 	}
18768 
18769 	result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
18770 					&zmgr->startuprefreshrl);
18771 	if (result != ISC_R_SUCCESS) {
18772 		goto free_startupnotifyrl;
18773 	}
18774 
18775 	/* Key file I/O locks. */
18776 	zonemgr_keymgmt_init(zmgr);
18777 
18778 	/* Default to 20 refresh queries / notifies / checkds per second. */
18779 	setrl(zmgr->checkdsrl, &zmgr->checkdsrate, 20);
18780 	setrl(zmgr->notifyrl, &zmgr->notifyrate, 20);
18781 	setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, 20);
18782 	setrl(zmgr->refreshrl, &zmgr->serialqueryrate, 20);
18783 	setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, 20);
18784 	isc_ratelimiter_setpushpop(zmgr->startupnotifyrl, true);
18785 	isc_ratelimiter_setpushpop(zmgr->startuprefreshrl, true);
18786 
18787 	zmgr->iolimit = 1;
18788 	zmgr->ioactive = 0;
18789 	ISC_LIST_INIT(zmgr->high);
18790 	ISC_LIST_INIT(zmgr->low);
18791 
18792 	isc_mutex_init(&zmgr->iolock);
18793 
18794 	zmgr->magic = ZONEMGR_MAGIC;
18795 
18796 	*zmgrp = zmgr;
18797 	return (ISC_R_SUCCESS);
18798 
18799 #if 0
18800  free_iolock:
18801 	isc_mutex_destroy(&zmgr->iolock);
18802 #endif /* if 0 */
18803 free_startupnotifyrl:
18804 	isc_ratelimiter_detach(&zmgr->startupnotifyrl);
18805 free_refreshrl:
18806 	isc_ratelimiter_detach(&zmgr->refreshrl);
18807 free_notifyrl:
18808 	isc_ratelimiter_detach(&zmgr->notifyrl);
18809 free_checkdsrl:
18810 	isc_ratelimiter_detach(&zmgr->checkdsrl);
18811 free_task:
18812 	isc_task_detach(&zmgr->task);
18813 free_urlock:
18814 	isc_rwlock_destroy(&zmgr->urlock);
18815 	isc_rwlock_destroy(&zmgr->rwlock);
18816 	isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
18817 	isc_mem_detach(&mctx);
18818 	return (result);
18819 }
18820 
18821 isc_result_t
dns_zonemgr_createzone(dns_zonemgr_t * zmgr,dns_zone_t ** zonep)18822 dns_zonemgr_createzone(dns_zonemgr_t *zmgr, dns_zone_t **zonep) {
18823 	isc_result_t result;
18824 	isc_mem_t *mctx = NULL;
18825 	dns_zone_t *zone = NULL;
18826 	void *item;
18827 
18828 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18829 	REQUIRE(zonep != NULL && *zonep == NULL);
18830 
18831 	if (zmgr->mctxpool == NULL) {
18832 		return (ISC_R_FAILURE);
18833 	}
18834 
18835 	item = isc_pool_get(zmgr->mctxpool);
18836 	if (item == NULL) {
18837 		return (ISC_R_FAILURE);
18838 	}
18839 
18840 	isc_mem_attach((isc_mem_t *)item, &mctx);
18841 	result = dns_zone_create(&zone, mctx);
18842 	isc_mem_detach(&mctx);
18843 
18844 	if (result == ISC_R_SUCCESS) {
18845 		*zonep = zone;
18846 	}
18847 
18848 	return (result);
18849 }
18850 
18851 isc_result_t
dns_zonemgr_managezone(dns_zonemgr_t * zmgr,dns_zone_t * zone)18852 dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
18853 	isc_result_t result;
18854 
18855 	REQUIRE(DNS_ZONE_VALID(zone));
18856 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18857 
18858 	if (zmgr->zonetasks == NULL) {
18859 		return (ISC_R_FAILURE);
18860 	}
18861 
18862 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18863 	LOCK_ZONE(zone);
18864 	REQUIRE(zone->task == NULL);
18865 	REQUIRE(zone->timer == NULL);
18866 	REQUIRE(zone->zmgr == NULL);
18867 
18868 	isc_taskpool_gettask(zmgr->zonetasks, &zone->task);
18869 	isc_taskpool_gettask(zmgr->loadtasks, &zone->loadtask);
18870 
18871 	/*
18872 	 * Set the task name.  The tag will arbitrarily point to one
18873 	 * of the zones sharing the task (in practice, the one
18874 	 * to be managed last).
18875 	 */
18876 	isc_task_setname(zone->task, "zone", zone);
18877 	isc_task_setname(zone->loadtask, "loadzone", zone);
18878 
18879 	result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive, NULL,
18880 				  NULL, zone->task, zone_timer, zone,
18881 				  &zone->timer);
18882 
18883 	if (result != ISC_R_SUCCESS) {
18884 		goto cleanup_tasks;
18885 	}
18886 
18887 	/*
18888 	 * The timer "holds" a iref.
18889 	 */
18890 	isc_refcount_increment0(&zone->irefs);
18891 
18892 	zonemgr_keymgmt_add(zmgr, zone, &zone->kfio);
18893 	INSIST(zone->kfio != NULL);
18894 
18895 	ISC_LIST_APPEND(zmgr->zones, zone, link);
18896 	zone->zmgr = zmgr;
18897 	isc_refcount_increment(&zmgr->refs);
18898 
18899 	goto unlock;
18900 
18901 cleanup_tasks:
18902 	isc_task_detach(&zone->loadtask);
18903 	isc_task_detach(&zone->task);
18904 
18905 unlock:
18906 	UNLOCK_ZONE(zone);
18907 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18908 	return (result);
18909 }
18910 
18911 void
dns_zonemgr_releasezone(dns_zonemgr_t * zmgr,dns_zone_t * zone)18912 dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
18913 	REQUIRE(DNS_ZONE_VALID(zone));
18914 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18915 	REQUIRE(zone->zmgr == zmgr);
18916 
18917 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18918 	LOCK_ZONE(zone);
18919 
18920 	ISC_LIST_UNLINK(zmgr->zones, zone, link);
18921 
18922 	if (zone->kfio != NULL) {
18923 		zonemgr_keymgmt_delete(zmgr, zone, &zone->kfio);
18924 		ENSURE(zone->kfio == NULL);
18925 	}
18926 
18927 	/* Detach below, outside of the write lock. */
18928 	zone->zmgr = NULL;
18929 
18930 	UNLOCK_ZONE(zone);
18931 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18932 
18933 	dns_zonemgr_detach(&zmgr);
18934 }
18935 
18936 void
dns_zonemgr_attach(dns_zonemgr_t * source,dns_zonemgr_t ** target)18937 dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) {
18938 	REQUIRE(DNS_ZONEMGR_VALID(source));
18939 	REQUIRE(target != NULL && *target == NULL);
18940 
18941 	isc_refcount_increment(&source->refs);
18942 
18943 	*target = source;
18944 }
18945 
18946 void
dns_zonemgr_detach(dns_zonemgr_t ** zmgrp)18947 dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
18948 	dns_zonemgr_t *zmgr;
18949 
18950 	REQUIRE(zmgrp != NULL);
18951 	zmgr = *zmgrp;
18952 	*zmgrp = NULL;
18953 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18954 
18955 	if (isc_refcount_decrement(&zmgr->refs) == 1) {
18956 		zonemgr_free(zmgr);
18957 	}
18958 }
18959 
18960 isc_result_t
dns_zonemgr_forcemaint(dns_zonemgr_t * zmgr)18961 dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
18962 	dns_zone_t *p;
18963 
18964 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18965 
18966 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
18967 	for (p = ISC_LIST_HEAD(zmgr->zones); p != NULL;
18968 	     p = ISC_LIST_NEXT(p, link))
18969 	{
18970 		dns_zone_maintenance(p);
18971 	}
18972 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
18973 
18974 	/*
18975 	 * Recent configuration changes may have increased the
18976 	 * amount of available transfers quota.  Make sure any
18977 	 * transfers currently blocked on quota get started if
18978 	 * possible.
18979 	 */
18980 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18981 	zmgr_resume_xfrs(zmgr, true);
18982 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18983 	return (ISC_R_SUCCESS);
18984 }
18985 
18986 void
dns_zonemgr_resumexfrs(dns_zonemgr_t * zmgr)18987 dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) {
18988 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18989 
18990 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18991 	zmgr_resume_xfrs(zmgr, true);
18992 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18993 }
18994 
18995 void
dns_zonemgr_shutdown(dns_zonemgr_t * zmgr)18996 dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
18997 	dns_zone_t *zone;
18998 
18999 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19000 
19001 	isc_ratelimiter_shutdown(zmgr->checkdsrl);
19002 	isc_ratelimiter_shutdown(zmgr->notifyrl);
19003 	isc_ratelimiter_shutdown(zmgr->refreshrl);
19004 	isc_ratelimiter_shutdown(zmgr->startupnotifyrl);
19005 	isc_ratelimiter_shutdown(zmgr->startuprefreshrl);
19006 
19007 	if (zmgr->task != NULL) {
19008 		isc_task_destroy(&zmgr->task);
19009 	}
19010 	if (zmgr->zonetasks != NULL) {
19011 		isc_taskpool_destroy(&zmgr->zonetasks);
19012 	}
19013 	if (zmgr->loadtasks != NULL) {
19014 		isc_taskpool_destroy(&zmgr->loadtasks);
19015 	}
19016 	if (zmgr->mctxpool != NULL) {
19017 		isc_pool_destroy(&zmgr->mctxpool);
19018 	}
19019 
19020 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
19021 	for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
19022 	     zone = ISC_LIST_NEXT(zone, link))
19023 	{
19024 		LOCK_ZONE(zone);
19025 		forward_cancel(zone);
19026 		UNLOCK_ZONE(zone);
19027 	}
19028 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
19029 }
19030 
19031 static isc_result_t
mctxinit(void ** target,void * arg)19032 mctxinit(void **target, void *arg) {
19033 	isc_mem_t *mctx = NULL;
19034 
19035 	UNUSED(arg);
19036 
19037 	REQUIRE(target != NULL && *target == NULL);
19038 
19039 	isc_mem_create(&mctx);
19040 	isc_mem_setname(mctx, "zonemgr-pool", NULL);
19041 
19042 	*target = mctx;
19043 	return (ISC_R_SUCCESS);
19044 }
19045 
19046 static void
mctxfree(void ** target)19047 mctxfree(void **target) {
19048 	isc_mem_t *mctx = *(isc_mem_t **)target;
19049 	isc_mem_detach(&mctx);
19050 	*target = NULL;
19051 }
19052 
19053 #define ZONES_PER_TASK 100
19054 #define ZONES_PER_MCTX 1000
19055 
19056 isc_result_t
dns_zonemgr_setsize(dns_zonemgr_t * zmgr,int num_zones)19057 dns_zonemgr_setsize(dns_zonemgr_t *zmgr, int num_zones) {
19058 	isc_result_t result;
19059 	int ntasks = num_zones / ZONES_PER_TASK;
19060 	int nmctx = num_zones / ZONES_PER_MCTX;
19061 	isc_taskpool_t *pool = NULL;
19062 	isc_pool_t *mctxpool = NULL;
19063 
19064 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19065 
19066 	/*
19067 	 * For anything fewer than 1000 zones we use 10 tasks in
19068 	 * the task pools.  More than that, and we'll scale at one
19069 	 * task per 100 zones.  Similarly, for anything smaller than
19070 	 * 2000 zones we use 2 memory contexts, then scale at 1:1000.
19071 	 */
19072 	if (ntasks < 10) {
19073 		ntasks = 10;
19074 	}
19075 	if (nmctx < 2) {
19076 		nmctx = 2;
19077 	}
19078 
19079 	/* Create or resize the zone task pools. */
19080 	if (zmgr->zonetasks == NULL) {
19081 		result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx, ntasks,
19082 					     2, false, &pool);
19083 	} else {
19084 		result = isc_taskpool_expand(&zmgr->zonetasks, ntasks, false,
19085 					     &pool);
19086 	}
19087 
19088 	if (result == ISC_R_SUCCESS) {
19089 		zmgr->zonetasks = pool;
19090 	}
19091 
19092 	pool = NULL;
19093 	if (zmgr->loadtasks == NULL) {
19094 		result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx, ntasks,
19095 					     UINT_MAX, true, &pool);
19096 	} else {
19097 		result = isc_taskpool_expand(&zmgr->loadtasks, ntasks, true,
19098 					     &pool);
19099 	}
19100 
19101 	if (result == ISC_R_SUCCESS) {
19102 		zmgr->loadtasks = pool;
19103 	}
19104 
19105 	/* Create or resize the zone memory context pool. */
19106 	if (zmgr->mctxpool == NULL) {
19107 		result = isc_pool_create(zmgr->mctx, nmctx, mctxfree, mctxinit,
19108 					 NULL, &mctxpool);
19109 	} else {
19110 		result = isc_pool_expand(&zmgr->mctxpool, nmctx, &mctxpool);
19111 	}
19112 
19113 	if (result == ISC_R_SUCCESS) {
19114 		zmgr->mctxpool = mctxpool;
19115 	}
19116 
19117 	return (result);
19118 }
19119 
19120 static void
zonemgr_free(dns_zonemgr_t * zmgr)19121 zonemgr_free(dns_zonemgr_t *zmgr) {
19122 	isc_mem_t *mctx;
19123 
19124 	INSIST(ISC_LIST_EMPTY(zmgr->zones));
19125 
19126 	zmgr->magic = 0;
19127 
19128 	isc_refcount_destroy(&zmgr->refs);
19129 	isc_mutex_destroy(&zmgr->iolock);
19130 	isc_ratelimiter_detach(&zmgr->checkdsrl);
19131 	isc_ratelimiter_detach(&zmgr->notifyrl);
19132 	isc_ratelimiter_detach(&zmgr->refreshrl);
19133 	isc_ratelimiter_detach(&zmgr->startupnotifyrl);
19134 	isc_ratelimiter_detach(&zmgr->startuprefreshrl);
19135 
19136 	isc_rwlock_destroy(&zmgr->urlock);
19137 	isc_rwlock_destroy(&zmgr->rwlock);
19138 
19139 	zonemgr_keymgmt_destroy(zmgr);
19140 
19141 	mctx = zmgr->mctx;
19142 	isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
19143 	isc_mem_detach(&mctx);
19144 }
19145 
19146 void
dns_zonemgr_settransfersin(dns_zonemgr_t * zmgr,uint32_t value)19147 dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, uint32_t value) {
19148 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19149 
19150 	zmgr->transfersin = value;
19151 }
19152 
19153 uint32_t
dns_zonemgr_getttransfersin(dns_zonemgr_t * zmgr)19154 dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) {
19155 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19156 
19157 	return (zmgr->transfersin);
19158 }
19159 
19160 void
dns_zonemgr_settransfersperns(dns_zonemgr_t * zmgr,uint32_t value)19161 dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, uint32_t value) {
19162 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19163 
19164 	zmgr->transfersperns = value;
19165 }
19166 
19167 uint32_t
dns_zonemgr_getttransfersperns(dns_zonemgr_t * zmgr)19168 dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr) {
19169 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19170 
19171 	return (zmgr->transfersperns);
19172 }
19173 
19174 isc_taskmgr_t *
dns_zonemgr_gettaskmgr(dns_zonemgr_t * zmgr)19175 dns_zonemgr_gettaskmgr(dns_zonemgr_t *zmgr) {
19176 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19177 
19178 	return (zmgr->taskmgr);
19179 }
19180 
19181 /*
19182  * Try to start a new incoming zone transfer to fill a quota
19183  * slot that was just vacated.
19184  *
19185  * Requires:
19186  *	The zone manager is locked by the caller.
19187  */
19188 static void
zmgr_resume_xfrs(dns_zonemgr_t * zmgr,bool multi)19189 zmgr_resume_xfrs(dns_zonemgr_t *zmgr, bool multi) {
19190 	dns_zone_t *zone;
19191 	dns_zone_t *next;
19192 
19193 	for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin); zone != NULL;
19194 	     zone = next)
19195 	{
19196 		isc_result_t result;
19197 		next = ISC_LIST_NEXT(zone, statelink);
19198 		result = zmgr_start_xfrin_ifquota(zmgr, zone);
19199 		if (result == ISC_R_SUCCESS) {
19200 			if (multi) {
19201 				continue;
19202 			}
19203 			/*
19204 			 * We successfully filled the slot.  We're done.
19205 			 */
19206 			break;
19207 		} else if (result == ISC_R_QUOTA) {
19208 			/*
19209 			 * Not enough quota.  This is probably the per-server
19210 			 * quota, because we usually get called when a unit of
19211 			 * global quota has just been freed.  Try the next
19212 			 * zone, it may succeed if it uses another master.
19213 			 */
19214 			continue;
19215 		} else {
19216 			dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
19217 				      ISC_LOG_DEBUG(1),
19218 				      "starting zone transfer: %s",
19219 				      isc_result_totext(result));
19220 			break;
19221 		}
19222 	}
19223 }
19224 
19225 /*
19226  * Try to start an incoming zone transfer for 'zone', quota permitting.
19227  *
19228  * Requires:
19229  *	The zone manager is locked by the caller.
19230  *
19231  * Returns:
19232  *	ISC_R_SUCCESS	There was enough quota and we attempted to
19233  *			start a transfer.  zone_xfrdone() has been or will
19234  *			be called.
19235  *	ISC_R_QUOTA	Not enough quota.
19236  *	Others		Failure.
19237  */
19238 static isc_result_t
zmgr_start_xfrin_ifquota(dns_zonemgr_t * zmgr,dns_zone_t * zone)19239 zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
19240 	dns_peer_t *peer = NULL;
19241 	isc_netaddr_t masterip;
19242 	uint32_t nxfrsin, nxfrsperns;
19243 	dns_zone_t *x;
19244 	uint32_t maxtransfersin, maxtransfersperns;
19245 	isc_event_t *e;
19246 
19247 	/*
19248 	 * If we are exiting just pretend we got quota so the zone will
19249 	 * be cleaned up in the zone's task context.
19250 	 */
19251 	LOCK_ZONE(zone);
19252 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
19253 		UNLOCK_ZONE(zone);
19254 		goto gotquota;
19255 	}
19256 
19257 	/*
19258 	 * Find any configured information about the server we'd
19259 	 * like to transfer this zone from.
19260 	 */
19261 	isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
19262 	(void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
19263 	UNLOCK_ZONE(zone);
19264 
19265 	/*
19266 	 * Determine the total maximum number of simultaneous
19267 	 * transfers allowed, and the maximum for this specific
19268 	 * master.
19269 	 */
19270 	maxtransfersin = zmgr->transfersin;
19271 	maxtransfersperns = zmgr->transfersperns;
19272 	if (peer != NULL) {
19273 		(void)dns_peer_gettransfers(peer, &maxtransfersperns);
19274 	}
19275 
19276 	/*
19277 	 * Count the total number of transfers that are in progress,
19278 	 * and the number of transfers in progress from this master.
19279 	 * We linearly scan a list of all transfers; if this turns
19280 	 * out to be too slow, we could hash on the master address.
19281 	 */
19282 	nxfrsin = nxfrsperns = 0;
19283 	for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress); x != NULL;
19284 	     x = ISC_LIST_NEXT(x, statelink))
19285 	{
19286 		isc_netaddr_t xip;
19287 
19288 		LOCK_ZONE(x);
19289 		isc_netaddr_fromsockaddr(&xip, &x->masteraddr);
19290 		UNLOCK_ZONE(x);
19291 
19292 		nxfrsin++;
19293 		if (isc_netaddr_equal(&xip, &masterip)) {
19294 			nxfrsperns++;
19295 		}
19296 	}
19297 
19298 	/* Enforce quota. */
19299 	if (nxfrsin >= maxtransfersin) {
19300 		return (ISC_R_QUOTA);
19301 	}
19302 
19303 	if (nxfrsperns >= maxtransfersperns) {
19304 		return (ISC_R_QUOTA);
19305 	}
19306 
19307 gotquota:
19308 	/*
19309 	 * We have sufficient quota.  Move the zone to the "xfrin_in_progress"
19310 	 * list and send it an event to let it start the actual transfer in the
19311 	 * context of its own task.
19312 	 */
19313 	e = isc_event_allocate(zmgr->mctx, zmgr, DNS_EVENT_ZONESTARTXFRIN,
19314 			       got_transfer_quota, zone, sizeof(isc_event_t));
19315 
19316 	LOCK_ZONE(zone);
19317 	INSIST(zone->statelist == &zmgr->waiting_for_xfrin);
19318 	ISC_LIST_UNLINK(zmgr->waiting_for_xfrin, zone, statelink);
19319 	ISC_LIST_APPEND(zmgr->xfrin_in_progress, zone, statelink);
19320 	zone->statelist = &zmgr->xfrin_in_progress;
19321 	isc_task_send(zone->task, &e);
19322 	dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
19323 		      "Transfer started.");
19324 	UNLOCK_ZONE(zone);
19325 
19326 	return (ISC_R_SUCCESS);
19327 }
19328 
19329 void
dns_zonemgr_setiolimit(dns_zonemgr_t * zmgr,uint32_t iolimit)19330 dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, uint32_t iolimit) {
19331 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19332 	REQUIRE(iolimit > 0);
19333 
19334 	zmgr->iolimit = iolimit;
19335 }
19336 
19337 uint32_t
dns_zonemgr_getiolimit(dns_zonemgr_t * zmgr)19338 dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr) {
19339 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19340 
19341 	return (zmgr->iolimit);
19342 }
19343 
19344 /*
19345  * Get permission to request a file handle from the OS.
19346  * An event will be sent to action when one is available.
19347  * There are two queues available (high and low), the high
19348  * queue will be serviced before the low one.
19349  *
19350  * zonemgr_putio() must be called after the event is delivered to
19351  * 'action'.
19352  */
19353 
19354 static isc_result_t
zonemgr_getio(dns_zonemgr_t * zmgr,bool high,isc_task_t * task,isc_taskaction_t action,void * arg,dns_io_t ** iop)19355 zonemgr_getio(dns_zonemgr_t *zmgr, bool high, isc_task_t *task,
19356 	      isc_taskaction_t action, void *arg, dns_io_t **iop) {
19357 	dns_io_t *io;
19358 	bool queue;
19359 
19360 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19361 	REQUIRE(iop != NULL && *iop == NULL);
19362 
19363 	io = isc_mem_get(zmgr->mctx, sizeof(*io));
19364 
19365 	io->event = isc_event_allocate(zmgr->mctx, task, DNS_EVENT_IOREADY,
19366 				       action, arg, sizeof(*io->event));
19367 
19368 	io->zmgr = zmgr;
19369 	io->high = high;
19370 	io->task = NULL;
19371 	isc_task_attach(task, &io->task);
19372 	ISC_LINK_INIT(io, link);
19373 	io->magic = IO_MAGIC;
19374 
19375 	LOCK(&zmgr->iolock);
19376 	zmgr->ioactive++;
19377 	queue = (zmgr->ioactive > zmgr->iolimit);
19378 	if (queue) {
19379 		if (io->high) {
19380 			ISC_LIST_APPEND(zmgr->high, io, link);
19381 		} else {
19382 			ISC_LIST_APPEND(zmgr->low, io, link);
19383 		}
19384 	}
19385 	UNLOCK(&zmgr->iolock);
19386 	*iop = io;
19387 
19388 	if (!queue) {
19389 		isc_task_send(io->task, &io->event);
19390 	}
19391 	return (ISC_R_SUCCESS);
19392 }
19393 
19394 static void
zonemgr_putio(dns_io_t ** iop)19395 zonemgr_putio(dns_io_t **iop) {
19396 	dns_io_t *io;
19397 	dns_io_t *next;
19398 	dns_zonemgr_t *zmgr;
19399 
19400 	REQUIRE(iop != NULL);
19401 	io = *iop;
19402 	*iop = NULL;
19403 	REQUIRE(DNS_IO_VALID(io));
19404 
19405 	INSIST(!ISC_LINK_LINKED(io, link));
19406 	INSIST(io->event == NULL);
19407 
19408 	zmgr = io->zmgr;
19409 	isc_task_detach(&io->task);
19410 	io->magic = 0;
19411 	isc_mem_put(zmgr->mctx, io, sizeof(*io));
19412 
19413 	LOCK(&zmgr->iolock);
19414 	INSIST(zmgr->ioactive > 0);
19415 	zmgr->ioactive--;
19416 	next = HEAD(zmgr->high);
19417 	if (next == NULL) {
19418 		next = HEAD(zmgr->low);
19419 	}
19420 	if (next != NULL) {
19421 		if (next->high) {
19422 			ISC_LIST_UNLINK(zmgr->high, next, link);
19423 		} else {
19424 			ISC_LIST_UNLINK(zmgr->low, next, link);
19425 		}
19426 		INSIST(next->event != NULL);
19427 	}
19428 	UNLOCK(&zmgr->iolock);
19429 	if (next != NULL) {
19430 		isc_task_send(next->task, &next->event);
19431 	}
19432 }
19433 
19434 static void
zonemgr_cancelio(dns_io_t * io)19435 zonemgr_cancelio(dns_io_t *io) {
19436 	bool send_event = false;
19437 
19438 	REQUIRE(DNS_IO_VALID(io));
19439 
19440 	/*
19441 	 * If we are queued to be run then dequeue.
19442 	 */
19443 	LOCK(&io->zmgr->iolock);
19444 	if (ISC_LINK_LINKED(io, link)) {
19445 		if (io->high) {
19446 			ISC_LIST_UNLINK(io->zmgr->high, io, link);
19447 		} else {
19448 			ISC_LIST_UNLINK(io->zmgr->low, io, link);
19449 		}
19450 
19451 		send_event = true;
19452 		INSIST(io->event != NULL);
19453 	}
19454 	UNLOCK(&io->zmgr->iolock);
19455 	if (send_event) {
19456 		io->event->ev_attributes |= ISC_EVENTATTR_CANCELED;
19457 		isc_task_send(io->task, &io->event);
19458 	}
19459 }
19460 
19461 static void
zone_saveunique(dns_zone_t * zone,const char * path,const char * templat)19462 zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
19463 	char *buf;
19464 	int buflen;
19465 	isc_result_t result;
19466 
19467 	buflen = strlen(path) + strlen(templat) + 2;
19468 
19469 	buf = isc_mem_get(zone->mctx, buflen);
19470 
19471 	result = isc_file_template(path, templat, buf, buflen);
19472 	if (result != ISC_R_SUCCESS) {
19473 		goto cleanup;
19474 	}
19475 
19476 	result = isc_file_renameunique(path, buf);
19477 	if (result != ISC_R_SUCCESS) {
19478 		goto cleanup;
19479 	}
19480 
19481 	dns_zone_log(zone, ISC_LOG_WARNING,
19482 		     "unable to load from '%s'; "
19483 		     "renaming file to '%s' for failure analysis and "
19484 		     "retransferring.",
19485 		     path, buf);
19486 
19487 cleanup:
19488 	isc_mem_put(zone->mctx, buf, buflen);
19489 }
19490 
19491 static void
setrl(isc_ratelimiter_t * rl,unsigned int * rate,unsigned int value)19492 setrl(isc_ratelimiter_t *rl, unsigned int *rate, unsigned int value) {
19493 	isc_interval_t interval;
19494 	uint32_t s, ns;
19495 	uint32_t pertic;
19496 	isc_result_t result;
19497 
19498 	if (value == 0) {
19499 		value = 1;
19500 	}
19501 
19502 	if (value == 1) {
19503 		s = 1;
19504 		ns = 0;
19505 		pertic = 1;
19506 	} else if (value <= 10) {
19507 		s = 0;
19508 		ns = 1000000000 / value;
19509 		pertic = 1;
19510 	} else {
19511 		s = 0;
19512 		ns = (1000000000 / value) * 10;
19513 		pertic = 10;
19514 	}
19515 
19516 	isc_interval_set(&interval, s, ns);
19517 
19518 	result = isc_ratelimiter_setinterval(rl, &interval);
19519 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
19520 	isc_ratelimiter_setpertic(rl, pertic);
19521 
19522 	*rate = value;
19523 }
19524 
19525 void
dns_zonemgr_setcheckdsrate(dns_zonemgr_t * zmgr,unsigned int value)19526 dns_zonemgr_setcheckdsrate(dns_zonemgr_t *zmgr, unsigned int value) {
19527 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19528 
19529 	setrl(zmgr->checkdsrl, &zmgr->checkdsrate, value);
19530 }
19531 
19532 void
dns_zonemgr_setnotifyrate(dns_zonemgr_t * zmgr,unsigned int value)19533 dns_zonemgr_setnotifyrate(dns_zonemgr_t *zmgr, unsigned int value) {
19534 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19535 
19536 	setrl(zmgr->notifyrl, &zmgr->notifyrate, value);
19537 }
19538 
19539 void
dns_zonemgr_setstartupnotifyrate(dns_zonemgr_t * zmgr,unsigned int value)19540 dns_zonemgr_setstartupnotifyrate(dns_zonemgr_t *zmgr, unsigned int value) {
19541 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19542 
19543 	setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, value);
19544 }
19545 
19546 void
dns_zonemgr_setserialqueryrate(dns_zonemgr_t * zmgr,unsigned int value)19547 dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) {
19548 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19549 
19550 	setrl(zmgr->refreshrl, &zmgr->serialqueryrate, value);
19551 	/* XXXMPA separate out once we have the code to support this. */
19552 	setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, value);
19553 }
19554 
19555 unsigned int
dns_zonemgr_getnotifyrate(dns_zonemgr_t * zmgr)19556 dns_zonemgr_getnotifyrate(dns_zonemgr_t *zmgr) {
19557 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19558 
19559 	return (zmgr->notifyrate);
19560 }
19561 
19562 unsigned int
dns_zonemgr_getstartupnotifyrate(dns_zonemgr_t * zmgr)19563 dns_zonemgr_getstartupnotifyrate(dns_zonemgr_t *zmgr) {
19564 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19565 
19566 	return (zmgr->startupnotifyrate);
19567 }
19568 
19569 unsigned int
dns_zonemgr_getserialqueryrate(dns_zonemgr_t * zmgr)19570 dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
19571 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19572 
19573 	return (zmgr->serialqueryrate);
19574 }
19575 
19576 bool
dns_zonemgr_unreachable(dns_zonemgr_t * zmgr,isc_sockaddr_t * remote,isc_sockaddr_t * local,isc_time_t * now)19577 dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
19578 			isc_sockaddr_t *local, isc_time_t *now) {
19579 	unsigned int i;
19580 	uint32_t seconds = isc_time_seconds(now);
19581 	uint32_t count = 0;
19582 
19583 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19584 
19585 	RWLOCK(&zmgr->urlock, isc_rwlocktype_read);
19586 	for (i = 0; i < UNREACH_CACHE_SIZE; i++) {
19587 		if (atomic_load(&zmgr->unreachable[i].expire) >= seconds &&
19588 		    isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
19589 		    isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
19590 		{
19591 			atomic_store_relaxed(&zmgr->unreachable[i].last,
19592 					     seconds);
19593 			count = zmgr->unreachable[i].count;
19594 			break;
19595 		}
19596 	}
19597 	RWUNLOCK(&zmgr->urlock, isc_rwlocktype_read);
19598 	return (i < UNREACH_CACHE_SIZE && count > 1U);
19599 }
19600 
19601 void
dns_zonemgr_unreachabledel(dns_zonemgr_t * zmgr,isc_sockaddr_t * remote,isc_sockaddr_t * local)19602 dns_zonemgr_unreachabledel(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
19603 			   isc_sockaddr_t *local) {
19604 	unsigned int i;
19605 	char master[ISC_SOCKADDR_FORMATSIZE];
19606 	char source[ISC_SOCKADDR_FORMATSIZE];
19607 
19608 	isc_sockaddr_format(remote, master, sizeof(master));
19609 	isc_sockaddr_format(local, source, sizeof(source));
19610 
19611 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19612 
19613 	RWLOCK(&zmgr->urlock, isc_rwlocktype_read);
19614 	for (i = 0; i < UNREACH_CACHE_SIZE; i++) {
19615 		if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
19616 		    isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
19617 		{
19618 			atomic_store_relaxed(&zmgr->unreachable[i].expire, 0);
19619 			break;
19620 		}
19621 	}
19622 	RWUNLOCK(&zmgr->urlock, isc_rwlocktype_read);
19623 }
19624 
19625 void
dns_zonemgr_unreachableadd(dns_zonemgr_t * zmgr,isc_sockaddr_t * remote,isc_sockaddr_t * local,isc_time_t * now)19626 dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
19627 			   isc_sockaddr_t *local, isc_time_t *now) {
19628 	uint32_t seconds = isc_time_seconds(now);
19629 	uint32_t expire = 0, last = seconds;
19630 	unsigned int slot = UNREACH_CACHE_SIZE, oldest = 0;
19631 	bool update_entry = true;
19632 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19633 
19634 	RWLOCK(&zmgr->urlock, isc_rwlocktype_write);
19635 	for (unsigned int i = 0; i < UNREACH_CACHE_SIZE; i++) {
19636 		/* Existing entry? */
19637 		if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
19638 		    isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
19639 		{
19640 			update_entry = false;
19641 			slot = i;
19642 			expire = atomic_load_relaxed(
19643 				&zmgr->unreachable[i].expire);
19644 			break;
19645 		}
19646 		/* Pick first empty slot? */
19647 		if (atomic_load_relaxed(&zmgr->unreachable[i].expire) < seconds)
19648 		{
19649 			slot = i;
19650 			break;
19651 		}
19652 		/* The worst case, least recently used slot? */
19653 		if (atomic_load_relaxed(&zmgr->unreachable[i].last) < last) {
19654 			last = atomic_load_relaxed(&zmgr->unreachable[i].last);
19655 			oldest = i;
19656 		}
19657 	}
19658 
19659 	/* We haven't found any existing or free slots, use the oldest */
19660 	if (slot == UNREACH_CACHE_SIZE) {
19661 		slot = oldest;
19662 	}
19663 
19664 	if (expire < seconds) {
19665 		/* Expired or new entry, reset count to 1 */
19666 		zmgr->unreachable[slot].count = 1;
19667 	} else {
19668 		zmgr->unreachable[slot].count++;
19669 	}
19670 	atomic_store_relaxed(&zmgr->unreachable[slot].expire,
19671 			     seconds + UNREACH_HOLD_TIME);
19672 	atomic_store_relaxed(&zmgr->unreachable[slot].last, seconds);
19673 	if (update_entry) {
19674 		zmgr->unreachable[slot].remote = *remote;
19675 		zmgr->unreachable[slot].local = *local;
19676 	}
19677 
19678 	RWUNLOCK(&zmgr->urlock, isc_rwlocktype_write);
19679 }
19680 
19681 void
dns_zone_forcereload(dns_zone_t * zone)19682 dns_zone_forcereload(dns_zone_t *zone) {
19683 	REQUIRE(DNS_ZONE_VALID(zone));
19684 
19685 	if (zone->type == dns_zone_primary ||
19686 	    (zone->type == dns_zone_redirect && zone->masters == NULL))
19687 	{
19688 		return;
19689 	}
19690 
19691 	LOCK_ZONE(zone);
19692 	DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
19693 	UNLOCK_ZONE(zone);
19694 	dns_zone_refresh(zone);
19695 }
19696 
19697 bool
dns_zone_isforced(dns_zone_t * zone)19698 dns_zone_isforced(dns_zone_t *zone) {
19699 	REQUIRE(DNS_ZONE_VALID(zone));
19700 
19701 	return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER));
19702 }
19703 
19704 isc_result_t
dns_zone_setstatistics(dns_zone_t * zone,bool on)19705 dns_zone_setstatistics(dns_zone_t *zone, bool on) {
19706 	/*
19707 	 * This function is obsoleted.
19708 	 */
19709 	UNUSED(zone);
19710 	UNUSED(on);
19711 	return (ISC_R_NOTIMPLEMENTED);
19712 }
19713 
19714 uint64_t *
dns_zone_getstatscounters(dns_zone_t * zone)19715 dns_zone_getstatscounters(dns_zone_t *zone) {
19716 	/*
19717 	 * This function is obsoleted.
19718 	 */
19719 	UNUSED(zone);
19720 	return (NULL);
19721 }
19722 
19723 void
dns_zone_setstats(dns_zone_t * zone,isc_stats_t * stats)19724 dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats) {
19725 	REQUIRE(DNS_ZONE_VALID(zone));
19726 	REQUIRE(zone->stats == NULL);
19727 
19728 	LOCK_ZONE(zone);
19729 	zone->stats = NULL;
19730 	isc_stats_attach(stats, &zone->stats);
19731 	UNLOCK_ZONE(zone);
19732 }
19733 
19734 void
dns_zone_setrequeststats(dns_zone_t * zone,isc_stats_t * stats)19735 dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats) {
19736 	REQUIRE(DNS_ZONE_VALID(zone));
19737 
19738 	LOCK_ZONE(zone);
19739 	if (zone->requeststats_on && stats == NULL) {
19740 		zone->requeststats_on = false;
19741 	} else if (!zone->requeststats_on && stats != NULL) {
19742 		if (zone->requeststats == NULL) {
19743 			isc_stats_attach(stats, &zone->requeststats);
19744 		}
19745 		zone->requeststats_on = true;
19746 	}
19747 	UNLOCK_ZONE(zone);
19748 }
19749 
19750 void
dns_zone_setrcvquerystats(dns_zone_t * zone,dns_stats_t * stats)19751 dns_zone_setrcvquerystats(dns_zone_t *zone, dns_stats_t *stats) {
19752 	REQUIRE(DNS_ZONE_VALID(zone));
19753 
19754 	LOCK_ZONE(zone);
19755 	if (zone->requeststats_on && stats != NULL) {
19756 		if (zone->rcvquerystats == NULL) {
19757 			dns_stats_attach(stats, &zone->rcvquerystats);
19758 			zone->requeststats_on = true;
19759 		}
19760 	}
19761 	UNLOCK_ZONE(zone);
19762 }
19763 
19764 void
dns_zone_setdnssecsignstats(dns_zone_t * zone,dns_stats_t * stats)19765 dns_zone_setdnssecsignstats(dns_zone_t *zone, dns_stats_t *stats) {
19766 	REQUIRE(DNS_ZONE_VALID(zone));
19767 
19768 	LOCK_ZONE(zone);
19769 	if (stats != NULL && zone->dnssecsignstats == NULL) {
19770 		dns_stats_attach(stats, &zone->dnssecsignstats);
19771 	}
19772 	UNLOCK_ZONE(zone);
19773 }
19774 
19775 dns_stats_t *
dns_zone_getdnssecsignstats(dns_zone_t * zone)19776 dns_zone_getdnssecsignstats(dns_zone_t *zone) {
19777 	REQUIRE(DNS_ZONE_VALID(zone));
19778 
19779 	return (zone->dnssecsignstats);
19780 }
19781 
19782 isc_stats_t *
dns_zone_getrequeststats(dns_zone_t * zone)19783 dns_zone_getrequeststats(dns_zone_t *zone) {
19784 	/*
19785 	 * We don't lock zone for efficiency reason.  This is not catastrophic
19786 	 * because requeststats must always be valid when requeststats_on is
19787 	 * true.
19788 	 * Some counters may be incremented while requeststats_on is becoming
19789 	 * false, or some cannot be incremented just after the statistics are
19790 	 * installed, but it shouldn't matter much in practice.
19791 	 */
19792 	if (zone->requeststats_on) {
19793 		return (zone->requeststats);
19794 	} else {
19795 		return (NULL);
19796 	}
19797 }
19798 
19799 /*
19800  * Return the received query stats bucket
19801  * see note from dns_zone_getrequeststats()
19802  */
19803 dns_stats_t *
dns_zone_getrcvquerystats(dns_zone_t * zone)19804 dns_zone_getrcvquerystats(dns_zone_t *zone) {
19805 	if (zone->requeststats_on) {
19806 		return (zone->rcvquerystats);
19807 	} else {
19808 		return (NULL);
19809 	}
19810 }
19811 
19812 void
dns_zone_dialup(dns_zone_t * zone)19813 dns_zone_dialup(dns_zone_t *zone) {
19814 	REQUIRE(DNS_ZONE_VALID(zone));
19815 
19816 	zone_debuglog(zone, "dns_zone_dialup", 3, "notify = %d, refresh = %d",
19817 		      DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY),
19818 		      DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH));
19819 
19820 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY)) {
19821 		dns_zone_notify(zone);
19822 	}
19823 	if (zone->type != dns_zone_primary && zone->masters != NULL &&
19824 	    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
19825 	{
19826 		dns_zone_refresh(zone);
19827 	}
19828 }
19829 
19830 void
dns_zone_setdialup(dns_zone_t * zone,dns_dialuptype_t dialup)19831 dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
19832 	REQUIRE(DNS_ZONE_VALID(zone));
19833 
19834 	LOCK_ZONE(zone);
19835 	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
19836 				       DNS_ZONEFLG_DIALREFRESH |
19837 				       DNS_ZONEFLG_NOREFRESH);
19838 	switch (dialup) {
19839 	case dns_dialuptype_no:
19840 		break;
19841 	case dns_dialuptype_yes:
19842 		DNS_ZONE_SETFLAG(zone, (DNS_ZONEFLG_DIALNOTIFY |
19843 					DNS_ZONEFLG_DIALREFRESH |
19844 					DNS_ZONEFLG_NOREFRESH));
19845 		break;
19846 	case dns_dialuptype_notify:
19847 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
19848 		break;
19849 	case dns_dialuptype_notifypassive:
19850 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
19851 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
19852 		break;
19853 	case dns_dialuptype_refresh:
19854 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALREFRESH);
19855 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
19856 		break;
19857 	case dns_dialuptype_passive:
19858 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
19859 		break;
19860 	default:
19861 		UNREACHABLE();
19862 	}
19863 	UNLOCK_ZONE(zone);
19864 }
19865 
19866 isc_result_t
dns_zone_setkeydirectory(dns_zone_t * zone,const char * directory)19867 dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory) {
19868 	isc_result_t result = ISC_R_SUCCESS;
19869 
19870 	REQUIRE(DNS_ZONE_VALID(zone));
19871 
19872 	LOCK_ZONE(zone);
19873 	result = dns_zone_setstring(zone, &zone->keydirectory, directory);
19874 	UNLOCK_ZONE(zone);
19875 
19876 	return (result);
19877 }
19878 
19879 const char *
dns_zone_getkeydirectory(dns_zone_t * zone)19880 dns_zone_getkeydirectory(dns_zone_t *zone) {
19881 	REQUIRE(DNS_ZONE_VALID(zone));
19882 
19883 	return (zone->keydirectory);
19884 }
19885 
19886 unsigned int
dns_zonemgr_getcount(dns_zonemgr_t * zmgr,int state)19887 dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state) {
19888 	dns_zone_t *zone;
19889 	unsigned int count = 0;
19890 
19891 	REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19892 
19893 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
19894 	switch (state) {
19895 	case DNS_ZONESTATE_XFERRUNNING:
19896 		for (zone = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
19897 		     zone != NULL; zone = ISC_LIST_NEXT(zone, statelink))
19898 		{
19899 			count++;
19900 		}
19901 		break;
19902 	case DNS_ZONESTATE_XFERDEFERRED:
19903 		for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
19904 		     zone != NULL; zone = ISC_LIST_NEXT(zone, statelink))
19905 		{
19906 			count++;
19907 		}
19908 		break;
19909 	case DNS_ZONESTATE_SOAQUERY:
19910 		for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
19911 		     zone = ISC_LIST_NEXT(zone, link))
19912 		{
19913 			if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
19914 				count++;
19915 			}
19916 		}
19917 		break;
19918 	case DNS_ZONESTATE_ANY:
19919 		for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
19920 		     zone = ISC_LIST_NEXT(zone, link))
19921 		{
19922 			dns_view_t *view = zone->view;
19923 			if (view != NULL && strcmp(view->name, "_bind") == 0) {
19924 				continue;
19925 			}
19926 			count++;
19927 		}
19928 		break;
19929 	case DNS_ZONESTATE_AUTOMATIC:
19930 		for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
19931 		     zone = ISC_LIST_NEXT(zone, link))
19932 		{
19933 			dns_view_t *view = zone->view;
19934 			if (view != NULL && strcmp(view->name, "_bind") == 0) {
19935 				continue;
19936 			}
19937 			if (zone->automatic) {
19938 				count++;
19939 			}
19940 		}
19941 		break;
19942 	default:
19943 		UNREACHABLE();
19944 	}
19945 
19946 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
19947 
19948 	return (count);
19949 }
19950 
19951 void
dns_zone_lock_keyfiles(dns_zone_t * zone)19952 dns_zone_lock_keyfiles(dns_zone_t *zone) {
19953 	REQUIRE(DNS_ZONE_VALID(zone));
19954 
19955 	if (zone->kasp == NULL) {
19956 		/* No need to lock, nothing is writing key files. */
19957 		return;
19958 	}
19959 
19960 	REQUIRE(DNS_KEYFILEIO_VALID(zone->kfio));
19961 	isc_mutex_lock(&zone->kfio->lock);
19962 }
19963 
19964 void
dns_zone_unlock_keyfiles(dns_zone_t * zone)19965 dns_zone_unlock_keyfiles(dns_zone_t *zone) {
19966 	REQUIRE(DNS_ZONE_VALID(zone));
19967 
19968 	if (zone->kasp == NULL) {
19969 		/* No need to lock, nothing is writing key files. */
19970 		return;
19971 	}
19972 
19973 	REQUIRE(DNS_KEYFILEIO_VALID(zone->kfio));
19974 	isc_mutex_unlock(&zone->kfio->lock);
19975 }
19976 
19977 isc_result_t
dns_zone_checknames(dns_zone_t * zone,const dns_name_t * name,dns_rdata_t * rdata)19978 dns_zone_checknames(dns_zone_t *zone, const dns_name_t *name,
19979 		    dns_rdata_t *rdata) {
19980 	bool ok = true;
19981 	bool fail = false;
19982 	char namebuf[DNS_NAME_FORMATSIZE];
19983 	char namebuf2[DNS_NAME_FORMATSIZE];
19984 	char typebuf[DNS_RDATATYPE_FORMATSIZE];
19985 	int level = ISC_LOG_WARNING;
19986 	dns_name_t bad;
19987 
19988 	REQUIRE(DNS_ZONE_VALID(zone));
19989 
19990 	if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES) &&
19991 	    rdata->type != dns_rdatatype_nsec3)
19992 	{
19993 		return (ISC_R_SUCCESS);
19994 	}
19995 
19996 	if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL) ||
19997 	    rdata->type == dns_rdatatype_nsec3)
19998 	{
19999 		level = ISC_LOG_ERROR;
20000 		fail = true;
20001 	}
20002 
20003 	ok = dns_rdata_checkowner(name, rdata->rdclass, rdata->type, true);
20004 	if (!ok) {
20005 		dns_name_format(name, namebuf, sizeof(namebuf));
20006 		dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
20007 		dns_zone_log(zone, level, "%s/%s: %s", namebuf, typebuf,
20008 			     dns_result_totext(DNS_R_BADOWNERNAME));
20009 		if (fail) {
20010 			return (DNS_R_BADOWNERNAME);
20011 		}
20012 	}
20013 
20014 	dns_name_init(&bad, NULL);
20015 	ok = dns_rdata_checknames(rdata, name, &bad);
20016 	if (!ok) {
20017 		dns_name_format(name, namebuf, sizeof(namebuf));
20018 		dns_name_format(&bad, namebuf2, sizeof(namebuf2));
20019 		dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
20020 		dns_zone_log(zone, level, "%s/%s: %s: %s ", namebuf, typebuf,
20021 			     namebuf2, dns_result_totext(DNS_R_BADNAME));
20022 		if (fail) {
20023 			return (DNS_R_BADNAME);
20024 		}
20025 	}
20026 
20027 	return (ISC_R_SUCCESS);
20028 }
20029 
20030 void
dns_zone_setcheckmx(dns_zone_t * zone,dns_checkmxfunc_t checkmx)20031 dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx) {
20032 	REQUIRE(DNS_ZONE_VALID(zone));
20033 	zone->checkmx = checkmx;
20034 }
20035 
20036 void
dns_zone_setchecksrv(dns_zone_t * zone,dns_checksrvfunc_t checksrv)20037 dns_zone_setchecksrv(dns_zone_t *zone, dns_checksrvfunc_t checksrv) {
20038 	REQUIRE(DNS_ZONE_VALID(zone));
20039 	zone->checksrv = checksrv;
20040 }
20041 
20042 void
dns_zone_setcheckns(dns_zone_t * zone,dns_checknsfunc_t checkns)20043 dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns) {
20044 	REQUIRE(DNS_ZONE_VALID(zone));
20045 	zone->checkns = checkns;
20046 }
20047 
20048 void
dns_zone_setisself(dns_zone_t * zone,dns_isselffunc_t isself,void * arg)20049 dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg) {
20050 	REQUIRE(DNS_ZONE_VALID(zone));
20051 
20052 	LOCK_ZONE(zone);
20053 	zone->isself = isself;
20054 	zone->isselfarg = arg;
20055 	UNLOCK_ZONE(zone);
20056 }
20057 
20058 void
dns_zone_setnotifydelay(dns_zone_t * zone,uint32_t delay)20059 dns_zone_setnotifydelay(dns_zone_t *zone, uint32_t delay) {
20060 	REQUIRE(DNS_ZONE_VALID(zone));
20061 
20062 	LOCK_ZONE(zone);
20063 	zone->notifydelay = delay;
20064 	UNLOCK_ZONE(zone);
20065 }
20066 
20067 uint32_t
dns_zone_getnotifydelay(dns_zone_t * zone)20068 dns_zone_getnotifydelay(dns_zone_t *zone) {
20069 	REQUIRE(DNS_ZONE_VALID(zone));
20070 
20071 	return (zone->notifydelay);
20072 }
20073 
20074 isc_result_t
dns_zone_signwithkey(dns_zone_t * zone,dns_secalg_t algorithm,uint16_t keyid,bool deleteit)20075 dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid,
20076 		     bool deleteit) {
20077 	isc_result_t result;
20078 	REQUIRE(DNS_ZONE_VALID(zone));
20079 
20080 	dnssec_log(zone, ISC_LOG_NOTICE,
20081 		   "dns_zone_signwithkey(algorithm=%u, keyid=%u)", algorithm,
20082 		   keyid);
20083 	LOCK_ZONE(zone);
20084 	result = zone_signwithkey(zone, algorithm, keyid, deleteit);
20085 	UNLOCK_ZONE(zone);
20086 
20087 	return (result);
20088 }
20089 
20090 /*
20091  * Called when a dynamic update for an NSEC3PARAM record is received.
20092  *
20093  * If set, transform the NSEC3 salt into human-readable form so that it can be
20094  * logged.  Then call zone_addnsec3chain(), passing NSEC3PARAM RDATA to it.
20095  */
20096 isc_result_t
dns_zone_addnsec3chain(dns_zone_t * zone,dns_rdata_nsec3param_t * nsec3param)20097 dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
20098 	isc_result_t result;
20099 	char salt[255 * 2 + 1];
20100 
20101 	REQUIRE(DNS_ZONE_VALID(zone));
20102 
20103 	result = dns_nsec3param_salttotext(nsec3param, salt, sizeof(salt));
20104 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
20105 	dnssec_log(zone, ISC_LOG_NOTICE,
20106 		   "dns_zone_addnsec3chain(hash=%u, iterations=%u, salt=%s)",
20107 		   nsec3param->hash, nsec3param->iterations, salt);
20108 	LOCK_ZONE(zone);
20109 	result = zone_addnsec3chain(zone, nsec3param);
20110 	UNLOCK_ZONE(zone);
20111 
20112 	return (result);
20113 }
20114 
20115 void
dns_zone_setnodes(dns_zone_t * zone,uint32_t nodes)20116 dns_zone_setnodes(dns_zone_t *zone, uint32_t nodes) {
20117 	REQUIRE(DNS_ZONE_VALID(zone));
20118 
20119 	if (nodes == 0) {
20120 		nodes = 1;
20121 	}
20122 	zone->nodes = nodes;
20123 }
20124 
20125 void
dns_zone_setsignatures(dns_zone_t * zone,uint32_t signatures)20126 dns_zone_setsignatures(dns_zone_t *zone, uint32_t signatures) {
20127 	REQUIRE(DNS_ZONE_VALID(zone));
20128 
20129 	/*
20130 	 * We treat signatures as a signed value so explicitly
20131 	 * limit its range here.
20132 	 */
20133 	if (signatures > INT32_MAX) {
20134 		signatures = INT32_MAX;
20135 	} else if (signatures == 0) {
20136 		signatures = 1;
20137 	}
20138 	zone->signatures = signatures;
20139 }
20140 
20141 uint32_t
dns_zone_getsignatures(dns_zone_t * zone)20142 dns_zone_getsignatures(dns_zone_t *zone) {
20143 	REQUIRE(DNS_ZONE_VALID(zone));
20144 	return (zone->signatures);
20145 }
20146 
20147 void
dns_zone_setprivatetype(dns_zone_t * zone,dns_rdatatype_t type)20148 dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type) {
20149 	REQUIRE(DNS_ZONE_VALID(zone));
20150 	zone->privatetype = type;
20151 }
20152 
20153 dns_rdatatype_t
dns_zone_getprivatetype(dns_zone_t * zone)20154 dns_zone_getprivatetype(dns_zone_t *zone) {
20155 	REQUIRE(DNS_ZONE_VALID(zone));
20156 	return (zone->privatetype);
20157 }
20158 
20159 static isc_result_t
zone_signwithkey(dns_zone_t * zone,dns_secalg_t algorithm,uint16_t keyid,bool deleteit)20160 zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid,
20161 		 bool deleteit) {
20162 	dns_signing_t *signing;
20163 	dns_signing_t *current;
20164 	isc_result_t result = ISC_R_SUCCESS;
20165 	isc_time_t now;
20166 	dns_db_t *db = NULL;
20167 
20168 	signing = isc_mem_get(zone->mctx, sizeof *signing);
20169 
20170 	signing->magic = 0;
20171 	signing->db = NULL;
20172 	signing->dbiterator = NULL;
20173 	signing->algorithm = algorithm;
20174 	signing->keyid = keyid;
20175 	signing->deleteit = deleteit;
20176 	signing->done = false;
20177 
20178 	TIME_NOW(&now);
20179 
20180 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
20181 	if (zone->db != NULL) {
20182 		dns_db_attach(zone->db, &db);
20183 	}
20184 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
20185 
20186 	if (db == NULL) {
20187 		result = ISC_R_NOTFOUND;
20188 		goto cleanup;
20189 	}
20190 
20191 	dns_db_attach(db, &signing->db);
20192 
20193 	for (current = ISC_LIST_HEAD(zone->signing); current != NULL;
20194 	     current = ISC_LIST_NEXT(current, link))
20195 	{
20196 		if (current->db == signing->db &&
20197 		    current->algorithm == signing->algorithm &&
20198 		    current->keyid == signing->keyid)
20199 		{
20200 			if (current->deleteit != signing->deleteit) {
20201 				current->done = true;
20202 			} else {
20203 				goto cleanup;
20204 			}
20205 		}
20206 	}
20207 
20208 	result = dns_db_createiterator(signing->db, 0, &signing->dbiterator);
20209 
20210 	if (result == ISC_R_SUCCESS) {
20211 		result = dns_dbiterator_first(signing->dbiterator);
20212 	}
20213 	if (result == ISC_R_SUCCESS) {
20214 		dns_dbiterator_pause(signing->dbiterator);
20215 		ISC_LIST_INITANDAPPEND(zone->signing, signing, link);
20216 		signing = NULL;
20217 		if (isc_time_isepoch(&zone->signingtime)) {
20218 			zone->signingtime = now;
20219 			if (zone->task != NULL) {
20220 				zone_settimer(zone, &now);
20221 			}
20222 		}
20223 	}
20224 
20225 cleanup:
20226 	if (signing != NULL) {
20227 		if (signing->db != NULL) {
20228 			dns_db_detach(&signing->db);
20229 		}
20230 		if (signing->dbiterator != NULL) {
20231 			dns_dbiterator_destroy(&signing->dbiterator);
20232 		}
20233 		isc_mem_put(zone->mctx, signing, sizeof *signing);
20234 	}
20235 	if (db != NULL) {
20236 		dns_db_detach(&db);
20237 	}
20238 	return (result);
20239 }
20240 
20241 /* Called once; *timep should be set to the current time. */
20242 static isc_result_t
next_keyevent(dst_key_t * key,isc_stdtime_t * timep)20243 next_keyevent(dst_key_t *key, isc_stdtime_t *timep) {
20244 	isc_result_t result;
20245 	isc_stdtime_t now, then = 0, event;
20246 	int i;
20247 
20248 	now = *timep;
20249 
20250 	for (i = 0; i <= DST_MAX_TIMES; i++) {
20251 		result = dst_key_gettime(key, i, &event);
20252 		if (result == ISC_R_SUCCESS && event > now &&
20253 		    (then == 0 || event < then))
20254 		{
20255 			then = event;
20256 		}
20257 	}
20258 
20259 	if (then != 0) {
20260 		*timep = then;
20261 		return (ISC_R_SUCCESS);
20262 	}
20263 
20264 	return (ISC_R_NOTFOUND);
20265 }
20266 
20267 static isc_result_t
rr_exists(dns_db_t * db,dns_dbversion_t * ver,dns_name_t * name,const dns_rdata_t * rdata,bool * flag)20268 rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
20269 	  const dns_rdata_t *rdata, bool *flag) {
20270 	dns_rdataset_t rdataset;
20271 	dns_dbnode_t *node = NULL;
20272 	isc_result_t result;
20273 
20274 	dns_rdataset_init(&rdataset);
20275 	if (rdata->type == dns_rdatatype_nsec3) {
20276 		CHECK(dns_db_findnsec3node(db, name, false, &node));
20277 	} else {
20278 		CHECK(dns_db_findnode(db, name, false, &node));
20279 	}
20280 	result = dns_db_findrdataset(db, node, ver, rdata->type, 0,
20281 				     (isc_stdtime_t)0, &rdataset, NULL);
20282 	if (result == ISC_R_NOTFOUND) {
20283 		*flag = false;
20284 		result = ISC_R_SUCCESS;
20285 		goto failure;
20286 	}
20287 
20288 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
20289 	     result = dns_rdataset_next(&rdataset))
20290 	{
20291 		dns_rdata_t myrdata = DNS_RDATA_INIT;
20292 		dns_rdataset_current(&rdataset, &myrdata);
20293 		if (!dns_rdata_compare(&myrdata, rdata)) {
20294 			break;
20295 		}
20296 	}
20297 	dns_rdataset_disassociate(&rdataset);
20298 	if (result == ISC_R_SUCCESS) {
20299 		*flag = true;
20300 	} else if (result == ISC_R_NOMORE) {
20301 		*flag = false;
20302 		result = ISC_R_SUCCESS;
20303 	}
20304 
20305 failure:
20306 	if (node != NULL) {
20307 		dns_db_detachnode(db, &node);
20308 	}
20309 	return (result);
20310 }
20311 
20312 /*
20313  * Add records to signal the state of signing or of key removal.
20314  */
20315 static isc_result_t
add_signing_records(dns_db_t * db,dns_rdatatype_t privatetype,dns_dbversion_t * ver,dns_diff_t * diff,bool sign_all)20316 add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
20317 		    dns_dbversion_t *ver, dns_diff_t *diff, bool sign_all) {
20318 	dns_difftuple_t *tuple, *newtuple = NULL;
20319 	dns_rdata_dnskey_t dnskey;
20320 	dns_rdata_t rdata = DNS_RDATA_INIT;
20321 	bool flag;
20322 	isc_region_t r;
20323 	isc_result_t result = ISC_R_SUCCESS;
20324 	uint16_t keyid;
20325 	unsigned char buf[5];
20326 	dns_name_t *name = dns_db_origin(db);
20327 
20328 	for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL;
20329 	     tuple = ISC_LIST_NEXT(tuple, link))
20330 	{
20331 		if (tuple->rdata.type != dns_rdatatype_dnskey) {
20332 			continue;
20333 		}
20334 
20335 		result = dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
20336 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
20337 		if ((dnskey.flags & (DNS_KEYFLAG_OWNERMASK |
20338 				     DNS_KEYTYPE_NOAUTH)) != DNS_KEYOWNER_ZONE)
20339 		{
20340 			continue;
20341 		}
20342 
20343 		dns_rdata_toregion(&tuple->rdata, &r);
20344 
20345 		keyid = dst_region_computeid(&r);
20346 
20347 		buf[0] = dnskey.algorithm;
20348 		buf[1] = (keyid & 0xff00) >> 8;
20349 		buf[2] = (keyid & 0xff);
20350 		buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1;
20351 		buf[4] = 0;
20352 		rdata.data = buf;
20353 		rdata.length = sizeof(buf);
20354 		rdata.type = privatetype;
20355 		rdata.rdclass = tuple->rdata.rdclass;
20356 
20357 		if (sign_all || tuple->op == DNS_DIFFOP_DEL) {
20358 			CHECK(rr_exists(db, ver, name, &rdata, &flag));
20359 			if (flag) {
20360 				continue;
20361 			}
20362 
20363 			CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
20364 						   name, 0, &rdata, &newtuple));
20365 			CHECK(do_one_tuple(&newtuple, db, ver, diff));
20366 			INSIST(newtuple == NULL);
20367 		}
20368 
20369 		/*
20370 		 * Remove any record which says this operation has already
20371 		 * completed.
20372 		 */
20373 		buf[4] = 1;
20374 		CHECK(rr_exists(db, ver, name, &rdata, &flag));
20375 		if (flag) {
20376 			CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL,
20377 						   name, 0, &rdata, &newtuple));
20378 			CHECK(do_one_tuple(&newtuple, db, ver, diff));
20379 			INSIST(newtuple == NULL);
20380 		}
20381 	}
20382 failure:
20383 	return (result);
20384 }
20385 
20386 /*
20387  * See if dns__zone_updatesigs() will update signature for RRset 'rrtype' at
20388  * the apex, and if not tickle them and cause to sign so that newly activated
20389  * keys are used.
20390  */
20391 static isc_result_t
tickle_apex_rrset(dns_rdatatype_t rrtype,dns_zone_t * zone,dns_db_t * db,dns_dbversion_t * ver,isc_stdtime_t now,dns_diff_t * diff,dns__zonediff_t * zonediff,dst_key_t ** keys,unsigned int nkeys,isc_stdtime_t inception,isc_stdtime_t keyexpire,bool check_ksk,bool keyset_kskonly)20392 tickle_apex_rrset(dns_rdatatype_t rrtype, dns_zone_t *zone, dns_db_t *db,
20393 		  dns_dbversion_t *ver, isc_stdtime_t now, dns_diff_t *diff,
20394 		  dns__zonediff_t *zonediff, dst_key_t **keys,
20395 		  unsigned int nkeys, isc_stdtime_t inception,
20396 		  isc_stdtime_t keyexpire, bool check_ksk,
20397 		  bool keyset_kskonly) {
20398 	dns_difftuple_t *tuple;
20399 	isc_result_t result;
20400 
20401 	for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL;
20402 	     tuple = ISC_LIST_NEXT(tuple, link))
20403 	{
20404 		if (tuple->rdata.type == rrtype &&
20405 		    dns_name_equal(&tuple->name, &zone->origin))
20406 		{
20407 			break;
20408 		}
20409 	}
20410 
20411 	if (tuple == NULL) {
20412 		result = del_sigs(zone, db, ver, &zone->origin, rrtype,
20413 				  zonediff, keys, nkeys, now, false);
20414 		if (result != ISC_R_SUCCESS) {
20415 			dnssec_log(zone, ISC_LOG_ERROR,
20416 				   "sign_apex:del_sigs -> %s",
20417 				   dns_result_totext(result));
20418 			return (result);
20419 		}
20420 		result = add_sigs(db, ver, &zone->origin, zone, rrtype,
20421 				  zonediff->diff, keys, nkeys, zone->mctx,
20422 				  inception, keyexpire, check_ksk,
20423 				  keyset_kskonly);
20424 		if (result != ISC_R_SUCCESS) {
20425 			dnssec_log(zone, ISC_LOG_ERROR,
20426 				   "sign_apex:add_sigs -> %s",
20427 				   dns_result_totext(result));
20428 			return (result);
20429 		}
20430 	}
20431 
20432 	return (ISC_R_SUCCESS);
20433 }
20434 
20435 static isc_result_t
sign_apex(dns_zone_t * zone,dns_db_t * db,dns_dbversion_t * ver,isc_stdtime_t now,dns_diff_t * diff,dns__zonediff_t * zonediff)20436 sign_apex(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
20437 	  isc_stdtime_t now, dns_diff_t *diff, dns__zonediff_t *zonediff) {
20438 	isc_result_t result;
20439 	isc_stdtime_t inception, soaexpire, keyexpire;
20440 	bool check_ksk, keyset_kskonly;
20441 	dst_key_t *zone_keys[DNS_MAXZONEKEYS];
20442 	unsigned int nkeys = 0, i;
20443 
20444 	result = dns__zone_findkeys(zone, db, ver, now, zone->mctx,
20445 				    DNS_MAXZONEKEYS, zone_keys, &nkeys);
20446 	if (result != ISC_R_SUCCESS) {
20447 		dnssec_log(zone, ISC_LOG_ERROR,
20448 			   "sign_apex:dns__zone_findkeys -> %s",
20449 			   dns_result_totext(result));
20450 		return (result);
20451 	}
20452 
20453 	inception = now - 3600; /* Allow for clock skew. */
20454 	soaexpire = now + dns_zone_getsigvalidityinterval(zone);
20455 
20456 	keyexpire = dns_zone_getkeyvalidityinterval(zone);
20457 	if (keyexpire == 0) {
20458 		keyexpire = soaexpire - 1;
20459 	} else {
20460 		keyexpire += now;
20461 	}
20462 
20463 	check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
20464 	keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
20465 
20466 	/*
20467 	 * See if dns__zone_updatesigs() will update DNSKEY/CDS/CDNSKEY
20468 	 * signature and if not cause them to sign so that newly activated
20469 	 * keys are used.
20470 	 */
20471 	result = tickle_apex_rrset(dns_rdatatype_dnskey, zone, db, ver, now,
20472 				   diff, zonediff, zone_keys, nkeys, inception,
20473 				   keyexpire, check_ksk, keyset_kskonly);
20474 	if (result != ISC_R_SUCCESS) {
20475 		goto failure;
20476 	}
20477 	result = tickle_apex_rrset(dns_rdatatype_cds, zone, db, ver, now, diff,
20478 				   zonediff, zone_keys, nkeys, inception,
20479 				   keyexpire, check_ksk, keyset_kskonly);
20480 	if (result != ISC_R_SUCCESS) {
20481 		goto failure;
20482 	}
20483 	result = tickle_apex_rrset(dns_rdatatype_cdnskey, zone, db, ver, now,
20484 				   diff, zonediff, zone_keys, nkeys, inception,
20485 				   keyexpire, check_ksk, keyset_kskonly);
20486 	if (result != ISC_R_SUCCESS) {
20487 		goto failure;
20488 	}
20489 
20490 	result = dns__zone_updatesigs(diff, db, ver, zone_keys, nkeys, zone,
20491 				      inception, soaexpire, keyexpire, now,
20492 				      check_ksk, keyset_kskonly, zonediff);
20493 
20494 	if (result != ISC_R_SUCCESS) {
20495 		dnssec_log(zone, ISC_LOG_ERROR,
20496 			   "sign_apex:dns__zone_updatesigs -> %s",
20497 			   dns_result_totext(result));
20498 		goto failure;
20499 	}
20500 
20501 failure:
20502 	for (i = 0; i < nkeys; i++) {
20503 		dst_key_free(&zone_keys[i]);
20504 	}
20505 	return (result);
20506 }
20507 
20508 /*
20509  * Prevent the zone entering a inconsistent state where
20510  * NSEC only DNSKEYs are present with NSEC3 chains.
20511  * See update.c:check_dnssec()
20512  */
20513 static bool
dnskey_sane(dns_zone_t * zone,dns_db_t * db,dns_dbversion_t * ver,dns_diff_t * diff)20514 dnskey_sane(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
20515 	    dns_diff_t *diff) {
20516 	isc_result_t result;
20517 	dns_difftuple_t *tuple;
20518 	bool nseconly = false, nsec3 = false;
20519 	dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
20520 
20521 	/* Scan the tuples for an NSEC-only DNSKEY */
20522 	for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL;
20523 	     tuple = ISC_LIST_NEXT(tuple, link))
20524 	{
20525 		uint8_t alg;
20526 		if (tuple->rdata.type != dns_rdatatype_dnskey ||
20527 		    tuple->op != DNS_DIFFOP_ADD)
20528 		{
20529 			continue;
20530 		}
20531 
20532 		alg = tuple->rdata.data[3];
20533 		if (alg == DST_ALG_RSASHA1) {
20534 			nseconly = true;
20535 			break;
20536 		}
20537 	}
20538 
20539 	/* Check existing DB for NSEC-only DNSKEY */
20540 	if (!nseconly) {
20541 		result = dns_nsec_nseconly(db, ver, &nseconly);
20542 		if (result == ISC_R_NOTFOUND) {
20543 			result = ISC_R_SUCCESS;
20544 		}
20545 		CHECK(result);
20546 	}
20547 
20548 	/* Check existing DB for NSEC3 */
20549 	if (!nsec3) {
20550 		CHECK(dns_nsec3_activex(db, ver, false, privatetype, &nsec3));
20551 	}
20552 
20553 	/* Refuse to allow NSEC3 with NSEC-only keys */
20554 	if (nseconly && nsec3) {
20555 		dnssec_log(zone, ISC_LOG_ERROR,
20556 			   "NSEC only DNSKEYs and NSEC3 chains not allowed");
20557 		goto failure;
20558 	}
20559 
20560 	return (true);
20561 
20562 failure:
20563 	return (false);
20564 }
20565 
20566 static isc_result_t
clean_nsec3param(dns_zone_t * zone,dns_db_t * db,dns_dbversion_t * ver,dns_diff_t * diff)20567 clean_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
20568 		 dns_diff_t *diff) {
20569 	isc_result_t result;
20570 	dns_dbnode_t *node = NULL;
20571 	dns_rdataset_t rdataset;
20572 
20573 	dns_rdataset_init(&rdataset);
20574 	CHECK(dns_db_getoriginnode(db, &node));
20575 
20576 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
20577 				     dns_rdatatype_none, 0, &rdataset, NULL);
20578 	if (dns_rdataset_isassociated(&rdataset)) {
20579 		dns_rdataset_disassociate(&rdataset);
20580 	}
20581 	if (result != ISC_R_NOTFOUND) {
20582 		goto failure;
20583 	}
20584 
20585 	result = dns_nsec3param_deletechains(db, ver, zone, true, diff);
20586 
20587 failure:
20588 	if (node != NULL) {
20589 		dns_db_detachnode(db, &node);
20590 	}
20591 	return (result);
20592 }
20593 
20594 /*
20595  * Given an RRSIG rdataset and an algorithm, determine whether there
20596  * are any signatures using that algorithm.
20597  */
20598 static bool
signed_with_alg(dns_rdataset_t * rdataset,dns_secalg_t alg)20599 signed_with_alg(dns_rdataset_t *rdataset, dns_secalg_t alg) {
20600 	dns_rdata_t rdata = DNS_RDATA_INIT;
20601 	dns_rdata_rrsig_t rrsig;
20602 	isc_result_t result;
20603 
20604 	REQUIRE(rdataset == NULL || rdataset->type == dns_rdatatype_rrsig);
20605 	if (rdataset == NULL || !dns_rdataset_isassociated(rdataset)) {
20606 		return (false);
20607 	}
20608 
20609 	for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
20610 	     result = dns_rdataset_next(rdataset))
20611 	{
20612 		dns_rdataset_current(rdataset, &rdata);
20613 		result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
20614 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
20615 		dns_rdata_reset(&rdata);
20616 		if (rrsig.algorithm == alg) {
20617 			return (true);
20618 		}
20619 	}
20620 
20621 	return (false);
20622 }
20623 
20624 static isc_result_t
add_chains(dns_zone_t * zone,dns_db_t * db,dns_dbversion_t * ver,dns_diff_t * diff)20625 add_chains(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
20626 	   dns_diff_t *diff) {
20627 	dns_name_t *origin;
20628 	bool build_nsec3;
20629 	isc_result_t result;
20630 
20631 	origin = dns_db_origin(db);
20632 	CHECK(dns_private_chains(db, ver, zone->privatetype, NULL,
20633 				 &build_nsec3));
20634 	if (build_nsec3) {
20635 		CHECK(dns_nsec3_addnsec3sx(db, ver, origin, zone_nsecttl(zone),
20636 					   false, zone->privatetype, diff));
20637 	}
20638 	CHECK(updatesecure(db, ver, origin, zone_nsecttl(zone), true, diff));
20639 
20640 failure:
20641 	return (result);
20642 }
20643 
20644 static void
dnssec_report(const char * format,...)20645 dnssec_report(const char *format, ...) {
20646 	va_list args;
20647 	va_start(args, format);
20648 	isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_ZONE,
20649 		       ISC_LOG_INFO, format, args);
20650 	va_end(args);
20651 }
20652 
20653 static void
checkds_destroy(dns_checkds_t * checkds,bool locked)20654 checkds_destroy(dns_checkds_t *checkds, bool locked) {
20655 	isc_mem_t *mctx;
20656 
20657 	REQUIRE(DNS_CHECKDS_VALID(checkds));
20658 
20659 	dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
20660 		     "checkds: destroy DS query");
20661 
20662 	if (checkds->zone != NULL) {
20663 		if (!locked) {
20664 			LOCK_ZONE(checkds->zone);
20665 		}
20666 		REQUIRE(LOCKED_ZONE(checkds->zone));
20667 		if (ISC_LINK_LINKED(checkds, link)) {
20668 			ISC_LIST_UNLINK(checkds->zone->checkds_requests,
20669 					checkds, link);
20670 		}
20671 		if (!locked) {
20672 			UNLOCK_ZONE(checkds->zone);
20673 		}
20674 		if (locked) {
20675 			zone_idetach(&checkds->zone);
20676 		} else {
20677 			dns_zone_idetach(&checkds->zone);
20678 		}
20679 	}
20680 	if (checkds->request != NULL) {
20681 		dns_request_destroy(&checkds->request);
20682 	}
20683 	if (checkds->key != NULL) {
20684 		dns_tsigkey_detach(&checkds->key);
20685 	}
20686 	mctx = checkds->mctx;
20687 	isc_mem_put(checkds->mctx, checkds, sizeof(*checkds));
20688 	isc_mem_detach(&mctx);
20689 }
20690 
20691 static isc_result_t
make_dnskey(dst_key_t * key,unsigned char * buf,int bufsize,dns_rdata_t * target)20692 make_dnskey(dst_key_t *key, unsigned char *buf, int bufsize,
20693 	    dns_rdata_t *target) {
20694 	isc_result_t result;
20695 	isc_buffer_t b;
20696 	isc_region_t r;
20697 
20698 	isc_buffer_init(&b, buf, bufsize);
20699 	result = dst_key_todns(key, &b);
20700 	if (result != ISC_R_SUCCESS) {
20701 		return (result);
20702 	}
20703 
20704 	dns_rdata_reset(target);
20705 	isc_buffer_usedregion(&b, &r);
20706 	dns_rdata_fromregion(target, dst_key_class(key), dns_rdatatype_dnskey,
20707 			     &r);
20708 	return (ISC_R_SUCCESS);
20709 }
20710 
20711 static bool
do_checkds(dns_zone_t * zone,dst_key_t * key,isc_stdtime_t now,bool dspublish)20712 do_checkds(dns_zone_t *zone, dst_key_t *key, isc_stdtime_t now,
20713 	   bool dspublish) {
20714 	dns_kasp_t *kasp = dns_zone_getkasp(zone);
20715 	const char *dir = dns_zone_getkeydirectory(zone);
20716 	isc_result_t result;
20717 	uint32_t count = 0;
20718 
20719 	if (dspublish) {
20720 		(void)dst_key_getnum(key, DST_NUM_DSPUBCOUNT, &count);
20721 		count += 1;
20722 		dst_key_setnum(key, DST_NUM_DSPUBCOUNT, count);
20723 		dns_zone_log(zone, ISC_LOG_DEBUG(3),
20724 			     "checkds: %u DS published "
20725 			     "for key %u",
20726 			     count, dst_key_id(key));
20727 
20728 		if (count != zone->parentalscnt) {
20729 			return false;
20730 		}
20731 	} else {
20732 		(void)dst_key_getnum(key, DST_NUM_DSDELCOUNT, &count);
20733 		count += 1;
20734 		dst_key_setnum(key, DST_NUM_DSDELCOUNT, count);
20735 		dns_zone_log(zone, ISC_LOG_DEBUG(3),
20736 			     "checkds: %u DS withdrawn "
20737 			     "for key %u",
20738 			     count, dst_key_id(key));
20739 
20740 		if (count != zone->parentalscnt) {
20741 			return false;
20742 		}
20743 	}
20744 
20745 	dns_zone_log(zone, ISC_LOG_DEBUG(3),
20746 		     "checkds: checkds %s for key "
20747 		     "%u",
20748 		     dspublish ? "published" : "withdrawn", dst_key_id(key));
20749 
20750 	dns_zone_lock_keyfiles(zone);
20751 	result = dns_keymgr_checkds_id(kasp, &zone->checkds_ok, dir, now, now,
20752 				       dspublish, dst_key_id(key),
20753 				       dst_key_alg(key));
20754 	dns_zone_unlock_keyfiles(zone);
20755 
20756 	if (result != ISC_R_SUCCESS) {
20757 		dns_zone_log(zone, ISC_LOG_WARNING,
20758 			     "checkds: checkds for key %u failed: %s",
20759 			     dst_key_id(key), isc_result_totext(result));
20760 		return false;
20761 	}
20762 
20763 	return true;
20764 }
20765 
20766 static isc_result_t
validate_ds(dns_zone_t * zone,dns_message_t * message)20767 validate_ds(dns_zone_t *zone, dns_message_t *message) {
20768 	UNUSED(zone);
20769 	UNUSED(message);
20770 
20771 	/* Get closest trust anchor */
20772 
20773 	/* Check that trust anchor is (grand)parent of zone. */
20774 
20775 	/* Find the DNSKEY signing the message. */
20776 
20777 	/* Check that DNSKEY is in chain of trust. */
20778 
20779 	/* Validate DS RRset. */
20780 
20781 	return (ISC_R_SUCCESS);
20782 }
20783 
20784 static void
checkds_done(isc_task_t * task,isc_event_t * event)20785 checkds_done(isc_task_t *task, isc_event_t *event) {
20786 	char addrbuf[ISC_SOCKADDR_FORMATSIZE];
20787 	char rcode[128];
20788 	dns_checkds_t *checkds;
20789 	dns_zone_t *zone;
20790 	dns_db_t *db = NULL;
20791 	dns_dbversion_t *version = NULL;
20792 	dns_dnsseckey_t *key;
20793 	dns_dnsseckeylist_t keys;
20794 	dns_kasp_t *kasp = NULL;
20795 	dns_message_t *message = NULL;
20796 	dns_rdataset_t *ds_rrset = NULL;
20797 	dns_requestevent_t *revent = (dns_requestevent_t *)event;
20798 	isc_buffer_t buf;
20799 	isc_result_t result;
20800 	isc_stdtime_t now;
20801 	isc_time_t timenow;
20802 	bool rekey = false;
20803 	bool empty = false;
20804 
20805 	UNUSED(task);
20806 
20807 	checkds = event->ev_arg;
20808 	REQUIRE(DNS_CHECKDS_VALID(checkds));
20809 
20810 	zone = checkds->zone;
20811 	INSIST(task == zone->task);
20812 
20813 	ISC_LIST_INIT(keys);
20814 
20815 	kasp = zone->kasp;
20816 	INSIST(kasp != NULL);
20817 
20818 	isc_buffer_init(&buf, rcode, sizeof(rcode));
20819 	isc_sockaddr_format(&checkds->dst, addrbuf, sizeof(addrbuf));
20820 
20821 	dns_zone_log(zone, ISC_LOG_DEBUG(1), "checkds: DS query to %s: done",
20822 		     addrbuf);
20823 
20824 	dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &message);
20825 	INSIST(message != NULL);
20826 
20827 	CHECK(revent->result);
20828 	CHECK(dns_request_getresponse(revent->request, message,
20829 				      DNS_MESSAGEPARSE_PRESERVEORDER));
20830 	CHECK(dns_rcode_totext(message->rcode, &buf));
20831 
20832 	dns_zone_log(zone, ISC_LOG_DEBUG(3),
20833 		     "checkds: DS response from %s: %.*s", addrbuf,
20834 		     (int)buf.used, rcode);
20835 
20836 	/* Validate response. */
20837 	CHECK(validate_ds(zone, message));
20838 
20839 	if (message->rcode != dns_rcode_noerror) {
20840 		dns_zone_log(zone, ISC_LOG_NOTICE,
20841 			     "checkds: bad DS response from %s: %.*s", addrbuf,
20842 			     (int)buf.used, rcode);
20843 		goto failure;
20844 	}
20845 
20846 	/* Lookup DS RRset. */
20847 	result = dns_message_firstname(message, DNS_SECTION_ANSWER);
20848 	while (result == ISC_R_SUCCESS) {
20849 		dns_name_t *name = NULL;
20850 		dns_rdataset_t *rdataset;
20851 
20852 		dns_message_currentname(message, DNS_SECTION_ANSWER, &name);
20853 		if (dns_name_compare(&zone->origin, name) != 0) {
20854 			goto next;
20855 		}
20856 
20857 		for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL;
20858 		     rdataset = ISC_LIST_NEXT(rdataset, link))
20859 		{
20860 			if (rdataset->type != dns_rdatatype_ds) {
20861 				goto next;
20862 			}
20863 
20864 			ds_rrset = rdataset;
20865 			break;
20866 		}
20867 
20868 		if (ds_rrset != NULL) {
20869 			break;
20870 		}
20871 
20872 	next:
20873 		result = dns_message_nextname(message, DNS_SECTION_ANSWER);
20874 	}
20875 
20876 	if (ds_rrset == NULL) {
20877 		empty = true;
20878 		dns_zone_log(zone, ISC_LOG_NOTICE,
20879 			     "checkds: empty DS response from %s", addrbuf);
20880 	}
20881 
20882 	TIME_NOW(&timenow);
20883 	now = isc_time_seconds(&timenow);
20884 
20885 	CHECK(dns_zone_getdb(zone, &db));
20886 	dns_db_currentversion(db, &version);
20887 
20888 	KASP_LOCK(kasp);
20889 	LOCK_ZONE(zone);
20890 	for (key = ISC_LIST_HEAD(zone->checkds_ok); key != NULL;
20891 	     key = ISC_LIST_NEXT(key, link))
20892 	{
20893 		bool alldone = false, found = false;
20894 		bool checkdspub = false, checkdsdel = false, ksk = false;
20895 		dst_key_state_t ds_state = DST_KEY_STATE_NA;
20896 		isc_stdtime_t published = 0, withdrawn = 0;
20897 		isc_result_t ret = ISC_R_SUCCESS;
20898 
20899 		/* Is this key have the KSK role? */
20900 		(void)dst_key_role(key->key, &ksk, NULL);
20901 		if (!ksk) {
20902 			continue;
20903 		}
20904 
20905 		/* Do we need to check the DS RRset for this key? */
20906 		(void)dst_key_getstate(key->key, DST_KEY_DS, &ds_state);
20907 		(void)dst_key_gettime(key->key, DST_TIME_DSPUBLISH, &published);
20908 		(void)dst_key_gettime(key->key, DST_TIME_DSDELETE, &withdrawn);
20909 
20910 		if (ds_state == DST_KEY_STATE_RUMOURED && published == 0) {
20911 			checkdspub = true;
20912 		} else if (ds_state == DST_KEY_STATE_UNRETENTIVE &&
20913 			   withdrawn == 0)
20914 		{
20915 			checkdsdel = true;
20916 		}
20917 		if (!checkdspub && !checkdsdel) {
20918 			continue;
20919 		}
20920 
20921 		if (empty) {
20922 			goto dswithdrawn;
20923 		}
20924 
20925 		/* Find the appropriate DS record. */
20926 		ret = dns_rdataset_first(ds_rrset);
20927 		while (ret == ISC_R_SUCCESS) {
20928 			dns_rdata_ds_t ds;
20929 			dns_rdata_t dnskey = DNS_RDATA_INIT;
20930 			dns_rdata_t dsrdata = DNS_RDATA_INIT;
20931 			dns_rdata_t rdata = DNS_RDATA_INIT;
20932 			isc_result_t r;
20933 			unsigned char dsbuf[DNS_DS_BUFFERSIZE];
20934 			unsigned char keybuf[DST_KEY_MAXSIZE];
20935 
20936 			dns_rdataset_current(ds_rrset, &rdata);
20937 			r = dns_rdata_tostruct(&rdata, &ds, NULL);
20938 			if (r != ISC_R_SUCCESS) {
20939 				goto nextds;
20940 			}
20941 			/* Check key tag and algorithm. */
20942 			if (dst_key_id(key->key) != ds.key_tag) {
20943 				goto nextds;
20944 			}
20945 			if (dst_key_alg(key->key) != ds.algorithm) {
20946 				goto nextds;
20947 			}
20948 			/* Derive DS from DNSKEY, see if the rdata is equal. */
20949 			make_dnskey(key->key, keybuf, sizeof(keybuf), &dnskey);
20950 			r = dns_ds_buildrdata(&zone->origin, &dnskey,
20951 					      ds.digest_type, dsbuf, &dsrdata);
20952 			if (r != ISC_R_SUCCESS) {
20953 				goto nextds;
20954 			}
20955 			if (dns_rdata_compare(&rdata, &dsrdata) == 0) {
20956 				found = true;
20957 				if (checkdspub) {
20958 					/* DS Published. */
20959 					alldone = do_checkds(zone, key->key,
20960 							     now, true);
20961 					if (alldone) {
20962 						rekey = true;
20963 					}
20964 				}
20965 			}
20966 
20967 		nextds:
20968 			ret = dns_rdataset_next(ds_rrset);
20969 		}
20970 
20971 	dswithdrawn:
20972 		/* DS withdrawn. */
20973 		if (checkdsdel && !found) {
20974 			alldone = do_checkds(zone, key->key, now, false);
20975 			if (alldone) {
20976 				rekey = true;
20977 			}
20978 		}
20979 	}
20980 	UNLOCK_ZONE(zone);
20981 	KASP_UNLOCK(kasp);
20982 
20983 	/* Rekey after checkds. */
20984 	if (rekey) {
20985 		dns_zone_rekey(zone, false);
20986 	}
20987 
20988 failure:
20989 	if (result != ISC_R_SUCCESS) {
20990 		dns_zone_log(zone, ISC_LOG_DEBUG(3),
20991 			     "checkds: DS request failed: %s",
20992 			     isc_result_totext(result));
20993 	}
20994 
20995 	if (version != NULL) {
20996 		dns_db_closeversion(db, &version, false);
20997 	}
20998 	if (db != NULL) {
20999 		dns_db_detach(&db);
21000 	}
21001 
21002 	while (!ISC_LIST_EMPTY(keys)) {
21003 		key = ISC_LIST_HEAD(keys);
21004 		ISC_LIST_UNLINK(keys, key, link);
21005 		dns_dnsseckey_destroy(dns_zone_getmctx(zone), &key);
21006 	}
21007 
21008 	isc_event_free(&event);
21009 	checkds_destroy(checkds, false);
21010 	dns_message_detach(&message);
21011 }
21012 
21013 static bool
checkds_isqueued(dns_zone_t * zone,isc_sockaddr_t * addr,dns_tsigkey_t * key)21014 checkds_isqueued(dns_zone_t *zone, isc_sockaddr_t *addr, dns_tsigkey_t *key) {
21015 	dns_checkds_t *checkds;
21016 
21017 	for (checkds = ISC_LIST_HEAD(zone->checkds_requests); checkds != NULL;
21018 	     checkds = ISC_LIST_NEXT(checkds, link))
21019 	{
21020 		if (checkds->request != NULL) {
21021 			continue;
21022 		}
21023 		if (addr != NULL && isc_sockaddr_equal(addr, &checkds->dst) &&
21024 		    checkds->key == key)
21025 		{
21026 			return (true);
21027 		}
21028 	}
21029 	return (false);
21030 }
21031 
21032 static isc_result_t
checkds_create(isc_mem_t * mctx,unsigned int flags,dns_checkds_t ** checkdsp)21033 checkds_create(isc_mem_t *mctx, unsigned int flags, dns_checkds_t **checkdsp) {
21034 	dns_checkds_t *checkds;
21035 
21036 	REQUIRE(checkdsp != NULL && *checkdsp == NULL);
21037 
21038 	checkds = isc_mem_get(mctx, sizeof(*checkds));
21039 	*checkds = (dns_checkds_t){
21040 		.flags = flags,
21041 	};
21042 
21043 	isc_mem_attach(mctx, &checkds->mctx);
21044 	isc_sockaddr_any(&checkds->dst);
21045 	ISC_LINK_INIT(checkds, link);
21046 	checkds->magic = CHECKDS_MAGIC;
21047 	*checkdsp = checkds;
21048 	return (ISC_R_SUCCESS);
21049 }
21050 
21051 static isc_result_t
checkds_createmessage(dns_zone_t * zone,dns_message_t ** messagep)21052 checkds_createmessage(dns_zone_t *zone, dns_message_t **messagep) {
21053 	dns_message_t *message = NULL;
21054 
21055 	dns_name_t *tempname = NULL;
21056 	dns_rdataset_t *temprdataset = NULL;
21057 
21058 	isc_result_t result;
21059 
21060 	REQUIRE(DNS_ZONE_VALID(zone));
21061 	REQUIRE(messagep != NULL && *messagep == NULL);
21062 
21063 	dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER, &message);
21064 
21065 	message->opcode = dns_opcode_query;
21066 	message->rdclass = zone->rdclass;
21067 
21068 	result = dns_message_gettempname(message, &tempname);
21069 	if (result != ISC_R_SUCCESS) {
21070 		goto cleanup;
21071 	}
21072 
21073 	result = dns_message_gettemprdataset(message, &temprdataset);
21074 	if (result != ISC_R_SUCCESS) {
21075 		goto cleanup;
21076 	}
21077 
21078 	/*
21079 	 * Make question.
21080 	 */
21081 	dns_name_init(tempname, NULL);
21082 	dns_name_clone(&zone->origin, tempname);
21083 	dns_rdataset_makequestion(temprdataset, zone->rdclass,
21084 				  dns_rdatatype_ds);
21085 	ISC_LIST_APPEND(tempname->list, temprdataset, link);
21086 	dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
21087 	tempname = NULL;
21088 	temprdataset = NULL;
21089 
21090 	*messagep = message;
21091 	return (ISC_R_SUCCESS);
21092 
21093 cleanup:
21094 	if (tempname != NULL) {
21095 		dns_message_puttempname(message, &tempname);
21096 	}
21097 	if (temprdataset != NULL) {
21098 		dns_message_puttemprdataset(message, &temprdataset);
21099 	}
21100 	dns_message_detach(&message);
21101 	return (result);
21102 }
21103 
21104 static void
checkds_send_toaddr(isc_task_t * task,isc_event_t * event)21105 checkds_send_toaddr(isc_task_t *task, isc_event_t *event) {
21106 	dns_checkds_t *checkds;
21107 	isc_result_t result;
21108 	dns_message_t *message = NULL;
21109 	isc_netaddr_t dstip;
21110 	dns_tsigkey_t *key = NULL;
21111 	char addrbuf[ISC_SOCKADDR_FORMATSIZE];
21112 	isc_sockaddr_t src;
21113 	unsigned int options, timeout;
21114 	bool have_checkdssource = false;
21115 	bool have_checkdsdscp = false;
21116 	isc_dscp_t dscp = -1;
21117 
21118 	checkds = event->ev_arg;
21119 	REQUIRE(DNS_CHECKDS_VALID(checkds));
21120 
21121 	UNUSED(task);
21122 
21123 	LOCK_ZONE(checkds->zone);
21124 
21125 	checkds->event = NULL;
21126 
21127 	if (DNS_ZONE_FLAG(checkds->zone, DNS_ZONEFLG_LOADED) == 0) {
21128 		result = ISC_R_CANCELED;
21129 		goto cleanup;
21130 	}
21131 
21132 	if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
21133 	    DNS_ZONE_FLAG(checkds->zone, DNS_ZONEFLG_EXITING) ||
21134 	    checkds->zone->view->requestmgr == NULL ||
21135 	    checkds->zone->db == NULL)
21136 	{
21137 		result = ISC_R_CANCELED;
21138 		goto cleanup;
21139 	}
21140 
21141 	/*
21142 	 * The raw IPv4 address should also exist.  Don't send to the
21143 	 * mapped form.
21144 	 */
21145 	if (isc_sockaddr_pf(&checkds->dst) == PF_INET6 &&
21146 	    IN6_IS_ADDR_V4MAPPED(&checkds->dst.type.sin6.sin6_addr))
21147 	{
21148 		isc_sockaddr_format(&checkds->dst, addrbuf, sizeof(addrbuf));
21149 		dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
21150 			     "checkds: ignoring IPv6 mapped IPV4 address: %s",
21151 			     addrbuf);
21152 		result = ISC_R_CANCELED;
21153 		goto cleanup;
21154 	}
21155 
21156 	result = checkds_createmessage(checkds->zone, &message);
21157 	if (result != ISC_R_SUCCESS) {
21158 		goto cleanup;
21159 	}
21160 
21161 	isc_sockaddr_format(&checkds->dst, addrbuf, sizeof(addrbuf));
21162 	if (checkds->key != NULL) {
21163 		/* Transfer ownership of key */
21164 		key = checkds->key;
21165 		checkds->key = NULL;
21166 	} else {
21167 		isc_netaddr_fromsockaddr(&dstip, &checkds->dst);
21168 		result = dns_view_getpeertsig(checkds->zone->view, &dstip,
21169 					      &key);
21170 		if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
21171 			dns_zone_log(checkds->zone, ISC_LOG_ERROR,
21172 				     "checkds: DS query to %s not sent. "
21173 				     "Peer TSIG key lookup failure.",
21174 				     addrbuf);
21175 			goto cleanup_message;
21176 		}
21177 	}
21178 
21179 	if (key != NULL) {
21180 		char namebuf[DNS_NAME_FORMATSIZE];
21181 
21182 		dns_name_format(&key->name, namebuf, sizeof(namebuf));
21183 		dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
21184 			     "checkds: sending DS query to %s : TSIG (%s)",
21185 			     addrbuf, namebuf);
21186 	} else {
21187 		dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
21188 			     "checkds: sending DS query to %s", addrbuf);
21189 	}
21190 	options = 0;
21191 	if (checkds->zone->view->peers != NULL) {
21192 		dns_peer_t *peer = NULL;
21193 		bool usetcp = false;
21194 		result = dns_peerlist_peerbyaddr(checkds->zone->view->peers,
21195 						 &dstip, &peer);
21196 		if (result == ISC_R_SUCCESS) {
21197 			result = dns_peer_getquerysource(peer, &src);
21198 			if (result == ISC_R_SUCCESS) {
21199 				have_checkdssource = true;
21200 			}
21201 			dns_peer_getquerydscp(peer, &dscp);
21202 			if (dscp != -1) {
21203 				have_checkdsdscp = true;
21204 			}
21205 			result = dns_peer_getforcetcp(peer, &usetcp);
21206 			if (result == ISC_R_SUCCESS && usetcp) {
21207 				options |= DNS_FETCHOPT_TCP;
21208 			}
21209 		}
21210 	}
21211 	switch (isc_sockaddr_pf(&checkds->dst)) {
21212 	case PF_INET:
21213 		if (!have_checkdssource) {
21214 			src = checkds->zone->parentalsrc4;
21215 		}
21216 		if (!have_checkdsdscp) {
21217 			dscp = checkds->zone->parentalsrc4dscp;
21218 		}
21219 		break;
21220 	case PF_INET6:
21221 		if (!have_checkdssource) {
21222 			src = checkds->zone->parentalsrc6;
21223 		}
21224 		if (!have_checkdsdscp) {
21225 			dscp = checkds->zone->parentalsrc6dscp;
21226 		}
21227 		break;
21228 	default:
21229 		result = ISC_R_NOTIMPLEMENTED;
21230 		goto cleanup_key;
21231 	}
21232 
21233 	dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
21234 		     "checkds: create request for DS query to %s", addrbuf);
21235 
21236 	timeout = 15;
21237 	options |= DNS_REQUESTOPT_TCP;
21238 	result = dns_request_createvia(
21239 		checkds->zone->view->requestmgr, message, &src, &checkds->dst,
21240 		dscp, options, key, timeout * 3, timeout, 0,
21241 		checkds->zone->task, checkds_done, checkds, &checkds->request);
21242 	if (result != ISC_R_SUCCESS) {
21243 		dns_zone_log(
21244 			checkds->zone, ISC_LOG_DEBUG(3),
21245 			"checkds: dns_request_createvia() to %s failed: %s",
21246 			addrbuf, dns_result_totext(result));
21247 	}
21248 
21249 cleanup_key:
21250 	if (key != NULL) {
21251 		dns_tsigkey_detach(&key);
21252 	}
21253 cleanup_message:
21254 	dns_message_detach(&message);
21255 cleanup:
21256 	UNLOCK_ZONE(checkds->zone);
21257 	isc_event_free(&event);
21258 	if (result != ISC_R_SUCCESS) {
21259 		checkds_destroy(checkds, false);
21260 	}
21261 }
21262 
21263 static isc_result_t
checkds_send_queue(dns_checkds_t * checkds)21264 checkds_send_queue(dns_checkds_t *checkds) {
21265 	isc_event_t *e;
21266 	isc_result_t result;
21267 
21268 	INSIST(checkds->event == NULL);
21269 	e = isc_event_allocate(checkds->mctx, NULL, DNS_EVENT_CHECKDSSENDTOADDR,
21270 			       checkds_send_toaddr, checkds,
21271 			       sizeof(isc_event_t));
21272 	e->ev_arg = checkds;
21273 	e->ev_sender = NULL;
21274 	result = isc_ratelimiter_enqueue(checkds->zone->zmgr->checkdsrl,
21275 					 checkds->zone->task, &e);
21276 	if (result != ISC_R_SUCCESS) {
21277 		isc_event_free(&e);
21278 		checkds->event = NULL;
21279 	}
21280 	return (result);
21281 }
21282 
21283 static void
checkds_send(dns_zone_t * zone)21284 checkds_send(dns_zone_t *zone) {
21285 	dns_view_t *view = dns_zone_getview(zone);
21286 	isc_result_t result;
21287 	unsigned int flags = 0;
21288 
21289 	/*
21290 	 * Zone lock held by caller.
21291 	 */
21292 	REQUIRE(LOCKED_ZONE(zone));
21293 
21294 	dns_zone_log(zone, ISC_LOG_DEBUG(3),
21295 		     "checkds: start sending DS queries to %u parentals",
21296 		     zone->parentalscnt);
21297 
21298 	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
21299 		dns_zone_log(zone, ISC_LOG_DEBUG(3),
21300 			     "checkds: abort, named exiting");
21301 		return;
21302 	}
21303 
21304 	for (unsigned int i = 0; i < zone->parentalscnt; i++) {
21305 		dns_tsigkey_t *key = NULL;
21306 		isc_sockaddr_t dst;
21307 		dns_checkds_t *checkds = NULL;
21308 
21309 		if ((zone->parentalkeynames != NULL) &&
21310 		    (zone->parentalkeynames[i] != NULL))
21311 		{
21312 			dns_name_t *keyname = zone->parentalkeynames[i];
21313 			(void)dns_view_gettsig(view, keyname, &key);
21314 		}
21315 
21316 		dst = zone->parentals[i];
21317 
21318 		if (checkds_isqueued(zone, &dst, key)) {
21319 			dns_zone_log(zone, ISC_LOG_DEBUG(3),
21320 				     "checkds: DS query to parent "
21321 				     "%d is queued",
21322 				     i);
21323 			if (key != NULL) {
21324 				dns_tsigkey_detach(&key);
21325 			}
21326 			continue;
21327 		}
21328 
21329 		dns_zone_log(zone, ISC_LOG_DEBUG(3),
21330 			     "checkds: create DS query for "
21331 			     "parent %d",
21332 			     i);
21333 
21334 		result = checkds_create(zone->mctx, flags, &checkds);
21335 		if (result != ISC_R_SUCCESS) {
21336 			dns_zone_log(zone, ISC_LOG_DEBUG(3),
21337 				     "checkds: create DS query for "
21338 				     "parent %d failed",
21339 				     i);
21340 			continue;
21341 		}
21342 		zone_iattach(zone, &checkds->zone);
21343 		checkds->dst = dst;
21344 
21345 		INSIST(checkds->key == NULL);
21346 		if (key != NULL) {
21347 			checkds->key = key;
21348 			key = NULL;
21349 		}
21350 
21351 		ISC_LIST_APPEND(zone->checkds_requests, checkds, link);
21352 		result = checkds_send_queue(checkds);
21353 		if (result != ISC_R_SUCCESS) {
21354 			dns_zone_log(zone, ISC_LOG_DEBUG(3),
21355 				     "checkds: send DS query to "
21356 				     "parent %d failed",
21357 				     i);
21358 			checkds_destroy(checkds, true);
21359 		}
21360 	}
21361 }
21362 
21363 static void
zone_checkds(dns_zone_t * zone)21364 zone_checkds(dns_zone_t *zone) {
21365 	bool cdscheck = false;
21366 
21367 	for (dns_dnsseckey_t *key = ISC_LIST_HEAD(zone->checkds_ok);
21368 	     key != NULL; key = ISC_LIST_NEXT(key, link))
21369 	{
21370 		dst_key_state_t ds_state = DST_KEY_STATE_NA;
21371 		bool ksk = false;
21372 		isc_stdtime_t published = 0, withdrawn = 0;
21373 
21374 		/* Is this key have the KSK role? */
21375 		(void)dst_key_role(key->key, &ksk, NULL);
21376 		if (!ksk) {
21377 			continue;
21378 		}
21379 
21380 		/* Do we need to check the DS RRset? */
21381 		(void)dst_key_getstate(key->key, DST_KEY_DS, &ds_state);
21382 		(void)dst_key_gettime(key->key, DST_TIME_DSPUBLISH, &published);
21383 		(void)dst_key_gettime(key->key, DST_TIME_DSDELETE, &withdrawn);
21384 
21385 		if (ds_state == DST_KEY_STATE_RUMOURED && published == 0) {
21386 			dst_key_setnum(key->key, DST_NUM_DSPUBCOUNT, 0);
21387 			cdscheck = true;
21388 		} else if (ds_state == DST_KEY_STATE_UNRETENTIVE &&
21389 			   withdrawn == 0)
21390 		{
21391 			dst_key_setnum(key->key, DST_NUM_DSDELCOUNT, 0);
21392 			cdscheck = true;
21393 		}
21394 	}
21395 
21396 	if (cdscheck) {
21397 		/* Request the DS RRset. */
21398 		LOCK_ZONE(zone);
21399 		checkds_send(zone);
21400 		UNLOCK_ZONE(zone);
21401 	}
21402 }
21403 
21404 static void
zone_rekey(dns_zone_t * zone)21405 zone_rekey(dns_zone_t *zone) {
21406 	isc_result_t result;
21407 	dns_db_t *db = NULL;
21408 	dns_dbnode_t *node = NULL;
21409 	dns_dbversion_t *ver = NULL;
21410 	dns_rdataset_t cdsset, soaset, soasigs, keyset, keysigs, cdnskeyset;
21411 	dns_dnsseckeylist_t dnskeys, keys, rmkeys;
21412 	dns_dnsseckey_t *key = NULL;
21413 	dns_diff_t diff, _sig_diff;
21414 	dns_kasp_t *kasp;
21415 	dns__zonediff_t zonediff;
21416 	bool commit = false, newactive = false;
21417 	bool newalg = false;
21418 	bool fullsign;
21419 	dns_ttl_t ttl = 3600;
21420 	const char *dir = NULL;
21421 	isc_mem_t *mctx = NULL;
21422 	isc_stdtime_t now, nexttime = 0;
21423 	isc_time_t timenow;
21424 	isc_interval_t ival;
21425 	char timebuf[80];
21426 
21427 	REQUIRE(DNS_ZONE_VALID(zone));
21428 
21429 	ISC_LIST_INIT(dnskeys);
21430 	ISC_LIST_INIT(keys);
21431 	ISC_LIST_INIT(rmkeys);
21432 	dns_rdataset_init(&soaset);
21433 	dns_rdataset_init(&soasigs);
21434 	dns_rdataset_init(&keyset);
21435 	dns_rdataset_init(&keysigs);
21436 	dns_rdataset_init(&cdsset);
21437 	dns_rdataset_init(&cdnskeyset);
21438 	dir = dns_zone_getkeydirectory(zone);
21439 	mctx = zone->mctx;
21440 	dns_diff_init(mctx, &diff);
21441 	dns_diff_init(mctx, &_sig_diff);
21442 	zonediff_init(&zonediff, &_sig_diff);
21443 
21444 	CHECK(dns_zone_getdb(zone, &db));
21445 	CHECK(dns_db_newversion(db, &ver));
21446 	CHECK(dns_db_getoriginnode(db, &node));
21447 
21448 	TIME_NOW(&timenow);
21449 	now = isc_time_seconds(&timenow);
21450 
21451 	kasp = dns_zone_getkasp(zone);
21452 
21453 	dnssec_log(zone, ISC_LOG_INFO, "reconfiguring zone keys");
21454 
21455 	/* Get the SOA record's TTL */
21456 	CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_soa,
21457 				  dns_rdatatype_none, 0, &soaset, &soasigs));
21458 	ttl = soaset.ttl;
21459 	dns_rdataset_disassociate(&soaset);
21460 
21461 	/* Get the DNSKEY rdataset */
21462 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
21463 				     dns_rdatatype_none, 0, &keyset, &keysigs);
21464 	if (result == ISC_R_SUCCESS) {
21465 		ttl = keyset.ttl;
21466 
21467 		dns_zone_lock_keyfiles(zone);
21468 
21469 		result = dns_dnssec_keylistfromrdataset(
21470 			&zone->origin, dir, mctx, &keyset, &keysigs, &soasigs,
21471 			false, false, &dnskeys);
21472 
21473 		dns_zone_unlock_keyfiles(zone);
21474 
21475 		if (result != ISC_R_SUCCESS) {
21476 			goto failure;
21477 		}
21478 	} else if (result != ISC_R_NOTFOUND) {
21479 		goto failure;
21480 	}
21481 
21482 	/* Get the CDS rdataset */
21483 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_cds,
21484 				     dns_rdatatype_none, 0, &cdsset, NULL);
21485 	if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdsset)) {
21486 		dns_rdataset_disassociate(&cdsset);
21487 	}
21488 
21489 	/* Get the CDNSKEY rdataset */
21490 	result = dns_db_findrdataset(db, node, ver, dns_rdatatype_cdnskey,
21491 				     dns_rdatatype_none, 0, &cdnskeyset, NULL);
21492 	if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdnskeyset)) {
21493 		dns_rdataset_disassociate(&cdnskeyset);
21494 	}
21495 
21496 	/*
21497 	 * True when called from "rndc sign".  Indicates the zone should be
21498 	 * fully signed now.
21499 	 */
21500 	fullsign = DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_FULLSIGN);
21501 
21502 	KASP_LOCK(kasp);
21503 
21504 	dns_zone_lock_keyfiles(zone);
21505 	result = dns_dnssec_findmatchingkeys(&zone->origin, dir, now, mctx,
21506 					     &keys);
21507 	dns_zone_unlock_keyfiles(zone);
21508 
21509 	if (result != ISC_R_SUCCESS) {
21510 		dnssec_log(zone, ISC_LOG_DEBUG(1),
21511 			   "zone_rekey:dns_dnssec_findmatchingkeys failed: %s",
21512 			   isc_result_totext(result));
21513 	}
21514 
21515 	if (kasp != NULL) {
21516 		/*
21517 		 * Check DS at parental agents. Clear ongoing checks.
21518 		 */
21519 		LOCK_ZONE(zone);
21520 		checkds_cancel(zone);
21521 		clear_keylist(&zone->checkds_ok, zone->mctx);
21522 		ISC_LIST_INIT(zone->checkds_ok);
21523 		UNLOCK_ZONE(zone);
21524 
21525 		result = dns_zone_getdnsseckeys(zone, db, ver, now,
21526 						&zone->checkds_ok);
21527 
21528 		if (result == ISC_R_SUCCESS) {
21529 			zone_checkds(zone);
21530 		} else {
21531 			dnssec_log(zone,
21532 				   (result == ISC_R_NOTFOUND) ? ISC_LOG_DEBUG(1)
21533 							      : ISC_LOG_ERROR,
21534 				   "zone_rekey:dns_zone_getdnsseckeys failed: "
21535 				   "%s",
21536 				   isc_result_totext(result));
21537 		}
21538 
21539 		if (result == ISC_R_SUCCESS || result == ISC_R_NOTFOUND) {
21540 			dns_zone_lock_keyfiles(zone);
21541 			result = dns_keymgr_run(&zone->origin, zone->rdclass,
21542 						dir, mctx, &keys, &dnskeys,
21543 						kasp, now, &nexttime);
21544 			dns_zone_unlock_keyfiles(zone);
21545 
21546 			if (result != ISC_R_SUCCESS) {
21547 				dnssec_log(zone, ISC_LOG_ERROR,
21548 					   "zone_rekey:dns_dnssec_keymgr "
21549 					   "failed: %s",
21550 					   isc_result_totext(result));
21551 				KASP_UNLOCK(kasp);
21552 				goto failure;
21553 			}
21554 		}
21555 	}
21556 
21557 	KASP_UNLOCK(kasp);
21558 
21559 	if (result == ISC_R_SUCCESS) {
21560 		bool cdsdel = false;
21561 		bool cdnskeydel = false;
21562 		isc_stdtime_t when;
21563 
21564 		/*
21565 		 * Publish CDS/CDNSKEY DELETE records if the zone is
21566 		 * transitioning from secure to insecure.
21567 		 */
21568 		if (kasp != NULL) {
21569 			if (strcmp(dns_kasp_getname(kasp), "insecure") == 0) {
21570 				cdsdel = true;
21571 				cdnskeydel = true;
21572 			}
21573 		} else {
21574 			/* Check if there is a CDS DELETE record. */
21575 			if (dns_rdataset_isassociated(&cdsset)) {
21576 				for (result = dns_rdataset_first(&cdsset);
21577 				     result == ISC_R_SUCCESS;
21578 				     result = dns_rdataset_next(&cdsset))
21579 				{
21580 					dns_rdata_t crdata = DNS_RDATA_INIT;
21581 					dns_rdataset_current(&cdsset, &crdata);
21582 					/*
21583 					 * CDS deletion record has this form
21584 					 * "0 0 0 00" which is 5 zero octets.
21585 					 */
21586 					if (crdata.length == 5U &&
21587 					    memcmp(crdata.data,
21588 						   (unsigned char[5]){ 0, 0, 0,
21589 								       0, 0 },
21590 						   5) == 0)
21591 					{
21592 						cdsdel = true;
21593 						break;
21594 					}
21595 				}
21596 			}
21597 
21598 			/* Check if there is a CDNSKEY DELETE record. */
21599 			if (dns_rdataset_isassociated(&cdnskeyset)) {
21600 				for (result = dns_rdataset_first(&cdnskeyset);
21601 				     result == ISC_R_SUCCESS;
21602 				     result = dns_rdataset_next(&cdnskeyset))
21603 				{
21604 					dns_rdata_t crdata = DNS_RDATA_INIT;
21605 					dns_rdataset_current(&cdnskeyset,
21606 							     &crdata);
21607 					/*
21608 					 * CDNSKEY deletion record has this form
21609 					 * "0 3 0 AA==" which is 2 zero octets,
21610 					 * a 3, and 2 zero octets.
21611 					 */
21612 					if (crdata.length == 5U &&
21613 					    memcmp(crdata.data,
21614 						   (unsigned char[5]){ 0, 0, 3,
21615 								       0, 0 },
21616 						   5) == 0)
21617 					{
21618 						cdnskeydel = true;
21619 						break;
21620 					}
21621 				}
21622 			}
21623 		}
21624 
21625 		/*
21626 		 * Only update DNSKEY TTL if we have a policy.
21627 		 */
21628 		if (kasp != NULL) {
21629 			ttl = dns_kasp_dnskeyttl(kasp);
21630 		}
21631 
21632 		result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys,
21633 					       &zone->origin, ttl, &diff, mctx,
21634 					       dnssec_report);
21635 		/*
21636 		 * Keys couldn't be updated for some reason;
21637 		 * try again later.
21638 		 */
21639 		if (result != ISC_R_SUCCESS) {
21640 			dnssec_log(zone, ISC_LOG_ERROR,
21641 				   "zone_rekey:couldn't update zone keys: %s",
21642 				   isc_result_totext(result));
21643 			goto failure;
21644 		}
21645 
21646 		/*
21647 		 * Update CDS / CDNSKEY records.
21648 		 */
21649 		result = dns_dnssec_syncupdate(&dnskeys, &rmkeys, &cdsset,
21650 					       &cdnskeyset, now, ttl, &diff,
21651 					       mctx);
21652 		if (result != ISC_R_SUCCESS) {
21653 			dnssec_log(zone, ISC_LOG_ERROR,
21654 				   "zone_rekey:couldn't update CDS/CDNSKEY: %s",
21655 				   isc_result_totext(result));
21656 			goto failure;
21657 		}
21658 
21659 		if (cdsdel || cdnskeydel) {
21660 			/*
21661 			 * Only publish CDS/CDNSKEY DELETE records if there is
21662 			 * a KSK that can be used to verify the RRset. This
21663 			 * means there must be a key with the KSK role that is
21664 			 * published and is used for signing.
21665 			 */
21666 			bool allow = false;
21667 			for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
21668 			     key = ISC_LIST_NEXT(key, link))
21669 			{
21670 				dst_key_t *dstk = key->key;
21671 
21672 				if (dst_key_is_published(dstk, now, &when) &&
21673 				    dst_key_is_signing(dstk, DST_BOOL_KSK, now,
21674 						       &when))
21675 				{
21676 					allow = true;
21677 					break;
21678 				}
21679 			}
21680 			if (cdsdel) {
21681 				cdsdel = allow;
21682 			}
21683 			if (cdnskeydel) {
21684 				cdnskeydel = allow;
21685 			}
21686 		}
21687 		result = dns_dnssec_syncdelete(
21688 			&cdsset, &cdnskeyset, &zone->origin, zone->rdclass, ttl,
21689 			&diff, mctx, cdsdel, cdnskeydel);
21690 		if (result != ISC_R_SUCCESS) {
21691 			dnssec_log(zone, ISC_LOG_ERROR,
21692 				   "zone_rekey:couldn't update CDS/CDNSKEY "
21693 				   "DELETE records: %s",
21694 				   isc_result_totext(result));
21695 			goto failure;
21696 		}
21697 
21698 		/*
21699 		 * See if any pre-existing keys have newly become active;
21700 		 * also, see if any new key is for a new algorithm, as in that
21701 		 * event, we need to sign the zone fully.  (If there's a new
21702 		 * key, but it's for an already-existing algorithm, then
21703 		 * the zone signing can be handled incrementally.)
21704 		 */
21705 		for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
21706 		     key = ISC_LIST_NEXT(key, link))
21707 		{
21708 			if (!key->first_sign) {
21709 				continue;
21710 			}
21711 
21712 			newactive = true;
21713 
21714 			if (!dns_rdataset_isassociated(&keysigs)) {
21715 				newalg = true;
21716 				break;
21717 			}
21718 
21719 			if (signed_with_alg(&keysigs, dst_key_alg(key->key))) {
21720 				/*
21721 				 * This isn't a new algorithm; clear
21722 				 * first_sign so we won't sign the
21723 				 * whole zone with this key later.
21724 				 */
21725 				key->first_sign = false;
21726 			} else {
21727 				newalg = true;
21728 				break;
21729 			}
21730 		}
21731 
21732 		if ((newactive || fullsign || !ISC_LIST_EMPTY(diff.tuples)) &&
21733 		    dnskey_sane(zone, db, ver, &diff))
21734 		{
21735 			CHECK(dns_diff_apply(&diff, db, ver));
21736 			CHECK(clean_nsec3param(zone, db, ver, &diff));
21737 			CHECK(add_signing_records(db, zone->privatetype, ver,
21738 						  &diff, (newalg || fullsign)));
21739 			CHECK(update_soa_serial(zone, db, ver, &diff, mctx,
21740 						zone->updatemethod));
21741 			CHECK(add_chains(zone, db, ver, &diff));
21742 			CHECK(sign_apex(zone, db, ver, now, &diff, &zonediff));
21743 			CHECK(zone_journal(zone, zonediff.diff, NULL,
21744 					   "zone_rekey"));
21745 			commit = true;
21746 		}
21747 	}
21748 
21749 	dns_db_closeversion(db, &ver, true);
21750 
21751 	LOCK_ZONE(zone);
21752 
21753 	if (commit) {
21754 		dns_difftuple_t *tuple;
21755 		dns_stats_t *dnssecsignstats =
21756 			dns_zone_getdnssecsignstats(zone);
21757 
21758 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
21759 
21760 		zone_needdump(zone, DNS_DUMP_DELAY);
21761 
21762 		zone_settimer(zone, &timenow);
21763 
21764 		/* Remove any signatures from removed keys.  */
21765 		if (!ISC_LIST_EMPTY(rmkeys)) {
21766 			for (key = ISC_LIST_HEAD(rmkeys); key != NULL;
21767 			     key = ISC_LIST_NEXT(key, link))
21768 			{
21769 				result = zone_signwithkey(
21770 					zone, dst_key_alg(key->key),
21771 					dst_key_id(key->key), true);
21772 				if (result != ISC_R_SUCCESS) {
21773 					dnssec_log(zone, ISC_LOG_ERROR,
21774 						   "zone_signwithkey failed: "
21775 						   "%s",
21776 						   dns_result_totext(result));
21777 				}
21778 
21779 				/* Clear DNSSEC sign statistics. */
21780 				if (dnssecsignstats != NULL) {
21781 					dns_dnssecsignstats_clear(
21782 						dnssecsignstats,
21783 						dst_key_id(key->key),
21784 						dst_key_alg(key->key));
21785 					/*
21786 					 * Also clear the dnssec-sign
21787 					 * statistics of the revoked key id.
21788 					 */
21789 					dns_dnssecsignstats_clear(
21790 						dnssecsignstats,
21791 						dst_key_rid(key->key),
21792 						dst_key_alg(key->key));
21793 				}
21794 			}
21795 		}
21796 
21797 		if (fullsign) {
21798 			/*
21799 			 * "rndc sign" was called, so we now sign the zone
21800 			 * with all active keys, whether they're new or not.
21801 			 */
21802 			for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
21803 			     key = ISC_LIST_NEXT(key, link))
21804 			{
21805 				if (!key->force_sign && !key->hint_sign) {
21806 					continue;
21807 				}
21808 
21809 				result = zone_signwithkey(
21810 					zone, dst_key_alg(key->key),
21811 					dst_key_id(key->key), false);
21812 				if (result != ISC_R_SUCCESS) {
21813 					dnssec_log(zone, ISC_LOG_ERROR,
21814 						   "zone_signwithkey failed: "
21815 						   "%s",
21816 						   dns_result_totext(result));
21817 				}
21818 			}
21819 		} else if (newalg) {
21820 			/*
21821 			 * We haven't been told to sign fully, but a new
21822 			 * algorithm was added to the DNSKEY.  We sign
21823 			 * the full zone, but only with newly active
21824 			 * keys.
21825 			 */
21826 			for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
21827 			     key = ISC_LIST_NEXT(key, link))
21828 			{
21829 				if (!key->first_sign) {
21830 					continue;
21831 				}
21832 
21833 				result = zone_signwithkey(
21834 					zone, dst_key_alg(key->key),
21835 					dst_key_id(key->key), false);
21836 				if (result != ISC_R_SUCCESS) {
21837 					dnssec_log(zone, ISC_LOG_ERROR,
21838 						   "zone_signwithkey failed: "
21839 						   "%s",
21840 						   dns_result_totext(result));
21841 				}
21842 			}
21843 		}
21844 
21845 		/*
21846 		 * Clear fullsign flag, if it was set, so we don't do
21847 		 * another full signing next time.
21848 		 */
21849 		DNS_ZONEKEY_CLROPTION(zone, DNS_ZONEKEY_FULLSIGN);
21850 
21851 		/*
21852 		 * Cause the zone to add/delete NSEC3 chains for the
21853 		 * deferred NSEC3PARAM changes.
21854 		 */
21855 		for (tuple = ISC_LIST_HEAD(zonediff.diff->tuples);
21856 		     tuple != NULL; tuple = ISC_LIST_NEXT(tuple, link))
21857 		{
21858 			unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
21859 			dns_rdata_t rdata = DNS_RDATA_INIT;
21860 			dns_rdata_nsec3param_t nsec3param;
21861 
21862 			if (tuple->rdata.type != zone->privatetype ||
21863 			    tuple->op != DNS_DIFFOP_ADD)
21864 			{
21865 				continue;
21866 			}
21867 
21868 			if (!dns_nsec3param_fromprivate(&tuple->rdata, &rdata,
21869 							buf, sizeof(buf)))
21870 			{
21871 				continue;
21872 			}
21873 
21874 			result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
21875 			RUNTIME_CHECK(result == ISC_R_SUCCESS);
21876 			if (nsec3param.flags == 0) {
21877 				continue;
21878 			}
21879 
21880 			result = zone_addnsec3chain(zone, &nsec3param);
21881 			if (result != ISC_R_SUCCESS) {
21882 				dnssec_log(zone, ISC_LOG_ERROR,
21883 					   "zone_addnsec3chain failed: %s",
21884 					   dns_result_totext(result));
21885 			}
21886 		}
21887 
21888 		/*
21889 		 * Activate any NSEC3 chain updates that may have
21890 		 * been scheduled before this rekey.
21891 		 */
21892 		if (fullsign || newalg) {
21893 			resume_addnsec3chain(zone);
21894 		}
21895 
21896 		/*
21897 		 * Schedule the next resigning event
21898 		 */
21899 		set_resigntime(zone);
21900 	}
21901 
21902 	isc_time_settoepoch(&zone->refreshkeytime);
21903 
21904 	/*
21905 	 * If keymgr provided a next time, use the calculated next rekey time.
21906 	 */
21907 	if (kasp != NULL) {
21908 		isc_time_t timenext;
21909 		uint32_t nexttime_seconds;
21910 
21911 		/*
21912 		 * Set the key refresh timer to the next scheduled key event
21913 		 * or to 'dnssec-loadkeys-interval' seconds in the future
21914 		 * if no next key event is scheduled (nexttime == 0).
21915 		 */
21916 		if (nexttime > 0) {
21917 			nexttime_seconds = nexttime - now;
21918 		} else {
21919 			nexttime_seconds = zone->refreshkeyinterval;
21920 		}
21921 
21922 		DNS_ZONE_TIME_ADD(&timenow, nexttime_seconds, &timenext);
21923 		zone->refreshkeytime = timenext;
21924 		zone_settimer(zone, &timenow);
21925 		isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
21926 
21927 		dnssec_log(zone, ISC_LOG_DEBUG(3),
21928 			   "next key event in %u seconds", nexttime_seconds);
21929 		dnssec_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
21930 	}
21931 	/*
21932 	 * If we're doing key maintenance, set the key refresh timer to
21933 	 * the next scheduled key event or to 'dnssec-loadkeys-interval'
21934 	 * seconds in the future, whichever is sooner.
21935 	 */
21936 	else if (DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
21937 	{
21938 		isc_time_t timethen;
21939 		isc_stdtime_t then;
21940 
21941 		DNS_ZONE_TIME_ADD(&timenow, zone->refreshkeyinterval,
21942 				  &timethen);
21943 		zone->refreshkeytime = timethen;
21944 
21945 		for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
21946 		     key = ISC_LIST_NEXT(key, link))
21947 		{
21948 			then = now;
21949 			result = next_keyevent(key->key, &then);
21950 			if (result != ISC_R_SUCCESS) {
21951 				continue;
21952 			}
21953 
21954 			DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
21955 			if (isc_time_compare(&timethen, &zone->refreshkeytime) <
21956 			    0)
21957 			{
21958 				zone->refreshkeytime = timethen;
21959 			}
21960 		}
21961 
21962 		zone_settimer(zone, &timenow);
21963 
21964 		isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
21965 		dnssec_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
21966 	}
21967 	UNLOCK_ZONE(zone);
21968 
21969 	if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
21970 		for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
21971 		     key = ISC_LIST_NEXT(key, link))
21972 		{
21973 			/* This debug log is used in the kasp system test */
21974 			char algbuf[DNS_SECALG_FORMATSIZE];
21975 			dns_secalg_format(dst_key_alg(key->key), algbuf,
21976 					  sizeof(algbuf));
21977 			dnssec_log(zone, ISC_LOG_DEBUG(3),
21978 				   "zone_rekey done: key %d/%s",
21979 				   dst_key_id(key->key), algbuf);
21980 		}
21981 	}
21982 
21983 	result = ISC_R_SUCCESS;
21984 
21985 failure:
21986 	LOCK_ZONE(zone);
21987 	if (result != ISC_R_SUCCESS) {
21988 		/*
21989 		 * Something went wrong; try again in ten minutes or
21990 		 * after a key refresh interval, whichever is shorter.
21991 		 */
21992 		dnssec_log(zone, ISC_LOG_DEBUG(3),
21993 			   "zone_rekey failure: %s (retry in %u seconds)",
21994 			   isc_result_totext(result),
21995 			   ISC_MIN(zone->refreshkeyinterval, 600));
21996 		isc_interval_set(&ival, ISC_MIN(zone->refreshkeyinterval, 600),
21997 				 0);
21998 		isc_time_nowplusinterval(&zone->refreshkeytime, &ival);
21999 	}
22000 	UNLOCK_ZONE(zone);
22001 
22002 	dns_diff_clear(&diff);
22003 	dns_diff_clear(&_sig_diff);
22004 
22005 	clear_keylist(&dnskeys, mctx);
22006 	clear_keylist(&keys, mctx);
22007 	clear_keylist(&rmkeys, mctx);
22008 
22009 	if (ver != NULL) {
22010 		dns_db_closeversion(db, &ver, false);
22011 	}
22012 	if (dns_rdataset_isassociated(&cdsset)) {
22013 		dns_rdataset_disassociate(&cdsset);
22014 	}
22015 	if (dns_rdataset_isassociated(&keyset)) {
22016 		dns_rdataset_disassociate(&keyset);
22017 	}
22018 	if (dns_rdataset_isassociated(&keysigs)) {
22019 		dns_rdataset_disassociate(&keysigs);
22020 	}
22021 	if (dns_rdataset_isassociated(&soasigs)) {
22022 		dns_rdataset_disassociate(&soasigs);
22023 	}
22024 	if (dns_rdataset_isassociated(&cdnskeyset)) {
22025 		dns_rdataset_disassociate(&cdnskeyset);
22026 	}
22027 	if (node != NULL) {
22028 		dns_db_detachnode(db, &node);
22029 	}
22030 	if (db != NULL) {
22031 		dns_db_detach(&db);
22032 	}
22033 
22034 	INSIST(ver == NULL);
22035 }
22036 
22037 void
dns_zone_rekey(dns_zone_t * zone,bool fullsign)22038 dns_zone_rekey(dns_zone_t *zone, bool fullsign) {
22039 	isc_time_t now;
22040 
22041 	if (zone->type == dns_zone_primary && zone->task != NULL) {
22042 		LOCK_ZONE(zone);
22043 
22044 		if (fullsign) {
22045 			DNS_ZONEKEY_SETOPTION(zone, DNS_ZONEKEY_FULLSIGN);
22046 		}
22047 
22048 		TIME_NOW(&now);
22049 		zone->refreshkeytime = now;
22050 		zone_settimer(zone, &now);
22051 
22052 		UNLOCK_ZONE(zone);
22053 	}
22054 }
22055 
22056 isc_result_t
dns_zone_nscheck(dns_zone_t * zone,dns_db_t * db,dns_dbversion_t * version,unsigned int * errors)22057 dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
22058 		 unsigned int *errors) {
22059 	isc_result_t result;
22060 	dns_dbnode_t *node = NULL;
22061 
22062 	REQUIRE(DNS_ZONE_VALID(zone));
22063 	REQUIRE(errors != NULL);
22064 
22065 	result = dns_db_getoriginnode(db, &node);
22066 	if (result != ISC_R_SUCCESS) {
22067 		return (result);
22068 	}
22069 	result = zone_count_ns_rr(zone, db, node, version, NULL, errors, false);
22070 	dns_db_detachnode(db, &node);
22071 	return (result);
22072 }
22073 
22074 isc_result_t
dns_zone_cdscheck(dns_zone_t * zone,dns_db_t * db,dns_dbversion_t * version)22075 dns_zone_cdscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version) {
22076 	isc_result_t result;
22077 	dns_dbnode_t *node = NULL;
22078 	dns_rdataset_t dnskey, cds, cdnskey;
22079 	unsigned char algorithms[256];
22080 	unsigned int i;
22081 	bool empty = false;
22082 
22083 	enum { notexpected = 0, expected = 1, found = 2 };
22084 
22085 	REQUIRE(DNS_ZONE_VALID(zone));
22086 
22087 	result = dns_db_getoriginnode(db, &node);
22088 	if (result != ISC_R_SUCCESS) {
22089 		return (result);
22090 	}
22091 
22092 	dns_rdataset_init(&cds);
22093 	dns_rdataset_init(&dnskey);
22094 	dns_rdataset_init(&cdnskey);
22095 
22096 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_cds,
22097 				     dns_rdatatype_none, 0, &cds, NULL);
22098 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
22099 		goto failure;
22100 	}
22101 
22102 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_cdnskey,
22103 				     dns_rdatatype_none, 0, &cdnskey, NULL);
22104 	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
22105 		goto failure;
22106 	}
22107 
22108 	if (!dns_rdataset_isassociated(&cds) &&
22109 	    !dns_rdataset_isassociated(&cdnskey))
22110 	{
22111 		result = ISC_R_SUCCESS;
22112 		goto failure;
22113 	}
22114 
22115 	result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
22116 				     dns_rdatatype_none, 0, &dnskey, NULL);
22117 	if (result == ISC_R_NOTFOUND) {
22118 		empty = true;
22119 	} else if (result != ISC_R_SUCCESS) {
22120 		goto failure;
22121 	}
22122 
22123 	/*
22124 	 * For each DNSSEC algorithm in the CDS RRset there must be
22125 	 * a matching DNSKEY record with the exception of a CDS deletion
22126 	 * record which must be by itself.
22127 	 */
22128 	if (dns_rdataset_isassociated(&cds)) {
22129 		bool delete = false;
22130 		memset(algorithms, notexpected, sizeof(algorithms));
22131 		for (result = dns_rdataset_first(&cds); result == ISC_R_SUCCESS;
22132 		     result = dns_rdataset_next(&cds))
22133 		{
22134 			dns_rdata_t crdata = DNS_RDATA_INIT;
22135 			dns_rdata_cds_t structcds;
22136 
22137 			dns_rdataset_current(&cds, &crdata);
22138 			/*
22139 			 * CDS deletion record has this form "0 0 0 00" which
22140 			 * is 5 zero octets.
22141 			 */
22142 			if (crdata.length == 5U &&
22143 			    memcmp(crdata.data,
22144 				   (unsigned char[5]){ 0, 0, 0, 0, 0 }, 5) == 0)
22145 			{
22146 				delete = true;
22147 				continue;
22148 			}
22149 
22150 			if (empty) {
22151 				result = DNS_R_BADCDS;
22152 				goto failure;
22153 			}
22154 
22155 			CHECK(dns_rdata_tostruct(&crdata, &structcds, NULL));
22156 			if (algorithms[structcds.algorithm] == 0) {
22157 				algorithms[structcds.algorithm] = expected;
22158 			}
22159 			for (result = dns_rdataset_first(&dnskey);
22160 			     result == ISC_R_SUCCESS;
22161 			     result = dns_rdataset_next(&dnskey))
22162 			{
22163 				dns_rdata_t rdata = DNS_RDATA_INIT;
22164 				dns_rdata_dnskey_t structdnskey;
22165 
22166 				dns_rdataset_current(&dnskey, &rdata);
22167 				CHECK(dns_rdata_tostruct(&rdata, &structdnskey,
22168 							 NULL));
22169 
22170 				if (structdnskey.algorithm ==
22171 				    structcds.algorithm)
22172 				{
22173 					algorithms[structcds.algorithm] = found;
22174 				}
22175 			}
22176 			if (result != ISC_R_NOMORE) {
22177 				goto failure;
22178 			}
22179 		}
22180 		for (i = 0; i < sizeof(algorithms); i++) {
22181 			if (delete) {
22182 				if (algorithms[i] != notexpected) {
22183 					result = DNS_R_BADCDS;
22184 					goto failure;
22185 				}
22186 			} else if (algorithms[i] == expected) {
22187 				result = DNS_R_BADCDS;
22188 				goto failure;
22189 			}
22190 		}
22191 	}
22192 
22193 	/*
22194 	 * For each DNSSEC algorithm in the CDNSKEY RRset there must be
22195 	 * a matching DNSKEY record with the exception of a CDNSKEY deletion
22196 	 * record which must be by itself.
22197 	 */
22198 	if (dns_rdataset_isassociated(&cdnskey)) {
22199 		bool delete = false;
22200 		memset(algorithms, notexpected, sizeof(algorithms));
22201 		for (result = dns_rdataset_first(&cdnskey);
22202 		     result == ISC_R_SUCCESS;
22203 		     result = dns_rdataset_next(&cdnskey))
22204 		{
22205 			dns_rdata_t crdata = DNS_RDATA_INIT;
22206 			dns_rdata_cdnskey_t structcdnskey;
22207 
22208 			dns_rdataset_current(&cdnskey, &crdata);
22209 			/*
22210 			 * CDNSKEY deletion record has this form
22211 			 * "0 3 0 AA==" which is 2 zero octets, a 3,
22212 			 * and 2 zero octets.
22213 			 */
22214 			if (crdata.length == 5U &&
22215 			    memcmp(crdata.data,
22216 				   (unsigned char[5]){ 0, 0, 3, 0, 0 }, 5) == 0)
22217 			{
22218 				delete = true;
22219 				continue;
22220 			}
22221 
22222 			if (empty) {
22223 				result = DNS_R_BADCDNSKEY;
22224 				goto failure;
22225 			}
22226 
22227 			CHECK(dns_rdata_tostruct(&crdata, &structcdnskey,
22228 						 NULL));
22229 			if (algorithms[structcdnskey.algorithm] == 0) {
22230 				algorithms[structcdnskey.algorithm] = expected;
22231 			}
22232 			for (result = dns_rdataset_first(&dnskey);
22233 			     result == ISC_R_SUCCESS;
22234 			     result = dns_rdataset_next(&dnskey))
22235 			{
22236 				dns_rdata_t rdata = DNS_RDATA_INIT;
22237 				dns_rdata_dnskey_t structdnskey;
22238 
22239 				dns_rdataset_current(&dnskey, &rdata);
22240 				CHECK(dns_rdata_tostruct(&rdata, &structdnskey,
22241 							 NULL));
22242 
22243 				if (structdnskey.algorithm ==
22244 				    structcdnskey.algorithm)
22245 				{
22246 					algorithms[structcdnskey.algorithm] =
22247 						found;
22248 				}
22249 			}
22250 			if (result != ISC_R_NOMORE) {
22251 				goto failure;
22252 			}
22253 		}
22254 		for (i = 0; i < sizeof(algorithms); i++) {
22255 			if (delete) {
22256 				if (algorithms[i] != notexpected) {
22257 					result = DNS_R_BADCDNSKEY;
22258 					goto failure;
22259 				}
22260 			} else if (algorithms[i] == expected) {
22261 				result = DNS_R_BADCDNSKEY;
22262 				goto failure;
22263 			}
22264 		}
22265 	}
22266 	result = ISC_R_SUCCESS;
22267 
22268 failure:
22269 	if (dns_rdataset_isassociated(&cds)) {
22270 		dns_rdataset_disassociate(&cds);
22271 	}
22272 	if (dns_rdataset_isassociated(&dnskey)) {
22273 		dns_rdataset_disassociate(&dnskey);
22274 	}
22275 	if (dns_rdataset_isassociated(&cdnskey)) {
22276 		dns_rdataset_disassociate(&cdnskey);
22277 	}
22278 	dns_db_detachnode(db, &node);
22279 	return (result);
22280 }
22281 
22282 void
dns_zone_setautomatic(dns_zone_t * zone,bool automatic)22283 dns_zone_setautomatic(dns_zone_t *zone, bool automatic) {
22284 	REQUIRE(DNS_ZONE_VALID(zone));
22285 
22286 	LOCK_ZONE(zone);
22287 	zone->automatic = automatic;
22288 	UNLOCK_ZONE(zone);
22289 }
22290 
22291 bool
dns_zone_getautomatic(dns_zone_t * zone)22292 dns_zone_getautomatic(dns_zone_t *zone) {
22293 	REQUIRE(DNS_ZONE_VALID(zone));
22294 	return (zone->automatic);
22295 }
22296 
22297 void
dns_zone_setadded(dns_zone_t * zone,bool added)22298 dns_zone_setadded(dns_zone_t *zone, bool added) {
22299 	REQUIRE(DNS_ZONE_VALID(zone));
22300 
22301 	LOCK_ZONE(zone);
22302 	zone->added = added;
22303 	UNLOCK_ZONE(zone);
22304 }
22305 
22306 bool
dns_zone_getadded(dns_zone_t * zone)22307 dns_zone_getadded(dns_zone_t *zone) {
22308 	REQUIRE(DNS_ZONE_VALID(zone));
22309 	return (zone->added);
22310 }
22311 
22312 isc_result_t
dns_zone_dlzpostload(dns_zone_t * zone,dns_db_t * db)22313 dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db) {
22314 	isc_time_t loadtime;
22315 	isc_result_t result;
22316 	dns_zone_t *secure = NULL;
22317 
22318 	TIME_NOW(&loadtime);
22319 
22320 	/*
22321 	 * Lock hierarchy: zmgr, zone, raw.
22322 	 */
22323 again:
22324 	LOCK_ZONE(zone);
22325 	INSIST(zone != zone->raw);
22326 	if (inline_secure(zone)) {
22327 		LOCK_ZONE(zone->raw);
22328 	} else if (inline_raw(zone)) {
22329 		secure = zone->secure;
22330 		TRYLOCK_ZONE(result, secure);
22331 		if (result != ISC_R_SUCCESS) {
22332 			UNLOCK_ZONE(zone);
22333 			secure = NULL;
22334 			isc_thread_yield();
22335 			goto again;
22336 		}
22337 	}
22338 	result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
22339 	if (inline_secure(zone)) {
22340 		UNLOCK_ZONE(zone->raw);
22341 	} else if (secure != NULL) {
22342 		UNLOCK_ZONE(secure);
22343 	}
22344 	UNLOCK_ZONE(zone);
22345 	return (result);
22346 }
22347 
22348 isc_result_t
dns_zone_setrefreshkeyinterval(dns_zone_t * zone,uint32_t interval)22349 dns_zone_setrefreshkeyinterval(dns_zone_t *zone, uint32_t interval) {
22350 	REQUIRE(DNS_ZONE_VALID(zone));
22351 	if (interval == 0) {
22352 		return (ISC_R_RANGE);
22353 	}
22354 	/* Maximum value: 24 hours (3600 minutes) */
22355 	if (interval > (24 * 60)) {
22356 		interval = (24 * 60);
22357 	}
22358 	/* Multiply by 60 for seconds */
22359 	zone->refreshkeyinterval = interval * 60;
22360 	return (ISC_R_SUCCESS);
22361 }
22362 
22363 void
dns_zone_setrequestixfr(dns_zone_t * zone,bool flag)22364 dns_zone_setrequestixfr(dns_zone_t *zone, bool flag) {
22365 	REQUIRE(DNS_ZONE_VALID(zone));
22366 	zone->requestixfr = flag;
22367 }
22368 
22369 bool
dns_zone_getrequestixfr(dns_zone_t * zone)22370 dns_zone_getrequestixfr(dns_zone_t *zone) {
22371 	REQUIRE(DNS_ZONE_VALID(zone));
22372 	return (zone->requestixfr);
22373 }
22374 
22375 void
dns_zone_setixfrratio(dns_zone_t * zone,uint32_t ratio)22376 dns_zone_setixfrratio(dns_zone_t *zone, uint32_t ratio) {
22377 	REQUIRE(DNS_ZONE_VALID(zone));
22378 	zone->ixfr_ratio = ratio;
22379 }
22380 
22381 uint32_t
dns_zone_getixfrratio(dns_zone_t * zone)22382 dns_zone_getixfrratio(dns_zone_t *zone) {
22383 	REQUIRE(DNS_ZONE_VALID(zone));
22384 	return (zone->ixfr_ratio);
22385 }
22386 
22387 void
dns_zone_setrequestexpire(dns_zone_t * zone,bool flag)22388 dns_zone_setrequestexpire(dns_zone_t *zone, bool flag) {
22389 	REQUIRE(DNS_ZONE_VALID(zone));
22390 	zone->requestexpire = flag;
22391 }
22392 
22393 bool
dns_zone_getrequestexpire(dns_zone_t * zone)22394 dns_zone_getrequestexpire(dns_zone_t *zone) {
22395 	REQUIRE(DNS_ZONE_VALID(zone));
22396 	return (zone->requestexpire);
22397 }
22398 
22399 void
dns_zone_setserialupdatemethod(dns_zone_t * zone,dns_updatemethod_t method)22400 dns_zone_setserialupdatemethod(dns_zone_t *zone, dns_updatemethod_t method) {
22401 	REQUIRE(DNS_ZONE_VALID(zone));
22402 	zone->updatemethod = method;
22403 }
22404 
22405 dns_updatemethod_t
dns_zone_getserialupdatemethod(dns_zone_t * zone)22406 dns_zone_getserialupdatemethod(dns_zone_t *zone) {
22407 	REQUIRE(DNS_ZONE_VALID(zone));
22408 	return (zone->updatemethod);
22409 }
22410 
22411 /*
22412  * Lock hierarchy: zmgr, zone, raw.
22413  */
22414 isc_result_t
dns_zone_link(dns_zone_t * zone,dns_zone_t * raw)22415 dns_zone_link(dns_zone_t *zone, dns_zone_t *raw) {
22416 	isc_result_t result;
22417 	dns_zonemgr_t *zmgr;
22418 
22419 	REQUIRE(DNS_ZONE_VALID(zone));
22420 	REQUIRE(zone->zmgr != NULL);
22421 	REQUIRE(zone->task != NULL);
22422 	REQUIRE(zone->loadtask != NULL);
22423 	REQUIRE(zone->raw == NULL);
22424 
22425 	REQUIRE(DNS_ZONE_VALID(raw));
22426 	REQUIRE(raw->zmgr == NULL);
22427 	REQUIRE(raw->task == NULL);
22428 	REQUIRE(raw->loadtask == NULL);
22429 	REQUIRE(raw->secure == NULL);
22430 
22431 	REQUIRE(zone != raw);
22432 
22433 	/*
22434 	 * Lock hierarchy: zmgr, zone, raw.
22435 	 */
22436 	zmgr = zone->zmgr;
22437 	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
22438 	LOCK_ZONE(zone);
22439 	LOCK_ZONE(raw);
22440 
22441 	result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive, NULL,
22442 				  NULL, zone->task, zone_timer, raw,
22443 				  &raw->timer);
22444 	if (result != ISC_R_SUCCESS) {
22445 		goto unlock;
22446 	}
22447 
22448 	/*
22449 	 * The timer "holds" a iref.
22450 	 */
22451 	isc_refcount_increment0(&raw->irefs);
22452 
22453 	/* dns_zone_attach(raw, &zone->raw); */
22454 	isc_refcount_increment(&raw->erefs);
22455 	zone->raw = raw;
22456 
22457 	/* dns_zone_iattach(zone,  &raw->secure); */
22458 	zone_iattach(zone, &raw->secure);
22459 
22460 	isc_task_attach(zone->task, &raw->task);
22461 	isc_task_attach(zone->loadtask, &raw->loadtask);
22462 
22463 	ISC_LIST_APPEND(zmgr->zones, raw, link);
22464 	raw->zmgr = zmgr;
22465 	isc_refcount_increment(&zmgr->refs);
22466 
22467 unlock:
22468 	UNLOCK_ZONE(raw);
22469 	UNLOCK_ZONE(zone);
22470 	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
22471 	return (result);
22472 }
22473 
22474 void
dns_zone_getraw(dns_zone_t * zone,dns_zone_t ** raw)22475 dns_zone_getraw(dns_zone_t *zone, dns_zone_t **raw) {
22476 	REQUIRE(DNS_ZONE_VALID(zone));
22477 	REQUIRE(raw != NULL && *raw == NULL);
22478 
22479 	LOCK(&zone->lock);
22480 	INSIST(zone != zone->raw);
22481 	if (zone->raw != NULL) {
22482 		dns_zone_attach(zone->raw, raw);
22483 	}
22484 	UNLOCK(&zone->lock);
22485 }
22486 
22487 struct keydone {
22488 	isc_event_t event;
22489 	bool all;
22490 	unsigned char data[5];
22491 };
22492 
22493 #define PENDINGFLAGS (DNS_NSEC3FLAG_CREATE | DNS_NSEC3FLAG_INITIAL)
22494 
22495 static void
keydone(isc_task_t * task,isc_event_t * event)22496 keydone(isc_task_t *task, isc_event_t *event) {
22497 	const char *me = "keydone";
22498 	bool commit = false;
22499 	isc_result_t result;
22500 	dns_rdata_t rdata = DNS_RDATA_INIT;
22501 	dns_dbversion_t *oldver = NULL, *newver = NULL;
22502 	dns_zone_t *zone;
22503 	dns_db_t *db = NULL;
22504 	dns_dbnode_t *node = NULL;
22505 	dns_rdataset_t rdataset;
22506 	dns_diff_t diff;
22507 	struct keydone *kd = (struct keydone *)event;
22508 	dns_update_log_t log = { update_log_cb, NULL };
22509 	bool clear_pending = false;
22510 
22511 	UNUSED(task);
22512 
22513 	zone = event->ev_arg;
22514 	INSIST(DNS_ZONE_VALID(zone));
22515 
22516 	ENTER;
22517 
22518 	dns_rdataset_init(&rdataset);
22519 	dns_diff_init(zone->mctx, &diff);
22520 
22521 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
22522 	if (zone->db != NULL) {
22523 		dns_db_attach(zone->db, &db);
22524 	}
22525 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
22526 	if (db == NULL) {
22527 		goto failure;
22528 	}
22529 
22530 	dns_db_currentversion(db, &oldver);
22531 	result = dns_db_newversion(db, &newver);
22532 	if (result != ISC_R_SUCCESS) {
22533 		dnssec_log(zone, ISC_LOG_ERROR,
22534 			   "keydone:dns_db_newversion -> %s",
22535 			   dns_result_totext(result));
22536 		goto failure;
22537 	}
22538 
22539 	result = dns_db_getoriginnode(db, &node);
22540 	if (result != ISC_R_SUCCESS) {
22541 		goto failure;
22542 	}
22543 
22544 	result = dns_db_findrdataset(db, node, newver, zone->privatetype,
22545 				     dns_rdatatype_none, 0, &rdataset, NULL);
22546 	if (result == ISC_R_NOTFOUND) {
22547 		INSIST(!dns_rdataset_isassociated(&rdataset));
22548 		goto failure;
22549 	}
22550 	if (result != ISC_R_SUCCESS) {
22551 		INSIST(!dns_rdataset_isassociated(&rdataset));
22552 		goto failure;
22553 	}
22554 
22555 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
22556 	     result = dns_rdataset_next(&rdataset))
22557 	{
22558 		bool found = false;
22559 
22560 		dns_rdataset_current(&rdataset, &rdata);
22561 
22562 		if (kd->all) {
22563 			if (rdata.length == 5 && rdata.data[0] != 0 &&
22564 			    rdata.data[3] == 0 && rdata.data[4] == 1)
22565 			{
22566 				found = true;
22567 			} else if (rdata.data[0] == 0 &&
22568 				   (rdata.data[2] & PENDINGFLAGS) != 0)
22569 			{
22570 				found = true;
22571 				clear_pending = true;
22572 			}
22573 		} else if (rdata.length == 5 &&
22574 			   memcmp(rdata.data, kd->data, 5) == 0)
22575 		{
22576 			found = true;
22577 		}
22578 
22579 		if (found) {
22580 			CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_DEL,
22581 					    &zone->origin, rdataset.ttl,
22582 					    &rdata));
22583 		}
22584 		dns_rdata_reset(&rdata);
22585 	}
22586 
22587 	if (!ISC_LIST_EMPTY(diff.tuples)) {
22588 		/* Write changes to journal file. */
22589 		CHECK(update_soa_serial(zone, db, newver, &diff, zone->mctx,
22590 					zone->updatemethod));
22591 
22592 		result = dns_update_signatures(&log, zone, db, oldver, newver,
22593 					       &diff,
22594 					       zone->sigvalidityinterval);
22595 		if (!clear_pending) {
22596 			CHECK(result);
22597 		}
22598 
22599 		CHECK(zone_journal(zone, &diff, NULL, "keydone"));
22600 		commit = true;
22601 
22602 		LOCK_ZONE(zone);
22603 		DNS_ZONE_SETFLAG(zone,
22604 				 DNS_ZONEFLG_LOADED | DNS_ZONEFLG_NEEDNOTIFY);
22605 		zone_needdump(zone, 30);
22606 		UNLOCK_ZONE(zone);
22607 	}
22608 
22609 failure:
22610 	if (dns_rdataset_isassociated(&rdataset)) {
22611 		dns_rdataset_disassociate(&rdataset);
22612 	}
22613 	if (db != NULL) {
22614 		if (node != NULL) {
22615 			dns_db_detachnode(db, &node);
22616 		}
22617 		if (oldver != NULL) {
22618 			dns_db_closeversion(db, &oldver, false);
22619 		}
22620 		if (newver != NULL) {
22621 			dns_db_closeversion(db, &newver, commit);
22622 		}
22623 		dns_db_detach(&db);
22624 	}
22625 	dns_diff_clear(&diff);
22626 	isc_event_free(&event);
22627 	dns_zone_idetach(&zone);
22628 
22629 	INSIST(oldver == NULL);
22630 	INSIST(newver == NULL);
22631 }
22632 
22633 isc_result_t
dns_zone_keydone(dns_zone_t * zone,const char * keystr)22634 dns_zone_keydone(dns_zone_t *zone, const char *keystr) {
22635 	isc_result_t result = ISC_R_SUCCESS;
22636 	isc_event_t *e;
22637 	isc_buffer_t b;
22638 	dns_zone_t *dummy = NULL;
22639 	struct keydone *kd;
22640 
22641 	REQUIRE(DNS_ZONE_VALID(zone));
22642 
22643 	LOCK_ZONE(zone);
22644 
22645 	e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_KEYDONE, keydone,
22646 			       zone, sizeof(struct keydone));
22647 
22648 	kd = (struct keydone *)e;
22649 	if (strcasecmp(keystr, "all") == 0) {
22650 		kd->all = true;
22651 	} else {
22652 		isc_textregion_t r;
22653 		const char *algstr;
22654 		dns_keytag_t keyid;
22655 		dns_secalg_t alg;
22656 		size_t n;
22657 
22658 		kd->all = false;
22659 
22660 		n = sscanf(keystr, "%hu/", &keyid);
22661 		if (n == 0U) {
22662 			CHECK(ISC_R_FAILURE);
22663 		}
22664 
22665 		algstr = strchr(keystr, '/');
22666 		if (algstr != NULL) {
22667 			algstr++;
22668 		} else {
22669 			CHECK(ISC_R_FAILURE);
22670 		}
22671 
22672 		n = sscanf(algstr, "%hhu", &alg);
22673 		if (n == 0U) {
22674 			DE_CONST(algstr, r.base);
22675 			r.length = strlen(algstr);
22676 			CHECK(dns_secalg_fromtext(&alg, &r));
22677 		}
22678 
22679 		/* construct a private-type rdata */
22680 		isc_buffer_init(&b, kd->data, sizeof(kd->data));
22681 		isc_buffer_putuint8(&b, alg);
22682 		isc_buffer_putuint8(&b, (keyid & 0xff00) >> 8);
22683 		isc_buffer_putuint8(&b, (keyid & 0xff));
22684 		isc_buffer_putuint8(&b, 0);
22685 		isc_buffer_putuint8(&b, 1);
22686 	}
22687 
22688 	zone_iattach(zone, &dummy);
22689 	isc_task_send(zone->task, &e);
22690 
22691 failure:
22692 	if (e != NULL) {
22693 		isc_event_free(&e);
22694 	}
22695 	UNLOCK_ZONE(zone);
22696 	return (result);
22697 }
22698 
22699 /*
22700  * Called from the zone task's queue after the relevant event is posted by
22701  * dns_zone_setnsec3param().
22702  */
22703 static void
setnsec3param(isc_task_t * task,isc_event_t * event)22704 setnsec3param(isc_task_t *task, isc_event_t *event) {
22705 	const char *me = "setnsec3param";
22706 	dns_zone_t *zone = event->ev_arg;
22707 	bool loadpending;
22708 
22709 	INSIST(DNS_ZONE_VALID(zone));
22710 
22711 	UNUSED(task);
22712 
22713 	ENTER;
22714 
22715 	LOCK_ZONE(zone);
22716 	loadpending = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING);
22717 	UNLOCK_ZONE(zone);
22718 
22719 	/*
22720 	 * If receive_secure_serial is still processing or we have a
22721 	 * queued event append rss_post queue.
22722 	 */
22723 	if (zone->rss_newver != NULL || ISC_LIST_HEAD(zone->rss_post) != NULL) {
22724 		/*
22725 		 * Wait for receive_secure_serial() to finish processing.
22726 		 */
22727 		ISC_LIST_APPEND(zone->rss_post, event, ev_link);
22728 	} else {
22729 		bool rescheduled = false;
22730 		ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
22731 		/*
22732 		 * The zone is not yet fully loaded. Reschedule the event to
22733 		 * be picked up later. This turns this function into a busy
22734 		 * wait, but it only happens at startup.
22735 		 */
22736 		if (zone->db == NULL && loadpending) {
22737 			rescheduled = true;
22738 			isc_task_send(task, &event);
22739 		}
22740 		ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
22741 		if (rescheduled) {
22742 			return;
22743 		}
22744 
22745 		rss_post(zone, event);
22746 	}
22747 	dns_zone_idetach(&zone);
22748 }
22749 
22750 static void
salt2text(unsigned char * salt,uint8_t saltlen,unsigned char * text,unsigned int textlen)22751 salt2text(unsigned char *salt, uint8_t saltlen, unsigned char *text,
22752 	  unsigned int textlen) {
22753 	isc_region_t r;
22754 	isc_buffer_t buf;
22755 	isc_result_t result;
22756 
22757 	r.base = salt;
22758 	r.length = (unsigned int)saltlen;
22759 
22760 	isc_buffer_init(&buf, text, textlen);
22761 	result = isc_hex_totext(&r, 2, "", &buf);
22762 	if (result == ISC_R_SUCCESS) {
22763 		text[saltlen * 2] = 0;
22764 	} else {
22765 		text[0] = 0;
22766 	}
22767 }
22768 
22769 /*
22770  * Check whether NSEC3 chain addition or removal specified by the private-type
22771  * record passed with the event was already queued (or even fully performed).
22772  * If not, modify the relevant private-type records at the zone apex and call
22773  * resume_addnsec3chain().
22774  */
22775 static void
rss_post(dns_zone_t * zone,isc_event_t * event)22776 rss_post(dns_zone_t *zone, isc_event_t *event) {
22777 	const char *me = "rss_post";
22778 	bool commit = false;
22779 	isc_result_t result;
22780 	dns_dbversion_t *oldver = NULL, *newver = NULL;
22781 	dns_db_t *db = NULL;
22782 	dns_dbnode_t *node = NULL;
22783 	dns_rdataset_t prdataset, nrdataset;
22784 	dns_diff_t diff;
22785 	struct np3event *npe = (struct np3event *)event;
22786 	nsec3param_t *np;
22787 	dns_update_log_t log = { update_log_cb, NULL };
22788 	dns_rdata_t rdata;
22789 	bool nseconly;
22790 	bool exists = false;
22791 
22792 	ENTER;
22793 
22794 	np = &npe->params;
22795 
22796 	dns_rdataset_init(&prdataset);
22797 	dns_rdataset_init(&nrdataset);
22798 	dns_diff_init(zone->mctx, &diff);
22799 
22800 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
22801 	if (zone->db != NULL) {
22802 		dns_db_attach(zone->db, &db);
22803 	}
22804 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
22805 	if (db == NULL) {
22806 		goto failure;
22807 	}
22808 
22809 	dns_db_currentversion(db, &oldver);
22810 	result = dns_db_newversion(db, &newver);
22811 	if (result != ISC_R_SUCCESS) {
22812 		dnssec_log(zone, ISC_LOG_ERROR,
22813 			   "setnsec3param:dns_db_newversion -> %s",
22814 			   dns_result_totext(result));
22815 		goto failure;
22816 	}
22817 
22818 	CHECK(dns_db_getoriginnode(db, &node));
22819 
22820 	/*
22821 	 * Do we need to look up the NSEC3 parameters?
22822 	 */
22823 	if (np->lookup) {
22824 		dns_rdata_nsec3param_t param;
22825 		dns_rdata_t nrdata = DNS_RDATA_INIT;
22826 		dns_rdata_t prdata = DNS_RDATA_INIT;
22827 		unsigned char nbuf[DNS_NSEC3PARAM_BUFFERSIZE];
22828 		unsigned char saltbuf[255];
22829 		isc_buffer_t b;
22830 
22831 		param.salt = NULL;
22832 		result = dns__zone_lookup_nsec3param(zone, &np->rdata, &param,
22833 						     saltbuf, np->resalt);
22834 		if (result == ISC_R_SUCCESS) {
22835 			/*
22836 			 * Success because the NSEC3PARAM already exists, but
22837 			 * function returns void, so goto failure to clean up.
22838 			 */
22839 			goto failure;
22840 		}
22841 		if (result != DNS_R_NSEC3RESALT && result != ISC_R_NOTFOUND) {
22842 			dnssec_log(zone, ISC_LOG_DEBUG(3),
22843 				   "setnsec3param:lookup nsec3param -> %s",
22844 				   isc_result_totext(result));
22845 			goto failure;
22846 		}
22847 
22848 		INSIST(param.salt != NULL);
22849 
22850 		/* Update NSEC3 parameters. */
22851 		np->rdata.hash = param.hash;
22852 		np->rdata.flags = param.flags;
22853 		np->rdata.iterations = param.iterations;
22854 		np->rdata.salt_length = param.salt_length;
22855 		np->rdata.salt = param.salt;
22856 
22857 		isc_buffer_init(&b, nbuf, sizeof(nbuf));
22858 		CHECK(dns_rdata_fromstruct(&nrdata, zone->rdclass,
22859 					   dns_rdatatype_nsec3param, &np->rdata,
22860 					   &b));
22861 		dns_nsec3param_toprivate(&nrdata, &prdata, zone->privatetype,
22862 					 np->data, sizeof(np->data));
22863 		np->length = prdata.length;
22864 		np->nsec = false;
22865 	}
22866 
22867 	/*
22868 	 * Does a private-type record already exist for this chain?
22869 	 */
22870 	result = dns_db_findrdataset(db, node, newver, zone->privatetype,
22871 				     dns_rdatatype_none, 0, &prdataset, NULL);
22872 	if (result == ISC_R_SUCCESS) {
22873 		for (result = dns_rdataset_first(&prdataset);
22874 		     result == ISC_R_SUCCESS;
22875 		     result = dns_rdataset_next(&prdataset))
22876 		{
22877 			dns_rdata_init(&rdata);
22878 			dns_rdataset_current(&prdataset, &rdata);
22879 
22880 			if (np->length == rdata.length &&
22881 			    memcmp(rdata.data, np->data, np->length) == 0)
22882 			{
22883 				exists = true;
22884 				break;
22885 			}
22886 		}
22887 	} else if (result != ISC_R_NOTFOUND) {
22888 		INSIST(!dns_rdataset_isassociated(&prdataset));
22889 		goto failure;
22890 	}
22891 
22892 	/*
22893 	 * Does the chain already exist?
22894 	 */
22895 	result = dns_db_findrdataset(db, node, newver, dns_rdatatype_nsec3param,
22896 				     dns_rdatatype_none, 0, &nrdataset, NULL);
22897 	if (result == ISC_R_SUCCESS) {
22898 		for (result = dns_rdataset_first(&nrdataset);
22899 		     result == ISC_R_SUCCESS;
22900 		     result = dns_rdataset_next(&nrdataset))
22901 		{
22902 			dns_rdata_init(&rdata);
22903 			dns_rdataset_current(&nrdataset, &rdata);
22904 
22905 			if (np->length == (rdata.length + 1) &&
22906 			    memcmp(rdata.data, np->data + 1, np->length - 1) ==
22907 				    0)
22908 			{
22909 				exists = true;
22910 				break;
22911 			}
22912 		}
22913 	} else if (result != ISC_R_NOTFOUND) {
22914 		INSIST(!dns_rdataset_isassociated(&nrdataset));
22915 		goto failure;
22916 	}
22917 
22918 	/*
22919 	 * We need to remove any existing NSEC3 chains if the supplied NSEC3
22920 	 * parameters are supposed to replace the current ones or if we are
22921 	 * switching to NSEC.
22922 	 */
22923 	if (!exists && np->replace && (np->length != 0 || np->nsec)) {
22924 		CHECK(dns_nsec3param_deletechains(db, newver, zone, !np->nsec,
22925 						  &diff));
22926 	}
22927 
22928 	if (!exists && np->length != 0) {
22929 		/*
22930 		 * We're creating an NSEC3 chain.  Add the private-type record
22931 		 * passed in the event handler's argument to the zone apex.
22932 		 *
22933 		 * If the zone is not currently capable of supporting an NSEC3
22934 		 * chain (due to the DNSKEY RRset at the zone apex not existing
22935 		 * or containing at least one key using an NSEC-only
22936 		 * algorithm), add the INITIAL flag, so these parameters can be
22937 		 * used later when NSEC3 becomes available.
22938 		 */
22939 		dns_rdata_init(&rdata);
22940 
22941 		np->data[2] |= DNS_NSEC3FLAG_CREATE;
22942 		result = dns_nsec_nseconly(db, newver, &nseconly);
22943 		if (result == ISC_R_NOTFOUND || nseconly) {
22944 			np->data[2] |= DNS_NSEC3FLAG_INITIAL;
22945 		}
22946 
22947 		rdata.length = np->length;
22948 		rdata.data = np->data;
22949 		rdata.type = zone->privatetype;
22950 		rdata.rdclass = zone->rdclass;
22951 		CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_ADD,
22952 				    &zone->origin, 0, &rdata));
22953 	}
22954 
22955 	/*
22956 	 * If we changed anything in the zone, write changes to journal file
22957 	 * and set commit to true so that resume_addnsec3chain() will be
22958 	 * called below in order to kick off adding/removing relevant NSEC3
22959 	 * records.
22960 	 */
22961 	if (!ISC_LIST_EMPTY(diff.tuples)) {
22962 		CHECK(update_soa_serial(zone, db, newver, &diff, zone->mctx,
22963 					zone->updatemethod));
22964 		result = dns_update_signatures(&log, zone, db, oldver, newver,
22965 					       &diff,
22966 					       zone->sigvalidityinterval);
22967 		if (result != ISC_R_NOTFOUND) {
22968 			CHECK(result);
22969 		}
22970 		CHECK(zone_journal(zone, &diff, NULL, "setnsec3param"));
22971 		commit = true;
22972 
22973 		LOCK_ZONE(zone);
22974 		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
22975 		zone_needdump(zone, 30);
22976 		UNLOCK_ZONE(zone);
22977 	}
22978 
22979 failure:
22980 	if (dns_rdataset_isassociated(&prdataset)) {
22981 		dns_rdataset_disassociate(&prdataset);
22982 	}
22983 	if (dns_rdataset_isassociated(&nrdataset)) {
22984 		dns_rdataset_disassociate(&nrdataset);
22985 	}
22986 	if (node != NULL) {
22987 		dns_db_detachnode(db, &node);
22988 	}
22989 	if (oldver != NULL) {
22990 		dns_db_closeversion(db, &oldver, false);
22991 	}
22992 	if (newver != NULL) {
22993 		dns_db_closeversion(db, &newver, commit);
22994 	}
22995 	if (db != NULL) {
22996 		dns_db_detach(&db);
22997 	}
22998 	if (commit) {
22999 		LOCK_ZONE(zone);
23000 		resume_addnsec3chain(zone);
23001 		UNLOCK_ZONE(zone);
23002 	}
23003 	dns_diff_clear(&diff);
23004 	isc_event_free(&event);
23005 
23006 	INSIST(oldver == NULL);
23007 	INSIST(newver == NULL);
23008 }
23009 
23010 /*
23011  * Check if zone has NSEC3PARAM (and thus a chain) with the right parameters.
23012  *
23013  * If 'salt' is NULL, a match is found if the salt has the requested length,
23014  * otherwise the NSEC3 salt must match the requested salt value too.
23015  *
23016  * Returns  ISC_R_SUCCESS, if a match is found, or an error if no match is
23017  * found, or if the db lookup failed.
23018  */
23019 isc_result_t
dns__zone_lookup_nsec3param(dns_zone_t * zone,dns_rdata_nsec3param_t * lookup,dns_rdata_nsec3param_t * param,unsigned char saltbuf[255],bool resalt)23020 dns__zone_lookup_nsec3param(dns_zone_t *zone, dns_rdata_nsec3param_t *lookup,
23021 			    dns_rdata_nsec3param_t *param,
23022 			    unsigned char saltbuf[255], bool resalt) {
23023 	isc_result_t result = ISC_R_UNEXPECTED;
23024 	dns_dbnode_t *node = NULL;
23025 	dns_db_t *db = NULL;
23026 	dns_dbversion_t *version = NULL;
23027 	dns_rdataset_t rdataset;
23028 	dns_rdata_nsec3param_t nsec3param;
23029 	dns_rdata_t rdata = DNS_RDATA_INIT;
23030 
23031 	REQUIRE(DNS_ZONE_VALID(zone));
23032 
23033 	dns_rdataset_init(&rdataset);
23034 
23035 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
23036 	if (zone->db != NULL) {
23037 		dns_db_attach(zone->db, &db);
23038 	}
23039 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
23040 	if (db == NULL) {
23041 		result = ISC_R_FAILURE;
23042 		goto setparam;
23043 	}
23044 
23045 	result = dns_db_findnode(db, &zone->origin, false, &node);
23046 	if (result != ISC_R_SUCCESS) {
23047 		dns_zone_log(zone, ISC_LOG_ERROR,
23048 			     "dns__zone_lookup_nsec3param:"
23049 			     "dns_db_findnode -> %s",
23050 			     dns_result_totext(result));
23051 		result = ISC_R_FAILURE;
23052 		goto setparam;
23053 	}
23054 	dns_db_currentversion(db, &version);
23055 
23056 	result = dns_db_findrdataset(db, node, version,
23057 				     dns_rdatatype_nsec3param,
23058 				     dns_rdatatype_none, 0, &rdataset, NULL);
23059 	if (result != ISC_R_SUCCESS) {
23060 		INSIST(!dns_rdataset_isassociated(&rdataset));
23061 		if (result != ISC_R_NOTFOUND) {
23062 			dns_zone_log(zone, ISC_LOG_ERROR,
23063 				     "dns__zone_lookup_nsec3param:"
23064 				     "dns_db_findrdataset -> %s",
23065 				     dns_result_totext(result));
23066 		}
23067 		goto setparam;
23068 	}
23069 
23070 	for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
23071 	     result = dns_rdataset_next(&rdataset))
23072 	{
23073 		dns_rdataset_current(&rdataset, &rdata);
23074 		result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
23075 		INSIST(result == ISC_R_SUCCESS);
23076 		dns_rdata_reset(&rdata);
23077 
23078 		/* Check parameters. */
23079 		if (nsec3param.hash != lookup->hash) {
23080 			continue;
23081 		}
23082 		if (nsec3param.iterations != lookup->iterations) {
23083 			continue;
23084 		}
23085 		if (nsec3param.salt_length != lookup->salt_length) {
23086 			continue;
23087 		}
23088 		if (lookup->salt != NULL) {
23089 			if (memcmp(nsec3param.salt, lookup->salt,
23090 				   lookup->salt_length) != 0)
23091 			{
23092 				continue;
23093 			}
23094 		}
23095 		/* Found a match. */
23096 		result = ISC_R_SUCCESS;
23097 		param->hash = nsec3param.hash;
23098 		param->flags = nsec3param.flags;
23099 		param->iterations = nsec3param.iterations;
23100 		param->salt_length = nsec3param.salt_length;
23101 		param->salt = nsec3param.salt;
23102 		break;
23103 	}
23104 
23105 	if (result == ISC_R_NOMORE) {
23106 		result = ISC_R_NOTFOUND;
23107 	}
23108 
23109 setparam:
23110 	if (result != ISC_R_SUCCESS) {
23111 		/* Found no match. */
23112 		param->hash = lookup->hash;
23113 		param->flags = lookup->flags;
23114 		param->iterations = lookup->iterations;
23115 		param->salt_length = lookup->salt_length;
23116 		param->salt = lookup->salt;
23117 	}
23118 
23119 	if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) {
23120 		goto failure;
23121 	}
23122 
23123 	if (param->salt_length == 0) {
23124 		DE_CONST("-", param->salt);
23125 	} else if (resalt || param->salt == NULL) {
23126 		unsigned char *newsalt;
23127 		unsigned char salttext[255 * 2 + 1];
23128 		do {
23129 			/* Generate a new salt. */
23130 			result = dns_nsec3_generate_salt(saltbuf,
23131 							 param->salt_length);
23132 			if (result != ISC_R_SUCCESS) {
23133 				break;
23134 			}
23135 			newsalt = saltbuf;
23136 			salt2text(newsalt, param->salt_length, salttext,
23137 				  sizeof(salttext));
23138 			dnssec_log(zone, ISC_LOG_INFO, "generated salt: %s",
23139 				   salttext);
23140 			/* Check for salt conflict. */
23141 			if (param->salt != NULL &&
23142 			    memcmp(newsalt, param->salt, param->salt_length) ==
23143 				    0)
23144 			{
23145 				result = ISC_R_SUCCESS;
23146 			} else {
23147 				param->salt = newsalt;
23148 				result = DNS_R_NSEC3RESALT;
23149 			}
23150 		} while (result == ISC_R_SUCCESS);
23151 
23152 		INSIST(result != ISC_R_SUCCESS);
23153 	}
23154 
23155 failure:
23156 	if (dns_rdataset_isassociated(&rdataset)) {
23157 		dns_rdataset_disassociate(&rdataset);
23158 	}
23159 	if (node != NULL) {
23160 		dns_db_detachnode(db, &node);
23161 	}
23162 	if (version != NULL) {
23163 		dns_db_closeversion(db, &version, false);
23164 	}
23165 	if (db != NULL) {
23166 		dns_db_detach(&db);
23167 	}
23168 
23169 	return (result);
23170 }
23171 
23172 /*
23173  * Called when an "rndc signing -nsec3param ..." command is received, or the
23174  * 'dnssec-policy' has changed.
23175  *
23176  * Allocate and prepare an nsec3param_t structure which holds information about
23177  * the NSEC3 changes requested for the zone:
23178  *
23179  *   - if NSEC3 is to be disabled ("-nsec3param none"), only set the "nsec"
23180  *     field of the structure to true and the "replace" field to the value
23181  *     of the "replace" argument, leaving other fields initialized to zeros, to
23182  *     signal that the zone should be signed using NSEC instead of NSEC3,
23183  *
23184  *   - otherwise, prepare NSEC3PARAM RDATA that will eventually be inserted at
23185  *     the zone apex, convert it to a private-type record and store the latter
23186  *     in the "data" field of the nsec3param_t structure.
23187  *
23188  * Once the nsec3param_t structure is prepared, post an event to the zone's
23189  * task which will cause setnsec3param() to be called with the prepared
23190  * structure passed as an argument.
23191  */
23192 isc_result_t
dns_zone_setnsec3param(dns_zone_t * zone,uint8_t hash,uint8_t flags,uint16_t iter,uint8_t saltlen,unsigned char * salt,bool replace,bool resalt)23193 dns_zone_setnsec3param(dns_zone_t *zone, uint8_t hash, uint8_t flags,
23194 		       uint16_t iter, uint8_t saltlen, unsigned char *salt,
23195 		       bool replace, bool resalt) {
23196 	isc_result_t result = ISC_R_SUCCESS;
23197 	dns_rdata_nsec3param_t param, lookup;
23198 	dns_rdata_t nrdata = DNS_RDATA_INIT;
23199 	dns_rdata_t prdata = DNS_RDATA_INIT;
23200 	unsigned char nbuf[DNS_NSEC3PARAM_BUFFERSIZE];
23201 	unsigned char saltbuf[255];
23202 	struct np3event *npe;
23203 	nsec3param_t *np;
23204 	dns_zone_t *dummy = NULL;
23205 	isc_buffer_t b;
23206 	isc_event_t *e = NULL;
23207 	bool do_lookup = false;
23208 
23209 	REQUIRE(DNS_ZONE_VALID(zone));
23210 
23211 	LOCK_ZONE(zone);
23212 
23213 	/*
23214 	 * First check if the requested NSEC3 parameters are already set,
23215 	 * if so, no need to set again.
23216 	 */
23217 	if (hash != 0) {
23218 		lookup.hash = hash;
23219 		lookup.flags = flags;
23220 		lookup.iterations = iter;
23221 		lookup.salt_length = saltlen;
23222 		lookup.salt = salt;
23223 		param.salt = NULL;
23224 		result = dns__zone_lookup_nsec3param(zone, &lookup, &param,
23225 						     saltbuf, resalt);
23226 		if (result == ISC_R_SUCCESS) {
23227 			UNLOCK_ZONE(zone);
23228 			return (ISC_R_SUCCESS);
23229 		}
23230 		/*
23231 		 * Schedule lookup if lookup above failed (may happen if zone
23232 		 * db is NULL for example).
23233 		 */
23234 		do_lookup = (param.salt == NULL) ? true : false;
23235 	}
23236 
23237 	e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETNSEC3PARAM,
23238 			       setnsec3param, zone, sizeof(struct np3event));
23239 
23240 	npe = (struct np3event *)e;
23241 	np = &npe->params;
23242 	np->replace = replace;
23243 	np->resalt = resalt;
23244 	np->lookup = do_lookup;
23245 	if (hash == 0) {
23246 		np->length = 0;
23247 		np->nsec = true;
23248 		dnssec_log(zone, ISC_LOG_DEBUG(3), "setnsec3param:nsec");
23249 	} else {
23250 		param.common.rdclass = zone->rdclass;
23251 		param.common.rdtype = dns_rdatatype_nsec3param;
23252 		ISC_LINK_INIT(&param.common, link);
23253 		param.mctx = NULL;
23254 		/* nsec3 specific param set in dns__zone_lookup_nsec3param() */
23255 		isc_buffer_init(&b, nbuf, sizeof(nbuf));
23256 
23257 		if (param.salt != NULL) {
23258 			CHECK(dns_rdata_fromstruct(&nrdata, zone->rdclass,
23259 						   dns_rdatatype_nsec3param,
23260 						   &param, &b));
23261 			dns_nsec3param_toprivate(&nrdata, &prdata,
23262 						 zone->privatetype, np->data,
23263 						 sizeof(np->data));
23264 			np->length = prdata.length;
23265 		}
23266 
23267 		np->rdata = param;
23268 		np->nsec = false;
23269 
23270 		if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
23271 			unsigned char salttext[255 * 2 + 1];
23272 			if (param.salt != NULL) {
23273 				salt2text(param.salt, param.salt_length,
23274 					  salttext, sizeof(salttext));
23275 			}
23276 			dnssec_log(zone, ISC_LOG_DEBUG(3),
23277 				   "setnsec3param:nsec3 %u %u %u %u:%s",
23278 				   param.hash, param.flags, param.iterations,
23279 				   param.salt_length,
23280 				   param.salt == NULL ? "unknown"
23281 						      : (char *)salttext);
23282 		}
23283 	}
23284 
23285 	/*
23286 	 * setnsec3param() will silently return early if the zone does not yet
23287 	 * have a database.  Prevent that by queueing the event up if zone->db
23288 	 * is NULL.  All events queued here are subsequently processed by
23289 	 * receive_secure_db() if it ever gets called or simply freed by
23290 	 * zone_free() otherwise.
23291 	 */
23292 
23293 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
23294 	if (zone->db != NULL) {
23295 		zone_iattach(zone, &dummy);
23296 		isc_task_send(zone->task, &e);
23297 	} else {
23298 		ISC_LIST_APPEND(zone->setnsec3param_queue, e, ev_link);
23299 		e = NULL;
23300 	}
23301 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
23302 
23303 	result = ISC_R_SUCCESS;
23304 
23305 failure:
23306 	if (e != NULL) {
23307 		isc_event_free(&e);
23308 	}
23309 	UNLOCK_ZONE(zone);
23310 	return (result);
23311 }
23312 
23313 isc_result_t
dns_zone_getloadtime(dns_zone_t * zone,isc_time_t * loadtime)23314 dns_zone_getloadtime(dns_zone_t *zone, isc_time_t *loadtime) {
23315 	REQUIRE(DNS_ZONE_VALID(zone));
23316 	REQUIRE(loadtime != NULL);
23317 
23318 	LOCK_ZONE(zone);
23319 	*loadtime = zone->loadtime;
23320 	UNLOCK_ZONE(zone);
23321 	return (ISC_R_SUCCESS);
23322 }
23323 
23324 isc_result_t
dns_zone_getexpiretime(dns_zone_t * zone,isc_time_t * expiretime)23325 dns_zone_getexpiretime(dns_zone_t *zone, isc_time_t *expiretime) {
23326 	REQUIRE(DNS_ZONE_VALID(zone));
23327 	REQUIRE(expiretime != NULL);
23328 
23329 	LOCK_ZONE(zone);
23330 	*expiretime = zone->expiretime;
23331 	UNLOCK_ZONE(zone);
23332 	return (ISC_R_SUCCESS);
23333 }
23334 
23335 isc_result_t
dns_zone_getrefreshtime(dns_zone_t * zone,isc_time_t * refreshtime)23336 dns_zone_getrefreshtime(dns_zone_t *zone, isc_time_t *refreshtime) {
23337 	REQUIRE(DNS_ZONE_VALID(zone));
23338 	REQUIRE(refreshtime != NULL);
23339 
23340 	LOCK_ZONE(zone);
23341 	*refreshtime = zone->refreshtime;
23342 	UNLOCK_ZONE(zone);
23343 	return (ISC_R_SUCCESS);
23344 }
23345 
23346 isc_result_t
dns_zone_getrefreshkeytime(dns_zone_t * zone,isc_time_t * refreshkeytime)23347 dns_zone_getrefreshkeytime(dns_zone_t *zone, isc_time_t *refreshkeytime) {
23348 	REQUIRE(DNS_ZONE_VALID(zone));
23349 	REQUIRE(refreshkeytime != NULL);
23350 
23351 	LOCK_ZONE(zone);
23352 	*refreshkeytime = zone->refreshkeytime;
23353 	UNLOCK_ZONE(zone);
23354 	return (ISC_R_SUCCESS);
23355 }
23356 
23357 unsigned int
dns_zone_getincludes(dns_zone_t * zone,char *** includesp)23358 dns_zone_getincludes(dns_zone_t *zone, char ***includesp) {
23359 	dns_include_t *include;
23360 	char **array = NULL;
23361 	unsigned int n = 0;
23362 
23363 	REQUIRE(DNS_ZONE_VALID(zone));
23364 	REQUIRE(includesp != NULL && *includesp == NULL);
23365 
23366 	LOCK_ZONE(zone);
23367 	if (zone->nincludes == 0) {
23368 		goto done;
23369 	}
23370 
23371 	array = isc_mem_allocate(zone->mctx, sizeof(char *) * zone->nincludes);
23372 	for (include = ISC_LIST_HEAD(zone->includes); include != NULL;
23373 	     include = ISC_LIST_NEXT(include, link))
23374 	{
23375 		INSIST(n < zone->nincludes);
23376 		array[n++] = isc_mem_strdup(zone->mctx, include->name);
23377 	}
23378 	INSIST(n == zone->nincludes);
23379 	*includesp = array;
23380 
23381 done:
23382 	UNLOCK_ZONE(zone);
23383 	return (n);
23384 }
23385 
23386 void
dns_zone_setstatlevel(dns_zone_t * zone,dns_zonestat_level_t level)23387 dns_zone_setstatlevel(dns_zone_t *zone, dns_zonestat_level_t level) {
23388 	REQUIRE(DNS_ZONE_VALID(zone));
23389 
23390 	zone->statlevel = level;
23391 }
23392 
23393 dns_zonestat_level_t
dns_zone_getstatlevel(dns_zone_t * zone)23394 dns_zone_getstatlevel(dns_zone_t *zone) {
23395 	REQUIRE(DNS_ZONE_VALID(zone));
23396 
23397 	return (zone->statlevel);
23398 }
23399 
23400 static void
setserial(isc_task_t * task,isc_event_t * event)23401 setserial(isc_task_t *task, isc_event_t *event) {
23402 	uint32_t oldserial, desired;
23403 	const char *me = "setserial";
23404 	bool commit = false;
23405 	isc_result_t result;
23406 	dns_dbversion_t *oldver = NULL, *newver = NULL;
23407 	dns_zone_t *zone;
23408 	dns_db_t *db = NULL;
23409 	dns_diff_t diff;
23410 	struct ssevent *sse = (struct ssevent *)event;
23411 	dns_update_log_t log = { update_log_cb, NULL };
23412 	dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
23413 
23414 	UNUSED(task);
23415 
23416 	zone = event->ev_arg;
23417 	INSIST(DNS_ZONE_VALID(zone));
23418 
23419 	ENTER;
23420 
23421 	if (zone->update_disabled) {
23422 		goto disabled;
23423 	}
23424 
23425 	desired = sse->serial;
23426 
23427 	dns_diff_init(zone->mctx, &diff);
23428 
23429 	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
23430 	if (zone->db != NULL) {
23431 		dns_db_attach(zone->db, &db);
23432 	}
23433 	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
23434 	if (db == NULL) {
23435 		goto failure;
23436 	}
23437 
23438 	dns_db_currentversion(db, &oldver);
23439 	result = dns_db_newversion(db, &newver);
23440 	if (result != ISC_R_SUCCESS) {
23441 		dns_zone_log(zone, ISC_LOG_ERROR,
23442 			     "setserial:dns_db_newversion -> %s",
23443 			     dns_result_totext(result));
23444 		goto failure;
23445 	}
23446 
23447 	CHECK(dns_db_createsoatuple(db, oldver, diff.mctx, DNS_DIFFOP_DEL,
23448 				    &oldtuple));
23449 	CHECK(dns_difftuple_copy(oldtuple, &newtuple));
23450 	newtuple->op = DNS_DIFFOP_ADD;
23451 
23452 	oldserial = dns_soa_getserial(&oldtuple->rdata);
23453 	if (desired == 0U) {
23454 		desired = 1;
23455 	}
23456 	if (!isc_serial_gt(desired, oldserial)) {
23457 		if (desired != oldserial) {
23458 			dns_zone_log(zone, ISC_LOG_INFO,
23459 				     "setserial: desired serial (%u) "
23460 				     "out of range (%u-%u)",
23461 				     desired, oldserial + 1,
23462 				     (oldserial + 0x7fffffff));
23463 		}
23464 		goto failure;
23465 	}
23466 
23467 	dns_soa_setserial(desired, &newtuple->rdata);
23468 	CHECK(do_one_tuple(&oldtuple, db, newver, &diff));
23469 	CHECK(do_one_tuple(&newtuple, db, newver, &diff));
23470 	result = dns_update_signatures(&log, zone, db, oldver, newver, &diff,
23471 				       zone->sigvalidityinterval);
23472 	if (result != ISC_R_NOTFOUND) {
23473 		CHECK(result);
23474 	}
23475 
23476 	/* Write changes to journal file. */
23477 	CHECK(zone_journal(zone, &diff, NULL, "setserial"));
23478 	commit = true;
23479 
23480 	LOCK_ZONE(zone);
23481 	zone_needdump(zone, 30);
23482 	UNLOCK_ZONE(zone);
23483 
23484 failure:
23485 	if (oldtuple != NULL) {
23486 		dns_difftuple_free(&oldtuple);
23487 	}
23488 	if (newtuple != NULL) {
23489 		dns_difftuple_free(&newtuple);
23490 	}
23491 	if (oldver != NULL) {
23492 		dns_db_closeversion(db, &oldver, false);
23493 	}
23494 	if (newver != NULL) {
23495 		dns_db_closeversion(db, &newver, commit);
23496 	}
23497 	if (db != NULL) {
23498 		dns_db_detach(&db);
23499 	}
23500 	dns_diff_clear(&diff);
23501 
23502 disabled:
23503 	isc_event_free(&event);
23504 	dns_zone_idetach(&zone);
23505 
23506 	INSIST(oldver == NULL);
23507 	INSIST(newver == NULL);
23508 }
23509 
23510 isc_result_t
dns_zone_setserial(dns_zone_t * zone,uint32_t serial)23511 dns_zone_setserial(dns_zone_t *zone, uint32_t serial) {
23512 	isc_result_t result = ISC_R_SUCCESS;
23513 	dns_zone_t *dummy = NULL;
23514 	isc_event_t *e = NULL;
23515 	struct ssevent *sse;
23516 
23517 	REQUIRE(DNS_ZONE_VALID(zone));
23518 
23519 	LOCK_ZONE(zone);
23520 
23521 	if (!inline_secure(zone)) {
23522 		if (!dns_zone_isdynamic(zone, true)) {
23523 			result = DNS_R_NOTDYNAMIC;
23524 			goto failure;
23525 		}
23526 	}
23527 
23528 	if (zone->update_disabled) {
23529 		result = DNS_R_FROZEN;
23530 		goto failure;
23531 	}
23532 
23533 	e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETSERIAL, setserial,
23534 			       zone, sizeof(struct ssevent));
23535 
23536 	sse = (struct ssevent *)e;
23537 	sse->serial = serial;
23538 
23539 	zone_iattach(zone, &dummy);
23540 	isc_task_send(zone->task, &e);
23541 
23542 failure:
23543 	if (e != NULL) {
23544 		isc_event_free(&e);
23545 	}
23546 	UNLOCK_ZONE(zone);
23547 	return (result);
23548 }
23549 
23550 isc_stats_t *
dns_zone_getgluecachestats(dns_zone_t * zone)23551 dns_zone_getgluecachestats(dns_zone_t *zone) {
23552 	REQUIRE(DNS_ZONE_VALID(zone));
23553 
23554 	return (zone->gluecachestats);
23555 }
23556 
23557 bool
dns_zone_isloaded(dns_zone_t * zone)23558 dns_zone_isloaded(dns_zone_t *zone) {
23559 	REQUIRE(DNS_ZONE_VALID(zone));
23560 
23561 	return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED));
23562 }
23563 
23564 isc_result_t
dns_zone_verifydb(dns_zone_t * zone,dns_db_t * db,dns_dbversion_t * ver)23565 dns_zone_verifydb(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver) {
23566 	dns_dbversion_t *version = NULL;
23567 	dns_keytable_t *secroots = NULL;
23568 	isc_result_t result;
23569 	dns_name_t *origin;
23570 
23571 	const char me[] = "dns_zone_verifydb";
23572 
23573 	REQUIRE(DNS_ZONE_VALID(zone));
23574 	REQUIRE(db != NULL);
23575 
23576 	ENTER;
23577 
23578 	if (dns_zone_gettype(zone) != dns_zone_mirror) {
23579 		return (ISC_R_SUCCESS);
23580 	}
23581 
23582 	if (ver == NULL) {
23583 		dns_db_currentversion(db, &version);
23584 	} else {
23585 		version = ver;
23586 	}
23587 
23588 	if (zone->view != NULL) {
23589 		result = dns_view_getsecroots(zone->view, &secroots);
23590 		if (result != ISC_R_SUCCESS) {
23591 			goto done;
23592 		}
23593 	}
23594 
23595 	origin = dns_db_origin(db);
23596 	result = dns_zoneverify_dnssec(zone, db, version, origin, secroots,
23597 				       zone->mctx, true, false, dnssec_report);
23598 
23599 done:
23600 	if (secroots != NULL) {
23601 		dns_keytable_detach(&secroots);
23602 	}
23603 
23604 	if (ver == NULL) {
23605 		dns_db_closeversion(db, &version, false);
23606 	}
23607 
23608 	if (result != ISC_R_SUCCESS) {
23609 		dnssec_log(zone, ISC_LOG_ERROR, "zone verification failed: %s",
23610 			   isc_result_totext(result));
23611 		result = DNS_R_VERIFYFAILURE;
23612 	}
23613 
23614 	return (result);
23615 }
23616 
23617 static dns_ttl_t
zone_nsecttl(dns_zone_t * zone)23618 zone_nsecttl(dns_zone_t *zone) {
23619 	REQUIRE(DNS_ZONE_VALID(zone));
23620 
23621 	return (ISC_MIN(zone->minimum, zone->soattl));
23622 }
23623