zone.c revision 1.26 1 /* $NetBSD: zone.c,v 1.26 2026/01/29 18:37:50 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/async.h>
23 #include <isc/atomic.h>
24 #include <isc/file.h>
25 #include <isc/hash.h>
26 #include <isc/hashmap.h>
27 #include <isc/hex.h>
28 #include <isc/loop.h>
29 #include <isc/md.h>
30 #include <isc/mutex.h>
31 #include <isc/overflow.h>
32 #include <isc/random.h>
33 #include <isc/ratelimiter.h>
34 #include <isc/refcount.h>
35 #include <isc/result.h>
36 #include <isc/rwlock.h>
37 #include <isc/serial.h>
38 #include <isc/stats.h>
39 #include <isc/stdtime.h>
40 #include <isc/strerr.h>
41 #include <isc/string.h>
42 #include <isc/thread.h>
43 #include <isc/tid.h>
44 #include <isc/timer.h>
45 #include <isc/tls.h>
46 #include <isc/util.h>
47
48 #include <dns/acl.h>
49 #include <dns/adb.h>
50 #include <dns/callbacks.h>
51 #include <dns/catz.h>
52 #include <dns/db.h>
53 #include <dns/dbiterator.h>
54 #include <dns/dlz.h>
55 #include <dns/dnssec.h>
56 #include <dns/journal.h>
57 #include <dns/kasp.h>
58 #include <dns/keydata.h>
59 #include <dns/keymgr.h>
60 #include <dns/keytable.h>
61 #include <dns/keyvalues.h>
62 #include <dns/log.h>
63 #include <dns/master.h>
64 #include <dns/masterdump.h>
65 #include <dns/message.h>
66 #include <dns/name.h>
67 #include <dns/nsec.h>
68 #include <dns/nsec3.h>
69 #include <dns/opcode.h>
70 #include <dns/peer.h>
71 #include <dns/private.h>
72 #include <dns/rcode.h>
73 #include <dns/rdata.h>
74 #include <dns/rdataclass.h>
75 #include <dns/rdatalist.h>
76 #include <dns/rdataset.h>
77 #include <dns/rdatasetiter.h>
78 #include <dns/rdatastruct.h>
79 #include <dns/rdatatype.h>
80 #include <dns/remote.h>
81 #include <dns/request.h>
82 #include <dns/resolver.h>
83 #include <dns/rriterator.h>
84 #include <dns/skr.h>
85 #include <dns/soa.h>
86 #include <dns/ssu.h>
87 #include <dns/stats.h>
88 #include <dns/time.h>
89 #include <dns/tsig.h>
90 #include <dns/ttl.h>
91 #include <dns/update.h>
92 #include <dns/xfrin.h>
93 #include <dns/zone.h>
94 #include <dns/zoneverify.h>
95 #include <dns/zt.h>
96
97 #include <dst/dst.h>
98
99 #include "zone_p.h"
100
101 #define ZONE_MAGIC ISC_MAGIC('Z', 'O', 'N', 'E')
102 #define DNS_ZONE_VALID(zone) ISC_MAGIC_VALID(zone, ZONE_MAGIC)
103
104 #define NOTIFY_MAGIC ISC_MAGIC('N', 't', 'f', 'y')
105 #define DNS_NOTIFY_VALID(notify) ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)
106
107 #define CHECKDS_MAGIC ISC_MAGIC('C', 'h', 'D', 'S')
108 #define DNS_CHECKDS_VALID(checkds) ISC_MAGIC_VALID(checkds, CHECKDS_MAGIC)
109
110 #define STUB_MAGIC ISC_MAGIC('S', 't', 'u', 'b')
111 #define DNS_STUB_VALID(stub) ISC_MAGIC_VALID(stub, STUB_MAGIC)
112
113 #define ZONEMGR_MAGIC ISC_MAGIC('Z', 'm', 'g', 'r')
114 #define DNS_ZONEMGR_VALID(stub) ISC_MAGIC_VALID(stub, ZONEMGR_MAGIC)
115
116 #define FORWARD_MAGIC ISC_MAGIC('F', 'o', 'r', 'w')
117 #define DNS_FORWARD_VALID(load) ISC_MAGIC_VALID(load, FORWARD_MAGIC)
118
119 #define IO_MAGIC ISC_MAGIC('Z', 'm', 'I', 'O')
120 #define DNS_IO_VALID(load) ISC_MAGIC_VALID(load, IO_MAGIC)
121
122 #define KEYMGMT_MAGIC ISC_MAGIC('M', 'g', 'm', 't')
123 #define DNS_KEYMGMT_VALID(load) ISC_MAGIC_VALID(load, KEYMGMT_MAGIC)
124
125 #define KEYFILEIO_MAGIC ISC_MAGIC('K', 'y', 'I', 'O')
126 #define DNS_KEYFILEIO_VALID(kfio) ISC_MAGIC_VALID(kfio, KEYFILEIO_MAGIC)
127
128 /*%
129 * Ensure 'a' is at least 'min' but not more than 'max'.
130 */
131 #define RANGE(a, min, max) (((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max)))
132
133 #define NSEC3REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
134
135 /*%
136 * Key flags
137 */
138 #define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
139 #define KSK(x) ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
140 #define ID(x) dst_key_id(x)
141 #define ALG(x) dst_key_alg(x)
142
143 /*%
144 * KASP flags
145 */
146 #define KASP_LOCK(k) \
147 if ((k) != NULL) { \
148 LOCK(&((k)->lock)); \
149 }
150
151 #define KASP_UNLOCK(k) \
152 if ((k) != NULL) { \
153 UNLOCK(&((k)->lock)); \
154 }
155
156 /*
157 * Default values.
158 */
159 #define DNS_DEFAULT_IDLEIN 3600 /*%< 1 hour */
160 #define DNS_DEFAULT_IDLEOUT 3600 /*%< 1 hour */
161 #define MAX_XFER_TIME (2 * 3600) /*%< Documented default is 2 hours */
162 #define RESIGN_DELAY 3600 /*%< 1 hour */
163
164 #ifndef DNS_MAX_EXPIRE
165 #define DNS_MAX_EXPIRE 14515200 /*%< 24 weeks */
166 #endif /* ifndef DNS_MAX_EXPIRE */
167
168 #ifndef DNS_DUMP_DELAY
169 #define DNS_DUMP_DELAY 900 /*%< 15 minutes */
170 #endif /* ifndef DNS_DUMP_DELAY */
171
172 typedef struct dns_notify dns_notify_t;
173 typedef struct dns_checkds dns_checkds_t;
174 typedef struct dns_stub dns_stub_t;
175 typedef struct dns_load dns_load_t;
176 typedef struct dns_forward dns_forward_t;
177 typedef ISC_LIST(dns_forward_t) dns_forwardlist_t;
178 typedef struct dns_keymgmt dns_keymgmt_t;
179 typedef struct dns_signing dns_signing_t;
180 typedef ISC_LIST(dns_signing_t) dns_signinglist_t;
181 typedef struct dns_nsec3chain dns_nsec3chain_t;
182 typedef ISC_LIST(dns_nsec3chain_t) dns_nsec3chainlist_t;
183 typedef struct dns_nsfetch dns_nsfetch_t;
184 typedef struct dns_keyfetch dns_keyfetch_t;
185 typedef struct dns_asyncload dns_asyncload_t;
186 typedef struct dns_include dns_include_t;
187
188 #define DNS_ZONE_CHECKLOCK
189 #ifdef DNS_ZONE_CHECKLOCK
190 #define LOCK_ZONE(z) \
191 do { \
192 LOCK(&(z)->lock); \
193 INSIST(!(z)->locked); \
194 (z)->locked = true; \
195 } while (0)
196 #define UNLOCK_ZONE(z) \
197 do { \
198 INSIST((z)->locked); \
199 (z)->locked = false; \
200 UNLOCK(&(z)->lock); \
201 } while (0)
202 #define LOCKED_ZONE(z) ((z)->locked)
203 #define TRYLOCK_ZONE(result, z) \
204 do { \
205 result = isc_mutex_trylock(&(z)->lock); \
206 if (result == ISC_R_SUCCESS) { \
207 INSIST(!(z)->locked); \
208 (z)->locked = true; \
209 } \
210 } while (0)
211 #else /* ifdef DNS_ZONE_CHECKLOCK */
212 #define LOCK_ZONE(z) LOCK(&(z)->lock)
213 #define UNLOCK_ZONE(z) UNLOCK(&(z)->lock)
214 #define LOCKED_ZONE(z) true
215 #define TRYLOCK_ZONE(result, z) \
216 do { \
217 result = isc_mutex_trylock(&(z)->lock); \
218 } while (0)
219 #endif /* ifdef DNS_ZONE_CHECKLOCK */
220
221 #define ZONEDB_INITLOCK(l) isc_rwlock_init(l)
222 #define ZONEDB_DESTROYLOCK(l) isc_rwlock_destroy(l)
223 #define ZONEDB_LOCK(l, t) RWLOCK((l), (t))
224 #define ZONEDB_UNLOCK(l, t) RWUNLOCK((l), (t))
225
226 #ifdef ENABLE_AFL
227 extern bool dns_fuzzing_resolver;
228 #endif /* ifdef ENABLE_AFL */
229
230 /*%
231 * Hold key file IO locks.
232 */
233 typedef struct dns_keyfileio {
234 unsigned int magic;
235 isc_mutex_t lock;
236 isc_refcount_t references;
237 dns_name_t *name;
238 dns_fixedname_t fname;
239 } dns_keyfileio_t;
240
241 struct dns_keymgmt {
242 unsigned int magic;
243 isc_rwlock_t lock;
244 isc_mem_t *mctx;
245 isc_hashmap_t *table;
246 };
247
248 /*
249 * Initial size of the keymgmt hash table.
250 */
251 #define DNS_KEYMGMT_HASH_BITS 12
252
253 struct dns_zone {
254 /* Unlocked */
255 unsigned int magic;
256 isc_mutex_t lock;
257 #ifndef _LP64
258 isc_mutex_t atomic_lock;
259 #endif
260 #ifdef DNS_ZONE_CHECKLOCK
261 bool locked;
262 #endif /* ifdef DNS_ZONE_CHECKLOCK */
263 isc_mem_t *mctx;
264 isc_refcount_t references;
265
266 isc_rwlock_t dblock;
267 dns_db_t *db; /* Locked by dblock */
268
269 unsigned int tid;
270
271 /* Locked */
272 dns_zonemgr_t *zmgr;
273 ISC_LINK(dns_zone_t) link; /* Used by zmgr. */
274 isc_loop_t *loop;
275 isc_timer_t *timer;
276 isc_refcount_t irefs;
277 dns_name_t origin;
278 char *masterfile;
279 const FILE *stream; /* loading from a stream? */
280 ISC_LIST(dns_include_t) includes; /* Include files */
281 ISC_LIST(dns_include_t) newincludes; /* Loading */
282 unsigned int nincludes;
283 dns_masterformat_t masterformat;
284 const dns_master_style_t *masterstyle;
285 char *journal;
286 int32_t journalsize;
287 dns_rdataclass_t rdclass;
288 dns_zonetype_t type;
289 #ifdef _LP64
290 atomic_uint_fast64_t flags;
291 atomic_uint_fast64_t options;
292 #else
293 uint64_t flags;
294 uint64_t options;
295 #endif
296 unsigned int db_argc;
297 char **db_argv;
298 isc_time_t expiretime;
299 isc_time_t refreshtime;
300 isc_time_t dumptime;
301 isc_time_t loadtime;
302 isc_time_t notifytime;
303 isc_time_t resigntime;
304 isc_time_t keywarntime;
305 isc_time_t signingtime;
306 isc_time_t nsec3chaintime;
307 isc_time_t refreshkeytime;
308 isc_time_t xfrintime;
309 uint32_t refreshkeyinterval;
310 uint32_t refreshkeycount;
311 uint32_t refresh;
312 uint32_t retry;
313 uint32_t expire;
314 uint32_t minimum;
315 isc_stdtime_t key_expiry;
316 isc_stdtime_t log_key_expired_timer;
317 char *keydirectory;
318 dns_keyfileio_t *kfio;
319 dns_keystorelist_t *keystores;
320 dns_xfrin_t *xfr;
321
322 uint32_t maxrefresh;
323 uint32_t minrefresh;
324 uint32_t maxretry;
325 uint32_t minretry;
326
327 uint32_t maxrecords;
328 uint32_t maxrrperset;
329 uint32_t maxtypepername;
330
331 dns_remote_t primaries;
332
333 dns_remote_t parentals;
334 dns_dnsseckeylist_t checkds_ok;
335 dns_checkdstype_t checkdstype;
336 uint32_t nsfetchcount;
337 uint32_t parent_nscount;
338
339 dns_remote_t notify;
340 dns_notifytype_t notifytype;
341 isc_sockaddr_t notifyfrom;
342 isc_sockaddr_t notifysrc4;
343 isc_sockaddr_t notifysrc6;
344 isc_sockaddr_t parentalsrc4;
345 isc_sockaddr_t parentalsrc6;
346 isc_sockaddr_t xfrsource4;
347 isc_sockaddr_t xfrsource6;
348 isc_sockaddr_t sourceaddr;
349 dns_tsigkey_t *tsigkey; /* key used for xfr */
350 dns_transport_t *transport; /* transport used for xfr */
351 /* Access Control Lists */
352 dns_acl_t *update_acl;
353 dns_acl_t *forward_acl;
354 dns_acl_t *notify_acl;
355 dns_acl_t *query_acl;
356 dns_acl_t *queryon_acl;
357 dns_acl_t *xfr_acl;
358 bool update_disabled;
359 bool zero_no_soa_ttl;
360 dns_severity_t check_names;
361 ISC_LIST(dns_notify_t) notifies;
362 ISC_LIST(dns_checkds_t) checkds_requests;
363 dns_request_t *request;
364 dns_loadctx_t *loadctx;
365 dns_dumpctx_t *dumpctx;
366 uint32_t minxfrratebytesin;
367 uint32_t minxfrratesecondsin;
368 uint32_t maxxfrin;
369 uint32_t maxxfrout;
370 uint32_t idlein;
371 uint32_t idleout;
372 dns_ssutable_t *ssutable;
373 uint32_t sigvalidityinterval;
374 uint32_t keyvalidityinterval;
375 uint32_t sigresigninginterval;
376 dns_view_t *view;
377 dns_view_t *prev_view;
378 dns_kasp_t *kasp;
379 dns_kasp_t *defaultkasp;
380 dns_dnsseckeylist_t keyring;
381 dns_checkmxfunc_t checkmx;
382 dns_checksrvfunc_t checksrv;
383 dns_checknsfunc_t checkns;
384 /*%
385 * Zones in certain states such as "waiting for zone transfer"
386 * or "zone transfer in progress" are kept on per-state linked lists
387 * in the zone manager using the 'statelink' field. The 'statelist'
388 * field points at the list the zone is currently on. It the zone
389 * is not on any such list, statelist is NULL.
390 */
391 ISC_LINK(dns_zone_t) statelink;
392 dns_zonelist_t *statelist;
393 /*%
394 * Statistics counters about zone management.
395 */
396 isc_stats_t *stats;
397 /*%
398 * Optional per-zone statistics counters. Counted outside of this
399 * module.
400 */
401 dns_zonestat_level_t statlevel;
402 bool requeststats_on;
403 isc_stats_t *requeststats;
404 dns_stats_t *rcvquerystats;
405 dns_stats_t *dnssecsignstats;
406 uint32_t notifydelay;
407 uint32_t notifydefer;
408 dns_isselffunc_t isself;
409 void *isselfarg;
410
411 char *strnamerd;
412 char *strname;
413 char *strrdclass;
414 char *strviewname;
415
416 /*%
417 * Serial number for deferred journal compaction.
418 */
419 uint32_t compact_serial;
420 /*%
421 * Keys that are signing the zone for the first time.
422 */
423 dns_signinglist_t signing;
424 dns_nsec3chainlist_t nsec3chain;
425 /*%
426 * List of outstanding NSEC3PARAM change requests.
427 */
428 ISC_LIST(struct np3) setnsec3param_queue;
429 /*%
430 * Signing / re-signing quantum stopping parameters.
431 */
432 uint32_t signatures;
433 uint32_t nodes;
434 dns_rdatatype_t privatetype;
435
436 /*%
437 * Autosigning/key-maintenance options
438 */
439 #ifdef _LP64
440 atomic_uint_fast64_t keyopts;
441 #else
442 uint64_t keyopts;
443 #endif
444
445 /*%
446 * True if added by "rndc addzone"
447 */
448 bool added;
449
450 /*%
451 * True if added by automatically by named.
452 */
453 bool automatic;
454
455 /*%
456 * response policy data to be relayed to the database
457 */
458 dns_rpz_zones_t *rpzs;
459 dns_rpz_num_t rpz_num;
460
461 /*%
462 * catalog zone data
463 */
464 dns_catz_zones_t *catzs;
465
466 /*%
467 * parent catalog zone
468 */
469 dns_catz_zone_t *parentcatz;
470
471 /*%
472 * Serial number update method.
473 */
474 dns_updatemethod_t updatemethod;
475
476 /*%
477 * whether ixfr is requested
478 */
479 bool requestixfr;
480 uint32_t ixfr_ratio;
481
482 /*%
483 * whether EDNS EXPIRE is requested
484 */
485 bool requestexpire;
486
487 /*%
488 * Outstanding forwarded UPDATE requests.
489 */
490 dns_forwardlist_t forwards;
491
492 dns_zone_t *raw;
493 dns_zone_t *secure;
494
495 bool sourceserialset;
496 uint32_t sourceserial;
497
498 /*%
499 * soa and maximum zone ttl
500 */
501 dns_ttl_t soattl;
502 dns_ttl_t maxttl;
503
504 /*
505 * Inline zone signing state.
506 */
507 dns_diff_t rss_diff;
508 dns_dbversion_t *rss_newver;
509 dns_dbversion_t *rss_oldver;
510 dns_db_t *rss_db;
511 dns_zone_t *rss_raw;
512 struct rss *rss;
513 dns_update_state_t *rss_state;
514
515 isc_stats_t *gluecachestats;
516
517 /*%
518 * Offline KSK signed key responses.
519 */
520 dns_skr_t *skr;
521 dns_skrbundle_t *skrbundle;
522 };
523
524 #define zonediff_init(z, d) \
525 do { \
526 dns__zonediff_t *_z = (z); \
527 (_z)->diff = (d); \
528 (_z)->offline = false; \
529 } while (0)
530 #ifdef _LP64
531 #define ISC_ZONE_GET(z, f) atomic_load_relaxed(&(z)->f)
532 #define ISC_ZONE_SET(z, f, o) atomic_fetch_or(&(z)->f, (o))
533 #define ISC_ZONE_CLR(z, f, o) atomic_fetch_and(&(z)->f, ~(o))
534 #else
535 #define ISC_ZONE_GET(z, f) \
536 ({ \
537 isc_mutex_lock(&(z)->atomic_lock); \
538 uint64_t x = (z)->f; \
539 isc_mutex_unlock(&(z)->atomic_lock); \
540 x; \
541 })
542 #define ISC_ZONE_SET(z, f, o) \
543 ({ \
544 isc_mutex_lock(&(z)->atomic_lock); \
545 uint64_t x = ((z)->f | (o)); \
546 isc_mutex_unlock(&(z)->atomic_lock); \
547 x; \
548 })
549 #define ISC_ZONE_CLR(z, f, o) \
550 ({ \
551 isc_mutex_lock(&(z)->atomic_lock); \
552 uint64_t x = ((z)->f & ~(o)); \
553 isc_mutex_unlock(&(z)->atomic_lock); \
554 x; \
555 })
556 #endif
557 #define ISC_ZONE_TEST(z, f, o) ((ISC_ZONE_GET(z, f) & (o)) != 0)
558
559 #define DNS_ZONE_FLAG(z, f) ISC_ZONE_TEST(z, flags, f)
560 #define DNS_ZONE_SETFLAG(z, f) ISC_ZONE_SET(z, flags, f)
561 #define DNS_ZONE_CLRFLAG(z, f) ISC_ZONE_CLR(z, flags, f)
562 typedef enum {
563 DNS_ZONEFLG_REFRESH = 0x00000001U, /*%< refresh check in progress */
564 DNS_ZONEFLG_NEEDDUMP = 0x00000002U, /*%< zone need consolidation */
565 DNS_ZONEFLG_USEVC = 0x00000004U, /*%< use tcp for refresh query */
566 DNS_ZONEFLG_DUMPING = 0x00000008U, /*%< a dump is in progress */
567 DNS_ZONEFLG_HASINCLUDE = 0x00000010U, /*%< $INCLUDE in zone file */
568 DNS_ZONEFLG_LOADED = 0x00000020U, /*%< database has loaded */
569 DNS_ZONEFLG_EXITING = 0x00000040U, /*%< zone is being destroyed */
570 DNS_ZONEFLG_EXPIRED = 0x00000080U, /*%< zone has expired */
571 DNS_ZONEFLG_NEEDREFRESH = 0x00000100U, /*%< refresh check needed */
572 DNS_ZONEFLG_UPTODATE = 0x00000200U, /*%< zone contents are
573 * up-to-date */
574 DNS_ZONEFLG_NEEDNOTIFY = 0x00000400U, /*%< need to send out notify
575 * messages */
576 DNS_ZONEFLG_FIXJOURNAL = 0x00000800U, /*%< journal file had
577 * recoverable error,
578 * needs rewriting */
579 DNS_ZONEFLG_NOPRIMARIES = 0x00001000U, /*%< an attempt to refresh a
580 * zone with no primaries
581 * occurred */
582 DNS_ZONEFLG_LOADING = 0x00002000U, /*%< load from disk in progress*/
583 DNS_ZONEFLG_HAVETIMERS = 0x00004000U, /*%< timer values have been set
584 * from SOA (if not set, we
585 * are still using
586 * default timer values) */
587 DNS_ZONEFLG_FORCEXFER = 0x00008000U, /*%< Force a zone xfer */
588 DNS_ZONEFLG_NOREFRESH = 0x00010000U,
589 DNS_ZONEFLG_DIALNOTIFY = 0x00020000U,
590 DNS_ZONEFLG_DIALREFRESH = 0x00040000U,
591 DNS_ZONEFLG_SHUTDOWN = 0x00080000U,
592 DNS_ZONEFLG_NOIXFR = 0x00100000U, /*%< IXFR failed, force AXFR */
593 DNS_ZONEFLG_FLUSH = 0x00200000U,
594 DNS_ZONEFLG_NOEDNS = 0x00400000U,
595 DNS_ZONEFLG_USEALTXFRSRC = 0x00800000U, /*%< Obsoleted. */
596 DNS_ZONEFLG_SOABEFOREAXFR = 0x01000000U,
597 DNS_ZONEFLG_NEEDCOMPACT = 0x02000000U,
598 DNS_ZONEFLG_REFRESHING = 0x04000000U, /*%< Refreshing keydata */
599 DNS_ZONEFLG_THAW = 0x08000000U,
600 DNS_ZONEFLG_LOADPENDING = 0x10000000U, /*%< Loading scheduled */
601 DNS_ZONEFLG_NODELAY = 0x20000000U,
602 DNS_ZONEFLG_SENDSECURE = 0x40000000U,
603 DNS_ZONEFLG_NEEDSTARTUPNOTIFY = 0x80000000U, /*%< need to send out
604 * notify due to the zone
605 * just being loaded for
606 * the first time. */
607 DNS_ZONEFLG_NOTIFYNODEFER = 0x100000000U, /*%< ignore the
608 * notify-defer option. */
609 DNS_ZONEFLG_NOTIFYDEFERRED = 0x200000000U, /*%< notify was deferred
610 * according to the
611 * notify-defer option. */
612 DNS_ZONEFLG_FIRSTREFRESH = 0x400000000U, /*%< First refresh pending */
613 DNS_ZONEFLG___MAX = UINT64_MAX, /* trick to make the ENUM 64-bit wide */
614 } dns_zoneflg_t;
615
616
617 #define DNS_ZONE_OPTION(z, o) ISC_ZONE_TEST(z, options, o)
618 #define DNS_ZONE_SETOPTION(z, o) ISC_ZONE_SET(z, options, o)
619 #define DNS_ZONE_CLROPTION(z, o) ISC_ZONE_CLR(z, options, o)
620 #define DNS_ZONEKEY_OPTION(z, o) ISC_ZONE_TEST(z, keyopts, o)
621 #define DNS_ZONEKEY_SETOPTION(z, o) ISC_ZONE_SET(z, keyopts, o)
622 #define DNS_ZONEKEY_CLROPTION(z, o) ISC_ZONE_CLR(z, keyopts, o)
623
624
625 /* Flags for zone_load() */
626 typedef enum {
627 DNS_ZONELOADFLAG_NOSTAT = 0x00000001U, /* Do not stat() master files */
628 DNS_ZONELOADFLAG_THAW = 0x00000002U, /* Thaw the zone on successful
629 * load. */
630 } dns_zoneloadflag_t;
631
632 #define UNREACH_CACHE_SIZE 10U
633 #define UNREACH_HOLD_TIME 600 /* 10 minutes */
634
635 struct dns_unreachable {
636 isc_sockaddr_t remote;
637 isc_sockaddr_t local;
638 atomic_uint_fast32_t expire;
639 atomic_uint_fast32_t last;
640 uint32_t count;
641 };
642
643 struct dns_zonemgr {
644 unsigned int magic;
645 isc_mem_t *mctx;
646 isc_refcount_t refs;
647 isc_loopmgr_t *loopmgr;
648 isc_nm_t *netmgr;
649 uint32_t workers;
650 isc_mem_t **mctxpool;
651 isc_ratelimiter_t *checkdsrl;
652 isc_ratelimiter_t *notifyrl;
653 isc_ratelimiter_t *refreshrl;
654 isc_ratelimiter_t *startupnotifyrl;
655 isc_ratelimiter_t *startuprefreshrl;
656 isc_rwlock_t rwlock;
657 isc_rwlock_t urlock;
658
659 /* Locked by rwlock. */
660 dns_zonelist_t zones;
661 dns_zonelist_t waiting_for_xfrin;
662 dns_zonelist_t xfrin_in_progress;
663
664 /* Configuration data. */
665 uint32_t transfersin;
666 uint32_t transfersperns;
667 unsigned int checkdsrate;
668 unsigned int notifyrate;
669 unsigned int startupnotifyrate;
670 unsigned int serialqueryrate;
671 unsigned int startupserialqueryrate;
672
673 /* Locked by urlock. */
674 /* LRU cache */
675 struct dns_unreachable unreachable[UNREACH_CACHE_SIZE];
676
677 dns_keymgmt_t *keymgmt;
678
679 isc_tlsctx_cache_t *tlsctx_cache;
680 isc_rwlock_t tlsctx_cache_rwlock;
681 };
682
683 /*%
684 * Hold notify state.
685 */
686 struct dns_notify {
687 unsigned int magic;
688 unsigned int flags;
689 isc_mem_t *mctx;
690 dns_zone_t *zone;
691 dns_adbfind_t *find;
692 dns_request_t *request;
693 dns_name_t ns;
694 isc_sockaddr_t src;
695 isc_sockaddr_t dst;
696 dns_tsigkey_t *key;
697 dns_transport_t *transport;
698 ISC_LINK(dns_notify_t) link;
699 isc_rlevent_t *rlevent;
700 };
701
702 typedef enum dns_notify_flags {
703 DNS_NOTIFY_NOSOA = 1 << 0,
704 DNS_NOTIFY_STARTUP = 1 << 1,
705 DNS_NOTIFY_TCP = 1 << 2,
706 } dns_notify_flags_t;
707
708 /*%
709 * Hold checkds state.
710 */
711 struct dns_checkds {
712 unsigned int magic;
713 dns_notify_flags_t flags;
714 isc_mem_t *mctx;
715 dns_zone_t *zone;
716 dns_adbfind_t *find;
717 dns_request_t *request;
718 dns_name_t ns;
719 isc_sockaddr_t src;
720 isc_sockaddr_t dst;
721 dns_tsigkey_t *key;
722 dns_transport_t *transport;
723 ISC_LINK(dns_checkds_t) link;
724 isc_rlevent_t *rlevent;
725 };
726
727 /*%
728 * dns_stub holds state while performing a 'stub' transfer.
729 * 'db' is the zone's 'db' or a new one if this is the initial
730 * transfer.
731 */
732
733 struct dns_stub {
734 unsigned int magic;
735 isc_mem_t *mctx;
736 dns_zone_t *zone;
737 dns_db_t *db;
738 dns_dbversion_t *version;
739 atomic_uint_fast32_t pending_requests;
740 };
741
742 /*%
743 * Hold load state.
744 */
745 struct dns_load {
746 dns_zone_t *zone;
747 dns_db_t *db;
748 isc_time_t loadtime;
749 dns_rdatacallbacks_t callbacks;
750 };
751
752 /*%
753 * Hold forward state.
754 */
755 struct dns_forward {
756 unsigned int magic;
757 isc_mem_t *mctx;
758 dns_zone_t *zone;
759 isc_buffer_t *msgbuf;
760 dns_request_t *request;
761 uint32_t which;
762 isc_sockaddr_t addr;
763 dns_transport_t *transport;
764 dns_updatecallback_t callback;
765 void *callback_arg;
766 unsigned int options;
767 ISC_LINK(dns_forward_t) link;
768 };
769
770 /*%
771 * Hold state for when we are signing a zone with a new
772 * DNSKEY as result of an update.
773 */
774 struct dns_signing {
775 unsigned int magic;
776 dns_db_t *db;
777 dns_dbiterator_t *dbiterator;
778 dns_secalg_t algorithm;
779 uint16_t keyid;
780 bool deleteit;
781 bool fullsign;
782 bool done;
783 ISC_LINK(dns_signing_t) link;
784 };
785
786 struct dns_nsec3chain {
787 unsigned int magic;
788 dns_db_t *db;
789 dns_dbiterator_t *dbiterator;
790 dns_rdata_nsec3param_t nsec3param;
791 unsigned char salt[255];
792 bool done;
793 bool seen_nsec;
794 bool delete_nsec;
795 bool save_delete_nsec;
796 ISC_LINK(dns_nsec3chain_t) link;
797 };
798
799 /*%<
800 * 'dbiterator' contains a iterator for the database. If we are creating
801 * a NSEC3 chain only the non-NSEC3 nodes will be iterated. If we are
802 * removing a NSEC3 chain then both NSEC3 and non-NSEC3 nodes will be
803 * iterated.
804 *
805 * 'nsec3param' contains the parameters of the NSEC3 chain being created
806 * or removed.
807 *
808 * 'salt' is buffer space and is referenced via 'nsec3param.salt'.
809 *
810 * 'seen_nsec' will be set to true if, while iterating the zone to create a
811 * NSEC3 chain, a NSEC record is seen.
812 *
813 * 'delete_nsec' will be set to true if, at the completion of the creation
814 * of a NSEC3 chain, 'seen_nsec' is true. If 'delete_nsec' is true then we
815 * are in the process of deleting the NSEC chain.
816 *
817 * 'save_delete_nsec' is used to store the initial state of 'delete_nsec'
818 * so it can be recovered in the event of a error.
819 */
820
821 struct dns_keyfetch {
822 isc_mem_t *mctx;
823 dns_fixedname_t name;
824 dns_rdataset_t keydataset;
825 dns_rdataset_t dnskeyset;
826 dns_rdataset_t dnskeysigset;
827 dns_zone_t *zone;
828 dns_db_t *db;
829 dns_fetch_t *fetch;
830 };
831
832 struct dns_nsfetch {
833 isc_mem_t *mctx;
834 dns_fixedname_t name;
835 dns_name_t pname;
836 dns_rdataset_t nsrrset;
837 dns_rdataset_t nssigset;
838 dns_zone_t *zone;
839 dns_fetch_t *fetch;
840 };
841
842 /*%
843 * Hold state for an asynchronous load
844 */
845 struct dns_asyncload {
846 dns_zone_t *zone;
847 unsigned int flags;
848 dns_zt_callback_t *loaded;
849 void *loaded_arg;
850 };
851
852 /*%
853 * Reference to an include file encountered during loading
854 */
855 struct dns_include {
856 char *name;
857 isc_time_t filetime;
858 ISC_LINK(dns_include_t) link;
859 };
860
861 /*
862 * These can be overridden by the -T mkeytimers option on the command
863 * line, so that we can test with shorter periods than specified in
864 * RFC 5011.
865 */
866 #define HOUR 3600
867 #define DAY (24 * HOUR)
868 #define MONTH (30 * DAY)
869 unsigned int dns_zone_mkey_hour = HOUR;
870 unsigned int dns_zone_mkey_day = DAY;
871 unsigned int dns_zone_mkey_month = MONTH;
872
873 #define SEND_BUFFER_SIZE 2048
874
875 static void
876 zone_timer_set(dns_zone_t *zone, isc_time_t *next, isc_time_t *now);
877
878 typedef struct zone_settimer {
879 dns_zone_t *zone;
880 isc_time_t now;
881 } zone_settimer_t;
882
883 static void
884 zone_settimer(dns_zone_t *, isc_time_t *);
885 static void
886 cancel_refresh(dns_zone_t *);
887 static void
888 zone_debuglogc(dns_zone_t *zone, isc_logcategory_t *category, const char *me,
889 int debuglevel, const char *fmt, ...);
890 static void
891 zone_debuglog(dns_zone_t *zone, const char *, int debuglevel, const char *msg,
892 ...) ISC_FORMAT_PRINTF(4, 5);
893 static void
894 notify_log(dns_zone_t *zone, int level, const char *fmt, ...)
895 ISC_FORMAT_PRINTF(3, 4);
896 static void
897 dnssec_log(dns_zone_t *zone, int level, const char *fmt, ...)
898 ISC_FORMAT_PRINTF(3, 4);
899 static void
900 queue_xfrin(dns_zone_t *zone);
901 static isc_result_t
902 update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
903 dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
904 dns_rdata_t *rdata);
905 static void
906 zone_unload(dns_zone_t *zone);
907 static void
908 zone_expire(dns_zone_t *zone);
909 static void
910 zone_refresh(dns_zone_t *zone);
911 static void
912 zone_iattach(dns_zone_t *source, dns_zone_t **target);
913 static void
914 zone_idetach(dns_zone_t **zonep);
915 static isc_result_t
916 zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump);
917 static void
918 zone_attachdb(dns_zone_t *zone, dns_db_t *db);
919 static void
920 zone_detachdb(dns_zone_t *zone);
921 static void
922 zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs);
923 static void
924 zone_catz_disable(dns_zone_t *zone);
925 static isc_result_t
926 default_journal(dns_zone_t *zone);
927 static void
928 zone_xfrdone(dns_zone_t *zone, uint32_t *expireopt, isc_result_t result);
929 static isc_result_t
930 zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
931 isc_result_t result);
932 static void
933 zone_needdump(dns_zone_t *zone, unsigned int delay);
934 static void
935 zone_shutdown(void *arg);
936 static void
937 zone_loaddone(void *arg, isc_result_t result);
938 static isc_result_t
939 zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime);
940 static void
941 zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length);
942 static void
943 zone_name_tostr(dns_zone_t *zone, char *buf, size_t length);
944 static void
945 zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length);
946 static void
947 zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length);
948 static isc_result_t
949 zone_send_secureserial(dns_zone_t *zone, uint32_t serial);
950 static void
951 refresh_callback(void *arg);
952 static void
953 stub_callback(void *arg);
954 static void
955 queue_soa_query(dns_zone_t *zone);
956 static void
957 soa_query(void *arg);
958 static void
959 ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub);
960 static int
961 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type);
962 static void
963 checkds_cancel(dns_zone_t *zone);
964 static void
965 checkds_find_address(dns_checkds_t *checkds);
966 static void
967 checkds_send(dns_zone_t *zone);
968 static void
969 checkds_createmessage(dns_zone_t *zone, dns_message_t **messagep);
970 static void
971 checkds_done(void *arg);
972 static void
973 checkds_send_tons(dns_checkds_t *checkds);
974 static void
975 checkds_send_toaddr(void *arg);
976 static void
977 nsfetch_levelup(dns_nsfetch_t *nsfetch);
978 static void
979 notify_cancel(dns_zone_t *zone);
980 static void
981 notify_find_address(dns_notify_t *notify);
982 static void
983 notify_send(dns_notify_t *notify);
984 static isc_result_t
985 notify_createmessage(dns_zone_t *zone, unsigned int flags,
986 dns_message_t **messagep);
987 static void
988 notify_done(void *arg);
989 static void
990 notify_send_toaddr(void *arg);
991 static isc_result_t
992 zone_dump(dns_zone_t *, bool);
993 static void
994 got_transfer_quota(void *arg);
995 static isc_result_t
996 zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone);
997 static void
998 zmgr_resume_xfrs(dns_zonemgr_t *zmgr, bool multi);
999 static void
1000 zonemgr_free(dns_zonemgr_t *zmgr);
1001 static void
1002 rss_post(void *arg);
1003
1004 static isc_result_t
1005 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
1006 unsigned int *soacount, uint32_t *soattl, uint32_t *serial,
1007 uint32_t *refresh, uint32_t *retry, uint32_t *expire,
1008 uint32_t *minimum, unsigned int *errors);
1009
1010 static void
1011 zone_freedbargs(dns_zone_t *zone);
1012 static void
1013 forward_callback(void *arg);
1014 static void
1015 zone_saveunique(dns_zone_t *zone, const char *path, const char *templat);
1016 static void
1017 zone_maintenance(dns_zone_t *zone);
1018 static void
1019 zone_notify(dns_zone_t *zone, isc_time_t *now);
1020 static void
1021 dump_done(void *arg, isc_result_t result);
1022 static isc_result_t
1023 zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid,
1024 bool deleteit, bool fullsign);
1025 static isc_result_t
1026 delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
1027 dns_name_t *name, dns_diff_t *diff);
1028 static void
1029 zone_rekey(dns_zone_t *zone);
1030 static isc_result_t
1031 zone_send_securedb(dns_zone_t *zone, dns_db_t *db);
1032 static dns_ttl_t
1033 zone_nsecttl(dns_zone_t *zone);
1034 static void
1035 setrl(isc_ratelimiter_t *rl, unsigned int *rate, unsigned int value);
1036 static void
1037 zone_journal_compact(dns_zone_t *zone, dns_db_t *db, uint32_t serial);
1038 static isc_result_t
1039 zone_journal_rollforward(dns_zone_t *zone, dns_db_t *db, bool *needdump,
1040 bool *fixjournal);
1041 static void
1042 setnsec3param(void *arg);
1043
1044 static void
1045 zmgr_tlsctx_attach(dns_zonemgr_t *zmgr, isc_tlsctx_cache_t **ptlsctx_cache);
1046 /*%<
1047 * Attach to TLS client context cache used for zone transfers via
1048 * encrypted transports (e.g. XoT).
1049 *
1050 * The obtained reference needs to be detached by a call to
1051 * 'isc_tlsctx_cache_detach()' when not needed anymore.
1052 *
1053 * Requires:
1054 *\li 'zmgr' is a valid zone manager.
1055 *\li 'ptlsctx_cache' is not 'NULL' and points to 'NULL'.
1056 */
1057
1058 #define ENTER zone_debuglog(zone, __func__, 1, "enter")
1059
1060 static const unsigned int dbargc_default = 1;
1061 static const char *dbargv_default[] = { ZONEDB_DEFAULT };
1062
1063 #define DNS_ZONE_JITTER_ADD(a, b, c) \
1064 do { \
1065 isc_interval_t _i; \
1066 uint32_t _j; \
1067 _j = (b) - isc_random_uniform((b) / 4); \
1068 isc_interval_set(&_i, _j, 0); \
1069 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
1070 dns_zone_log(zone, ISC_LOG_WARNING, \
1071 "epoch approaching: upgrade required: " \
1072 "now + %s failed", \
1073 #b); \
1074 isc_interval_set(&_i, _j / 2, 0); \
1075 (void)isc_time_add((a), &_i, (c)); \
1076 } \
1077 } while (0)
1078
1079 #define DNS_ZONE_TIME_ADD(a, b, c) \
1080 do { \
1081 isc_interval_t _i; \
1082 isc_interval_set(&_i, (b), 0); \
1083 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
1084 dns_zone_log(zone, ISC_LOG_WARNING, \
1085 "epoch approaching: upgrade required: " \
1086 "now + %s failed", \
1087 #b); \
1088 isc_interval_set(&_i, (b) / 2, 0); \
1089 (void)isc_time_add((a), &_i, (c)); \
1090 } \
1091 } while (0)
1092
1093 #define DNS_ZONE_TIME_SUBTRACT(a, b, c) \
1094 do { \
1095 isc_interval_t _i; \
1096 isc_interval_set(&_i, (b), 0); \
1097 if (isc_time_subtract((a), &_i, (c)) != ISC_R_SUCCESS) { \
1098 dns_zone_log(zone, ISC_LOG_WARNING, \
1099 "epoch approaching: upgrade required: " \
1100 "isc_time_subtract() failed"); \
1101 isc_interval_set(&_i, (b) / 2, 0); \
1102 (void)isc_time_subtract((a), &_i, (c)); \
1103 } \
1104 } while (0)
1105
1106 typedef struct nsec3param nsec3param_t;
1107 struct nsec3param {
1108 dns_rdata_nsec3param_t rdata;
1109 unsigned char data[DNS_NSEC3PARAM_BUFFERSIZE + 1];
1110 unsigned int length;
1111 bool nsec;
1112 bool replace;
1113 bool resalt;
1114 bool lookup;
1115 ISC_LINK(nsec3param_t) link;
1116 };
1117 typedef ISC_LIST(nsec3param_t) nsec3paramlist_t;
1118
1119 struct np3 {
1120 dns_zone_t *zone;
1121 nsec3param_t params;
1122 ISC_LINK(struct np3) link;
1123 };
1124
1125 struct setserial {
1126 dns_zone_t *zone;
1127 uint32_t serial;
1128 };
1129
1130 struct stub_cb_args {
1131 dns_stub_t *stub;
1132 dns_tsigkey_t *tsig_key;
1133 uint16_t udpsize;
1134 int timeout;
1135 bool reqnsid;
1136 };
1137
1138 struct stub_glue_request {
1139 dns_request_t *request;
1140 dns_name_t name;
1141 struct stub_cb_args *args;
1142 bool ipv4;
1143 };
1144
1145 /*%
1146 * Increment resolver-related statistics counters. Zone must be locked.
1147 */
1148 static void
1149 inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
1150 if (zone->stats != NULL) {
1151 isc_stats_increment(zone->stats, counter);
1152 }
1153 }
1154
1155 /***
1156 *** Public functions.
1157 ***/
1158
1159 void
1160 dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx, unsigned int tid) {
1161 isc_time_t now;
1162 dns_zone_t *zone = NULL;
1163
1164 REQUIRE(zonep != NULL && *zonep == NULL);
1165 REQUIRE(mctx != NULL);
1166
1167 now = isc_time_now();
1168 zone = isc_mem_get(mctx, sizeof(*zone));
1169 *zone = (dns_zone_t){
1170 .masterformat = dns_masterformat_none,
1171 .journalsize = -1,
1172 .rdclass = dns_rdataclass_none,
1173 .type = dns_zone_none,
1174 .refresh = DNS_ZONE_DEFAULTREFRESH,
1175 .retry = DNS_ZONE_DEFAULTRETRY,
1176 .maxrefresh = DNS_ZONE_MAXREFRESH,
1177 .minrefresh = DNS_ZONE_MINREFRESH,
1178 .maxretry = DNS_ZONE_MAXRETRY,
1179 .minretry = DNS_ZONE_MINRETRY,
1180 .checkdstype = dns_checkdstype_yes,
1181 .notifytype = dns_notifytype_yes,
1182 .zero_no_soa_ttl = true,
1183 .check_names = dns_severity_ignore,
1184 .idlein = DNS_DEFAULT_IDLEIN,
1185 .idleout = DNS_DEFAULT_IDLEOUT,
1186 .maxxfrin = MAX_XFER_TIME,
1187 .maxxfrout = MAX_XFER_TIME,
1188 .sigvalidityinterval = 30 * 24 * 3600,
1189 .sigresigninginterval = 7 * 24 * 3600,
1190 .statlevel = dns_zonestat_none,
1191 .notifydelay = 5,
1192 .signatures = 10,
1193 .nodes = 100,
1194 .privatetype = (dns_rdatatype_t)0xffffU,
1195 .rpz_num = DNS_RPZ_INVALID_NUM,
1196 .requestixfr = true,
1197 .ixfr_ratio = 100,
1198 .requestexpire = true,
1199 .updatemethod = dns_updatemethod_increment,
1200 .tid = tid,
1201 .notifytime = now,
1202 .newincludes = ISC_LIST_INITIALIZER,
1203 .notifies = ISC_LIST_INITIALIZER,
1204 .checkds_requests = ISC_LIST_INITIALIZER,
1205 .signing = ISC_LIST_INITIALIZER,
1206 .nsec3chain = ISC_LIST_INITIALIZER,
1207 .setnsec3param_queue = ISC_LIST_INITIALIZER,
1208 .forwards = ISC_LIST_INITIALIZER,
1209 .link = ISC_LINK_INITIALIZER,
1210 .statelink = ISC_LINK_INITIALIZER,
1211 };
1212 dns_remote_t r = {
1213 .magic = DNS_REMOTE_MAGIC,
1214 };
1215
1216 isc_mem_attach(mctx, &zone->mctx);
1217 isc_mutex_init(&zone->lock);
1218 #ifndef _LP64
1219 isc_mutex_init(&zone->atomic_lock);
1220 #endif
1221 ZONEDB_INITLOCK(&zone->dblock);
1222
1223 isc_refcount_init(&zone->references, 1);
1224 isc_refcount_init(&zone->irefs, 0);
1225 dns_name_init(&zone->origin, NULL);
1226 isc_sockaddr_any(&zone->notifysrc4);
1227 isc_sockaddr_any6(&zone->notifysrc6);
1228 isc_sockaddr_any(&zone->parentalsrc4);
1229 isc_sockaddr_any6(&zone->parentalsrc6);
1230 isc_sockaddr_any(&zone->xfrsource4);
1231 isc_sockaddr_any6(&zone->xfrsource6);
1232
1233 zone->primaries = r;
1234 zone->parentals = r;
1235 zone->notify = r;
1236 zone->defaultkasp = NULL;
1237 ISC_LIST_INIT(zone->keyring);
1238
1239 isc_stats_create(mctx, &zone->gluecachestats,
1240 dns_gluecachestatscounter_max);
1241
1242 zone->magic = ZONE_MAGIC;
1243
1244 /* Must be after magic is set. */
1245 dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
1246
1247 *zonep = zone;
1248 }
1249
1250 static void
1251 clear_keylist(dns_dnsseckeylist_t *list, isc_mem_t *mctx) {
1252 dns_dnsseckey_t *key;
1253 while (!ISC_LIST_EMPTY(*list)) {
1254 key = ISC_LIST_HEAD(*list);
1255 ISC_LIST_UNLINK(*list, key, link);
1256 dns_dnsseckey_destroy(mctx, &key);
1257 }
1258 }
1259
1260 /*
1261 * Free a zone. Because we require that there be no more
1262 * outstanding events or references, no locking is necessary.
1263 */
1264 static void
1265 zone_free(dns_zone_t *zone) {
1266 dns_signing_t *signing = NULL;
1267 dns_nsec3chain_t *nsec3chain = NULL;
1268 dns_include_t *include = NULL;
1269
1270 REQUIRE(DNS_ZONE_VALID(zone));
1271 REQUIRE(!LOCKED_ZONE(zone));
1272 REQUIRE(zone->timer == NULL);
1273 REQUIRE(zone->zmgr == NULL);
1274
1275 isc_refcount_destroy(&zone->references);
1276 isc_refcount_destroy(&zone->irefs);
1277
1278 /*
1279 * Managed objects. Order is important.
1280 */
1281 if (zone->request != NULL) {
1282 dns_request_destroy(&zone->request); /* XXXMPA */
1283 }
1284 INSIST(zone->statelist == NULL);
1285 INSIST(zone->view == NULL);
1286 INSIST(zone->prev_view == NULL);
1287
1288 /* Unmanaged objects */
1289 for (struct np3 *npe = ISC_LIST_HEAD(zone->setnsec3param_queue);
1290 npe != NULL; npe = ISC_LIST_HEAD(zone->setnsec3param_queue))
1291 {
1292 ISC_LIST_UNLINK(zone->setnsec3param_queue, npe, link);
1293 isc_mem_put(zone->mctx, npe, sizeof(*npe));
1294 }
1295
1296 for (signing = ISC_LIST_HEAD(zone->signing); signing != NULL;
1297 signing = ISC_LIST_HEAD(zone->signing))
1298 {
1299 ISC_LIST_UNLINK(zone->signing, signing, link);
1300 dns_db_detach(&signing->db);
1301 dns_dbiterator_destroy(&signing->dbiterator);
1302 isc_mem_put(zone->mctx, signing, sizeof *signing);
1303 }
1304 for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain); nsec3chain != NULL;
1305 nsec3chain = ISC_LIST_HEAD(zone->nsec3chain))
1306 {
1307 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
1308 dns_db_detach(&nsec3chain->db);
1309 dns_dbiterator_destroy(&nsec3chain->dbiterator);
1310 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
1311 }
1312 for (include = ISC_LIST_HEAD(zone->includes); include != NULL;
1313 include = ISC_LIST_HEAD(zone->includes))
1314 {
1315 ISC_LIST_UNLINK(zone->includes, include, link);
1316 isc_mem_free(zone->mctx, include->name);
1317 isc_mem_put(zone->mctx, include, sizeof *include);
1318 }
1319 for (include = ISC_LIST_HEAD(zone->newincludes); include != NULL;
1320 include = ISC_LIST_HEAD(zone->newincludes))
1321 {
1322 ISC_LIST_UNLINK(zone->newincludes, include, link);
1323 isc_mem_free(zone->mctx, include->name);
1324 isc_mem_put(zone->mctx, include, sizeof *include);
1325 }
1326 if (zone->masterfile != NULL) {
1327 isc_mem_free(zone->mctx, zone->masterfile);
1328 }
1329 zone->masterfile = NULL;
1330 if (zone->keydirectory != NULL) {
1331 isc_mem_free(zone->mctx, zone->keydirectory);
1332 }
1333 zone->keydirectory = NULL;
1334 if (zone->kasp != NULL) {
1335 dns_kasp_detach(&zone->kasp);
1336 }
1337 if (zone->defaultkasp != NULL) {
1338 dns_kasp_detach(&zone->defaultkasp);
1339 }
1340 if (!ISC_LIST_EMPTY(zone->keyring)) {
1341 clear_keylist(&zone->keyring, zone->mctx);
1342 }
1343 if (!ISC_LIST_EMPTY(zone->checkds_ok)) {
1344 clear_keylist(&zone->checkds_ok, zone->mctx);
1345 }
1346 if (zone->skr != NULL) {
1347 zone->skrbundle = NULL;
1348 dns_skr_detach(&zone->skr);
1349 }
1350
1351 zone->journalsize = -1;
1352 if (zone->journal != NULL) {
1353 isc_mem_free(zone->mctx, zone->journal);
1354 }
1355 zone->journal = NULL;
1356 if (zone->stats != NULL) {
1357 isc_stats_detach(&zone->stats);
1358 }
1359 if (zone->requeststats != NULL) {
1360 isc_stats_detach(&zone->requeststats);
1361 }
1362 if (zone->rcvquerystats != NULL) {
1363 dns_stats_detach(&zone->rcvquerystats);
1364 }
1365 if (zone->dnssecsignstats != NULL) {
1366 dns_stats_detach(&zone->dnssecsignstats);
1367 }
1368 if (zone->db != NULL) {
1369 zone_detachdb(zone);
1370 }
1371 if (zone->rpzs != NULL) {
1372 REQUIRE(zone->rpz_num < zone->rpzs->p.num_zones);
1373 dns_rpz_zones_detach(&zone->rpzs);
1374 zone->rpz_num = DNS_RPZ_INVALID_NUM;
1375 }
1376 if (zone->catzs != NULL) {
1377 dns_catz_zones_detach(&zone->catzs);
1378 }
1379 zone_freedbargs(zone);
1380
1381 dns_zone_setparentals(zone, NULL, NULL, NULL, NULL, 0);
1382 dns_zone_setprimaries(zone, NULL, NULL, NULL, NULL, 0);
1383 dns_zone_setalsonotify(zone, NULL, NULL, NULL, NULL, 0);
1384
1385 zone->check_names = dns_severity_ignore;
1386 if (zone->update_acl != NULL) {
1387 dns_acl_detach(&zone->update_acl);
1388 }
1389 if (zone->forward_acl != NULL) {
1390 dns_acl_detach(&zone->forward_acl);
1391 }
1392 if (zone->notify_acl != NULL) {
1393 dns_acl_detach(&zone->notify_acl);
1394 }
1395 if (zone->query_acl != NULL) {
1396 dns_acl_detach(&zone->query_acl);
1397 }
1398 if (zone->queryon_acl != NULL) {
1399 dns_acl_detach(&zone->queryon_acl);
1400 }
1401 if (zone->xfr_acl != NULL) {
1402 dns_acl_detach(&zone->xfr_acl);
1403 }
1404 if (dns_name_dynamic(&zone->origin)) {
1405 dns_name_free(&zone->origin, zone->mctx);
1406 }
1407 if (zone->strnamerd != NULL) {
1408 isc_mem_free(zone->mctx, zone->strnamerd);
1409 }
1410 if (zone->strname != NULL) {
1411 isc_mem_free(zone->mctx, zone->strname);
1412 }
1413 if (zone->strrdclass != NULL) {
1414 isc_mem_free(zone->mctx, zone->strrdclass);
1415 }
1416 if (zone->strviewname != NULL) {
1417 isc_mem_free(zone->mctx, zone->strviewname);
1418 }
1419 if (zone->ssutable != NULL) {
1420 dns_ssutable_detach(&zone->ssutable);
1421 }
1422 if (zone->gluecachestats != NULL) {
1423 isc_stats_detach(&zone->gluecachestats);
1424 }
1425
1426 /* last stuff */
1427 ZONEDB_DESTROYLOCK(&zone->dblock);
1428 isc_mutex_destroy(&zone->lock);
1429 #ifndef _LP64
1430 isc_mutex_destroy(&zone->atomic_lock);
1431 #endif
1432 zone->magic = 0;
1433 isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
1434 }
1435
1436 /*
1437 * Returns true iff this the signed side of an inline-signing zone.
1438 * Caller should hold zone lock.
1439 */
1440 static bool
1441 inline_secure(dns_zone_t *zone) {
1442 REQUIRE(DNS_ZONE_VALID(zone));
1443 if (zone->raw != NULL) {
1444 return true;
1445 }
1446 return false;
1447 }
1448
1449 /*
1450 * Returns true iff this the unsigned side of an inline-signing zone
1451 * Caller should hold zone lock.
1452 */
1453 static bool
1454 inline_raw(dns_zone_t *zone) {
1455 REQUIRE(DNS_ZONE_VALID(zone));
1456 if (zone->secure != NULL) {
1457 return true;
1458 }
1459 return false;
1460 }
1461
1462 /*
1463 * Single shot.
1464 */
1465 void
1466 dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
1467 char namebuf[1024];
1468
1469 REQUIRE(DNS_ZONE_VALID(zone));
1470 REQUIRE(rdclass != dns_rdataclass_none);
1471
1472 /*
1473 * Test and set.
1474 */
1475 LOCK_ZONE(zone);
1476 INSIST(zone != zone->raw);
1477 REQUIRE(zone->rdclass == dns_rdataclass_none ||
1478 zone->rdclass == rdclass);
1479 zone->rdclass = rdclass;
1480
1481 if (zone->strnamerd != NULL) {
1482 isc_mem_free(zone->mctx, zone->strnamerd);
1483 }
1484 if (zone->strrdclass != NULL) {
1485 isc_mem_free(zone->mctx, zone->strrdclass);
1486 }
1487
1488 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1489 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1490 zone_rdclass_tostr(zone, namebuf, sizeof namebuf);
1491 zone->strrdclass = isc_mem_strdup(zone->mctx, namebuf);
1492
1493 if (inline_secure(zone)) {
1494 dns_zone_setclass(zone->raw, rdclass);
1495 }
1496 UNLOCK_ZONE(zone);
1497 }
1498
1499 dns_rdataclass_t
1500 dns_zone_getclass(dns_zone_t *zone) {
1501 REQUIRE(DNS_ZONE_VALID(zone));
1502
1503 return zone->rdclass;
1504 }
1505
1506 void
1507 dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
1508 REQUIRE(DNS_ZONE_VALID(zone));
1509
1510 LOCK_ZONE(zone);
1511 zone->notifytype = notifytype;
1512 UNLOCK_ZONE(zone);
1513 }
1514
1515 void
1516 dns_zone_setcheckdstype(dns_zone_t *zone, dns_checkdstype_t checkdstype) {
1517 REQUIRE(DNS_ZONE_VALID(zone));
1518
1519 LOCK_ZONE(zone);
1520 zone->checkdstype = checkdstype;
1521 UNLOCK_ZONE(zone);
1522 }
1523
1524 isc_result_t
1525 dns_zone_getserial(dns_zone_t *zone, uint32_t *serialp) {
1526 isc_result_t result;
1527 unsigned int soacount;
1528
1529 REQUIRE(DNS_ZONE_VALID(zone));
1530 REQUIRE(serialp != NULL);
1531
1532 LOCK_ZONE(zone);
1533 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1534 if (zone->db != NULL) {
1535 result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL,
1536 serialp, NULL, NULL, NULL, NULL,
1537 NULL);
1538 if (result == ISC_R_SUCCESS && soacount == 0) {
1539 result = ISC_R_FAILURE;
1540 }
1541 } else {
1542 result = DNS_R_NOTLOADED;
1543 }
1544 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1545 UNLOCK_ZONE(zone);
1546
1547 return result;
1548 }
1549
1550 /*
1551 * Single shot.
1552 */
1553 void
1554 dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) {
1555 char namebuf[1024];
1556
1557 REQUIRE(DNS_ZONE_VALID(zone));
1558 REQUIRE(type != dns_zone_none);
1559
1560 /*
1561 * Test and set.
1562 */
1563 LOCK_ZONE(zone);
1564 REQUIRE(zone->type == dns_zone_none || zone->type == type);
1565 zone->type = type;
1566
1567 if (zone->strnamerd != NULL) {
1568 isc_mem_free(zone->mctx, zone->strnamerd);
1569 }
1570
1571 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1572 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1573 UNLOCK_ZONE(zone);
1574 }
1575
1576 static void
1577 zone_freedbargs(dns_zone_t *zone) {
1578 unsigned int i;
1579
1580 /* Free the old database argument list. */
1581 if (zone->db_argv != NULL) {
1582 for (i = 0; i < zone->db_argc; i++) {
1583 isc_mem_free(zone->mctx, zone->db_argv[i]);
1584 }
1585 isc_mem_cput(zone->mctx, zone->db_argv, zone->db_argc,
1586 sizeof(*zone->db_argv));
1587 }
1588 zone->db_argc = 0;
1589 zone->db_argv = NULL;
1590 }
1591
1592 isc_result_t
1593 dns_zone_getdbtype(dns_zone_t *zone, char ***argv, isc_mem_t *mctx) {
1594 size_t size = 0;
1595 unsigned int i;
1596 isc_result_t result = ISC_R_SUCCESS;
1597 void *mem;
1598 char **tmp, *tmp2, *base;
1599
1600 REQUIRE(DNS_ZONE_VALID(zone));
1601 REQUIRE(argv != NULL && *argv == NULL);
1602
1603 LOCK_ZONE(zone);
1604 size = ISC_CHECKED_MUL(zone->db_argc + 1, sizeof(char *));
1605 for (i = 0; i < zone->db_argc; i++) {
1606 size += strlen(zone->db_argv[i]) + 1;
1607 }
1608 mem = isc_mem_allocate(mctx, size);
1609 {
1610 tmp = mem;
1611 tmp2 = mem;
1612 base = mem;
1613 tmp2 += ISC_CHECKED_MUL(zone->db_argc + 1, sizeof(char *));
1614 for (i = 0; i < zone->db_argc; i++) {
1615 *tmp++ = tmp2;
1616 strlcpy(tmp2, zone->db_argv[i], size - (tmp2 - base));
1617 tmp2 += strlen(tmp2) + 1;
1618 }
1619 *tmp = NULL;
1620 }
1621 UNLOCK_ZONE(zone);
1622 *argv = mem;
1623 return result;
1624 }
1625
1626 void
1627 dns_zone_setdbtype(dns_zone_t *zone, unsigned int dbargc,
1628 const char *const *dbargv) {
1629 char **argv = NULL;
1630 unsigned int i;
1631
1632 REQUIRE(DNS_ZONE_VALID(zone));
1633 REQUIRE(dbargc >= 1);
1634 REQUIRE(dbargv != NULL);
1635
1636 LOCK_ZONE(zone);
1637
1638 /* Set up a new database argument list. */
1639 argv = isc_mem_cget(zone->mctx, dbargc, sizeof(*argv));
1640 for (i = 0; i < dbargc; i++) {
1641 argv[i] = NULL;
1642 }
1643 for (i = 0; i < dbargc; i++) {
1644 argv[i] = isc_mem_strdup(zone->mctx, dbargv[i]);
1645 }
1646
1647 /* Free the old list. */
1648 zone_freedbargs(zone);
1649
1650 zone->db_argc = dbargc;
1651 zone->db_argv = argv;
1652
1653 UNLOCK_ZONE(zone);
1654 }
1655
1656 static void
1657 dns_zone_setview_helper(dns_zone_t *zone, dns_view_t *view) {
1658 char namebuf[1024];
1659
1660 if (zone->prev_view == NULL && zone->view != NULL) {
1661 dns_view_weakattach(zone->view, &zone->prev_view);
1662 }
1663
1664 INSIST(zone != zone->raw);
1665 if (zone->view != NULL) {
1666 dns_view_sfd_del(zone->view, &zone->origin);
1667 dns_view_weakdetach(&zone->view);
1668 }
1669 dns_view_weakattach(view, &zone->view);
1670 dns_view_sfd_add(view, &zone->origin);
1671
1672 if (zone->strviewname != NULL) {
1673 isc_mem_free(zone->mctx, zone->strviewname);
1674 }
1675 if (zone->strnamerd != NULL) {
1676 isc_mem_free(zone->mctx, zone->strnamerd);
1677 }
1678
1679 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1680 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1681 zone_viewname_tostr(zone, namebuf, sizeof namebuf);
1682 zone->strviewname = isc_mem_strdup(zone->mctx, namebuf);
1683
1684 if (inline_secure(zone)) {
1685 dns_zone_setview(zone->raw, view);
1686 }
1687 }
1688
1689 void
1690 dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
1691 REQUIRE(DNS_ZONE_VALID(zone));
1692
1693 LOCK_ZONE(zone);
1694 dns_zone_setview_helper(zone, view);
1695 UNLOCK_ZONE(zone);
1696 }
1697
1698 dns_view_t *
1699 dns_zone_getview(dns_zone_t *zone) {
1700 REQUIRE(DNS_ZONE_VALID(zone));
1701
1702 return zone->view;
1703 }
1704
1705 void
1706 dns_zone_setviewcommit(dns_zone_t *zone) {
1707 REQUIRE(DNS_ZONE_VALID(zone));
1708
1709 LOCK_ZONE(zone);
1710 if (zone->prev_view != NULL) {
1711 dns_view_weakdetach(&zone->prev_view);
1712 }
1713 if (inline_secure(zone)) {
1714 dns_zone_setviewcommit(zone->raw);
1715 }
1716 UNLOCK_ZONE(zone);
1717 }
1718
1719 void
1720 dns_zone_setviewrevert(dns_zone_t *zone) {
1721 REQUIRE(DNS_ZONE_VALID(zone));
1722
1723 LOCK_ZONE(zone);
1724 if (zone->prev_view != NULL) {
1725 dns_zone_setview_helper(zone, zone->prev_view);
1726 dns_view_weakdetach(&zone->prev_view);
1727 }
1728 if (zone->catzs != NULL) {
1729 zone_catz_enable(zone, zone->catzs);
1730 }
1731 if (inline_secure(zone)) {
1732 dns_zone_setviewrevert(zone->raw);
1733 }
1734 UNLOCK_ZONE(zone);
1735 }
1736
1737 isc_result_t
1738 dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
1739 isc_result_t result = ISC_R_SUCCESS;
1740 char namebuf[1024];
1741
1742 REQUIRE(DNS_ZONE_VALID(zone));
1743 REQUIRE(origin != NULL);
1744
1745 LOCK_ZONE(zone);
1746 INSIST(zone != zone->raw);
1747 if (dns_name_dynamic(&zone->origin)) {
1748 dns_name_free(&zone->origin, zone->mctx);
1749 dns_name_init(&zone->origin, NULL);
1750 }
1751 dns_name_dup(origin, zone->mctx, &zone->origin);
1752
1753 if (zone->strnamerd != NULL) {
1754 isc_mem_free(zone->mctx, zone->strnamerd);
1755 }
1756 if (zone->strname != NULL) {
1757 isc_mem_free(zone->mctx, zone->strname);
1758 }
1759
1760 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1761 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1762 zone_name_tostr(zone, namebuf, sizeof namebuf);
1763 zone->strname = isc_mem_strdup(zone->mctx, namebuf);
1764
1765 if (inline_secure(zone)) {
1766 result = dns_zone_setorigin(zone->raw, origin);
1767 }
1768 UNLOCK_ZONE(zone);
1769 return result;
1770 }
1771
1772 static isc_result_t
1773 dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
1774 char *copy;
1775
1776 if (value != NULL) {
1777 copy = isc_mem_strdup(zone->mctx, value);
1778 } else {
1779 copy = NULL;
1780 }
1781
1782 if (*field != NULL) {
1783 isc_mem_free(zone->mctx, *field);
1784 }
1785
1786 *field = copy;
1787 return ISC_R_SUCCESS;
1788 }
1789
1790 isc_result_t
1791 dns_zone_setfile(dns_zone_t *zone, const char *file, dns_masterformat_t format,
1792 const dns_master_style_t *style) {
1793 isc_result_t result = ISC_R_SUCCESS;
1794
1795 REQUIRE(DNS_ZONE_VALID(zone));
1796 REQUIRE(zone->stream == NULL);
1797
1798 LOCK_ZONE(zone);
1799 result = dns_zone_setstring(zone, &zone->masterfile, file);
1800 if (result == ISC_R_SUCCESS) {
1801 zone->masterformat = format;
1802 if (format == dns_masterformat_text) {
1803 zone->masterstyle = style;
1804 }
1805 result = default_journal(zone);
1806 }
1807 UNLOCK_ZONE(zone);
1808
1809 return result;
1810 }
1811
1812 const char *
1813 dns_zone_getfile(dns_zone_t *zone) {
1814 REQUIRE(DNS_ZONE_VALID(zone));
1815
1816 return zone->masterfile;
1817 }
1818
1819 isc_result_t
1820 dns_zone_setstream(dns_zone_t *zone, const FILE *stream,
1821 dns_masterformat_t format, const dns_master_style_t *style) {
1822 isc_result_t result = ISC_R_SUCCESS;
1823
1824 REQUIRE(DNS_ZONE_VALID(zone));
1825 REQUIRE(stream != NULL);
1826 REQUIRE(zone->masterfile == NULL);
1827
1828 LOCK_ZONE(zone);
1829 zone->stream = stream;
1830 zone->masterformat = format;
1831 if (format == dns_masterformat_text) {
1832 zone->masterstyle = style;
1833 }
1834 result = default_journal(zone);
1835 UNLOCK_ZONE(zone);
1836
1837 return result;
1838 }
1839
1840 dns_ttl_t
1841 dns_zone_getmaxttl(dns_zone_t *zone) {
1842 REQUIRE(DNS_ZONE_VALID(zone));
1843
1844 return zone->maxttl;
1845 }
1846
1847 void
1848 dns_zone_setmaxttl(dns_zone_t *zone, dns_ttl_t maxttl) {
1849 REQUIRE(DNS_ZONE_VALID(zone));
1850
1851 LOCK_ZONE(zone);
1852 if (maxttl != 0) {
1853 DNS_ZONE_SETOPTION(zone, DNS_ZONEOPT_CHECKTTL);
1854 } else {
1855 DNS_ZONE_CLROPTION(zone, DNS_ZONEOPT_CHECKTTL);
1856 }
1857 zone->maxttl = maxttl;
1858 UNLOCK_ZONE(zone);
1859
1860 return;
1861 }
1862
1863 static isc_result_t
1864 default_journal(dns_zone_t *zone) {
1865 isc_result_t result;
1866 char *journal;
1867
1868 REQUIRE(DNS_ZONE_VALID(zone));
1869 REQUIRE(LOCKED_ZONE(zone));
1870
1871 if (zone->masterfile != NULL) {
1872 /* Calculate string length including '\0'. */
1873 int len = strlen(zone->masterfile) + sizeof(".jnl");
1874 journal = isc_mem_allocate(zone->mctx, len);
1875 strlcpy(journal, zone->masterfile, len);
1876 strlcat(journal, ".jnl", len);
1877 } else {
1878 journal = NULL;
1879 }
1880 result = dns_zone_setstring(zone, &zone->journal, journal);
1881 if (journal != NULL) {
1882 isc_mem_free(zone->mctx, journal);
1883 }
1884 return result;
1885 }
1886
1887 isc_result_t
1888 dns_zone_setjournal(dns_zone_t *zone, const char *myjournal) {
1889 isc_result_t result = ISC_R_SUCCESS;
1890
1891 REQUIRE(DNS_ZONE_VALID(zone));
1892
1893 LOCK_ZONE(zone);
1894 result = dns_zone_setstring(zone, &zone->journal, myjournal);
1895 UNLOCK_ZONE(zone);
1896
1897 return result;
1898 }
1899
1900 char *
1901 dns_zone_getjournal(dns_zone_t *zone) {
1902 REQUIRE(DNS_ZONE_VALID(zone));
1903
1904 return zone->journal;
1905 }
1906
1907 /*
1908 * Return true iff the zone is "dynamic", in the sense that the zone's
1909 * master file (if any) is written by the server, rather than being
1910 * updated manually and read by the server.
1911 *
1912 * This is true for secondary zones, mirror zones, stub zones, key zones,
1913 * and zones that allow dynamic updates either by having an update
1914 * policy ("ssutable") or an "allow-update" ACL with a value other than
1915 * exactly "{ none; }".
1916 */
1917 bool
1918 dns_zone_isdynamic(dns_zone_t *zone, bool ignore_freeze) {
1919 REQUIRE(DNS_ZONE_VALID(zone));
1920
1921 if (zone->type == dns_zone_secondary || zone->type == dns_zone_mirror ||
1922 zone->type == dns_zone_stub || zone->type == dns_zone_key ||
1923 (zone->type == dns_zone_redirect &&
1924 dns_remote_addresses(&zone->primaries) != NULL))
1925 {
1926 return true;
1927 }
1928
1929 /* Inline zones are always dynamic. */
1930 if (zone->type == dns_zone_primary && zone->raw != NULL) {
1931 return true;
1932 }
1933
1934 /* If !ignore_freeze, we need check whether updates are disabled. */
1935 if (zone->type == dns_zone_primary &&
1936 (!zone->update_disabled || ignore_freeze) &&
1937 ((zone->ssutable != NULL) ||
1938 (zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl))))
1939 {
1940 return true;
1941 }
1942
1943 return false;
1944 }
1945
1946 /*
1947 * Set the response policy index and information for a zone.
1948 */
1949 isc_result_t
1950 dns_zone_rpz_enable(dns_zone_t *zone, dns_rpz_zones_t *rpzs,
1951 dns_rpz_num_t rpz_num) {
1952 /*
1953 * This must happen only once or be redundant.
1954 */
1955 LOCK_ZONE(zone);
1956 if (zone->rpzs != NULL) {
1957 REQUIRE(zone->rpzs == rpzs && zone->rpz_num == rpz_num);
1958 } else {
1959 REQUIRE(zone->rpz_num == DNS_RPZ_INVALID_NUM);
1960 dns_rpz_zones_attach(rpzs, &zone->rpzs);
1961 zone->rpz_num = rpz_num;
1962 }
1963 rpzs->defined |= DNS_RPZ_ZBIT(rpz_num);
1964 UNLOCK_ZONE(zone);
1965
1966 return ISC_R_SUCCESS;
1967 }
1968
1969 dns_rpz_num_t
1970 dns_zone_get_rpz_num(dns_zone_t *zone) {
1971 return zone->rpz_num;
1972 }
1973
1974 /*
1975 * If a zone is a response policy zone, mark its new database.
1976 */
1977 void
1978 dns_zone_rpz_enable_db(dns_zone_t *zone, dns_db_t *db) {
1979 if (zone->rpz_num == DNS_RPZ_INVALID_NUM) {
1980 return;
1981 }
1982 REQUIRE(zone->rpzs != NULL);
1983 dns_rpz_dbupdate_register(db, zone->rpzs->zones[zone->rpz_num]);
1984 }
1985
1986 static void
1987 dns_zone_rpz_disable_db(dns_zone_t *zone, dns_db_t *db) {
1988 if (zone->rpz_num == DNS_RPZ_INVALID_NUM) {
1989 return;
1990 }
1991 REQUIRE(zone->rpzs != NULL);
1992 dns_rpz_dbupdate_unregister(db, zone->rpzs->zones[zone->rpz_num]);
1993 }
1994
1995 /*
1996 * If a zone is a catalog zone, attach it to update notification in database.
1997 */
1998 void
1999 dns_zone_catz_enable_db(dns_zone_t *zone, dns_db_t *db) {
2000 REQUIRE(DNS_ZONE_VALID(zone));
2001 REQUIRE(db != NULL);
2002
2003 if (zone->catzs != NULL) {
2004 dns_catz_dbupdate_register(db, zone->catzs);
2005 }
2006 }
2007
2008 static void
2009 dns_zone_catz_disable_db(dns_zone_t *zone, dns_db_t *db) {
2010 REQUIRE(DNS_ZONE_VALID(zone));
2011 REQUIRE(db != NULL);
2012
2013 if (zone->catzs != NULL) {
2014 dns_catz_dbupdate_unregister(db, zone->catzs);
2015 }
2016 }
2017
2018 static void
2019 zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs) {
2020 REQUIRE(DNS_ZONE_VALID(zone));
2021 REQUIRE(catzs != NULL);
2022
2023 INSIST(zone->catzs == NULL || zone->catzs == catzs);
2024 dns_catz_catzs_set_view(catzs, zone->view);
2025 if (zone->catzs == NULL) {
2026 dns_catz_zones_attach(catzs, &zone->catzs);
2027 }
2028 }
2029
2030 void
2031 dns_zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs) {
2032 REQUIRE(DNS_ZONE_VALID(zone));
2033
2034 LOCK_ZONE(zone);
2035 zone_catz_enable(zone, catzs);
2036 UNLOCK_ZONE(zone);
2037 }
2038
2039 static void
2040 zone_catz_disable(dns_zone_t *zone) {
2041 REQUIRE(DNS_ZONE_VALID(zone));
2042
2043 if (zone->catzs != NULL) {
2044 if (zone->db != NULL) {
2045 dns_zone_catz_disable_db(zone, zone->db);
2046 }
2047 dns_catz_zones_detach(&zone->catzs);
2048 }
2049 }
2050
2051 void
2052 dns_zone_catz_disable(dns_zone_t *zone) {
2053 REQUIRE(DNS_ZONE_VALID(zone));
2054
2055 LOCK_ZONE(zone);
2056 zone_catz_disable(zone);
2057 UNLOCK_ZONE(zone);
2058 }
2059
2060 bool
2061 dns_zone_catz_is_enabled(dns_zone_t *zone) {
2062 REQUIRE(DNS_ZONE_VALID(zone));
2063
2064 return zone->catzs != NULL;
2065 }
2066
2067 /*
2068 * Set catalog zone ownership of the zone
2069 */
2070 void
2071 dns_zone_set_parentcatz(dns_zone_t *zone, dns_catz_zone_t *catz) {
2072 REQUIRE(DNS_ZONE_VALID(zone));
2073 REQUIRE(catz != NULL);
2074 LOCK_ZONE(zone);
2075 INSIST(zone->parentcatz == NULL || zone->parentcatz == catz);
2076 zone->parentcatz = catz;
2077 UNLOCK_ZONE(zone);
2078 }
2079
2080 dns_catz_zone_t *
2081 dns_zone_get_parentcatz(dns_zone_t *zone) {
2082 REQUIRE(DNS_ZONE_VALID(zone));
2083
2084 dns_catz_zone_t *parentcatz = NULL;
2085
2086 LOCK_ZONE(zone);
2087 parentcatz = zone->parentcatz;
2088 UNLOCK_ZONE(zone);
2089
2090 return parentcatz;
2091 }
2092
2093 static bool
2094 zone_touched(dns_zone_t *zone) {
2095 isc_result_t result;
2096 isc_time_t modtime;
2097 dns_include_t *include;
2098
2099 REQUIRE(DNS_ZONE_VALID(zone));
2100
2101 result = isc_file_getmodtime(zone->masterfile, &modtime);
2102 if (result != ISC_R_SUCCESS ||
2103 isc_time_compare(&modtime, &zone->loadtime) > 0)
2104 {
2105 return true;
2106 }
2107
2108 for (include = ISC_LIST_HEAD(zone->includes); include != NULL;
2109 include = ISC_LIST_NEXT(include, link))
2110 {
2111 result = isc_file_getmodtime(include->name, &modtime);
2112 if (result != ISC_R_SUCCESS ||
2113 isc_time_compare(&modtime, &include->filetime) > 0)
2114 {
2115 return true;
2116 }
2117 }
2118
2119 return false;
2120 }
2121
2122 /*
2123 * Note: when dealing with inline-signed zones, external callers will always
2124 * call zone_load() for the secure zone; zone_load() calls itself recursively
2125 * in order to load the raw zone.
2126 */
2127 static isc_result_t
2128 zone_load(dns_zone_t *zone, unsigned int flags, bool locked) {
2129 isc_result_t result;
2130 isc_time_t now;
2131 isc_time_t loadtime;
2132 dns_db_t *db = NULL;
2133 bool rbt, hasraw, is_dynamic;
2134
2135 REQUIRE(DNS_ZONE_VALID(zone));
2136
2137 if (!locked) {
2138 LOCK_ZONE(zone);
2139 }
2140
2141 INSIST(zone != zone->raw);
2142 hasraw = inline_secure(zone);
2143 if (hasraw) {
2144 /*
2145 * We are trying to load an inline-signed zone. First call
2146 * self recursively to try loading the raw version of the zone.
2147 * Assuming the raw zone file is readable, there are two
2148 * possibilities:
2149 *
2150 * a) the raw zone was not yet loaded and thus it will be
2151 * loaded now, synchronously; if this succeeds, a
2152 * subsequent attempt to load the signed zone file will
2153 * take place and thus zone_postload() will be called
2154 * twice: first for the raw zone and then for the secure
2155 * zone; the latter call will take care of syncing the raw
2156 * version with the secure version,
2157 *
2158 * b) the raw zone was already loaded and we are trying to
2159 * reload it, which will happen asynchronously; this means
2160 * zone_postload() will only be called for the raw zone
2161 * because "result" returned by the zone_load() call below
2162 * will not be ISC_R_SUCCESS but rather DNS_R_CONTINUE;
2163 * zone_postload() called for the raw zone will take care
2164 * of syncing the raw version with the secure version.
2165 */
2166 result = zone_load(zone->raw, flags, false);
2167 if (result != ISC_R_SUCCESS) {
2168 if (!locked) {
2169 UNLOCK_ZONE(zone);
2170 }
2171 return result;
2172 }
2173 LOCK_ZONE(zone->raw);
2174 }
2175
2176 now = isc_time_now();
2177
2178 INSIST(zone->type != dns_zone_none);
2179
2180 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
2181 if ((flags & DNS_ZONELOADFLAG_THAW) != 0) {
2182 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
2183 }
2184 result = DNS_R_CONTINUE;
2185 goto cleanup;
2186 }
2187
2188 INSIST(zone->db_argc >= 1);
2189
2190 rbt = strcmp(zone->db_argv[0], ZONEDB_DEFAULT) == 0;
2191
2192 if (zone->db != NULL && zone->masterfile == NULL && rbt) {
2193 /*
2194 * The zone has no master file configured.
2195 */
2196 result = ISC_R_SUCCESS;
2197 goto cleanup;
2198 }
2199
2200 is_dynamic = dns_zone_isdynamic(zone, false);
2201 if (zone->db != NULL && is_dynamic) {
2202 /*
2203 * This is a secondary, stub, or dynamically updated zone
2204 * being reloaded. Do nothing - the database we already
2205 * have is guaranteed to be up-to-date.
2206 */
2207 if (zone->type == dns_zone_primary && !hasraw) {
2208 result = DNS_R_DYNAMIC;
2209 } else {
2210 result = ISC_R_SUCCESS;
2211 }
2212 goto cleanup;
2213 }
2214
2215 /*
2216 * Store the current time before the zone is loaded, so that if the
2217 * file changes between the time of the load and the time that
2218 * zone->loadtime is set, then the file will still be reloaded
2219 * the next time dns_zone_load is called.
2220 */
2221 loadtime = isc_time_now();
2222
2223 /*
2224 * Don't do the load if the file that stores the zone is older
2225 * than the last time the zone was loaded. If the zone has not
2226 * been loaded yet, zone->loadtime will be the epoch.
2227 */
2228 if (zone->masterfile != NULL) {
2229 isc_time_t filetime;
2230
2231 /*
2232 * The file is already loaded. If we are just doing a
2233 * "rndc reconfig", we are done.
2234 */
2235 if (!isc_time_isepoch(&zone->loadtime) &&
2236 (flags & DNS_ZONELOADFLAG_NOSTAT) != 0)
2237 {
2238 result = ISC_R_SUCCESS;
2239 goto cleanup;
2240 }
2241
2242 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
2243 !zone_touched(zone))
2244 {
2245 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2246 ISC_LOG_DEBUG(1),
2247 "skipping load: master file "
2248 "older than last load");
2249 result = DNS_R_UPTODATE;
2250 goto cleanup;
2251 }
2252
2253 /*
2254 * If the file modification time is in the past
2255 * set loadtime to that value.
2256 */
2257 result = isc_file_getmodtime(zone->masterfile, &filetime);
2258 if (result == ISC_R_SUCCESS &&
2259 isc_time_compare(&loadtime, &filetime) > 0)
2260 {
2261 loadtime = filetime;
2262 }
2263 }
2264
2265 /*
2266 * Built in zones (with the exception of empty zones) don't need
2267 * to be reloaded.
2268 */
2269 if (zone->type == dns_zone_primary &&
2270 strcmp(zone->db_argv[0], "_builtin") == 0 &&
2271 (zone->db_argc < 2 || strcmp(zone->db_argv[1], "empty") != 0) &&
2272 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
2273 {
2274 result = ISC_R_SUCCESS;
2275 goto cleanup;
2276 }
2277
2278 /*
2279 * Zones associated with a DLZ don't need to be loaded either,
2280 * but we need to associate the database with the zone object.
2281 */
2282 if (strcmp(zone->db_argv[0], "dlz") == 0) {
2283 dns_dlzdb_t *dlzdb;
2284 dns_dlzfindzone_t findzone;
2285
2286 for (dlzdb = ISC_LIST_HEAD(zone->view->dlz_unsearched);
2287 dlzdb != NULL; dlzdb = ISC_LIST_NEXT(dlzdb, link))
2288 {
2289 INSIST(DNS_DLZ_VALID(dlzdb));
2290 if (strcmp(zone->db_argv[1], dlzdb->dlzname) == 0) {
2291 break;
2292 }
2293 }
2294
2295 if (dlzdb == NULL) {
2296 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2297 ISC_LOG_ERROR,
2298 "DLZ %s does not exist or is set "
2299 "to 'search yes;'",
2300 zone->db_argv[1]);
2301 result = ISC_R_NOTFOUND;
2302 goto cleanup;
2303 }
2304
2305 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
2306 /* ask SDLZ driver if the zone is supported */
2307 findzone = dlzdb->implementation->methods->findzone;
2308 result = (*findzone)(dlzdb->implementation->driverarg,
2309 dlzdb->dbdata, dlzdb->mctx,
2310 zone->view->rdclass, &zone->origin, NULL,
2311 NULL, &db);
2312 if (result != ISC_R_NOTFOUND) {
2313 if (zone->db != NULL) {
2314 zone_detachdb(zone);
2315 }
2316 zone_attachdb(zone, db);
2317 dns_db_detach(&db);
2318 result = ISC_R_SUCCESS;
2319 }
2320 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
2321
2322 if (result == ISC_R_SUCCESS) {
2323 if (dlzdb->configure_callback == NULL) {
2324 goto cleanup;
2325 }
2326
2327 result = (*dlzdb->configure_callback)(zone->view, dlzdb,
2328 zone);
2329 if (result != ISC_R_SUCCESS) {
2330 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2331 ISC_LOG_ERROR,
2332 "DLZ configuration callback: %s",
2333 isc_result_totext(result));
2334 }
2335 }
2336 goto cleanup;
2337 }
2338
2339 if ((zone->type == dns_zone_secondary ||
2340 zone->type == dns_zone_mirror || zone->type == dns_zone_stub ||
2341 (zone->type == dns_zone_redirect &&
2342 dns_remote_addresses(&zone->primaries) != NULL)) &&
2343 rbt)
2344 {
2345 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FIRSTREFRESH);
2346
2347 if (zone->stream == NULL &&
2348 (zone->masterfile == NULL ||
2349 !isc_file_exists(zone->masterfile)))
2350 {
2351 if (zone->masterfile != NULL) {
2352 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2353 ISC_LOG_DEBUG(1),
2354 "no master file");
2355 }
2356 zone->refreshtime = now;
2357 if (zone->loop != NULL) {
2358 zone_settimer(zone, &now);
2359 }
2360 result = ISC_R_SUCCESS;
2361 goto cleanup;
2362 }
2363 }
2364
2365 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
2366 "starting load");
2367
2368 result = dns_zone_makedb(zone, &db);
2369 if (result != ISC_R_SUCCESS) {
2370 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
2371 "loading zone: creating database: %s",
2372 isc_result_totext(result));
2373 goto cleanup;
2374 }
2375
2376 if (!dns_db_ispersistent(db)) {
2377 if (zone->masterfile != NULL || zone->stream != NULL) {
2378 result = zone_startload(db, zone, loadtime);
2379 } else {
2380 result = DNS_R_NOMASTERFILE;
2381 if (zone->type == dns_zone_primary ||
2382 (zone->type == dns_zone_redirect &&
2383 dns_remote_addresses(&zone->primaries) == NULL))
2384 {
2385 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2386 ISC_LOG_ERROR,
2387 "loading zone: "
2388 "no master file configured");
2389 goto cleanup;
2390 }
2391 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2392 ISC_LOG_INFO,
2393 "loading zone: "
2394 "no master file configured: continuing");
2395 }
2396 }
2397
2398 if (result == DNS_R_CONTINUE) {
2399 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING);
2400 if ((flags & DNS_ZONELOADFLAG_THAW) != 0) {
2401 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
2402 }
2403 goto cleanup;
2404 }
2405
2406 result = zone_postload(zone, db, loadtime, result);
2407
2408 cleanup:
2409 if (hasraw) {
2410 UNLOCK_ZONE(zone->raw);
2411 }
2412 if (!locked) {
2413 UNLOCK_ZONE(zone);
2414 }
2415 if (db != NULL) {
2416 dns_db_detach(&db);
2417 }
2418 return result;
2419 }
2420
2421 isc_result_t
2422 dns_zone_load(dns_zone_t *zone, bool newonly) {
2423 return zone_load(zone, newonly ? DNS_ZONELOADFLAG_NOSTAT : 0, false);
2424 }
2425
2426 static void
2427 zone_asyncload(void *arg) {
2428 dns_asyncload_t *asl = arg;
2429 dns_zone_t *zone = asl->zone;
2430 isc_result_t result;
2431
2432 REQUIRE(DNS_ZONE_VALID(zone));
2433
2434 LOCK_ZONE(zone);
2435 result = zone_load(zone, asl->flags, true);
2436 if (result != DNS_R_CONTINUE) {
2437 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
2438 }
2439 UNLOCK_ZONE(zone);
2440
2441 /* Inform the zone table we've finished loading */
2442 if (asl->loaded != NULL) {
2443 asl->loaded(asl->loaded_arg);
2444 }
2445
2446 isc_mem_put(zone->mctx, asl, sizeof(*asl));
2447 dns_zone_idetach(&zone);
2448 }
2449
2450 isc_result_t
2451 dns_zone_asyncload(dns_zone_t *zone, bool newonly, dns_zt_callback_t *done,
2452 void *arg) {
2453 dns_asyncload_t *asl = NULL;
2454
2455 REQUIRE(DNS_ZONE_VALID(zone));
2456
2457 if (zone->zmgr == NULL) {
2458 return ISC_R_FAILURE;
2459 }
2460
2461 /* If we already have a load pending, stop now */
2462 LOCK_ZONE(zone);
2463 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING)) {
2464 UNLOCK_ZONE(zone);
2465 return ISC_R_ALREADYRUNNING;
2466 }
2467
2468 asl = isc_mem_get(zone->mctx, sizeof(*asl));
2469
2470 asl->zone = NULL;
2471 asl->flags = newonly ? DNS_ZONELOADFLAG_NOSTAT : 0;
2472 asl->loaded = done;
2473 asl->loaded_arg = arg;
2474
2475 zone_iattach(zone, &asl->zone);
2476 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADPENDING);
2477 isc_async_run(zone->loop, zone_asyncload, asl);
2478 UNLOCK_ZONE(zone);
2479
2480 return ISC_R_SUCCESS;
2481 }
2482
2483 bool
2484 dns__zone_loadpending(dns_zone_t *zone) {
2485 REQUIRE(DNS_ZONE_VALID(zone));
2486
2487 return DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING);
2488 }
2489
2490 isc_result_t
2491 dns_zone_loadandthaw(dns_zone_t *zone) {
2492 isc_result_t result;
2493
2494 if (inline_raw(zone)) {
2495 result = zone_load(zone->secure, DNS_ZONELOADFLAG_THAW, false);
2496 } else {
2497 /*
2498 * When thawing a zone, we don't know what changes
2499 * have been made. If we do DNSSEC maintenance on this
2500 * zone, schedule a full sign for this zone.
2501 */
2502 if (zone->type == dns_zone_primary &&
2503 DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
2504 {
2505 DNS_ZONEKEY_SETOPTION(zone, DNS_ZONEKEY_FULLSIGN);
2506 }
2507 result = zone_load(zone, DNS_ZONELOADFLAG_THAW, false);
2508 }
2509
2510 switch (result) {
2511 case DNS_R_CONTINUE:
2512 /* Deferred thaw. */
2513 break;
2514 case DNS_R_UPTODATE:
2515 case ISC_R_SUCCESS:
2516 case DNS_R_SEENINCLUDE:
2517 zone->update_disabled = false;
2518 break;
2519 case DNS_R_NOMASTERFILE:
2520 zone->update_disabled = false;
2521 break;
2522 default:
2523 /* Error, remain in disabled state. */
2524 break;
2525 }
2526 return result;
2527 }
2528
2529 static unsigned int
2530 get_primary_options(dns_zone_t *zone) {
2531 unsigned int options;
2532
2533 options = DNS_MASTER_ZONE | DNS_MASTER_RESIGN;
2534 if (zone->type == dns_zone_secondary || zone->type == dns_zone_mirror ||
2535 (zone->type == dns_zone_redirect &&
2536 dns_remote_addresses(&zone->primaries) == NULL))
2537 {
2538 options |= DNS_MASTER_SECONDARY;
2539 }
2540 if (zone->type == dns_zone_key) {
2541 options |= DNS_MASTER_KEY;
2542 }
2543 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS)) {
2544 options |= DNS_MASTER_CHECKNS;
2545 }
2546 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS)) {
2547 options |= DNS_MASTER_FATALNS;
2548 }
2549 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES)) {
2550 options |= DNS_MASTER_CHECKNAMES;
2551 }
2552 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) {
2553 options |= DNS_MASTER_CHECKNAMESFAIL;
2554 }
2555 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMX)) {
2556 options |= DNS_MASTER_CHECKMX;
2557 }
2558 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL)) {
2559 options |= DNS_MASTER_CHECKMXFAIL;
2560 }
2561 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKWILDCARD)) {
2562 options |= DNS_MASTER_CHECKWILDCARD;
2563 }
2564 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKTTL)) {
2565 options |= DNS_MASTER_CHECKTTL;
2566 }
2567 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSVCB)) {
2568 options |= DNS_MASTER_CHECKSVCB;
2569 }
2570
2571 return options;
2572 }
2573
2574 static void
2575 zone_registerinclude(const char *filename, void *arg) {
2576 isc_result_t result;
2577 dns_zone_t *zone = (dns_zone_t *)arg;
2578 dns_include_t *inc = NULL;
2579
2580 REQUIRE(DNS_ZONE_VALID(zone));
2581
2582 if (filename == NULL) {
2583 return;
2584 }
2585
2586 /*
2587 * Suppress duplicates.
2588 */
2589 for (inc = ISC_LIST_HEAD(zone->newincludes); inc != NULL;
2590 inc = ISC_LIST_NEXT(inc, link))
2591 {
2592 if (strcmp(filename, inc->name) == 0) {
2593 return;
2594 }
2595 }
2596
2597 inc = isc_mem_get(zone->mctx, sizeof(dns_include_t));
2598 inc->name = isc_mem_strdup(zone->mctx, filename);
2599 ISC_LINK_INIT(inc, link);
2600
2601 result = isc_file_getmodtime(filename, &inc->filetime);
2602 if (result != ISC_R_SUCCESS) {
2603 isc_time_settoepoch(&inc->filetime);
2604 }
2605
2606 ISC_LIST_APPEND(zone->newincludes, inc, link);
2607 }
2608
2609 static void
2610 get_raw_serial(dns_zone_t *raw, dns_masterrawheader_t *rawdata) {
2611 isc_result_t result;
2612 unsigned int soacount;
2613
2614 LOCK(&raw->lock);
2615 if (raw->db != NULL) {
2616 result = zone_get_from_db(raw, raw->db, NULL, &soacount, NULL,
2617 &rawdata->sourceserial, NULL, NULL,
2618 NULL, NULL, NULL);
2619 if (result == ISC_R_SUCCESS && soacount > 0U) {
2620 rawdata->flags |= DNS_MASTERRAW_SOURCESERIALSET;
2621 }
2622 }
2623 UNLOCK(&raw->lock);
2624 }
2625
2626 /*
2627 * Save the raw serial number for inline-signing zones.
2628 * (XXX: Other information from the header will be used
2629 * for other purposes in the future, but for now this is
2630 * all we're interested in.)
2631 */
2632 static void
2633 zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
2634 if ((header->flags & DNS_MASTERRAW_SOURCESERIALSET) == 0) {
2635 return;
2636 }
2637
2638 zone->sourceserial = header->sourceserial;
2639 zone->sourceserialset = true;
2640 }
2641
2642 void
2643 dns_zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
2644 if (zone == NULL) {
2645 return;
2646 }
2647
2648 LOCK_ZONE(zone);
2649 zone_setrawdata(zone, header);
2650 UNLOCK_ZONE(zone);
2651 }
2652
2653 static isc_result_t
2654 zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
2655 isc_result_t result;
2656 isc_result_t tresult;
2657 unsigned int options;
2658 dns_load_t *load = isc_mem_get(zone->mctx, sizeof(*load));
2659
2660 ENTER;
2661
2662 *load = (dns_load_t){
2663 .loadtime = loadtime,
2664 };
2665
2666 dns_zone_rpz_enable_db(zone, db);
2667 dns_zone_catz_enable_db(zone, db);
2668
2669 options = get_primary_options(zone);
2670 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS)) {
2671 options |= DNS_MASTER_MANYERRORS;
2672 }
2673
2674 zone_iattach(zone, &load->zone);
2675 dns_db_attach(db, &load->db);
2676
2677 dns_rdatacallbacks_init(&load->callbacks);
2678 load->callbacks.rawdata = zone_setrawdata;
2679 zone_iattach(zone, &load->callbacks.zone);
2680
2681 result = dns_db_beginload(db, &load->callbacks);
2682 if (result != ISC_R_SUCCESS) {
2683 goto cleanup;
2684 }
2685
2686 if (zone->zmgr != NULL && zone->db != NULL) {
2687 result = dns_master_loadfileasync(
2688 zone->masterfile, dns_db_origin(db), dns_db_origin(db),
2689 zone->rdclass, options, 0, &load->callbacks, zone->loop,
2690 zone_loaddone, load, &zone->loadctx,
2691 zone_registerinclude, zone, zone->mctx,
2692 zone->masterformat, zone->maxttl);
2693 if (result != ISC_R_SUCCESS) {
2694 goto cleanup;
2695 }
2696
2697 return DNS_R_CONTINUE;
2698 } else if (zone->stream != NULL) {
2699 FILE *stream = UNCONST(zone->stream);
2700 result = dns_master_loadstream(
2701 stream, &zone->origin, &zone->origin, zone->rdclass,
2702 options, &load->callbacks, zone->mctx);
2703 } else {
2704 result = dns_master_loadfile(
2705 zone->masterfile, &zone->origin, &zone->origin,
2706 zone->rdclass, options, 0, &load->callbacks,
2707 zone_registerinclude, zone, zone->mctx,
2708 zone->masterformat, zone->maxttl);
2709 }
2710
2711 cleanup:
2712 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
2713 dns_zone_rpz_disable_db(zone, load->db);
2714 dns_zone_catz_disable_db(zone, load->db);
2715 }
2716
2717 tresult = dns_db_endload(db, &load->callbacks);
2718 if (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) {
2719 result = tresult;
2720 }
2721
2722 zone_idetach(&load->callbacks.zone);
2723 dns_db_detach(&load->db);
2724 zone_idetach(&load->zone);
2725
2726 isc_mem_put(zone->mctx, load, sizeof(*load));
2727 return result;
2728 }
2729
2730 static bool
2731 zone_check_mx(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2732 dns_name_t *owner) {
2733 isc_result_t result;
2734 char ownerbuf[DNS_NAME_FORMATSIZE];
2735 char namebuf[DNS_NAME_FORMATSIZE];
2736 char altbuf[DNS_NAME_FORMATSIZE];
2737 dns_fixedname_t fixed;
2738 dns_name_t *foundname;
2739 int level;
2740
2741 /*
2742 * "." means the services does not exist.
2743 */
2744 if (dns_name_equal(name, dns_rootname)) {
2745 return true;
2746 }
2747
2748 /*
2749 * Outside of zone.
2750 */
2751 if (!dns_name_issubdomain(name, &zone->origin)) {
2752 if (zone->checkmx != NULL) {
2753 return (zone->checkmx)(zone, name, owner);
2754 }
2755 return true;
2756 }
2757
2758 if (zone->type == dns_zone_primary) {
2759 level = ISC_LOG_ERROR;
2760 } else {
2761 level = ISC_LOG_WARNING;
2762 }
2763
2764 foundname = dns_fixedname_initname(&fixed);
2765
2766 result = dns_db_find(db, name, NULL, dns_rdatatype_a, 0, 0, NULL,
2767 foundname, NULL, NULL);
2768 if (result == ISC_R_SUCCESS) {
2769 return true;
2770 }
2771
2772 if (result == DNS_R_NXRRSET) {
2773 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa, 0, 0,
2774 NULL, foundname, NULL, NULL);
2775 if (result == ISC_R_SUCCESS) {
2776 return true;
2777 }
2778 }
2779
2780 dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2781 dns_name_format(name, namebuf, sizeof namebuf);
2782 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2783 result == DNS_R_EMPTYNAME)
2784 {
2785 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL)) {
2786 level = ISC_LOG_WARNING;
2787 }
2788 dns_zone_log(zone, level,
2789 "%s/MX '%s' has no address records (A or AAAA)",
2790 ownerbuf, namebuf);
2791 return (level == ISC_LOG_WARNING) ? true : false;
2792 }
2793
2794 if (result == DNS_R_CNAME) {
2795 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
2796 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2797 {
2798 level = ISC_LOG_WARNING;
2799 }
2800 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
2801 dns_zone_log(zone, level,
2802 "%s/MX '%s' is a CNAME (illegal)",
2803 ownerbuf, namebuf);
2804 }
2805 return (level == ISC_LOG_WARNING) ? true : false;
2806 }
2807
2808 if (result == DNS_R_DNAME) {
2809 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
2810 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2811 {
2812 level = ISC_LOG_WARNING;
2813 }
2814 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
2815 dns_name_format(foundname, altbuf, sizeof altbuf);
2816 dns_zone_log(zone, level,
2817 "%s/MX '%s' is below a DNAME"
2818 " '%s' (illegal)",
2819 ownerbuf, namebuf, altbuf);
2820 }
2821 return (level == ISC_LOG_WARNING) ? true : false;
2822 }
2823
2824 if (zone->checkmx != NULL && result == DNS_R_DELEGATION) {
2825 return (zone->checkmx)(zone, name, owner);
2826 }
2827
2828 return true;
2829 }
2830
2831 static bool
2832 zone_check_srv(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2833 dns_name_t *owner) {
2834 isc_result_t result;
2835 char ownerbuf[DNS_NAME_FORMATSIZE];
2836 char namebuf[DNS_NAME_FORMATSIZE];
2837 char altbuf[DNS_NAME_FORMATSIZE];
2838 dns_fixedname_t fixed;
2839 dns_name_t *foundname;
2840 int level;
2841
2842 /*
2843 * "." means the services does not exist.
2844 */
2845 if (dns_name_equal(name, dns_rootname)) {
2846 return true;
2847 }
2848
2849 /*
2850 * Outside of zone.
2851 */
2852 if (!dns_name_issubdomain(name, &zone->origin)) {
2853 if (zone->checksrv != NULL) {
2854 return (zone->checksrv)(zone, name, owner);
2855 }
2856 return true;
2857 }
2858
2859 if (zone->type == dns_zone_primary) {
2860 level = ISC_LOG_ERROR;
2861 } else {
2862 level = ISC_LOG_WARNING;
2863 }
2864
2865 foundname = dns_fixedname_initname(&fixed);
2866
2867 result = dns_db_find(db, name, NULL, dns_rdatatype_a, 0, 0, NULL,
2868 foundname, NULL, NULL);
2869 if (result == ISC_R_SUCCESS) {
2870 return true;
2871 }
2872
2873 if (result == DNS_R_NXRRSET) {
2874 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa, 0, 0,
2875 NULL, foundname, NULL, NULL);
2876 if (result == ISC_R_SUCCESS) {
2877 return true;
2878 }
2879 }
2880
2881 dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2882 dns_name_format(name, namebuf, sizeof namebuf);
2883 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2884 result == DNS_R_EMPTYNAME)
2885 {
2886 dns_zone_log(zone, level,
2887 "%s/SRV '%s' has no address records (A or AAAA)",
2888 ownerbuf, namebuf);
2889 /* XXX950 make fatal for 9.5.0. */
2890 return true;
2891 }
2892
2893 if (result == DNS_R_CNAME) {
2894 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
2895 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2896 {
2897 level = ISC_LOG_WARNING;
2898 }
2899 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
2900 dns_zone_log(zone, level,
2901 "%s/SRV '%s' is a CNAME (illegal)",
2902 ownerbuf, namebuf);
2903 }
2904 return (level == ISC_LOG_WARNING) ? true : false;
2905 }
2906
2907 if (result == DNS_R_DNAME) {
2908 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
2909 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2910 {
2911 level = ISC_LOG_WARNING;
2912 }
2913 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
2914 dns_name_format(foundname, altbuf, sizeof altbuf);
2915 dns_zone_log(zone, level,
2916 "%s/SRV '%s' is below a "
2917 "DNAME '%s' (illegal)",
2918 ownerbuf, namebuf, altbuf);
2919 }
2920 return (level == ISC_LOG_WARNING) ? true : false;
2921 }
2922
2923 if (zone->checksrv != NULL && result == DNS_R_DELEGATION) {
2924 return (zone->checksrv)(zone, name, owner);
2925 }
2926
2927 return true;
2928 }
2929
2930 static bool
2931 zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2932 dns_name_t *owner) {
2933 bool answer = true;
2934 isc_result_t result, tresult;
2935 char ownerbuf[DNS_NAME_FORMATSIZE];
2936 char namebuf[DNS_NAME_FORMATSIZE];
2937 char altbuf[DNS_NAME_FORMATSIZE];
2938 dns_fixedname_t fixed;
2939 dns_name_t *foundname;
2940 dns_rdataset_t a;
2941 dns_rdataset_t aaaa;
2942 int level;
2943
2944 /*
2945 * Outside of zone.
2946 */
2947 if (!dns_name_issubdomain(name, &zone->origin)) {
2948 if (zone->checkns != NULL) {
2949 return (zone->checkns)(zone, name, owner, NULL, NULL);
2950 }
2951 return true;
2952 }
2953
2954 if (zone->type == dns_zone_primary) {
2955 level = ISC_LOG_ERROR;
2956 } else {
2957 level = ISC_LOG_WARNING;
2958 }
2959
2960 foundname = dns_fixedname_initname(&fixed);
2961 dns_rdataset_init(&a);
2962 dns_rdataset_init(&aaaa);
2963
2964 /*
2965 * Perform a regular lookup to catch DNAME records then look
2966 * for glue.
2967 */
2968 result = dns_db_find(db, name, NULL, dns_rdatatype_a, 0, 0, NULL,
2969 foundname, &a, NULL);
2970 switch (result) {
2971 case ISC_R_SUCCESS:
2972 case DNS_R_DNAME:
2973 case DNS_R_CNAME:
2974 break;
2975 default:
2976 if (dns_rdataset_isassociated(&a)) {
2977 dns_rdataset_disassociate(&a);
2978 }
2979 result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2980 DNS_DBFIND_GLUEOK, 0, NULL, foundname, &a,
2981 NULL);
2982 }
2983 if (result == ISC_R_SUCCESS) {
2984 dns_rdataset_disassociate(&a);
2985 return true;
2986 } else if (result == DNS_R_DELEGATION) {
2987 dns_rdataset_disassociate(&a);
2988 }
2989
2990 if (result == DNS_R_NXRRSET || result == DNS_R_DELEGATION ||
2991 result == DNS_R_GLUE)
2992 {
2993 tresult = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2994 DNS_DBFIND_GLUEOK, 0, NULL, foundname,
2995 &aaaa, NULL);
2996 if (tresult == ISC_R_SUCCESS) {
2997 if (dns_rdataset_isassociated(&a)) {
2998 dns_rdataset_disassociate(&a);
2999 }
3000 dns_rdataset_disassociate(&aaaa);
3001 return true;
3002 }
3003 if (tresult == DNS_R_DELEGATION || tresult == DNS_R_DNAME) {
3004 dns_rdataset_disassociate(&aaaa);
3005 }
3006 if (result == DNS_R_GLUE || tresult == DNS_R_GLUE) {
3007 /*
3008 * Check glue against child zone.
3009 */
3010 if (zone->checkns != NULL) {
3011 answer = (zone->checkns)(zone, name, owner, &a,
3012 &aaaa);
3013 }
3014 if (dns_rdataset_isassociated(&a)) {
3015 dns_rdataset_disassociate(&a);
3016 }
3017 if (dns_rdataset_isassociated(&aaaa)) {
3018 dns_rdataset_disassociate(&aaaa);
3019 }
3020 return answer;
3021 }
3022 }
3023
3024 dns_name_format(owner, ownerbuf, sizeof ownerbuf);
3025 dns_name_format(name, namebuf, sizeof namebuf);
3026 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
3027 result == DNS_R_EMPTYNAME || result == DNS_R_DELEGATION)
3028 {
3029 const char *what;
3030 bool required = false;
3031 if (dns_name_issubdomain(name, owner)) {
3032 what = "REQUIRED GLUE ";
3033 required = true;
3034 } else if (result == DNS_R_DELEGATION) {
3035 what = "SIBLING GLUE ";
3036 } else {
3037 what = "";
3038 }
3039
3040 if (result != DNS_R_DELEGATION || required ||
3041 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSIBLING))
3042 {
3043 dns_zone_log(zone, level,
3044 "%s/NS '%s' has no %s"
3045 "address records (A or AAAA)",
3046 ownerbuf, namebuf, what);
3047 /*
3048 * Log missing address record.
3049 */
3050 if (result == DNS_R_DELEGATION && zone->checkns != NULL)
3051 {
3052 (void)(zone->checkns)(zone, name, owner, &a,
3053 &aaaa);
3054 }
3055 /* XXX950 make fatal for 9.5.0. */
3056 /* answer = false; */
3057 }
3058 } else if (result == DNS_R_CNAME) {
3059 dns_zone_log(zone, level, "%s/NS '%s' is a CNAME (illegal)",
3060 ownerbuf, namebuf);
3061 /* XXX950 make fatal for 9.5.0. */
3062 /* answer = false; */
3063 } else if (result == DNS_R_DNAME) {
3064 dns_name_format(foundname, altbuf, sizeof altbuf);
3065 dns_zone_log(zone, level,
3066 "%s/NS '%s' is below a DNAME '%s' (illegal)",
3067 ownerbuf, namebuf, altbuf);
3068 /* XXX950 make fatal for 9.5.0. */
3069 /* answer = false; */
3070 }
3071
3072 if (dns_rdataset_isassociated(&a)) {
3073 dns_rdataset_disassociate(&a);
3074 }
3075 if (dns_rdataset_isassociated(&aaaa)) {
3076 dns_rdataset_disassociate(&aaaa);
3077 }
3078 return answer;
3079 }
3080
3081 static bool
3082 zone_rrset_check_dup(dns_zone_t *zone, dns_name_t *owner,
3083 dns_rdataset_t *rdataset) {
3084 dns_rdataset_t tmprdataset;
3085 isc_result_t result;
3086 bool answer = true;
3087 bool format = true;
3088 int level = ISC_LOG_WARNING;
3089 char ownerbuf[DNS_NAME_FORMATSIZE];
3090 char typebuf[DNS_RDATATYPE_FORMATSIZE];
3091 unsigned int count1 = 0;
3092
3093 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRRFAIL)) {
3094 level = ISC_LOG_ERROR;
3095 }
3096
3097 dns_rdataset_init(&tmprdataset);
3098 for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
3099 result = dns_rdataset_next(rdataset))
3100 {
3101 dns_rdata_t rdata1 = DNS_RDATA_INIT;
3102 unsigned int count2 = 0;
3103
3104 count1++;
3105 dns_rdataset_current(rdataset, &rdata1);
3106 dns_rdataset_clone(rdataset, &tmprdataset);
3107 for (result = dns_rdataset_first(&tmprdataset);
3108 result == ISC_R_SUCCESS;
3109 result = dns_rdataset_next(&tmprdataset))
3110 {
3111 dns_rdata_t rdata2 = DNS_RDATA_INIT;
3112 count2++;
3113 if (count1 >= count2) {
3114 continue;
3115 }
3116 dns_rdataset_current(&tmprdataset, &rdata2);
3117 if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) {
3118 if (format) {
3119 dns_name_format(owner, ownerbuf,
3120 sizeof ownerbuf);
3121 dns_rdatatype_format(rdata1.type,
3122 typebuf,
3123 sizeof(typebuf));
3124 format = false;
3125 }
3126 dns_zone_log(zone, level,
3127 "%s/%s has "
3128 "semantically identical records",
3129 ownerbuf, typebuf);
3130 if (level == ISC_LOG_ERROR) {
3131 answer = false;
3132 }
3133 break;
3134 }
3135 }
3136 dns_rdataset_disassociate(&tmprdataset);
3137 if (!format) {
3138 break;
3139 }
3140 }
3141 return answer;
3142 }
3143
3144 static bool
3145 zone_check_dup(dns_zone_t *zone, dns_db_t *db) {
3146 dns_dbiterator_t *dbiterator = NULL;
3147 dns_dbnode_t *node = NULL;
3148 dns_fixedname_t fixed;
3149 dns_name_t *name;
3150 dns_rdataset_t rdataset;
3151 dns_rdatasetiter_t *rdsit = NULL;
3152 bool ok = true;
3153 isc_result_t result;
3154
3155 name = dns_fixedname_initname(&fixed);
3156 dns_rdataset_init(&rdataset);
3157
3158 result = dns_db_createiterator(db, 0, &dbiterator);
3159 if (result != ISC_R_SUCCESS) {
3160 return true;
3161 }
3162
3163 for (result = dns_dbiterator_first(dbiterator); result == ISC_R_SUCCESS;
3164 result = dns_dbiterator_next(dbiterator))
3165 {
3166 result = dns_dbiterator_current(dbiterator, &node, name);
3167 if (result != ISC_R_SUCCESS) {
3168 continue;
3169 }
3170
3171 result = dns_db_allrdatasets(db, node, NULL, 0, 0, &rdsit);
3172 if (result != ISC_R_SUCCESS) {
3173 continue;
3174 }
3175
3176 for (result = dns_rdatasetiter_first(rdsit);
3177 result == ISC_R_SUCCESS;
3178 result = dns_rdatasetiter_next(rdsit))
3179 {
3180 dns_rdatasetiter_current(rdsit, &rdataset);
3181 if (!zone_rrset_check_dup(zone, name, &rdataset)) {
3182 ok = false;
3183 }
3184 dns_rdataset_disassociate(&rdataset);
3185 }
3186 dns_rdatasetiter_destroy(&rdsit);
3187 dns_db_detachnode(db, &node);
3188 }
3189
3190 if (node != NULL) {
3191 dns_db_detachnode(db, &node);
3192 }
3193 dns_dbiterator_destroy(&dbiterator);
3194
3195 return ok;
3196 }
3197
3198 static bool
3199 isspf(const dns_rdata_t *rdata) {
3200 char buf[1024];
3201 const unsigned char *data = rdata->data;
3202 unsigned int rdl = rdata->length, i = 0, tl, len;
3203
3204 while (rdl > 0U) {
3205 len = tl = *data;
3206 ++data;
3207 --rdl;
3208 INSIST(tl <= rdl);
3209 if (len > sizeof(buf) - i - 1) {
3210 len = sizeof(buf) - i - 1;
3211 }
3212 memmove(buf + i, data, len);
3213 i += len;
3214 data += tl;
3215 rdl -= tl;
3216 }
3217
3218 if (i < 6U) {
3219 return false;
3220 }
3221
3222 buf[i] = 0;
3223 if (strncmp(buf, "v=spf1", 6) == 0 && (buf[6] == 0 || buf[6] == ' ')) {
3224 return true;
3225 }
3226 return false;
3227 }
3228
3229 static bool
3230 integrity_checks(dns_zone_t *zone, dns_db_t *db) {
3231 dns_dbiterator_t *dbiterator = NULL;
3232 dns_dbnode_t *node = NULL;
3233 dns_rdataset_t rdataset;
3234 dns_fixedname_t fixed;
3235 dns_fixedname_t fixedbottom;
3236 dns_rdata_mx_t mx;
3237 dns_rdata_ns_t ns;
3238 dns_rdata_in_srv_t srv;
3239 dns_name_t *name;
3240 dns_name_t *bottom;
3241 isc_result_t result;
3242 bool ok = true, have_spf, have_txt;
3243 int level;
3244 char namebuf[DNS_NAME_FORMATSIZE];
3245 bool logged_algorithm[DST_MAX_ALGS];
3246 bool logged_digest_type[DNS_DSDIGEST_MAX + 1];
3247
3248 name = dns_fixedname_initname(&fixed);
3249 bottom = dns_fixedname_initname(&fixedbottom);
3250 dns_rdataset_init(&rdataset);
3251
3252 result = dns_db_createiterator(db, 0, &dbiterator);
3253 if (result != ISC_R_SUCCESS) {
3254 return true;
3255 }
3256
3257 result = dns_dbiterator_first(dbiterator);
3258 while (result == ISC_R_SUCCESS) {
3259 result = dns_dbiterator_current(dbiterator, &node, name);
3260 if (result != ISC_R_SUCCESS) {
3261 goto cleanup;
3262 }
3263
3264 /*
3265 * Is this name visible in the zone?
3266 */
3267 if (!dns_name_issubdomain(name, &zone->origin) ||
3268 (dns_name_countlabels(bottom) > 0 &&
3269 dns_name_issubdomain(name, bottom)))
3270 {
3271 goto next;
3272 }
3273
3274 dns_dbiterator_pause(dbiterator);
3275
3276 /*
3277 * Check for deprecated KEY algorithms
3278 */
3279 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_key,
3280 0, 0, &rdataset, NULL);
3281 if (result != ISC_R_SUCCESS) {
3282 goto checkforns;
3283 }
3284
3285 memset(logged_algorithm, 0, sizeof(logged_algorithm));
3286 for (result = dns_rdataset_first(&rdataset);
3287 result == ISC_R_SUCCESS;
3288 result = dns_rdataset_next(&rdataset))
3289 {
3290 dns_rdata_t rdata = DNS_RDATA_INIT;
3291 dns_rdata_key_t key;
3292 dns_rdataset_current(&rdataset, &rdata);
3293
3294 result = dns_rdata_tostruct(&rdata, &key, NULL);
3295 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3296
3297 /*
3298 * If we ever deprecate a private algorithm use
3299 * dst_algorithm_fromdata() here.
3300 */
3301 switch (key.algorithm) {
3302 case DNS_KEYALG_RSASHA1:
3303 case DNS_KEYALG_NSEC3RSASHA1:
3304 if (!logged_algorithm[key.algorithm]) {
3305 char algbuf[DNS_SECALG_FORMATSIZE];
3306 dns_name_format(name, namebuf,
3307 sizeof(namebuf));
3308 dns_secalg_format(key.algorithm, algbuf,
3309 sizeof(algbuf));
3310 dnssec_log(zone, ISC_LOG_WARNING,
3311 "%s/KEY deprecated "
3312 "algorithm %u (%s)",
3313 namebuf, key.algorithm,
3314 algbuf);
3315 logged_algorithm[key.algorithm] = true;
3316 }
3317 break;
3318 default:
3319 break;
3320 }
3321 }
3322 dns_rdataset_disassociate(&rdataset);
3323
3324 checkforns:
3325 /*
3326 * Don't check the NS records at the origin.
3327 */
3328 if (dns_name_equal(name, &zone->origin)) {
3329 goto checkfords;
3330 }
3331
3332 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ns,
3333 0, 0, &rdataset, NULL);
3334 if (result != ISC_R_SUCCESS) {
3335 goto checkfords;
3336 }
3337
3338 /*
3339 * Remember bottom of zone due to NS.
3340 */
3341 dns_name_copy(name, bottom);
3342
3343 result = dns_rdataset_first(&rdataset);
3344 while (result == ISC_R_SUCCESS) {
3345 dns_rdata_t rdata = DNS_RDATA_INIT;
3346 dns_rdataset_current(&rdataset, &rdata);
3347 result = dns_rdata_tostruct(&rdata, &ns, NULL);
3348 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3349 if (!zone_check_glue(zone, db, &ns.name, name)) {
3350 ok = false;
3351 }
3352 dns_rdata_reset(&rdata);
3353 result = dns_rdataset_next(&rdataset);
3354 }
3355 dns_rdataset_disassociate(&rdataset);
3356
3357 /*
3358 * Check for deprecated DS digest types.
3359 */
3360 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ds,
3361 0, 0, &rdataset, NULL);
3362 if (result != ISC_R_SUCCESS) {
3363 goto next;
3364 }
3365
3366 memset(logged_algorithm, 0, sizeof(logged_algorithm));
3367 memset(logged_digest_type, 0, sizeof(logged_digest_type));
3368 for (result = dns_rdataset_first(&rdataset);
3369 result == ISC_R_SUCCESS;
3370 result = dns_rdataset_next(&rdataset))
3371 {
3372 dns_rdata_t rdata = DNS_RDATA_INIT;
3373 dns_rdataset_current(&rdataset, &rdata);
3374 dns_rdata_ds_t ds;
3375
3376 result = dns_rdata_tostruct(&rdata, &ds, NULL);
3377 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3378 switch (ds.digest_type) {
3379 case DNS_DSDIGEST_SHA1:
3380 case DNS_DSDIGEST_GOST:
3381 if (!logged_digest_type[ds.digest_type]) {
3382 char algbuf[DNS_DSDIGEST_FORMATSIZE];
3383 dns_name_format(name, namebuf,
3384 sizeof(namebuf));
3385 dns_dsdigest_format(ds.digest_type,
3386 algbuf,
3387 sizeof(algbuf));
3388 dnssec_log(zone, ISC_LOG_WARNING,
3389 "%s/DS deprecated digest "
3390 "type %u (%s)",
3391 namebuf, ds.digest_type,
3392 algbuf);
3393 logged_digest_type[ds.digest_type] =
3394 true;
3395 }
3396 break;
3397 }
3398
3399 /*
3400 * If we ever deprecate a private algorithm use
3401 * dst_algorithm_fromdata() here.
3402 */
3403 switch (ds.algorithm) {
3404 case DNS_KEYALG_RSASHA1:
3405 case DNS_KEYALG_NSEC3RSASHA1:
3406 if (!logged_algorithm[ds.algorithm]) {
3407 char algbuf[DNS_SECALG_FORMATSIZE];
3408 dns_name_format(name, namebuf,
3409 sizeof(namebuf));
3410 dns_secalg_format(ds.algorithm, algbuf,
3411 sizeof(algbuf));
3412 dnssec_log(zone, ISC_LOG_WARNING,
3413 "%s/DS deprecated algorithm "
3414 "%u (%s)",
3415 namebuf, ds.algorithm,
3416 algbuf);
3417 logged_algorithm[ds.algorithm] = true;
3418 }
3419 break;
3420 }
3421 }
3422 dns_rdataset_disassociate(&rdataset);
3423
3424 goto next;
3425
3426 checkfords:
3427 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ds,
3428 0, 0, &rdataset, NULL);
3429 if (result != ISC_R_SUCCESS) {
3430 goto checkfordname;
3431 }
3432 dns_rdataset_disassociate(&rdataset);
3433
3434 if (zone->type == dns_zone_primary) {
3435 level = ISC_LOG_ERROR;
3436 ok = false;
3437 } else {
3438 level = ISC_LOG_WARNING;
3439 }
3440 dns_name_format(name, namebuf, sizeof(namebuf));
3441 dns_zone_log(zone, level, "DS not at delegation point (%s)",
3442 namebuf);
3443
3444 checkfordname:
3445 result = dns_db_findrdataset(db, node, NULL,
3446 dns_rdatatype_dname, 0, 0,
3447 &rdataset, NULL);
3448 if (result == ISC_R_SUCCESS) {
3449 /*
3450 * Remember bottom of zone due to DNAME.
3451 */
3452 dns_name_copy(name, bottom);
3453 dns_rdataset_disassociate(&rdataset);
3454 }
3455
3456 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_mx,
3457 0, 0, &rdataset, NULL);
3458 if (result != ISC_R_SUCCESS) {
3459 goto checksrv;
3460 }
3461 result = dns_rdataset_first(&rdataset);
3462 while (result == ISC_R_SUCCESS) {
3463 dns_rdata_t rdata = DNS_RDATA_INIT;
3464 dns_rdataset_current(&rdataset, &rdata);
3465 result = dns_rdata_tostruct(&rdata, &mx, NULL);
3466 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3467 if (!zone_check_mx(zone, db, &mx.mx, name)) {
3468 ok = false;
3469 }
3470 dns_rdata_reset(&rdata);
3471 result = dns_rdataset_next(&rdataset);
3472 }
3473 dns_rdataset_disassociate(&rdataset);
3474
3475 checksrv:
3476 if (zone->rdclass != dns_rdataclass_in) {
3477 goto next;
3478 }
3479 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_srv,
3480 0, 0, &rdataset, NULL);
3481 if (result != ISC_R_SUCCESS) {
3482 goto checkspf;
3483 }
3484 result = dns_rdataset_first(&rdataset);
3485 while (result == ISC_R_SUCCESS) {
3486 dns_rdata_t rdata = DNS_RDATA_INIT;
3487 dns_rdataset_current(&rdataset, &rdata);
3488 result = dns_rdata_tostruct(&rdata, &srv, NULL);
3489 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3490 if (!zone_check_srv(zone, db, &srv.target, name)) {
3491 ok = false;
3492 }
3493 dns_rdata_reset(&rdata);
3494 result = dns_rdataset_next(&rdataset);
3495 }
3496 dns_rdataset_disassociate(&rdataset);
3497
3498 checkspf:
3499 /*
3500 * Check if there is a type SPF record without an
3501 * SPF-formatted type TXT record also being present.
3502 */
3503 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSPF)) {
3504 goto next;
3505 }
3506 if (zone->rdclass != dns_rdataclass_in) {
3507 goto next;
3508 }
3509 have_spf = have_txt = false;
3510 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_spf,
3511 0, 0, &rdataset, NULL);
3512 if (result == ISC_R_SUCCESS) {
3513 dns_rdataset_disassociate(&rdataset);
3514 have_spf = true;
3515 }
3516 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_txt,
3517 0, 0, &rdataset, NULL);
3518 if (result != ISC_R_SUCCESS) {
3519 goto notxt;
3520 }
3521 result = dns_rdataset_first(&rdataset);
3522 while (result == ISC_R_SUCCESS) {
3523 dns_rdata_t rdata = DNS_RDATA_INIT;
3524 dns_rdataset_current(&rdataset, &rdata);
3525 have_txt = isspf(&rdata);
3526 dns_rdata_reset(&rdata);
3527 if (have_txt) {
3528 break;
3529 }
3530 result = dns_rdataset_next(&rdataset);
3531 }
3532 dns_rdataset_disassociate(&rdataset);
3533
3534 notxt:
3535 if (have_spf && !have_txt) {
3536 dns_name_format(name, namebuf, sizeof(namebuf));
3537 dns_zone_log(zone, ISC_LOG_WARNING,
3538 "'%s' found type "
3539 "SPF record but no SPF TXT record found, "
3540 "add matching type TXT record",
3541 namebuf);
3542 }
3543
3544 next:
3545 dns_db_detachnode(db, &node);
3546 result = dns_dbiterator_next(dbiterator);
3547 }
3548
3549 cleanup:
3550 if (node != NULL) {
3551 dns_db_detachnode(db, &node);
3552 }
3553 dns_dbiterator_destroy(&dbiterator);
3554
3555 return ok;
3556 }
3557
3558 /*
3559 * OpenSSL verification of RSA keys with exponent 3 is known to be
3560 * broken prior OpenSSL 0.9.8c/0.9.7k. Look for such keys and warn
3561 * if they are in use.
3562 */
3563 static void
3564 zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
3565 dns_dbnode_t *node = NULL;
3566 dns_dbversion_t *version = NULL;
3567 dns_rdata_dnskey_t dnskey;
3568 dns_rdataset_t rdataset;
3569 isc_result_t result;
3570 bool logged_algorithm[DST_MAX_ALGS] = { 0 };
3571 bool alldeprecated = true;
3572
3573 result = dns_db_findnode(db, &zone->origin, false, &node);
3574 if (result != ISC_R_SUCCESS) {
3575 goto cleanup;
3576 }
3577
3578 dns_db_currentversion(db, &version);
3579 dns_rdataset_init(&rdataset);
3580 result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
3581 dns_rdatatype_none, 0, &rdataset, NULL);
3582 if (result != ISC_R_SUCCESS) {
3583 goto cleanup;
3584 }
3585
3586 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
3587 result = dns_rdataset_next(&rdataset))
3588 {
3589 char algbuf[DNS_SECALG_FORMATSIZE];
3590 dns_rdata_t rdata = DNS_RDATA_INIT;
3591 dns_rdataset_current(&rdataset, &rdata);
3592 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
3593 INSIST(result == ISC_R_SUCCESS);
3594
3595 /*
3596 * RFC 3110, section 4: Performance Considerations:
3597 *
3598 * A public exponent of 3 minimizes the effort needed to verify
3599 * a signature. Use of 3 as the public exponent is weak for
3600 * confidentiality uses since, if the same data can be collected
3601 * encrypted under three different keys with an exponent of 3
3602 * then, using the Chinese Remainder Theorem [NETSEC], the
3603 * original plain text can be easily recovered. If a key is
3604 * known to be used only for authentication, as is the case with
3605 * DNSSEC, then an exponent of 3 is acceptable. However other
3606 * applications in the future may wish to leverage DNS
3607 * distributed keys for applications that do require
3608 * confidentiality. For keys which might have such other uses,
3609 * a more conservative choice would be 65537 (F4, the fourth
3610 * fermat number).
3611 */
3612 if (dnskey.datalen > 1 && dnskey.data[0] == 1 &&
3613 dnskey.data[1] == 3 &&
3614 (dnskey.algorithm == DNS_KEYALG_RSAMD5 ||
3615 dnskey.algorithm == DNS_KEYALG_RSASHA1 ||
3616 dnskey.algorithm == DNS_KEYALG_NSEC3RSASHA1 ||
3617 dnskey.algorithm == DNS_KEYALG_RSASHA256 ||
3618 dnskey.algorithm == DNS_KEYALG_RSASHA512))
3619 {
3620 char algorithm[DNS_SECALG_FORMATSIZE];
3621 isc_region_t r;
3622
3623 dns_rdata_toregion(&rdata, &r);
3624 dns_secalg_format(dnskey.algorithm, algorithm,
3625 sizeof(algorithm));
3626
3627 dnssec_log(zone, ISC_LOG_WARNING,
3628 "weak %s (%u) key found (exponent=3, id=%u)",
3629 algorithm, dnskey.algorithm,
3630 dst_region_computeid(&r));
3631 }
3632
3633 switch (dnskey.algorithm) {
3634 case DNS_KEYALG_RSAMD5:
3635 case DNS_KEYALG_DSA:
3636 case DNS_KEYALG_RSASHA1:
3637 case DNS_KEYALG_NSEC3DSA:
3638 case DNS_KEYALG_NSEC3RSASHA1:
3639 case DNS_KEYALG_ECCGOST:
3640 if (!logged_algorithm[dnskey.algorithm]) {
3641 dns_secalg_format(dnskey.algorithm, algbuf,
3642 sizeof(algbuf));
3643 dnssec_log(zone, ISC_LOG_WARNING,
3644 "deprecated DNSKEY algorithm found: "
3645 "%u (%s)\n",
3646 dnskey.algorithm, algbuf);
3647 logged_algorithm[dnskey.algorithm] = true;
3648 }
3649 break;
3650 default:
3651 alldeprecated = false;
3652 break;
3653 }
3654 }
3655 dns_rdataset_disassociate(&rdataset);
3656
3657 if (alldeprecated) {
3658 dnssec_log(zone, ISC_LOG_WARNING,
3659 "all DNSKEY algorithms found are deprecated");
3660 }
3661
3662 cleanup:
3663 if (node != NULL) {
3664 dns_db_detachnode(db, &node);
3665 }
3666 if (version != NULL) {
3667 dns_db_closeversion(db, &version, false);
3668 }
3669 }
3670
3671 static void
3672 resume_signingwithkey(dns_zone_t *zone) {
3673 dns_dbnode_t *node = NULL;
3674 dns_dbversion_t *version = NULL;
3675 dns_rdata_t rdata = DNS_RDATA_INIT;
3676 dns_rdataset_t rdataset;
3677 isc_result_t result;
3678 dns_db_t *db = NULL;
3679
3680 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3681 if (zone->db != NULL) {
3682 dns_db_attach(zone->db, &db);
3683 }
3684 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3685 if (db == NULL) {
3686 goto cleanup;
3687 }
3688
3689 result = dns_db_findnode(db, &zone->origin, false, &node);
3690 if (result != ISC_R_SUCCESS) {
3691 goto cleanup;
3692 }
3693
3694 dns_db_currentversion(db, &version);
3695 dns_rdataset_init(&rdataset);
3696 result = dns_db_findrdataset(db, node, version, zone->privatetype,
3697 dns_rdatatype_none, 0, &rdataset, NULL);
3698 if (result != ISC_R_SUCCESS) {
3699 INSIST(!dns_rdataset_isassociated(&rdataset));
3700 goto cleanup;
3701 }
3702
3703 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
3704 result = dns_rdataset_next(&rdataset))
3705 {
3706 dns_rdataset_current(&rdataset, &rdata);
3707 if (rdata.length != 5 || rdata.data[0] == 0 ||
3708 rdata.data[4] != 0)
3709 {
3710 dns_rdata_reset(&rdata);
3711 continue;
3712 }
3713
3714 result = zone_signwithkey(zone, rdata.data[0],
3715 (rdata.data[1] << 8) | rdata.data[2],
3716 rdata.data[3], false);
3717 if (result != ISC_R_SUCCESS) {
3718 dnssec_log(zone, ISC_LOG_ERROR,
3719 "zone_signwithkey failed: %s",
3720 isc_result_totext(result));
3721 }
3722 dns_rdata_reset(&rdata);
3723 }
3724 dns_rdataset_disassociate(&rdataset);
3725
3726 cleanup:
3727 if (db != NULL) {
3728 if (node != NULL) {
3729 dns_db_detachnode(db, &node);
3730 }
3731 if (version != NULL) {
3732 dns_db_closeversion(db, &version, false);
3733 }
3734 dns_db_detach(&db);
3735 }
3736 }
3737
3738 /*
3739 * Initiate adding/removing NSEC3 records belonging to the chain defined by the
3740 * supplied NSEC3PARAM RDATA.
3741 *
3742 * Zone must be locked by caller.
3743 */
3744 static isc_result_t
3745 zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
3746 dns_nsec3chain_t *nsec3chain, *current;
3747 dns_dbversion_t *version = NULL;
3748 bool nseconly = false, nsec3ok = false;
3749 isc_result_t result;
3750 isc_time_t now;
3751 unsigned int options = 0;
3752 char saltbuf[255 * 2 + 1];
3753 char flags[sizeof("INITIAL|REMOVE|CREATE|NONSEC|OPTOUT")];
3754 dns_db_t *db = NULL;
3755
3756 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3757 if (zone->db != NULL) {
3758 dns_db_attach(zone->db, &db);
3759 }
3760 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3761
3762 if (db == NULL) {
3763 result = ISC_R_SUCCESS;
3764 goto cleanup;
3765 }
3766
3767 /*
3768 * If this zone is not NSEC3-capable, attempting to remove any NSEC3
3769 * chain from it is pointless as it would not be possible for the
3770 * latter to exist in the first place.
3771 */
3772 dns_db_currentversion(db, &version);
3773 result = dns_nsec_nseconly(db, version, NULL, &nseconly);
3774 nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
3775 dns_db_closeversion(db, &version, false);
3776 if (!nsec3ok && (nsec3param->flags & DNS_NSEC3FLAG_REMOVE) == 0) {
3777 result = ISC_R_SUCCESS;
3778 goto cleanup;
3779 }
3780
3781 /*
3782 * Allocate and initialize structure preserving state of
3783 * adding/removing records belonging to this NSEC3 chain between
3784 * separate zone_nsec3chain() calls.
3785 */
3786 nsec3chain = isc_mem_get(zone->mctx, sizeof *nsec3chain);
3787
3788 nsec3chain->magic = 0;
3789 nsec3chain->done = false;
3790 nsec3chain->db = NULL;
3791 nsec3chain->dbiterator = NULL;
3792 nsec3chain->nsec3param.common.rdclass = nsec3param->common.rdclass;
3793 nsec3chain->nsec3param.common.rdtype = nsec3param->common.rdtype;
3794 nsec3chain->nsec3param.hash = nsec3param->hash;
3795 nsec3chain->nsec3param.iterations = nsec3param->iterations;
3796 nsec3chain->nsec3param.flags = nsec3param->flags;
3797 nsec3chain->nsec3param.salt_length = nsec3param->salt_length;
3798 memmove(nsec3chain->salt, nsec3param->salt, nsec3param->salt_length);
3799 nsec3chain->nsec3param.salt = nsec3chain->salt;
3800 nsec3chain->seen_nsec = false;
3801 nsec3chain->delete_nsec = false;
3802 nsec3chain->save_delete_nsec = false;
3803
3804 /*
3805 * Log NSEC3 parameters defined by supplied NSEC3PARAM RDATA.
3806 */
3807 if (nsec3param->flags == 0) {
3808 strlcpy(flags, "NONE", sizeof(flags));
3809 } else {
3810 flags[0] = '\0';
3811 if ((nsec3param->flags & DNS_NSEC3FLAG_REMOVE) != 0) {
3812 strlcat(flags, "REMOVE", sizeof(flags));
3813 }
3814 if ((nsec3param->flags & DNS_NSEC3FLAG_INITIAL) != 0) {
3815 if (flags[0] == '\0') {
3816 strlcpy(flags, "INITIAL", sizeof(flags));
3817 } else {
3818 strlcat(flags, "|INITIAL", sizeof(flags));
3819 }
3820 }
3821 if ((nsec3param->flags & DNS_NSEC3FLAG_CREATE) != 0) {
3822 if (flags[0] == '\0') {
3823 strlcpy(flags, "CREATE", sizeof(flags));
3824 } else {
3825 strlcat(flags, "|CREATE", sizeof(flags));
3826 }
3827 }
3828 if ((nsec3param->flags & DNS_NSEC3FLAG_NONSEC) != 0) {
3829 if (flags[0] == '\0') {
3830 strlcpy(flags, "NONSEC", sizeof(flags));
3831 } else {
3832 strlcat(flags, "|NONSEC", sizeof(flags));
3833 }
3834 }
3835 if ((nsec3param->flags & DNS_NSEC3FLAG_OPTOUT) != 0) {
3836 if (flags[0] == '\0') {
3837 strlcpy(flags, "OPTOUT", sizeof(flags));
3838 } else {
3839 strlcat(flags, "|OPTOUT", sizeof(flags));
3840 }
3841 }
3842 }
3843 result = dns_nsec3param_salttotext(nsec3param, saltbuf,
3844 sizeof(saltbuf));
3845 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3846 dnssec_log(zone, ISC_LOG_INFO, "zone_addnsec3chain(%u,%s,%u,%s)",
3847 nsec3param->hash, flags, nsec3param->iterations, saltbuf);
3848
3849 /*
3850 * If the NSEC3 chain defined by the supplied NSEC3PARAM RDATA is
3851 * currently being processed, interrupt its processing to avoid
3852 * simultaneously adding and removing records for the same NSEC3 chain.
3853 */
3854 for (current = ISC_LIST_HEAD(zone->nsec3chain); current != NULL;
3855 current = ISC_LIST_NEXT(current, link))
3856 {
3857 if ((current->db == db) &&
3858 (current->nsec3param.hash == nsec3param->hash) &&
3859 (current->nsec3param.iterations ==
3860 nsec3param->iterations) &&
3861 (current->nsec3param.salt_length ==
3862 nsec3param->salt_length) &&
3863 memcmp(current->nsec3param.salt, nsec3param->salt,
3864 nsec3param->salt_length) == 0)
3865 {
3866 current->done = true;
3867 }
3868 }
3869
3870 /*
3871 * Attach zone database to the structure initialized above and create
3872 * an iterator for it with appropriate options in order to avoid
3873 * creating NSEC3 records for NSEC3 records.
3874 */
3875 dns_db_attach(db, &nsec3chain->db);
3876 if ((nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0) {
3877 options = DNS_DB_NONSEC3;
3878 }
3879 result = dns_db_createiterator(nsec3chain->db, options,
3880 &nsec3chain->dbiterator);
3881 if (result == ISC_R_SUCCESS) {
3882 result = dns_dbiterator_first(nsec3chain->dbiterator);
3883 }
3884 if (result == ISC_R_SUCCESS) {
3885 /*
3886 * Database iterator initialization succeeded. We are now
3887 * ready to kick off adding/removing records belonging to this
3888 * NSEC3 chain. Append the structure initialized above to the
3889 * "nsec3chain" list for the zone and set the appropriate zone
3890 * timer so that zone_nsec3chain() is called as soon as
3891 * possible.
3892 */
3893 dns_dbiterator_pause(nsec3chain->dbiterator);
3894 ISC_LIST_INITANDAPPEND(zone->nsec3chain, nsec3chain, link);
3895 nsec3chain = NULL;
3896 if (isc_time_isepoch(&zone->nsec3chaintime)) {
3897 now = isc_time_now();
3898 zone->nsec3chaintime = now;
3899 if (zone->loop != NULL) {
3900 zone_settimer(zone, &now);
3901 }
3902 }
3903 }
3904
3905 if (nsec3chain != NULL) {
3906 if (nsec3chain->db != NULL) {
3907 dns_db_detach(&nsec3chain->db);
3908 }
3909 if (nsec3chain->dbiterator != NULL) {
3910 dns_dbiterator_destroy(&nsec3chain->dbiterator);
3911 }
3912 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
3913 }
3914
3915 cleanup:
3916 if (db != NULL) {
3917 dns_db_detach(&db);
3918 }
3919 return result;
3920 }
3921
3922 /*
3923 * Find private-type records at the zone apex which signal that an NSEC3 chain
3924 * should be added or removed. For each such record, extract NSEC3PARAM RDATA
3925 * and pass it to zone_addnsec3chain().
3926 *
3927 * Zone must be locked by caller.
3928 */
3929 static void
3930 resume_addnsec3chain(dns_zone_t *zone) {
3931 dns_dbnode_t *node = NULL;
3932 dns_dbversion_t *version = NULL;
3933 dns_rdataset_t rdataset;
3934 isc_result_t result;
3935 dns_rdata_nsec3param_t nsec3param;
3936 bool nseconly = false, nsec3ok = false;
3937 dns_db_t *db = NULL;
3938
3939 INSIST(LOCKED_ZONE(zone));
3940
3941 if (zone->privatetype == 0) {
3942 return;
3943 }
3944
3945 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3946 if (zone->db != NULL) {
3947 dns_db_attach(zone->db, &db);
3948 }
3949 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3950 if (db == NULL) {
3951 goto cleanup;
3952 }
3953
3954 result = dns_db_findnode(db, &zone->origin, false, &node);
3955 if (result != ISC_R_SUCCESS) {
3956 goto cleanup;
3957 }
3958
3959 dns_db_currentversion(db, &version);
3960
3961 /*
3962 * In order to create NSEC3 chains we need the DNSKEY RRset at zone
3963 * apex to exist and contain no keys using NSEC-only algorithms.
3964 */
3965 result = dns_nsec_nseconly(db, version, NULL, &nseconly);
3966 nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
3967
3968 /*
3969 * Get the RRset containing all private-type records at the zone apex.
3970 */
3971 dns_rdataset_init(&rdataset);
3972 result = dns_db_findrdataset(db, node, version, zone->privatetype,
3973 dns_rdatatype_none, 0, &rdataset, NULL);
3974 if (result != ISC_R_SUCCESS) {
3975 INSIST(!dns_rdataset_isassociated(&rdataset));
3976 goto cleanup;
3977 }
3978
3979 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
3980 result = dns_rdataset_next(&rdataset))
3981 {
3982 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
3983 dns_rdata_t rdata = DNS_RDATA_INIT;
3984 dns_rdata_t private = DNS_RDATA_INIT;
3985
3986 dns_rdataset_current(&rdataset, &private);
3987 /*
3988 * Try extracting NSEC3PARAM RDATA from this private-type
3989 * record. Failure means this private-type record does not
3990 * represent an NSEC3PARAM record, so skip it.
3991 */
3992 if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
3993 sizeof(buf)))
3994 {
3995 continue;
3996 }
3997 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
3998 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3999 if (((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) ||
4000 ((nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0 && nsec3ok))
4001 {
4002 /*
4003 * Pass the NSEC3PARAM RDATA contained in this
4004 * private-type record to zone_addnsec3chain() so that
4005 * it can kick off adding or removing NSEC3 records.
4006 */
4007 result = zone_addnsec3chain(zone, &nsec3param);
4008 if (result != ISC_R_SUCCESS) {
4009 dnssec_log(zone, ISC_LOG_ERROR,
4010 "zone_addnsec3chain failed: %s",
4011 isc_result_totext(result));
4012 }
4013 }
4014 }
4015 dns_rdataset_disassociate(&rdataset);
4016
4017 cleanup:
4018 if (db != NULL) {
4019 if (node != NULL) {
4020 dns_db_detachnode(db, &node);
4021 }
4022 if (version != NULL) {
4023 dns_db_closeversion(db, &version, false);
4024 }
4025 dns_db_detach(&db);
4026 }
4027 }
4028
4029 static void
4030 set_resigntime(dns_zone_t *zone) {
4031 dns_fixedname_t fixed;
4032 isc_stdtime_t resign;
4033 isc_result_t result;
4034 uint32_t nanosecs;
4035 dns_db_t *db = NULL;
4036 dns_typepair_t typepair;
4037
4038 INSIST(LOCKED_ZONE(zone));
4039
4040 /* We only re-sign zones that can be dynamically updated */
4041 if (!dns_zone_isdynamic(zone, false)) {
4042 return;
4043 }
4044
4045 if (inline_raw(zone)) {
4046 return;
4047 }
4048
4049 dns_fixedname_init(&fixed);
4050
4051 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
4052 if (zone->db != NULL) {
4053 dns_db_attach(zone->db, &db);
4054 }
4055 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
4056 if (db == NULL) {
4057 isc_time_settoepoch(&zone->resigntime);
4058 return;
4059 }
4060
4061 result = dns_db_getsigningtime(db, &resign, dns_fixedname_name(&fixed),
4062 &typepair);
4063 if (result != ISC_R_SUCCESS) {
4064 isc_time_settoepoch(&zone->resigntime);
4065 goto cleanup;
4066 }
4067
4068 resign -= dns_zone_getsigresigninginterval(zone);
4069 nanosecs = isc_random_uniform(1000000000);
4070 isc_time_set(&zone->resigntime, resign, nanosecs);
4071
4072 cleanup:
4073 dns_db_detach(&db);
4074 return;
4075 }
4076
4077 static isc_result_t
4078 check_nsec3param(dns_zone_t *zone, dns_db_t *db) {
4079 bool ok = false;
4080 dns_dbnode_t *node = NULL;
4081 dns_dbversion_t *version = NULL;
4082 dns_rdata_nsec3param_t nsec3param;
4083 dns_rdataset_t rdataset;
4084 isc_result_t result;
4085 bool dynamic = (zone->type == dns_zone_primary)
4086 ? dns_zone_isdynamic(zone, false)
4087 : false;
4088
4089 dns_rdataset_init(&rdataset);
4090 result = dns_db_findnode(db, &zone->origin, false, &node);
4091 if (result != ISC_R_SUCCESS) {
4092 dns_zone_log(zone, ISC_LOG_ERROR,
4093 "nsec3param lookup failure: %s",
4094 isc_result_totext(result));
4095 return result;
4096 }
4097 dns_db_currentversion(db, &version);
4098
4099 result = dns_db_findrdataset(db, node, version,
4100 dns_rdatatype_nsec3param,
4101 dns_rdatatype_none, 0, &rdataset, NULL);
4102 if (result == ISC_R_NOTFOUND) {
4103 INSIST(!dns_rdataset_isassociated(&rdataset));
4104 result = ISC_R_SUCCESS;
4105 goto cleanup;
4106 }
4107 if (result != ISC_R_SUCCESS) {
4108 INSIST(!dns_rdataset_isassociated(&rdataset));
4109 dns_zone_log(zone, ISC_LOG_ERROR,
4110 "nsec3param lookup failure: %s",
4111 isc_result_totext(result));
4112 goto cleanup;
4113 }
4114
4115 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
4116 result = dns_rdataset_next(&rdataset))
4117 {
4118 dns_rdata_t rdata = DNS_RDATA_INIT;
4119
4120 dns_rdataset_current(&rdataset, &rdata);
4121 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
4122 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4123
4124 /*
4125 * For dynamic zones we must support every algorithm so we
4126 * can regenerate all the NSEC3 chains.
4127 * For non-dynamic zones we only need to find a supported
4128 * algorithm.
4129 */
4130 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NSEC3TESTZONE) &&
4131 nsec3param.hash == DNS_NSEC3_UNKNOWNALG && !dynamic)
4132 {
4133 dns_zone_log(zone, ISC_LOG_WARNING,
4134 "nsec3 test \"unknown\" hash algorithm "
4135 "found: %u",
4136 nsec3param.hash);
4137 ok = true;
4138 } else if (!dns_nsec3_supportedhash(nsec3param.hash)) {
4139 if (dynamic) {
4140 dns_zone_log(zone, ISC_LOG_ERROR,
4141 "unsupported nsec3 hash algorithm"
4142 " in dynamic zone: %u",
4143 nsec3param.hash);
4144 result = DNS_R_BADZONE;
4145 /* Stop second error message. */
4146 ok = true;
4147 break;
4148 } else {
4149 dns_zone_log(zone, ISC_LOG_WARNING,
4150 "unsupported nsec3 hash "
4151 "algorithm: %u",
4152 nsec3param.hash);
4153 }
4154 } else {
4155 ok = true;
4156 }
4157
4158 /*
4159 * Warn if the zone has excessive NSEC3 iterations.
4160 */
4161 if (nsec3param.iterations > dns_nsec3_maxiterations()) {
4162 dnssec_log(zone, ISC_LOG_WARNING,
4163 "excessive NSEC3PARAM iterations %u > %u",
4164 nsec3param.iterations,
4165 dns_nsec3_maxiterations());
4166 }
4167 }
4168 if (result == ISC_R_NOMORE) {
4169 result = ISC_R_SUCCESS;
4170 }
4171
4172 if (!ok) {
4173 result = DNS_R_BADZONE;
4174 dns_zone_log(zone, ISC_LOG_ERROR,
4175 "no supported nsec3 hash algorithm");
4176 }
4177
4178 cleanup:
4179 if (dns_rdataset_isassociated(&rdataset)) {
4180 dns_rdataset_disassociate(&rdataset);
4181 }
4182 dns_db_closeversion(db, &version, false);
4183 dns_db_detachnode(db, &node);
4184 return result;
4185 }
4186
4187 /*
4188 * Set the timer for refreshing the key zone to the soonest future time
4189 * of the set (current timer, keydata->refresh, keydata->addhd,
4190 * keydata->removehd).
4191 */
4192 static void
4193 set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key,
4194 isc_stdtime_t now, bool force) {
4195 isc_stdtime_t then;
4196 isc_time_t timenow, timethen;
4197 char timebuf[80];
4198
4199 ENTER;
4200 then = key->refresh;
4201 if (force) {
4202 then = now;
4203 }
4204 if (key->addhd > now && key->addhd < then) {
4205 then = key->addhd;
4206 }
4207 if (key->removehd > now && key->removehd < then) {
4208 then = key->removehd;
4209 }
4210
4211 timenow = isc_time_now();
4212 if (then > now) {
4213 DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
4214 } else {
4215 timethen = timenow;
4216 }
4217 if (isc_time_compare(&zone->refreshkeytime, &timenow) < 0 ||
4218 isc_time_compare(&timethen, &zone->refreshkeytime) < 0)
4219 {
4220 zone->refreshkeytime = timethen;
4221 }
4222
4223 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
4224 dns_zone_log(zone, ISC_LOG_DEBUG(1), "next key refresh: %s", timebuf);
4225 zone_settimer(zone, &timenow);
4226 }
4227
4228 /*
4229 * If keynode references a key or a DS rdataset, and if the key
4230 * zone does not contain a KEYDATA record for the corresponding name,
4231 * then create an empty KEYDATA and push it into the zone as a placeholder,
4232 * then schedule a key refresh immediately. This new KEYDATA record will be
4233 * updated during the refresh.
4234 *
4235 * If the key zone is changed, set '*changed' to true.
4236 */
4237 static isc_result_t
4238 create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
4239 dns_diff_t *diff, dns_keynode_t *keynode, dns_name_t *keyname,
4240 bool *changed) {
4241 isc_result_t result = ISC_R_SUCCESS;
4242 dns_rdata_t rdata = DNS_RDATA_INIT;
4243 dns_rdata_keydata_t kd;
4244 unsigned char rrdata[4096];
4245 isc_buffer_t rrdatabuf;
4246 isc_stdtime_t now = isc_stdtime_now();
4247
4248 REQUIRE(keynode != NULL);
4249
4250 ENTER;
4251
4252 /*
4253 * If the keynode has no trust anchor set, we shouldn't be here.
4254 */
4255 if (!dns_keynode_dsset(keynode, NULL)) {
4256 return ISC_R_FAILURE;
4257 }
4258
4259 memset(&kd, 0, sizeof(kd));
4260 kd.common.rdclass = zone->rdclass;
4261 kd.common.rdtype = dns_rdatatype_keydata;
4262 ISC_LINK_INIT(&kd.common, link);
4263
4264 isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
4265
4266 CHECK(dns_rdata_fromstruct(&rdata, zone->rdclass, dns_rdatatype_keydata,
4267 &kd, &rrdatabuf));
4268 /* Add rdata to zone. */
4269 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, keyname, 0, &rdata));
4270 *changed = true;
4271
4272 /* Refresh new keys from the zone apex as soon as possible. */
4273 set_refreshkeytimer(zone, &kd, now, true);
4274 return ISC_R_SUCCESS;
4275
4276 cleanup:
4277 return result;
4278 }
4279
4280 /*
4281 * Remove from the key zone all the KEYDATA records found in rdataset.
4282 */
4283 static isc_result_t
4284 delete_keydata(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
4285 dns_name_t *name, dns_rdataset_t *rdataset) {
4286 dns_rdata_t rdata = DNS_RDATA_INIT;
4287 isc_result_t result, uresult;
4288
4289 for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
4290 result = dns_rdataset_next(rdataset))
4291 {
4292 dns_rdata_reset(&rdata);
4293 dns_rdataset_current(rdataset, &rdata);
4294 uresult = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name, 0,
4295 &rdata);
4296 if (uresult != ISC_R_SUCCESS) {
4297 return uresult;
4298 }
4299 }
4300 if (result == ISC_R_NOMORE) {
4301 result = ISC_R_SUCCESS;
4302 }
4303 return result;
4304 }
4305
4306 /*
4307 * Compute the DNSSEC key ID for a DNSKEY record.
4308 */
4309 static isc_result_t
4310 compute_tag(dns_name_t *name, dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx,
4311 dns_keytag_t *tag) {
4312 isc_result_t result;
4313 dns_rdata_t rdata = DNS_RDATA_INIT;
4314 unsigned char data[4096];
4315 isc_buffer_t buffer;
4316 dst_key_t *dstkey = NULL;
4317
4318 isc_buffer_init(&buffer, data, sizeof(data));
4319 dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
4320 dns_rdatatype_dnskey, dnskey, &buffer);
4321
4322 result = dns_dnssec_keyfromrdata(name, &rdata, mctx, &dstkey);
4323 if (result == ISC_R_SUCCESS) {
4324 *tag = dst_key_id(dstkey);
4325 dst_key_free(&dstkey);
4326 }
4327
4328 return result;
4329 }
4330
4331 /*
4332 * Synth-from-dnssec callbacks to add/delete names from namespace tree.
4333 */
4334 static void
4335 sfd_add(const dns_name_t *name, void *arg) {
4336 if (arg != NULL) {
4337 dns_view_sfd_add(arg, name);
4338 }
4339 }
4340
4341 static void
4342 sfd_del(const dns_name_t *name, void *arg) {
4343 if (arg != NULL) {
4344 dns_view_sfd_del(arg, name);
4345 }
4346 }
4347
4348 /*
4349 * Add key to the security roots.
4350 */
4351 static void
4352 trust_key(dns_zone_t *zone, dns_name_t *keyname, dns_rdata_dnskey_t *dnskey,
4353 bool initial) {
4354 isc_result_t result;
4355 dns_rdata_t rdata = DNS_RDATA_INIT;
4356 unsigned char data[4096], digest[ISC_MAX_MD_SIZE];
4357 isc_buffer_t buffer;
4358 dns_keytable_t *sr = NULL;
4359 dns_rdata_ds_t ds;
4360
4361 result = dns_view_getsecroots(zone->view, &sr);
4362 if (result != ISC_R_SUCCESS) {
4363 return;
4364 }
4365
4366 /* Build DS record for key. */
4367 isc_buffer_init(&buffer, data, sizeof(data));
4368 dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
4369 dns_rdatatype_dnskey, dnskey, &buffer);
4370 CHECK(dns_ds_fromkeyrdata(keyname, &rdata, DNS_DSDIGEST_SHA256, digest,
4371 &ds));
4372 CHECK(dns_keytable_add(sr, true, initial, keyname, &ds, sfd_add,
4373 zone->view));
4374
4375 dns_keytable_detach(&sr);
4376
4377 cleanup:
4378 if (sr != NULL) {
4379 dns_keytable_detach(&sr);
4380 }
4381 return;
4382 }
4383
4384 /*
4385 * Add a null key to the security roots for so that all queries
4386 * to the zone will fail.
4387 */
4388 static void
4389 fail_secure(dns_zone_t *zone, dns_name_t *keyname) {
4390 isc_result_t result;
4391 dns_keytable_t *sr = NULL;
4392
4393 result = dns_view_getsecroots(zone->view, &sr);
4394 if (result == ISC_R_SUCCESS) {
4395 dns_keytable_marksecure(sr, keyname);
4396 dns_keytable_detach(&sr);
4397 }
4398 }
4399
4400 /*
4401 * Scan a set of KEYDATA records from the key zone. The ones that are
4402 * valid (i.e., the add holddown timer has expired) become trusted keys.
4403 */
4404 static void
4405 load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
4406 isc_result_t result;
4407 dns_rdata_t rdata = DNS_RDATA_INIT;
4408 dns_rdata_keydata_t keydata;
4409 dns_rdata_dnskey_t dnskey;
4410 int trusted = 0, revoked = 0, pending = 0;
4411 isc_stdtime_t now = isc_stdtime_now();
4412 dns_keytable_t *sr = NULL;
4413
4414 result = dns_view_getsecroots(zone->view, &sr);
4415 if (result == ISC_R_SUCCESS) {
4416 dns_keytable_delete(sr, name, sfd_del, zone->view);
4417 dns_keytable_detach(&sr);
4418 }
4419
4420 /* Now insert all the accepted trust anchors from this keydata set. */
4421 for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
4422 result = dns_rdataset_next(rdataset))
4423 {
4424 dns_rdata_reset(&rdata);
4425 dns_rdataset_current(rdataset, &rdata);
4426
4427 /* Convert rdata to keydata. */
4428 result = dns_rdata_tostruct(&rdata, &keydata, NULL);
4429 if (result == ISC_R_NOTIMPLEMENTED) {
4430 continue;
4431 }
4432 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4433
4434 /* Set the key refresh timer to force a fast refresh. */
4435 set_refreshkeytimer(zone, &keydata, now, true);
4436
4437 /* If the removal timer is nonzero, this key was revoked. */
4438 if (keydata.removehd != 0) {
4439 revoked++;
4440 continue;
4441 }
4442
4443 /*
4444 * If the add timer is still pending, this key is not
4445 * trusted yet.
4446 */
4447 if (now < keydata.addhd) {
4448 pending++;
4449 continue;
4450 }
4451
4452 /* Convert keydata to dnskey. */
4453 dns_keydata_todnskey(&keydata, &dnskey, NULL);
4454
4455 /* Add to keytables. */
4456 trusted++;
4457 trust_key(zone, name, &dnskey, keydata.addhd == 0);
4458 }
4459
4460 if (trusted == 0 && pending != 0) {
4461 char namebuf[DNS_NAME_FORMATSIZE];
4462 dns_name_format(name, namebuf, sizeof namebuf);
4463 dnssec_log(zone, ISC_LOG_ERROR,
4464 "No valid trust anchors for '%s'!", namebuf);
4465 dnssec_log(zone, ISC_LOG_ERROR,
4466 "%d key(s) revoked, %d still pending", revoked,
4467 pending);
4468 dnssec_log(zone, ISC_LOG_ERROR, "All queries to '%s' will fail",
4469 namebuf);
4470 fail_secure(zone, name);
4471 }
4472 }
4473
4474 static isc_result_t
4475 do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
4476 dns_diff_t *diff) {
4477 dns_diff_t temp_diff;
4478 isc_result_t result;
4479
4480 /*
4481 * Create a singleton diff.
4482 */
4483 dns_diff_init(diff->mctx, &temp_diff);
4484 ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
4485
4486 /*
4487 * Apply it to the database.
4488 */
4489 result = dns_diff_apply(&temp_diff, db, ver);
4490 ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
4491 if (result != ISC_R_SUCCESS) {
4492 dns_difftuple_free(tuple);
4493 return result;
4494 }
4495
4496 /*
4497 * Merge it into the current pending journal entry.
4498 */
4499 dns_diff_appendminimal(diff, tuple);
4500
4501 /*
4502 * Do not clear temp_diff.
4503 */
4504 return ISC_R_SUCCESS;
4505 }
4506
4507 static isc_result_t
4508 update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
4509 dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
4510 dns_rdata_t *rdata) {
4511 dns_difftuple_t *tuple = NULL;
4512 isc_result_t result;
4513 result = dns_difftuple_create(diff->mctx, op, name, ttl, rdata, &tuple);
4514 if (result != ISC_R_SUCCESS) {
4515 return result;
4516 }
4517 return do_one_tuple(&tuple, db, ver, diff);
4518 }
4519
4520 static isc_result_t
4521 update_soa_serial(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
4522 dns_diff_t *diff, isc_mem_t *mctx,
4523 dns_updatemethod_t method) {
4524 dns_difftuple_t *deltuple = NULL;
4525 dns_difftuple_t *addtuple = NULL;
4526 uint32_t serial;
4527 isc_result_t result;
4528 dns_updatemethod_t used = dns_updatemethod_none;
4529
4530 INSIST(method != dns_updatemethod_none);
4531
4532 CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple));
4533 CHECK(dns_difftuple_copy(deltuple, &addtuple));
4534 addtuple->op = DNS_DIFFOP_ADD;
4535
4536 serial = dns_soa_getserial(&addtuple->rdata);
4537 serial = dns_update_soaserial(serial, method, &used);
4538 if (method != used) {
4539 dns_zone_log(zone, ISC_LOG_WARNING,
4540 "update_soa_serial:new serial would be lower than "
4541 "old serial, using increment method instead");
4542 }
4543 dns_soa_setserial(serial, &addtuple->rdata);
4544 CHECK(do_one_tuple(&deltuple, db, ver, diff));
4545 CHECK(do_one_tuple(&addtuple, db, ver, diff));
4546 result = ISC_R_SUCCESS;
4547
4548 cleanup:
4549 if (addtuple != NULL) {
4550 dns_difftuple_free(&addtuple);
4551 }
4552 if (deltuple != NULL) {
4553 dns_difftuple_free(&deltuple);
4554 }
4555 return result;
4556 }
4557
4558 /*
4559 * Write all transactions in 'diff' to the zone journal file.
4560 */
4561 static isc_result_t
4562 zone_journal(dns_zone_t *zone, dns_diff_t *diff, uint32_t *sourceserial,
4563 const char *caller) {
4564 const char *journalfile;
4565 isc_result_t result = ISC_R_SUCCESS;
4566 dns_journal_t *journal = NULL;
4567 unsigned int mode = DNS_JOURNAL_CREATE | DNS_JOURNAL_WRITE;
4568
4569 ENTER;
4570 journalfile = dns_zone_getjournal(zone);
4571 if (journalfile != NULL) {
4572 result = dns_journal_open(zone->mctx, journalfile, mode,
4573 &journal);
4574 if (result != ISC_R_SUCCESS) {
4575 dns_zone_log(zone, ISC_LOG_ERROR,
4576 "%s:dns_journal_open -> %s", caller,
4577 isc_result_totext(result));
4578 return result;
4579 }
4580
4581 if (sourceserial != NULL) {
4582 dns_journal_set_sourceserial(journal, *sourceserial);
4583 }
4584
4585 result = dns_journal_write_transaction(journal, diff);
4586 if (result != ISC_R_SUCCESS) {
4587 dns_zone_log(zone, ISC_LOG_ERROR,
4588 "%s:dns_journal_write_transaction -> %s",
4589 caller, isc_result_totext(result));
4590 }
4591 dns_journal_destroy(&journal);
4592 }
4593
4594 return result;
4595 }
4596
4597 /*
4598 * Create an SOA record for a newly-created zone
4599 */
4600 static isc_result_t
4601 add_soa(dns_zone_t *zone, dns_db_t *db) {
4602 isc_result_t result;
4603 dns_rdata_t rdata = DNS_RDATA_INIT;
4604 unsigned char buf[DNS_SOA_BUFFERSIZE];
4605 dns_dbversion_t *ver = NULL;
4606 dns_diff_t diff;
4607
4608 dns_zone_log(zone, ISC_LOG_DEBUG(1), "creating SOA");
4609
4610 dns_diff_init(zone->mctx, &diff);
4611 result = dns_db_newversion(db, &ver);
4612 if (result != ISC_R_SUCCESS) {
4613 dns_zone_log(zone, ISC_LOG_ERROR,
4614 "add_soa:dns_db_newversion -> %s",
4615 isc_result_totext(result));
4616 goto cleanup;
4617 }
4618
4619 /* Build SOA record */
4620 result = dns_soa_buildrdata(&zone->origin, dns_rootname, zone->rdclass,
4621 0, 0, 0, 0, 0, buf, &rdata);
4622 if (result != ISC_R_SUCCESS) {
4623 dns_zone_log(zone, ISC_LOG_ERROR,
4624 "add_soa:dns_soa_buildrdata -> %s",
4625 isc_result_totext(result));
4626 goto cleanup;
4627 }
4628
4629 result = update_one_rr(db, ver, &diff, DNS_DIFFOP_ADD, &zone->origin, 0,
4630 &rdata);
4631
4632 cleanup:
4633 dns_diff_clear(&diff);
4634 if (ver != NULL) {
4635 dns_db_closeversion(db, &ver, result == ISC_R_SUCCESS);
4636 }
4637
4638 INSIST(ver == NULL);
4639
4640 return result;
4641 }
4642
4643 struct addifmissing_arg {
4644 dns_db_t *db;
4645 dns_dbversion_t *ver;
4646 dns_diff_t *diff;
4647 dns_zone_t *zone;
4648 bool *changed;
4649 isc_result_t result;
4650 };
4651
4652 static void
4653 addifmissing(dns_keytable_t *keytable, dns_keynode_t *keynode,
4654 dns_name_t *keyname, void *arg) {
4655 dns_db_t *db = ((struct addifmissing_arg *)arg)->db;
4656 dns_dbversion_t *ver = ((struct addifmissing_arg *)arg)->ver;
4657 dns_diff_t *diff = ((struct addifmissing_arg *)arg)->diff;
4658 dns_zone_t *zone = ((struct addifmissing_arg *)arg)->zone;
4659 bool *changed = ((struct addifmissing_arg *)arg)->changed;
4660 isc_result_t result;
4661 dns_fixedname_t fname;
4662
4663 UNUSED(keytable);
4664
4665 if (((struct addifmissing_arg *)arg)->result != ISC_R_SUCCESS) {
4666 return;
4667 }
4668
4669 if (!dns_keynode_managed(keynode)) {
4670 return;
4671 }
4672
4673 /*
4674 * If the keynode has no trust anchor set, return.
4675 */
4676 if (!dns_keynode_dsset(keynode, NULL)) {
4677 return;
4678 }
4679
4680 /*
4681 * Check whether there's already a KEYDATA entry for this name;
4682 * if so, we don't need to add another.
4683 */
4684 dns_fixedname_init(&fname);
4685 result = dns_db_find(db, keyname, ver, dns_rdatatype_keydata,
4686 DNS_DBFIND_NOWILD, 0, NULL,
4687 dns_fixedname_name(&fname), NULL, NULL);
4688 if (result == ISC_R_SUCCESS) {
4689 return;
4690 }
4691
4692 /*
4693 * Create the keydata.
4694 */
4695 result = create_keydata(zone, db, ver, diff, keynode, keyname, changed);
4696 if (result != ISC_R_SUCCESS && result != ISC_R_NOMORE) {
4697 ((struct addifmissing_arg *)arg)->result = result;
4698 }
4699 }
4700
4701 /*
4702 * Synchronize the set of initializing keys found in managed-keys {}
4703 * statements with the set of trust anchors found in the managed-keys.bind
4704 * zone. If a domain is no longer named in managed-keys, delete all keys
4705 * from that domain from the key zone. If a domain is configured as an
4706 * initial-key in trust-anchors, but there are no references to it in the
4707 * key zone, load the key zone with the initializing key(s) for that
4708 * domain and schedule a key refresh. If a domain is configured as
4709 * an initial-ds in trust-anchors, fetch the DNSKEY RRset, load the key
4710 * zone with the matching key, and schedule a key refresh.
4711 */
4712 static isc_result_t
4713 sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
4714 isc_result_t result = ISC_R_SUCCESS;
4715 bool changed = false;
4716 bool commit = false;
4717 dns_keynode_t *keynode = NULL;
4718 dns_view_t *view = zone->view;
4719 dns_keytable_t *sr = NULL;
4720 dns_dbversion_t *ver = NULL;
4721 dns_diff_t diff;
4722 dns_rriterator_t rrit;
4723 struct addifmissing_arg arg;
4724
4725 dns_zone_log(zone, ISC_LOG_DEBUG(1), "synchronizing trusted keys");
4726
4727 dns_diff_init(zone->mctx, &diff);
4728
4729 CHECK(dns_view_getsecroots(view, &sr));
4730
4731 result = dns_db_newversion(db, &ver);
4732 if (result != ISC_R_SUCCESS) {
4733 dnssec_log(zone, ISC_LOG_ERROR,
4734 "sync_keyzone:dns_db_newversion -> %s",
4735 isc_result_totext(result));
4736 goto cleanup;
4737 }
4738
4739 /*
4740 * Walk the zone DB. If we find any keys whose names are no longer
4741 * in trust-anchors, or which have been changed from initial to static,
4742 * (meaning they are permanent and not RFC5011-maintained), delete
4743 * them from the zone. Otherwise call load_secroots(), which
4744 * loads keys into secroots as appropriate.
4745 */
4746 dns_rriterator_init(&rrit, db, ver, 0);
4747 for (result = dns_rriterator_first(&rrit); result == ISC_R_SUCCESS;
4748 result = dns_rriterator_nextrrset(&rrit))
4749 {
4750 dns_rdataset_t *rdataset = NULL;
4751 dns_rdata_t rdata = DNS_RDATA_INIT;
4752 dns_rdata_keydata_t keydata;
4753 isc_stdtime_t now = isc_stdtime_now();
4754 bool load = true;
4755 dns_name_t *rrname = NULL;
4756 uint32_t ttl;
4757
4758 dns_rriterator_current(&rrit, &rrname, &ttl, &rdataset, NULL);
4759 if (!dns_rdataset_isassociated(rdataset)) {
4760 dns_rriterator_destroy(&rrit);
4761 goto cleanup;
4762 }
4763
4764 if (rdataset->type != dns_rdatatype_keydata) {
4765 continue;
4766 }
4767
4768 /*
4769 * The managed-keys zone can contain a placeholder instead of
4770 * legitimate data, in which case we will not use it, and we
4771 * will try to refresh it.
4772 */
4773 for (result = dns_rdataset_first(rdataset);
4774 result == ISC_R_SUCCESS;
4775 result = dns_rdataset_next(rdataset))
4776 {
4777 isc_result_t iresult;
4778
4779 dns_rdata_reset(&rdata);
4780 dns_rdataset_current(rdataset, &rdata);
4781
4782 iresult = dns_rdata_tostruct(&rdata, &keydata, NULL);
4783 /* Do we have a valid placeholder KEYDATA record? */
4784 if (iresult == ISC_R_SUCCESS && keydata.flags == 0 &&
4785 keydata.protocol == 0 && keydata.algorithm == 0)
4786 {
4787 set_refreshkeytimer(zone, &keydata, now, true);
4788 load = false;
4789 }
4790 }
4791
4792 /*
4793 * Release db wrlock to prevent LOR reports against
4794 * dns_keytable_forall() call below.
4795 */
4796 dns_rriterator_pause(&rrit);
4797 result = dns_keytable_find(sr, rrname, &keynode);
4798 if (result != ISC_R_SUCCESS || !dns_keynode_managed(keynode)) {
4799 CHECK(delete_keydata(db, ver, &diff, rrname, rdataset));
4800 changed = true;
4801 } else if (load) {
4802 load_secroots(zone, rrname, rdataset);
4803 }
4804
4805 if (keynode != NULL) {
4806 dns_keynode_detach(&keynode);
4807 }
4808 }
4809 dns_rriterator_destroy(&rrit);
4810
4811 /*
4812 * Walk secroots to find any initial keys that aren't in
4813 * the zone. If we find any, add them to the zone directly.
4814 * If any DS-style initial keys are found, refresh the key
4815 * zone so that they'll be looked up.
4816 */
4817 arg.db = db;
4818 arg.ver = ver;
4819 arg.result = ISC_R_SUCCESS;
4820 arg.diff = &diff;
4821 arg.zone = zone;
4822 arg.changed = &changed;
4823 dns_keytable_forall(sr, addifmissing, &arg);
4824 result = arg.result;
4825 if (changed) {
4826 /* Write changes to journal file. */
4827 CHECK(update_soa_serial(zone, db, ver, &diff, zone->mctx,
4828 zone->updatemethod));
4829 CHECK(zone_journal(zone, &diff, NULL, "sync_keyzone"));
4830
4831 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
4832 zone_needdump(zone, 30);
4833 commit = true;
4834 }
4835
4836 cleanup:
4837 if (result != ISC_R_SUCCESS) {
4838 dnssec_log(zone, ISC_LOG_ERROR,
4839 "unable to synchronize managed keys: %s",
4840 isc_result_totext(result));
4841 isc_time_settoepoch(&zone->refreshkeytime);
4842 }
4843 if (keynode != NULL) {
4844 dns_keynode_detach(&keynode);
4845 }
4846 if (sr != NULL) {
4847 dns_keytable_detach(&sr);
4848 }
4849 if (ver != NULL) {
4850 dns_db_closeversion(db, &ver, commit);
4851 }
4852 dns_diff_clear(&diff);
4853
4854 INSIST(ver == NULL);
4855
4856 return result;
4857 }
4858
4859 isc_result_t
4860 dns_zone_synckeyzone(dns_zone_t *zone) {
4861 isc_result_t result;
4862 dns_db_t *db = NULL;
4863
4864 if (zone->type != dns_zone_key) {
4865 return DNS_R_BADZONE;
4866 }
4867
4868 CHECK(dns_zone_getdb(zone, &db));
4869
4870 LOCK_ZONE(zone);
4871 result = sync_keyzone(zone, db);
4872 UNLOCK_ZONE(zone);
4873
4874 cleanup:
4875 if (db != NULL) {
4876 dns_db_detach(&db);
4877 }
4878 return result;
4879 }
4880
4881 static void
4882 maybe_send_secure(dns_zone_t *zone) {
4883 isc_result_t result;
4884
4885 /*
4886 * We've finished loading, or else failed to load, an inline-signing
4887 * 'secure' zone. We now need information about the status of the
4888 * 'raw' zone. If we failed to load, then we need it to send a
4889 * copy of its database; if we succeeded, we need it to send its
4890 * serial number so that we can sync with it. If it has not yet
4891 * loaded, we set a flag so that it will send the necessary
4892 * information when it has finished loading.
4893 */
4894 if (zone->raw->db != NULL) {
4895 if (zone->db != NULL) {
4896 uint32_t serial;
4897 unsigned int soacount;
4898
4899 result = zone_get_from_db(
4900 zone->raw, zone->raw->db, NULL, &soacount, NULL,
4901 &serial, NULL, NULL, NULL, NULL, NULL);
4902 if (result == ISC_R_SUCCESS && soacount > 0U) {
4903 zone_send_secureserial(zone->raw, serial);
4904 }
4905 } else {
4906 zone_send_securedb(zone->raw, zone->raw->db);
4907 }
4908 } else {
4909 DNS_ZONE_SETFLAG(zone->raw, DNS_ZONEFLG_SENDSECURE);
4910 }
4911 }
4912
4913 static bool
4914 zone_unchanged(dns_db_t *db1, dns_db_t *db2, isc_mem_t *mctx) {
4915 isc_result_t result;
4916 bool answer = false;
4917 dns_diff_t diff;
4918
4919 dns_diff_init(mctx, &diff);
4920 result = dns_db_diffx(&diff, db1, NULL, db2, NULL, NULL);
4921 if (result == ISC_R_SUCCESS && ISC_LIST_EMPTY(diff.tuples)) {
4922 answer = true;
4923 }
4924 dns_diff_clear(&diff);
4925 return answer;
4926 }
4927
4928 static void
4929 process_zone_setnsec3param(dns_zone_t *zone) {
4930 struct np3 *npe = NULL;
4931 while ((npe = ISC_LIST_HEAD(zone->setnsec3param_queue)) != NULL) {
4932 ISC_LIST_UNLINK(zone->setnsec3param_queue, npe, link);
4933 zone_iattach(zone, &npe->zone);
4934 isc_async_run(zone->loop, setnsec3param, npe);
4935 }
4936 }
4937
4938 /*
4939 * The zone is presumed to be locked.
4940 * If this is a inline_raw zone the secure version is also locked.
4941 */
4942 static isc_result_t
4943 zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
4944 isc_result_t result) {
4945 unsigned int soacount = 0;
4946 unsigned int nscount = 0;
4947 unsigned int errors = 0;
4948 uint32_t serial, oldserial, refresh, retry, expire, minimum, soattl;
4949 isc_time_t now;
4950 bool needdump = false;
4951 bool fixjournal = false;
4952 bool hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE);
4953 bool noprimary = false;
4954 bool had_db = false;
4955 dns_include_t *inc;
4956 bool is_dynamic = false;
4957
4958 INSIST(LOCKED_ZONE(zone));
4959 if (inline_raw(zone)) {
4960 INSIST(LOCKED_ZONE(zone->secure));
4961 }
4962
4963 now = isc_time_now();
4964
4965 /*
4966 * Initiate zone transfer? We may need a error code that
4967 * indicates that the "permanent" form does not exist.
4968 * XXX better error feedback to log.
4969 */
4970 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
4971 if (zone->type == dns_zone_secondary ||
4972 zone->type == dns_zone_mirror ||
4973 zone->type == dns_zone_stub ||
4974 (zone->type == dns_zone_redirect &&
4975 dns_remote_addresses(&zone->primaries) == NULL))
4976 {
4977 if (result == ISC_R_FILENOTFOUND) {
4978 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4979 ISC_LOG_DEBUG(1),
4980 "no master file");
4981 } else if (result != DNS_R_NOMASTERFILE) {
4982 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4983 ISC_LOG_ERROR,
4984 "loading from master file %s "
4985 "failed: %s",
4986 zone->masterfile,
4987 isc_result_totext(result));
4988 }
4989 } else if (zone->type == dns_zone_primary &&
4990 inline_secure(zone) && result == ISC_R_FILENOTFOUND)
4991 {
4992 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4993 ISC_LOG_DEBUG(1),
4994 "no master file, requesting db");
4995 maybe_send_secure(zone);
4996 } else {
4997 int level = ISC_LOG_ERROR;
4998 if (zone->type == dns_zone_key &&
4999 result == ISC_R_FILENOTFOUND)
5000 {
5001 level = ISC_LOG_DEBUG(1);
5002 }
5003 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, level,
5004 "loading from master file %s failed: %s",
5005 zone->masterfile,
5006 isc_result_totext(result));
5007 noprimary = true;
5008 }
5009
5010 if (zone->type != dns_zone_key) {
5011 goto cleanup;
5012 }
5013 }
5014
5015 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(2),
5016 "number of nodes in database: %u",
5017 dns_db_nodecount(db, dns_dbtree_main));
5018
5019 if (result == DNS_R_SEENINCLUDE) {
5020 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
5021 } else {
5022 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
5023 }
5024
5025 /*
5026 * If there's no master file for a key zone, then the zone is new:
5027 * create an SOA record. (We do this now, instead of later, so that
5028 * if there happens to be a journal file, we can roll forward from
5029 * a sane starting point.)
5030 */
5031 if (noprimary && zone->type == dns_zone_key) {
5032 result = add_soa(zone, db);
5033 if (result != ISC_R_SUCCESS) {
5034 goto cleanup;
5035 }
5036 }
5037
5038 /*
5039 * Apply update log, if any, on initial load.
5040 */
5041 if (zone->journal != NULL &&
5042 !DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE) &&
5043 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
5044 {
5045 result = zone_journal_rollforward(zone, db, &needdump,
5046 &fixjournal);
5047 if (result != ISC_R_SUCCESS) {
5048 goto cleanup;
5049 }
5050 }
5051
5052 /*
5053 * Obtain ns, soa and cname counts for top of zone.
5054 */
5055 INSIST(db != NULL);
5056 result = zone_get_from_db(zone, db, &nscount, &soacount, &soattl,
5057 &serial, &refresh, &retry, &expire, &minimum,
5058 &errors);
5059 if (result != ISC_R_SUCCESS && zone->type != dns_zone_key) {
5060 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
5061 "could not find NS and/or SOA records");
5062 }
5063
5064 /*
5065 * Process any queued NSEC3PARAM change requests. Only for dynamic
5066 * zones, an inline-signing zone will perform this action when
5067 * receiving the secure db (receive_secure_db).
5068 */
5069 is_dynamic = dns_zone_isdynamic(zone, true);
5070 if (is_dynamic) {
5071 process_zone_setnsec3param(zone);
5072 }
5073
5074 /*
5075 * Check to make sure the journal is up to date, and remove the
5076 * journal file if it isn't, as we wouldn't be able to apply
5077 * updates otherwise.
5078 */
5079 if (zone->journal != NULL && is_dynamic &&
5080 !DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS))
5081 {
5082 uint32_t jserial;
5083 dns_journal_t *journal = NULL;
5084 bool empty = false;
5085
5086 result = dns_journal_open(zone->mctx, zone->journal,
5087 DNS_JOURNAL_READ, &journal);
5088 if (result == ISC_R_SUCCESS) {
5089 jserial = dns_journal_last_serial(journal);
5090 empty = dns_journal_empty(journal);
5091 dns_journal_destroy(&journal);
5092 } else {
5093 jserial = serial;
5094 result = ISC_R_SUCCESS;
5095 }
5096
5097 if (jserial != serial) {
5098 if (!empty) {
5099 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5100 ISC_LOG_INFO,
5101 "journal file is out of date: "
5102 "removing journal file");
5103 }
5104 if (remove(zone->journal) < 0 && errno != ENOENT) {
5105 char strbuf[ISC_STRERRORSIZE];
5106 strerror_r(errno, strbuf, sizeof(strbuf));
5107 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
5108 DNS_LOGMODULE_ZONE,
5109 ISC_LOG_WARNING,
5110 "unable to remove journal "
5111 "'%s': '%s'",
5112 zone->journal, strbuf);
5113 }
5114 }
5115 }
5116
5117 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
5118 "loaded; checking validity");
5119
5120 /*
5121 * Primary / Secondary / Mirror / Stub zones require both NS and SOA
5122 * records at the top of the zone.
5123 */
5124
5125 switch (zone->type) {
5126 case dns_zone_dlz:
5127 case dns_zone_primary:
5128 case dns_zone_secondary:
5129 case dns_zone_mirror:
5130 case dns_zone_stub:
5131 case dns_zone_redirect:
5132 if (soacount != 1) {
5133 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5134 ISC_LOG_ERROR, "has %d SOA records",
5135 soacount);
5136 result = DNS_R_BADZONE;
5137 }
5138 if (nscount == 0) {
5139 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5140 ISC_LOG_ERROR, "has no NS records");
5141 result = DNS_R_BADZONE;
5142 }
5143 if (result != ISC_R_SUCCESS) {
5144 goto cleanup;
5145 }
5146 if (zone->type == dns_zone_primary && errors != 0) {
5147 result = DNS_R_BADZONE;
5148 goto cleanup;
5149 }
5150 if (zone->type != dns_zone_stub &&
5151 zone->type != dns_zone_redirect)
5152 {
5153 result = check_nsec3param(zone, db);
5154 if (result != ISC_R_SUCCESS) {
5155 goto cleanup;
5156 }
5157 }
5158 if (zone->type == dns_zone_primary &&
5159 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKINTEGRITY) &&
5160 !integrity_checks(zone, db))
5161 {
5162 result = DNS_R_BADZONE;
5163 goto cleanup;
5164 }
5165 if (zone->type == dns_zone_primary &&
5166 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRR) &&
5167 !zone_check_dup(zone, db))
5168 {
5169 result = DNS_R_BADZONE;
5170 goto cleanup;
5171 }
5172
5173 if (zone->type == dns_zone_primary) {
5174 result = dns_zone_cdscheck(zone, db, NULL);
5175 if (result != ISC_R_SUCCESS) {
5176 dns_zone_log(zone, ISC_LOG_ERROR,
5177 "CDS/CDNSKEY consistency checks "
5178 "failed");
5179 goto cleanup;
5180 }
5181 }
5182
5183 result = dns_zone_verifydb(zone, db, NULL);
5184 if (result != ISC_R_SUCCESS) {
5185 goto cleanup;
5186 }
5187
5188 if (zone->db != NULL) {
5189 unsigned int oldsoacount;
5190
5191 /*
5192 * This is checked in zone_replacedb() for
5193 * secondary zones as they don't reload from disk.
5194 */
5195 result = zone_get_from_db(
5196 zone, zone->db, NULL, &oldsoacount, NULL,
5197 &oldserial, NULL, NULL, NULL, NULL, NULL);
5198 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5199 RUNTIME_CHECK(oldsoacount > 0U);
5200 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
5201 !isc_serial_gt(serial, oldserial))
5202 {
5203 uint32_t serialmin, serialmax;
5204
5205 INSIST(zone->type == dns_zone_primary);
5206 INSIST(zone->raw == NULL);
5207
5208 if (serial == oldserial &&
5209 zone_unchanged(zone->db, db, zone->mctx))
5210 {
5211 dns_zone_logc(zone,
5212 DNS_LOGCATEGORY_ZONELOAD,
5213 ISC_LOG_INFO,
5214 "ixfr-from-differences: "
5215 "unchanged");
5216 zone->loadtime = loadtime;
5217 goto done;
5218 }
5219
5220 serialmin = (oldserial + 1) & 0xffffffffU;
5221 serialmax = (oldserial + 0x7fffffffU) &
5222 0xffffffffU;
5223 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5224 ISC_LOG_ERROR,
5225 "ixfr-from-differences: "
5226 "new serial (%u) out of range "
5227 "[%u - %u]",
5228 serial, serialmin, serialmax);
5229 result = DNS_R_BADZONE;
5230 goto cleanup;
5231 } else if (!isc_serial_ge(serial, oldserial)) {
5232 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5233 ISC_LOG_ERROR,
5234 "zone serial (%u/%u) has gone "
5235 "backwards",
5236 serial, oldserial);
5237 } else if (serial == oldserial && !hasinclude &&
5238 strcmp(zone->db_argv[0], "_builtin") != 0)
5239 {
5240 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5241 ISC_LOG_ERROR,
5242 "zone serial (%u) unchanged. "
5243 "zone may fail to transfer "
5244 "to secondaries.",
5245 serial);
5246 }
5247 }
5248
5249 if (zone->type == dns_zone_primary &&
5250 (zone->update_acl != NULL || zone->ssutable != NULL) &&
5251 dns_zone_getsigresigninginterval(zone) < (3 * refresh) &&
5252 dns_db_issecure(db))
5253 {
5254 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5255 ISC_LOG_WARNING,
5256 "sig-re-signing-interval less than "
5257 "3 * refresh.");
5258 }
5259
5260 zone->refresh = RANGE(refresh, zone->minrefresh,
5261 zone->maxrefresh);
5262 zone->retry = RANGE(retry, zone->minretry, zone->maxretry);
5263 zone->expire = RANGE(expire, zone->refresh + zone->retry,
5264 DNS_MAX_EXPIRE);
5265 zone->soattl = soattl;
5266 zone->minimum = minimum;
5267 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
5268
5269 if (zone->type == dns_zone_secondary ||
5270 zone->type == dns_zone_mirror ||
5271 zone->type == dns_zone_stub ||
5272 (zone->type == dns_zone_redirect &&
5273 dns_remote_addresses(&zone->primaries) != NULL))
5274 {
5275 isc_time_t t;
5276 uint32_t delay;
5277
5278 result = isc_file_getmodtime(zone->journal, &t);
5279 if (result != ISC_R_SUCCESS) {
5280 result = isc_file_getmodtime(zone->masterfile,
5281 &t);
5282 }
5283 if (result == ISC_R_SUCCESS) {
5284 DNS_ZONE_TIME_ADD(&t, zone->expire,
5285 &zone->expiretime);
5286 } else {
5287 DNS_ZONE_TIME_ADD(&now, zone->retry,
5288 &zone->expiretime);
5289 }
5290
5291 delay = (zone->retry -
5292 isc_random_uniform((zone->retry * 3) / 4));
5293 DNS_ZONE_TIME_ADD(&now, delay, &zone->refreshtime);
5294 if (isc_time_compare(&zone->refreshtime,
5295 &zone->expiretime) >= 0)
5296 {
5297 DNS_ZONE_SETFLAG(zone,
5298 DNS_ZONEFLG_FIRSTREFRESH);
5299 zone->refreshtime = now;
5300 } else {
5301 /* The zone is up to date. */
5302 DNS_ZONE_CLRFLAG(zone,
5303 DNS_ZONEFLG_FIRSTREFRESH);
5304 }
5305 }
5306
5307 break;
5308
5309 case dns_zone_key:
5310 /* Nothing needs to be done now */
5311 break;
5312
5313 default:
5314 UNEXPECTED_ERROR("unexpected zone type %d", zone->type);
5315 result = ISC_R_UNEXPECTED;
5316 goto cleanup;
5317 }
5318
5319 /*
5320 * Check for weak DNSKEY's.
5321 */
5322 if (zone->type == dns_zone_primary) {
5323 zone_check_dnskeys(zone, db);
5324 }
5325
5326 /*
5327 * Schedule DNSSEC key refresh.
5328 */
5329 if (zone->type == dns_zone_primary &&
5330 DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
5331 {
5332 zone->refreshkeytime = now;
5333 }
5334
5335 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
5336 if (zone->db != NULL) {
5337 had_db = true;
5338 result = zone_replacedb(zone, db, false);
5339 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
5340 if (result != ISC_R_SUCCESS) {
5341 goto cleanup;
5342 }
5343 } else {
5344 zone_attachdb(zone, db);
5345 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
5346 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED |
5347 DNS_ZONEFLG_NEEDSTARTUPNOTIFY);
5348 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SENDSECURE) &&
5349 inline_raw(zone))
5350 {
5351 if (zone->secure->db == NULL) {
5352 zone_send_securedb(zone, db);
5353 } else {
5354 zone_send_secureserial(zone, serial);
5355 }
5356 }
5357 }
5358
5359 /*
5360 * Finished loading inline-signing zone; need to get status
5361 * from the raw side now.
5362 */
5363 if (zone->type == dns_zone_primary && inline_secure(zone)) {
5364 maybe_send_secure(zone);
5365 }
5366
5367 result = ISC_R_SUCCESS;
5368
5369 if (fixjournal) {
5370 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FIXJOURNAL);
5371 zone_journal_compact(zone, zone->db, 0);
5372 }
5373 if (needdump) {
5374 if (zone->type == dns_zone_key) {
5375 zone_needdump(zone, 30);
5376 } else {
5377 zone_needdump(zone, DNS_DUMP_DELAY);
5378 }
5379 }
5380
5381 if (zone->loop != NULL) {
5382 if (zone->type == dns_zone_primary) {
5383 set_resigntime(zone);
5384 resume_signingwithkey(zone);
5385 resume_addnsec3chain(zone);
5386 }
5387
5388 is_dynamic = dns_zone_isdynamic(zone, false);
5389 if (zone->type == dns_zone_primary && is_dynamic &&
5390 dns_db_issecure(db) && !inline_raw(zone))
5391 {
5392 isc_stdtime_t resign;
5393 dns_name_t *name;
5394 dns_fixedname_t fixed;
5395 dns_typepair_t typepair;
5396
5397 name = dns_fixedname_initname(&fixed);
5398
5399 result = dns_db_getsigningtime(db, &resign, name,
5400 &typepair);
5401 if (result == ISC_R_SUCCESS) {
5402 isc_stdtime_t timenow = isc_stdtime_now();
5403 char namebuf[DNS_NAME_FORMATSIZE];
5404 char typebuf[DNS_RDATATYPE_FORMATSIZE];
5405
5406 dns_name_format(name, namebuf, sizeof(namebuf));
5407 dns_rdatatype_format(
5408 DNS_TYPEPAIR_COVERS(typepair), typebuf,
5409 sizeof(typebuf));
5410 dnssec_log(
5411 zone, ISC_LOG_DEBUG(3),
5412 "next resign: %s/%s "
5413 "in %d seconds",
5414 namebuf, typebuf,
5415 resign - timenow -
5416 dns_zone_getsigresigninginterval(
5417 zone));
5418 } else {
5419 dnssec_log(zone, ISC_LOG_WARNING,
5420 "signed dynamic zone has no "
5421 "resign event scheduled");
5422 }
5423 }
5424
5425 zone_settimer(zone, &now);
5426 }
5427
5428 /*
5429 * Clear old include list.
5430 */
5431 for (inc = ISC_LIST_HEAD(zone->includes); inc != NULL;
5432 inc = ISC_LIST_HEAD(zone->includes))
5433 {
5434 ISC_LIST_UNLINK(zone->includes, inc, link);
5435 isc_mem_free(zone->mctx, inc->name);
5436 isc_mem_put(zone->mctx, inc, sizeof(*inc));
5437 }
5438 zone->nincludes = 0;
5439
5440 /*
5441 * Transfer new include list.
5442 */
5443 for (inc = ISC_LIST_HEAD(zone->newincludes); inc != NULL;
5444 inc = ISC_LIST_HEAD(zone->newincludes))
5445 {
5446 ISC_LIST_UNLINK(zone->newincludes, inc, link);
5447 ISC_LIST_APPEND(zone->includes, inc, link);
5448 zone->nincludes++;
5449 }
5450
5451 if (!dns_db_ispersistent(db)) {
5452 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_INFO,
5453 "loaded serial %u%s", serial,
5454 dns_db_issecure(db) ? " (DNSSEC signed)" : "");
5455 }
5456
5457 if (!had_db && zone->type == dns_zone_mirror) {
5458 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_INFO,
5459 "mirror zone is now in use");
5460 }
5461
5462 zone->loadtime = loadtime;
5463 goto done;
5464
5465 cleanup:
5466 if (result != ISC_R_SUCCESS) {
5467 dns_zone_rpz_disable_db(zone, db);
5468 dns_zone_catz_disable_db(zone, db);
5469 }
5470
5471 for (inc = ISC_LIST_HEAD(zone->newincludes); inc != NULL;
5472 inc = ISC_LIST_HEAD(zone->newincludes))
5473 {
5474 ISC_LIST_UNLINK(zone->newincludes, inc, link);
5475 isc_mem_free(zone->mctx, inc->name);
5476 isc_mem_put(zone->mctx, inc, sizeof(*inc));
5477 }
5478 if (zone->type == dns_zone_secondary || zone->type == dns_zone_mirror ||
5479 zone->type == dns_zone_stub || zone->type == dns_zone_key ||
5480 (zone->type == dns_zone_redirect &&
5481 dns_remote_addresses(&zone->primaries) != NULL))
5482 {
5483 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FIRSTREFRESH);
5484
5485 if (result != ISC_R_NOMEMORY) {
5486 if (zone->journal != NULL) {
5487 zone_saveunique(zone, zone->journal,
5488 "jn-XXXXXXXX");
5489 }
5490 if (zone->masterfile != NULL) {
5491 zone_saveunique(zone, zone->masterfile,
5492 "db-XXXXXXXX");
5493 }
5494 }
5495
5496 /* Mark the zone for immediate refresh. */
5497 zone->refreshtime = now;
5498 if (zone->loop != NULL) {
5499 zone_settimer(zone, &now);
5500 }
5501 result = ISC_R_SUCCESS;
5502 } else if (zone->type == dns_zone_primary ||
5503 zone->type == dns_zone_redirect)
5504 {
5505 if (!(inline_secure(zone) && result == ISC_R_FILENOTFOUND)) {
5506 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5507 ISC_LOG_ERROR,
5508 "not loaded due to errors.");
5509 } else if (zone->type == dns_zone_primary) {
5510 result = ISC_R_SUCCESS;
5511 }
5512 }
5513
5514 done:
5515 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
5516 /*
5517 * If this is an inline-signed zone and we were called for the raw
5518 * zone, we need to clear DNS_ZONEFLG_LOADPENDING for the secure zone
5519 * as well, but only if this is a reload, not an initial zone load: in
5520 * the former case, zone_postload() will not be run for the secure
5521 * zone; in the latter case, it will be. Check which case we are
5522 * dealing with by consulting the DNS_ZONEFLG_LOADED flag for the
5523 * secure zone: if it is set, this must be a reload.
5524 */
5525 if (inline_raw(zone) && DNS_ZONE_FLAG(zone->secure, DNS_ZONEFLG_LOADED))
5526 {
5527 DNS_ZONE_CLRFLAG(zone->secure, DNS_ZONEFLG_LOADPENDING);
5528 /*
5529 * Re-start zone maintenance if it had been stalled
5530 * due to DNS_ZONEFLG_LOADPENDING being set when
5531 * zone_maintenance was called.
5532 */
5533 if (zone->secure->loop != NULL) {
5534 zone_settimer(zone->secure, &now);
5535 }
5536 }
5537
5538 zone_debuglog(zone, __func__, 99, "done");
5539
5540 return result;
5541 }
5542
5543 static bool
5544 exit_check(dns_zone_t *zone) {
5545 REQUIRE(LOCKED_ZONE(zone));
5546
5547 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) &&
5548 isc_refcount_current(&zone->irefs) == 0)
5549 {
5550 /*
5551 * DNS_ZONEFLG_SHUTDOWN can only be set if references == 0.
5552 */
5553 INSIST(isc_refcount_current(&zone->references) == 0);
5554 return true;
5555 }
5556 return false;
5557 }
5558
5559 static bool
5560 zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
5561 dns_name_t *name, bool logit) {
5562 isc_result_t result;
5563 char namebuf[DNS_NAME_FORMATSIZE];
5564 char altbuf[DNS_NAME_FORMATSIZE];
5565 dns_fixedname_t fixed;
5566 dns_name_t *foundname;
5567 int level;
5568
5569 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOCHECKNS)) {
5570 return true;
5571 }
5572
5573 if (zone->type == dns_zone_primary) {
5574 level = ISC_LOG_ERROR;
5575 } else {
5576 level = ISC_LOG_WARNING;
5577 }
5578
5579 foundname = dns_fixedname_initname(&fixed);
5580
5581 result = dns_db_find(db, name, version, dns_rdatatype_a, 0, 0, NULL,
5582 foundname, NULL, NULL);
5583 if (result == ISC_R_SUCCESS) {
5584 return true;
5585 }
5586
5587 if (result == DNS_R_NXRRSET) {
5588 result = dns_db_find(db, name, version, dns_rdatatype_aaaa, 0,
5589 0, NULL, foundname, NULL, NULL);
5590 if (result == ISC_R_SUCCESS) {
5591 return true;
5592 }
5593 }
5594
5595 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
5596 result == DNS_R_EMPTYNAME)
5597 {
5598 if (logit) {
5599 dns_name_format(name, namebuf, sizeof namebuf);
5600 dns_zone_log(zone, level,
5601 "NS '%s' has no address "
5602 "records (A or AAAA)",
5603 namebuf);
5604 }
5605 return false;
5606 }
5607
5608 if (result == DNS_R_CNAME) {
5609 if (logit) {
5610 dns_name_format(name, namebuf, sizeof namebuf);
5611 dns_zone_log(zone, level,
5612 "NS '%s' is a CNAME "
5613 "(illegal)",
5614 namebuf);
5615 }
5616 return false;
5617 }
5618
5619 if (result == DNS_R_DNAME) {
5620 if (logit) {
5621 dns_name_format(name, namebuf, sizeof namebuf);
5622 dns_name_format(foundname, altbuf, sizeof altbuf);
5623 dns_zone_log(zone, level,
5624 "NS '%s' is below a DNAME "
5625 "'%s' (illegal)",
5626 namebuf, altbuf);
5627 }
5628 return false;
5629 }
5630
5631 return true;
5632 }
5633
5634 static isc_result_t
5635 zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
5636 dns_dbversion_t *version, unsigned int *nscount,
5637 unsigned int *errors, bool logit) {
5638 isc_result_t result;
5639 unsigned int count = 0;
5640 unsigned int ecount = 0;
5641 dns_rdataset_t rdataset;
5642 dns_rdata_t rdata;
5643 dns_rdata_ns_t ns;
5644
5645 dns_rdataset_init(&rdataset);
5646 result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns,
5647 dns_rdatatype_none, 0, &rdataset, NULL);
5648 if (result == ISC_R_NOTFOUND) {
5649 INSIST(!dns_rdataset_isassociated(&rdataset));
5650 goto success;
5651 }
5652 if (result != ISC_R_SUCCESS) {
5653 INSIST(!dns_rdataset_isassociated(&rdataset));
5654 goto invalidate_rdataset;
5655 }
5656
5657 result = dns_rdataset_first(&rdataset);
5658 while (result == ISC_R_SUCCESS) {
5659 if (errors != NULL && zone->rdclass == dns_rdataclass_in &&
5660 (zone->type == dns_zone_primary ||
5661 zone->type == dns_zone_secondary ||
5662 zone->type == dns_zone_mirror))
5663 {
5664 dns_rdata_init(&rdata);
5665 dns_rdataset_current(&rdataset, &rdata);
5666 result = dns_rdata_tostruct(&rdata, &ns, NULL);
5667 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5668 if (dns_name_issubdomain(&ns.name, &zone->origin) &&
5669 !zone_check_ns(zone, db, version, &ns.name, logit))
5670 {
5671 ecount++;
5672 }
5673 }
5674 count++;
5675 result = dns_rdataset_next(&rdataset);
5676 }
5677 dns_rdataset_disassociate(&rdataset);
5678
5679 success:
5680 SET_IF_NOT_NULL(nscount, count);
5681 SET_IF_NOT_NULL(errors, ecount);
5682
5683 result = ISC_R_SUCCESS;
5684
5685 invalidate_rdataset:
5686 dns_rdataset_invalidate(&rdataset);
5687
5688 return result;
5689 }
5690
5691 #define SET_SOA_VALUES(soattl_v, serial_v, refresh_v, retry_v, expire_v, \
5692 minimum_v) \
5693 { \
5694 SET_IF_NOT_NULL(soattl, soattl_v); \
5695 SET_IF_NOT_NULL(serial, serial_v); \
5696 SET_IF_NOT_NULL(refresh, refresh_v); \
5697 SET_IF_NOT_NULL(retry, retry_v); \
5698 SET_IF_NOT_NULL(expire, expire_v); \
5699 SET_IF_NOT_NULL(minimum, minimum_v); \
5700 }
5701
5702 #define CLR_SOA_VALUES() \
5703 { \
5704 SET_SOA_VALUES(0, 0, 0, 0, 0, 0); \
5705 }
5706
5707 static isc_result_t
5708 zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
5709 unsigned int *soacount, uint32_t *soattl, uint32_t *serial,
5710 uint32_t *refresh, uint32_t *retry, uint32_t *expire,
5711 uint32_t *minimum) {
5712 isc_result_t result;
5713 unsigned int count = 0;
5714 dns_rdataset_t rdataset;
5715 dns_rdata_t rdata = DNS_RDATA_INIT;
5716
5717 dns_rdataset_init(&rdataset);
5718 result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
5719 dns_rdatatype_none, 0, &rdataset, NULL);
5720 if (result == ISC_R_NOTFOUND) {
5721 INSIST(!dns_rdataset_isassociated(&rdataset));
5722 result = ISC_R_SUCCESS;
5723 goto invalidate_rdataset;
5724 }
5725 if (result != ISC_R_SUCCESS) {
5726 INSIST(!dns_rdataset_isassociated(&rdataset));
5727 goto invalidate_rdataset;
5728 }
5729
5730 result = dns_rdataset_first(&rdataset);
5731 while (result == ISC_R_SUCCESS) {
5732 dns_rdata_init(&rdata);
5733 dns_rdataset_current(&rdataset, &rdata);
5734 count++;
5735 if (count == 1) {
5736 dns_rdata_soa_t soa;
5737 result = dns_rdata_tostruct(&rdata, &soa, NULL);
5738 SET_SOA_VALUES(rdataset.ttl, soa.serial, soa.refresh,
5739 soa.retry, soa.expire, soa.minimum);
5740 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5741 }
5742
5743 result = dns_rdataset_next(&rdataset);
5744 dns_rdata_reset(&rdata);
5745 }
5746 dns_rdataset_disassociate(&rdataset);
5747
5748 result = ISC_R_SUCCESS;
5749
5750 invalidate_rdataset:
5751 SET_IF_NOT_NULL(soacount, count);
5752 if (count == 0) {
5753 CLR_SOA_VALUES();
5754 }
5755
5756 dns_rdataset_invalidate(&rdataset);
5757
5758 return result;
5759 }
5760
5761 /*
5762 * zone must be locked.
5763 */
5764 static isc_result_t
5765 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
5766 unsigned int *soacount, uint32_t *soattl, uint32_t *serial,
5767 uint32_t *refresh, uint32_t *retry, uint32_t *expire,
5768 uint32_t *minimum, unsigned int *errors) {
5769 isc_result_t result;
5770 isc_result_t answer = ISC_R_SUCCESS;
5771 dns_dbversion_t *version = NULL;
5772 dns_dbnode_t *node;
5773
5774 REQUIRE(db != NULL);
5775 REQUIRE(zone != NULL);
5776
5777 dns_db_currentversion(db, &version);
5778
5779 SET_IF_NOT_NULL(nscount, 0);
5780 SET_IF_NOT_NULL(soacount, 0);
5781 SET_IF_NOT_NULL(errors, 0);
5782 CLR_SOA_VALUES();
5783
5784 node = NULL;
5785 result = dns_db_findnode(db, &zone->origin, false, &node);
5786 if (result != ISC_R_SUCCESS) {
5787 answer = result;
5788 goto closeversion;
5789 }
5790
5791 if (nscount != NULL || errors != NULL) {
5792 result = zone_count_ns_rr(zone, db, node, version, nscount,
5793 errors, true);
5794 if (result != ISC_R_SUCCESS) {
5795 answer = result;
5796 }
5797 }
5798
5799 if (soacount != NULL || soattl != NULL || serial != NULL ||
5800 refresh != NULL || retry != NULL || expire != NULL ||
5801 minimum != NULL)
5802 {
5803 result = zone_load_soa_rr(db, node, version, soacount, soattl,
5804 serial, refresh, retry, expire,
5805 minimum);
5806 if (result != ISC_R_SUCCESS) {
5807 answer = result;
5808 }
5809 }
5810
5811 dns_db_detachnode(db, &node);
5812 closeversion:
5813 dns_db_closeversion(db, &version, false);
5814
5815 return answer;
5816 }
5817
5818 static void
5819 zone_destroy(dns_zone_t *zone) {
5820 /*
5821 * Stop things being restarted after we cancel them below.
5822 */
5823 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
5824 dns_zone_log(zone, ISC_LOG_DEBUG(1), "final reference detached");
5825
5826 if (zone->loop == NULL) {
5827 /*
5828 * This zone is unmanaged; we're probably running in
5829 * named-checkzone or a unit test. There's no loop, so we
5830 * need to free it immediately.
5831 */
5832 zone_shutdown(zone);
5833 } else {
5834 /*
5835 * This zone has a loop; it can clean
5836 * itself up asynchronously.
5837 */
5838 isc_async_run(zone->loop, zone_shutdown, zone);
5839 }
5840 }
5841
5842 #if DNS_ZONE_TRACE
5843 ISC_REFCOUNT_TRACE_IMPL(dns_zone, zone_destroy);
5844 #else
5845 ISC_REFCOUNT_IMPL(dns_zone, zone_destroy);
5846 #endif
5847
5848 void
5849 dns_zone_iattach(dns_zone_t *source, dns_zone_t **target) {
5850 REQUIRE(DNS_ZONE_VALID(source));
5851
5852 LOCK_ZONE(source);
5853 zone_iattach(source, target);
5854 UNLOCK_ZONE(source);
5855 }
5856
5857 static void
5858 zone_iattach(dns_zone_t *source, dns_zone_t **target) {
5859 REQUIRE(DNS_ZONE_VALID(source));
5860 REQUIRE(LOCKED_ZONE(source));
5861 REQUIRE(target != NULL && *target == NULL);
5862 INSIST(isc_refcount_increment0(&source->irefs) +
5863 isc_refcount_current(&source->references) >
5864 0);
5865 *target = source;
5866 }
5867
5868 static void
5869 zone_idetach(dns_zone_t **zonep) {
5870 dns_zone_t *zone;
5871
5872 /*
5873 * 'zone' locked by caller.
5874 */
5875 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
5876 REQUIRE(LOCKED_ZONE(*zonep));
5877
5878 zone = *zonep;
5879 *zonep = NULL;
5880
5881 INSIST(isc_refcount_decrement(&zone->irefs) - 1 +
5882 isc_refcount_current(&zone->references) >
5883 0);
5884 }
5885
5886 void
5887 dns_zone_idetach(dns_zone_t **zonep) {
5888 dns_zone_t *zone;
5889
5890 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
5891
5892 zone = *zonep;
5893 *zonep = NULL;
5894
5895 if (isc_refcount_decrement(&zone->irefs) == 1) {
5896 bool free_needed;
5897 LOCK_ZONE(zone);
5898 free_needed = exit_check(zone);
5899 UNLOCK_ZONE(zone);
5900 if (free_needed) {
5901 zone_free(zone);
5902 }
5903 }
5904 }
5905
5906 isc_mem_t *
5907 dns_zone_getmctx(dns_zone_t *zone) {
5908 REQUIRE(DNS_ZONE_VALID(zone));
5909
5910 return zone->mctx;
5911 }
5912
5913 dns_zonemgr_t *
5914 dns_zone_getmgr(dns_zone_t *zone) {
5915 REQUIRE(DNS_ZONE_VALID(zone));
5916
5917 return zone->zmgr;
5918 }
5919
5920 void
5921 dns_zone_setkasp(dns_zone_t *zone, dns_kasp_t *kasp) {
5922 REQUIRE(DNS_ZONE_VALID(zone));
5923
5924 LOCK_ZONE(zone);
5925 if (zone->kasp != NULL) {
5926 dns_kasp_detach(&zone->kasp);
5927 }
5928 if (kasp != NULL) {
5929 dns_kasp_attach(kasp, &zone->kasp);
5930 }
5931 UNLOCK_ZONE(zone);
5932 }
5933
5934 void
5935 dns_zone_setdefaultkasp(dns_zone_t *zone, dns_kasp_t *kasp) {
5936 REQUIRE(DNS_ZONE_VALID(zone));
5937
5938 LOCK_ZONE(zone);
5939 if (zone->defaultkasp != NULL) {
5940 dns_kasp_detach(&zone->defaultkasp);
5941 }
5942 if (kasp != NULL) {
5943 dns_kasp_attach(kasp, &zone->defaultkasp);
5944 }
5945 UNLOCK_ZONE(zone);
5946 }
5947
5948 dns_kasp_t *
5949 dns_zone_getkasp(dns_zone_t *zone) {
5950 dns_kasp_t *kasp;
5951
5952 REQUIRE(DNS_ZONE_VALID(zone));
5953
5954 LOCK_ZONE(zone);
5955 if (inline_raw(zone) && zone->secure != NULL) {
5956 kasp = zone->secure->kasp;
5957 } else {
5958 kasp = zone->kasp;
5959 }
5960 UNLOCK_ZONE(zone);
5961
5962 return kasp;
5963 }
5964
5965 static void
5966 dns_zone_setskr(dns_zone_t *zone, dns_skr_t *skr) {
5967 REQUIRE(DNS_ZONE_VALID(zone));
5968
5969 LOCK_ZONE(zone);
5970 zone->skrbundle = NULL;
5971 if (zone->skr != NULL) {
5972 dns_skr_detach(&zone->skr);
5973 }
5974 if (skr != NULL) {
5975 dns_skr_attach(skr, &zone->skr);
5976 }
5977 UNLOCK_ZONE(zone);
5978 }
5979
5980 dns_skrbundle_t *
5981 dns_zone_getskrbundle(dns_zone_t *zone) {
5982 dns_skrbundle_t *bundle;
5983
5984 REQUIRE(DNS_ZONE_VALID(zone));
5985
5986 LOCK_ZONE(zone);
5987 if (inline_raw(zone) && zone->secure != NULL) {
5988 bundle = zone->secure->skrbundle;
5989 } else {
5990 bundle = zone->skrbundle;
5991 }
5992 UNLOCK_ZONE(zone);
5993
5994 return bundle;
5995 }
5996
5997 void
5998 dns_zone_setoption(dns_zone_t *zone, dns_zoneopt_t option, bool value) {
5999 REQUIRE(DNS_ZONE_VALID(zone));
6000
6001 if (value) {
6002 DNS_ZONE_SETOPTION(zone, option);
6003 } else {
6004 DNS_ZONE_CLROPTION(zone, option);
6005 }
6006 }
6007
6008 dns_zoneopt_t
6009 dns_zone_getoptions(dns_zone_t *zone) {
6010 REQUIRE(DNS_ZONE_VALID(zone));
6011
6012 return ISC_ZONE_GET(zone, options);
6013 }
6014
6015 void
6016 dns_zone_setkeyopt(dns_zone_t *zone, unsigned int keyopt, bool value) {
6017 REQUIRE(DNS_ZONE_VALID(zone));
6018
6019 if (value) {
6020 DNS_ZONEKEY_SETOPTION(zone, keyopt);
6021 } else {
6022 DNS_ZONEKEY_CLROPTION(zone, keyopt);
6023 }
6024 }
6025
6026 unsigned int
6027 dns_zone_getkeyopts(dns_zone_t *zone) {
6028 REQUIRE(DNS_ZONE_VALID(zone));
6029
6030 return ISC_ZONE_GET(zone, keyopts);
6031 }
6032
6033 void
6034 dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
6035 REQUIRE(DNS_ZONE_VALID(zone));
6036 REQUIRE(xfrsource != NULL);
6037
6038 LOCK_ZONE(zone);
6039 zone->xfrsource4 = *xfrsource;
6040 UNLOCK_ZONE(zone);
6041 }
6042
6043 void
6044 dns_zone_getxfrsource4(dns_zone_t *zone, isc_sockaddr_t *xfrsource) {
6045 REQUIRE(DNS_ZONE_VALID(zone));
6046 REQUIRE(xfrsource != NULL);
6047
6048 LOCK_ZONE(zone);
6049 *xfrsource = zone->xfrsource4;
6050 UNLOCK_ZONE(zone);
6051 }
6052
6053 void
6054 dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
6055 REQUIRE(DNS_ZONE_VALID(zone));
6056 REQUIRE(xfrsource != NULL);
6057
6058 LOCK_ZONE(zone);
6059 zone->xfrsource6 = *xfrsource;
6060 UNLOCK_ZONE(zone);
6061 }
6062
6063 void
6064 dns_zone_getxfrsource6(dns_zone_t *zone, isc_sockaddr_t *xfrsource) {
6065 REQUIRE(DNS_ZONE_VALID(zone));
6066 REQUIRE(xfrsource != NULL);
6067
6068 LOCK_ZONE(zone);
6069 *xfrsource = zone->xfrsource6;
6070 UNLOCK_ZONE(zone);
6071 }
6072
6073 void
6074 dns_zone_setparentalsrc4(dns_zone_t *zone, const isc_sockaddr_t *parentalsrc) {
6075 REQUIRE(DNS_ZONE_VALID(zone));
6076 REQUIRE(parentalsrc != NULL);
6077
6078 LOCK_ZONE(zone);
6079 zone->parentalsrc4 = *parentalsrc;
6080 UNLOCK_ZONE(zone);
6081 }
6082
6083 void
6084 dns_zone_getparentalsrc4(dns_zone_t *zone, isc_sockaddr_t *parentalsrc) {
6085 REQUIRE(DNS_ZONE_VALID(zone));
6086 REQUIRE(parentalsrc != NULL);
6087
6088 LOCK_ZONE(zone);
6089 *parentalsrc = zone->parentalsrc4;
6090 UNLOCK_ZONE(zone);
6091 }
6092
6093 void
6094 dns_zone_setparentalsrc6(dns_zone_t *zone, const isc_sockaddr_t *parentalsrc) {
6095 REQUIRE(DNS_ZONE_VALID(zone));
6096
6097 LOCK_ZONE(zone);
6098 zone->parentalsrc6 = *parentalsrc;
6099 UNLOCK_ZONE(zone);
6100 }
6101
6102 void
6103 dns_zone_getparentalsrc6(dns_zone_t *zone, isc_sockaddr_t *parentalsrc) {
6104 REQUIRE(DNS_ZONE_VALID(zone));
6105 REQUIRE(parentalsrc != NULL);
6106
6107 LOCK_ZONE(zone);
6108 *parentalsrc = zone->parentalsrc6;
6109 UNLOCK_ZONE(zone);
6110 }
6111
6112 void
6113 dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
6114 REQUIRE(DNS_ZONE_VALID(zone));
6115 REQUIRE(notifysrc != NULL);
6116
6117 LOCK_ZONE(zone);
6118 zone->notifysrc4 = *notifysrc;
6119 UNLOCK_ZONE(zone);
6120 }
6121
6122 void
6123 dns_zone_getnotifysrc4(dns_zone_t *zone, isc_sockaddr_t *notifysrc) {
6124 REQUIRE(DNS_ZONE_VALID(zone));
6125 REQUIRE(notifysrc != NULL);
6126
6127 LOCK_ZONE(zone);
6128 *notifysrc = zone->notifysrc4;
6129 UNLOCK_ZONE(zone);
6130 }
6131
6132 void
6133 dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
6134 REQUIRE(DNS_ZONE_VALID(zone));
6135 REQUIRE(notifysrc != NULL);
6136
6137 LOCK_ZONE(zone);
6138 zone->notifysrc6 = *notifysrc;
6139 UNLOCK_ZONE(zone);
6140 }
6141
6142 void
6143 dns_zone_getnotifysrc6(dns_zone_t *zone, isc_sockaddr_t *notifysrc) {
6144 REQUIRE(DNS_ZONE_VALID(zone));
6145 REQUIRE(notifysrc != NULL);
6146
6147 LOCK_ZONE(zone);
6148 *notifysrc = zone->notifysrc6;
6149 UNLOCK_ZONE(zone);
6150 }
6151
6152 void
6153 dns_zone_setalsonotify(dns_zone_t *zone, isc_sockaddr_t *addresses,
6154 isc_sockaddr_t *sources, dns_name_t **keynames,
6155 dns_name_t **tlsnames, uint32_t count) {
6156 dns_remote_t remote;
6157
6158 REQUIRE(DNS_ZONE_VALID(zone));
6159
6160 LOCK_ZONE(zone);
6161
6162 remote.magic = DNS_REMOTE_MAGIC;
6163 remote.addresses = addresses;
6164 remote.sources = sources;
6165 remote.keynames = keynames;
6166 remote.tlsnames = tlsnames;
6167 remote.addrcnt = count;
6168
6169 if (dns_remote_equal(&zone->notify, &remote)) {
6170 goto unlock;
6171 }
6172
6173 dns_remote_clear(&zone->notify);
6174
6175 /*
6176 * If count == 0, don't allocate any space for servers to notify.
6177 */
6178 if (count == 0) {
6179 goto unlock;
6180 }
6181
6182 /*
6183 * Now set up the notify address and key lists.
6184 */
6185 dns_remote_init(&zone->notify, count, addresses, sources, keynames,
6186 tlsnames, true, zone->mctx);
6187
6188 unlock:
6189 UNLOCK_ZONE(zone);
6190 }
6191
6192 static bool
6193 has_pf(isc_sockaddr_t *addresses, size_t count, int pf) {
6194 for (size_t i = 0; i < count; i++) {
6195 if (isc_sockaddr_pf(&addresses[i]) == pf) {
6196 return true;
6197 }
6198 }
6199 return false;
6200 }
6201
6202 static void
6203 report_no_active_addresses(dns_zone_t *zone, isc_sockaddr_t *addresses,
6204 size_t count, const char *what) {
6205 if (isc_net_probeipv4() == ISC_R_DISABLED) {
6206 if (!has_pf(addresses, count, AF_INET6)) {
6207 dns_zone_log(zone, ISC_LOG_NOTICE,
6208 "IPv4 disabled and no IPv6 %s", what);
6209 }
6210 } else if (isc_net_probeipv6() == ISC_R_DISABLED) {
6211 if (!has_pf(addresses, count, AF_INET)) {
6212 dns_zone_log(zone, ISC_LOG_NOTICE,
6213 "IPv6 disabled and no IPv4 %s", what);
6214 }
6215 }
6216 }
6217
6218 void
6219 dns_zone_setprimaries(dns_zone_t *zone, isc_sockaddr_t *addresses,
6220 isc_sockaddr_t *sources, dns_name_t **keynames,
6221 dns_name_t **tlsnames, uint32_t count) {
6222 dns_remote_t remote;
6223
6224 REQUIRE(DNS_ZONE_VALID(zone));
6225
6226 LOCK_ZONE(zone);
6227
6228 remote.magic = DNS_REMOTE_MAGIC;
6229 remote.addresses = addresses;
6230 remote.sources = sources;
6231 remote.keynames = keynames;
6232 remote.tlsnames = tlsnames;
6233 remote.addrcnt = count;
6234
6235 /*
6236 * The refresh code assumes that 'primaries' wouldn't change under it.
6237 * If it will change then kill off any current refresh in progress
6238 * and update the primaries info. If it won't change then we can just
6239 * unlock and exit.
6240 */
6241 if (!dns_remote_equal(&zone->primaries, &remote)) {
6242 if (zone->request != NULL) {
6243 dns_request_cancel(zone->request);
6244 }
6245 } else {
6246 goto unlock;
6247 }
6248
6249 dns_remote_clear(&zone->primaries);
6250
6251 /*
6252 * If count == 0, don't allocate any space for primaries.
6253 */
6254 if (count == 0) {
6255 goto unlock;
6256 }
6257
6258 report_no_active_addresses(zone, addresses, count, "primaries");
6259
6260 /*
6261 * Now set up the primaries and primary key lists.
6262 */
6263 dns_remote_init(&zone->primaries, count, addresses, sources, keynames,
6264 tlsnames, true, zone->mctx);
6265
6266 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOPRIMARIES);
6267
6268 unlock:
6269 UNLOCK_ZONE(zone);
6270 }
6271
6272 void
6273 dns_zone_setparentals(dns_zone_t *zone, isc_sockaddr_t *addresses,
6274 isc_sockaddr_t *sources, dns_name_t **keynames,
6275 dns_name_t **tlsnames, uint32_t count) {
6276 dns_remote_t remote;
6277
6278 REQUIRE(DNS_ZONE_VALID(zone));
6279
6280 LOCK_ZONE(zone);
6281
6282 remote.magic = DNS_REMOTE_MAGIC;
6283 remote.addresses = addresses;
6284 remote.sources = sources;
6285 remote.keynames = keynames;
6286 remote.tlsnames = tlsnames;
6287 remote.addrcnt = count;
6288
6289 if (dns_remote_equal(&zone->parentals, &remote)) {
6290 goto unlock;
6291 }
6292
6293 dns_remote_clear(&zone->parentals);
6294
6295 /*
6296 * If count == 0, don't allocate any space for parentals.
6297 */
6298 if (count == 0) {
6299 goto unlock;
6300 }
6301
6302 report_no_active_addresses(zone, addresses, count, "parental-agents");
6303
6304 /*
6305 * Now set up the parentals and parental key lists.
6306 */
6307 dns_remote_init(&zone->parentals, count, addresses, sources, keynames,
6308 tlsnames, true, zone->mctx);
6309
6310 dns_zone_log(zone, ISC_LOG_NOTICE, "checkds: set %u parentals", count);
6311
6312 unlock:
6313 UNLOCK_ZONE(zone);
6314 }
6315
6316 isc_result_t
6317 dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) {
6318 isc_result_t result = ISC_R_SUCCESS;
6319
6320 REQUIRE(DNS_ZONE_VALID(zone));
6321
6322 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6323 if (zone->db == NULL) {
6324 result = DNS_R_NOTLOADED;
6325 } else {
6326 dns_db_attach(zone->db, dpb);
6327 }
6328 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6329
6330 return result;
6331 }
6332
6333 void
6334 dns_zone_setdb(dns_zone_t *zone, dns_db_t *db) {
6335 REQUIRE(DNS_ZONE_VALID(zone));
6336 REQUIRE(zone->type == dns_zone_staticstub);
6337
6338 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
6339 REQUIRE(zone->db == NULL);
6340 dns_db_attach(db, &zone->db);
6341 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
6342 }
6343
6344 static bool
6345 was_dumping(dns_zone_t *zone) {
6346 REQUIRE(LOCKED_ZONE(zone));
6347
6348 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
6349 return true;
6350 }
6351
6352 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
6353 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
6354 isc_time_settoepoch(&zone->dumptime);
6355 return false;
6356 }
6357
6358 static isc_result_t
6359 keyfromfile(dns_zone_t *zone, dst_key_t *pubkey, isc_mem_t *mctx,
6360 dst_key_t **key) {
6361 const char *directory = zone->keydirectory;
6362 dns_kasp_t *kasp = zone->kasp;
6363 dst_key_t *foundkey = NULL;
6364 isc_result_t result = ISC_R_NOTFOUND;
6365
6366 if (kasp == NULL || (strcmp(dns_kasp_getname(kasp), "none") == 0) ||
6367 (strcmp(dns_kasp_getname(kasp), "insecure") == 0))
6368 {
6369 result = dst_key_fromfile(
6370 dst_key_name(pubkey), dst_key_id(pubkey),
6371 dst_key_alg(pubkey),
6372 DST_TYPE_PUBLIC | DST_TYPE_PRIVATE | DST_TYPE_STATE,
6373 directory, mctx, &foundkey);
6374 } else {
6375 for (dns_kasp_key_t *kkey = ISC_LIST_HEAD(dns_kasp_keys(kasp));
6376 kkey != NULL; kkey = ISC_LIST_NEXT(kkey, link))
6377 {
6378 dns_keystore_t *ks = dns_kasp_key_keystore(kkey);
6379 directory = dns_keystore_directory(ks,
6380 zone->keydirectory);
6381
6382 result = dst_key_fromfile(
6383 dst_key_name(pubkey), dst_key_id(pubkey),
6384 dst_key_alg(pubkey),
6385 DST_TYPE_PUBLIC | DST_TYPE_PRIVATE |
6386 DST_TYPE_STATE,
6387 directory, mctx, &foundkey);
6388 if (result == ISC_R_SUCCESS) {
6389 break;
6390 }
6391 }
6392 }
6393
6394 *key = foundkey;
6395 return result;
6396 }
6397
6398 #define is_zone_key(key) \
6399 ((dst_key_flags(key) & DNS_KEYFLAG_OWNERMASK) == DNS_KEYOWNER_ZONE)
6400
6401 static isc_result_t
6402 findzonekeys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
6403 dns_dbnode_t *node, const dns_name_t *name, isc_stdtime_t now,
6404 isc_mem_t *mctx, unsigned int maxkeys, dst_key_t **keys,
6405 unsigned int *nkeys) {
6406 dns_rdataset_t rdataset;
6407 dns_rdata_t rdata = DNS_RDATA_INIT;
6408 isc_result_t result;
6409 dst_key_t *pubkey = NULL;
6410 unsigned int count = 0;
6411
6412 *nkeys = 0;
6413 memset(keys, 0, sizeof(*keys) * maxkeys);
6414 dns_rdataset_init(&rdataset);
6415 CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey, 0, 0,
6416 &rdataset, NULL));
6417 CHECK(dns_rdataset_first(&rdataset));
6418 while (result == ISC_R_SUCCESS && count < maxkeys) {
6419 pubkey = NULL;
6420 dns_rdataset_current(&rdataset, &rdata);
6421 CHECK(dns_dnssec_keyfromrdata(name, &rdata, mctx, &pubkey));
6422 dst_key_setttl(pubkey, rdataset.ttl);
6423
6424 if (!is_zone_key(pubkey)) {
6425 goto next;
6426 }
6427 /* Corrupted .key file? */
6428 if (!dns_name_equal(name, dst_key_name(pubkey))) {
6429 goto next;
6430 }
6431 keys[count] = NULL;
6432 result = keyfromfile(zone, pubkey, mctx, &keys[count]);
6433
6434 /*
6435 * If the key was revoked and the private file
6436 * doesn't exist, maybe it was revoked internally
6437 * by named. Try loading the unrevoked version.
6438 */
6439 if (result == ISC_R_FILENOTFOUND) {
6440 uint32_t flags;
6441 flags = dst_key_flags(pubkey);
6442 if ((flags & DNS_KEYFLAG_REVOKE) != 0) {
6443 dst_key_setflags(pubkey,
6444 flags & ~DNS_KEYFLAG_REVOKE);
6445 result = keyfromfile(zone, pubkey, mctx,
6446 &keys[count]);
6447 if (result == ISC_R_SUCCESS &&
6448 dst_key_pubcompare(pubkey, keys[count],
6449 false))
6450 {
6451 dst_key_setflags(keys[count], flags);
6452 }
6453 dst_key_setflags(pubkey, flags);
6454 }
6455 }
6456
6457 if (result != ISC_R_SUCCESS) {
6458 char filename[DNS_NAME_FORMATSIZE +
6459 DNS_SECALG_FORMATSIZE +
6460 sizeof("key file for //65535")];
6461 isc_result_t result2;
6462 isc_buffer_t buf;
6463
6464 isc_buffer_init(&buf, filename, sizeof(filename));
6465 result2 = dst_key_getfilename(
6466 dst_key_name(pubkey), dst_key_id(pubkey),
6467 dst_key_alg(pubkey),
6468 DST_TYPE_PUBLIC | DST_TYPE_PRIVATE |
6469 DST_TYPE_STATE,
6470 NULL, mctx, &buf);
6471 if (result2 != ISC_R_SUCCESS) {
6472 char namebuf[DNS_NAME_FORMATSIZE];
6473 char algbuf[DNS_SECALG_FORMATSIZE];
6474
6475 dns_name_format(dst_key_name(pubkey), namebuf,
6476 sizeof(namebuf));
6477 dns_secalg_format(dst_key_alg(pubkey), algbuf,
6478 sizeof(algbuf));
6479 snprintf(filename, sizeof(filename) - 1,
6480 "key file for %s/%s/%d", namebuf,
6481 algbuf, dst_key_id(pubkey));
6482 }
6483
6484 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
6485 DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING,
6486 "dns_zone_findkeys: error reading %s: %s",
6487 filename, isc_result_totext(result));
6488 }
6489
6490 if (result == ISC_R_FILENOTFOUND || result == ISC_R_NOPERM) {
6491 keys[count] = pubkey;
6492 pubkey = NULL;
6493 count++;
6494 goto next;
6495 }
6496
6497 CHECK(result);
6498
6499 /*
6500 * If a key is marked inactive, skip it
6501 */
6502 if (!dns_dnssec_keyactive(keys[count], now)) {
6503 dst_key_setinactive(pubkey, true);
6504 dst_key_free(&keys[count]);
6505 keys[count] = pubkey;
6506 pubkey = NULL;
6507 count++;
6508 goto next;
6509 }
6510
6511 /*
6512 * Whatever the key's default TTL may have
6513 * been, the rdataset TTL takes priority.
6514 */
6515 dst_key_setttl(keys[count], rdataset.ttl);
6516 count++;
6517 next:
6518 if (pubkey != NULL) {
6519 dst_key_free(&pubkey);
6520 }
6521 dns_rdata_reset(&rdata);
6522 result = dns_rdataset_next(&rdataset);
6523 }
6524 if (result != ISC_R_NOMORE) {
6525 CHECK(result);
6526 }
6527 if (count == 0) {
6528 result = ISC_R_NOTFOUND;
6529 } else {
6530 result = ISC_R_SUCCESS;
6531 }
6532
6533 cleanup:
6534 if (dns_rdataset_isassociated(&rdataset)) {
6535 dns_rdataset_disassociate(&rdataset);
6536 }
6537 if (pubkey != NULL) {
6538 dst_key_free(&pubkey);
6539 }
6540 if (result != ISC_R_SUCCESS) {
6541 while (count > 0) {
6542 dst_key_free(&keys[--count]);
6543 }
6544 }
6545 *nkeys = count;
6546 return result;
6547 }
6548
6549 /*%
6550 * Find up to 'maxkeys' DNSSEC keys used for signing version 'ver' of database
6551 * 'db' for zone 'zone' in its key directory, then load these keys into 'keys'.
6552 * Only load the public part of a given key if it is not active at timestamp
6553 * 'now'. Store the number of keys found in 'nkeys'.
6554 */
6555 isc_result_t
6556 dns_zone_findkeys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
6557 isc_stdtime_t now, isc_mem_t *mctx, unsigned int maxkeys,
6558 dst_key_t **keys, unsigned int *nkeys) {
6559 isc_result_t result;
6560 dns_dbnode_t *node = NULL;
6561
6562 REQUIRE(DNS_ZONE_VALID(zone));
6563 REQUIRE(mctx != NULL);
6564 REQUIRE(nkeys != NULL);
6565 REQUIRE(keys != NULL);
6566
6567 CHECK(dns_db_findnode(db, dns_db_origin(db), false, &node));
6568
6569 dns_zone_lock_keyfiles(zone);
6570
6571 result = findzonekeys(zone, db, ver, node, dns_db_origin(db), now, mctx,
6572 maxkeys, keys, nkeys);
6573
6574 dns_zone_unlock_keyfiles(zone);
6575
6576 if (result == ISC_R_NOTFOUND) {
6577 result = ISC_R_SUCCESS;
6578 }
6579
6580 cleanup:
6581
6582 if (node != NULL) {
6583 dns_db_detachnode(db, &node);
6584 }
6585 return result;
6586 }
6587
6588 void
6589 dns_zone_prepare_shutdown(dns_zone_t *zone) {
6590 REQUIRE(DNS_ZONE_VALID(zone));
6591
6592 LOCK_ZONE(zone);
6593 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
6594 UNLOCK_ZONE(zone);
6595 }
6596
6597 /*%
6598 * Find DNSSEC keys used for signing zone with dnssec-policy. Load these keys
6599 * into 'keys'. Requires KASP to be locked.
6600 */
6601 isc_result_t
6602 dns_zone_getdnsseckeys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
6603 isc_stdtime_t now, dns_dnsseckeylist_t *keys) {
6604 isc_result_t result;
6605 const char *dir = dns_zone_getkeydirectory(zone);
6606 dns_dbnode_t *node = NULL;
6607 dns_dnsseckey_t *key, *key_next;
6608 dns_dnsseckeylist_t dnskeys;
6609 dns_name_t *origin = dns_zone_getorigin(zone);
6610 dns_kasp_t *kasp = zone->kasp;
6611 dns_rdataset_t keyset;
6612
6613 REQUIRE(DNS_ZONE_VALID(zone));
6614 REQUIRE(kasp != NULL);
6615
6616 ISC_LIST_INIT(dnskeys);
6617
6618 dns_rdataset_init(&keyset);
6619
6620 CHECK(dns_db_findnode(db, origin, false, &node));
6621
6622 /* Get keys from private key files. */
6623 dns_zone_lock_keyfiles(zone);
6624 result = dns_dnssec_findmatchingkeys(origin, kasp, dir, zone->keystores,
6625 now, false, dns_zone_getmctx(zone),
6626 keys);
6627 dns_zone_unlock_keyfiles(zone);
6628
6629 if (result != ISC_R_NOTFOUND) {
6630 CHECK(result);
6631 }
6632
6633 /* Get public keys (dnskeys). */
6634 dns_rdataset_init(&keyset);
6635 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
6636 dns_rdatatype_none, 0, &keyset, NULL);
6637 if (result == ISC_R_SUCCESS) {
6638 CHECK(dns_dnssec_keylistfromrdataset(
6639 origin, kasp, dir, dns_zone_getmctx(zone), &keyset,
6640 NULL, NULL, false, false, &dnskeys));
6641 } else if (result != ISC_R_NOTFOUND) {
6642 CHECK(result);
6643 }
6644
6645 /* Add new 'dnskeys' to 'keys'. */
6646 for (dns_dnsseckey_t *k1 = ISC_LIST_HEAD(dnskeys); k1 != NULL;
6647 k1 = key_next)
6648 {
6649 dns_dnsseckey_t *k2 = NULL;
6650 key_next = ISC_LIST_NEXT(k1, link);
6651
6652 for (k2 = ISC_LIST_HEAD(*keys); k2 != NULL;
6653 k2 = ISC_LIST_NEXT(k2, link))
6654 {
6655 if (dst_key_compare(k1->key, k2->key)) {
6656 break;
6657 }
6658 }
6659 /* No match found, add the new key. */
6660 if (k2 == NULL) {
6661 ISC_LIST_UNLINK(dnskeys, k1, link);
6662 ISC_LIST_APPEND(*keys, k1, link);
6663 }
6664 }
6665
6666 cleanup:
6667 if (dns_rdataset_isassociated(&keyset)) {
6668 dns_rdataset_disassociate(&keyset);
6669 }
6670 if (node != NULL) {
6671 dns_db_detachnode(db, &node);
6672 }
6673 while (!ISC_LIST_EMPTY(dnskeys)) {
6674 key = ISC_LIST_HEAD(dnskeys);
6675 ISC_LIST_UNLINK(dnskeys, key, link);
6676 dns_dnsseckey_destroy(dns_zone_getmctx(zone), &key);
6677 }
6678 return result;
6679 }
6680
6681 static isc_result_t
6682 offline(dns_db_t *db, dns_dbversion_t *ver, dns__zonediff_t *zonediff,
6683 dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata) {
6684 isc_result_t result;
6685
6686 if ((rdata->flags & DNS_RDATA_OFFLINE) != 0) {
6687 return ISC_R_SUCCESS;
6688 }
6689 result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_DELRESIGN,
6690 name, ttl, rdata);
6691 if (result != ISC_R_SUCCESS) {
6692 return result;
6693 }
6694 rdata->flags |= DNS_RDATA_OFFLINE;
6695 result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_ADDRESIGN,
6696 name, ttl, rdata);
6697 zonediff->offline = true;
6698 return result;
6699 }
6700
6701 static void
6702 set_key_expiry_warning(dns_zone_t *zone, isc_stdtime_t when,
6703 isc_stdtime_t now) {
6704 unsigned int delta;
6705 char timebuf[80];
6706
6707 LOCK_ZONE(zone);
6708 zone->key_expiry = when;
6709 if (when <= now) {
6710 dns_zone_log(zone, ISC_LOG_ERROR,
6711 "DNSKEY RRSIG(s) have expired");
6712 isc_time_settoepoch(&zone->keywarntime);
6713 } else if (when < now + 7 * 24 * 3600) {
6714 isc_time_t t;
6715 isc_time_set(&t, when, 0);
6716 isc_time_formattimestamp(&t, timebuf, 80);
6717 dns_zone_log(zone, ISC_LOG_WARNING,
6718 "DNSKEY RRSIG(s) will expire within 7 days: %s",
6719 timebuf);
6720 delta = when - now;
6721 delta--; /* loop prevention */
6722 delta /= 24 * 3600; /* to whole days */
6723 delta *= 24 * 3600; /* to seconds */
6724 isc_time_set(&zone->keywarntime, when - delta, 0);
6725 } else {
6726 isc_time_set(&zone->keywarntime, when - 7 * 24 * 3600, 0);
6727 isc_time_formattimestamp(&zone->keywarntime, timebuf, 80);
6728 dns_zone_log(zone, ISC_LOG_NOTICE, "setting keywarntime to %s",
6729 timebuf);
6730 }
6731 UNLOCK_ZONE(zone);
6732 }
6733
6734 /*
6735 * Helper function to del_sigs(). We don't want to delete RRSIGs that
6736 * have no new key.
6737 */
6738 static bool
6739 delsig_ok(dns_rdata_rrsig_t *rrsig_ptr, dst_key_t **keys, unsigned int nkeys,
6740 bool kasp, bool *warn) {
6741 unsigned int i = 0;
6742 isc_result_t ret;
6743 bool have_ksk = false, have_zsk = false;
6744 bool have_pksk = false, have_pzsk = false;
6745
6746 for (i = 0; i < nkeys; i++) {
6747 bool ksk, zsk;
6748
6749 if (have_pksk && have_ksk && have_pzsk && have_zsk) {
6750 break;
6751 }
6752
6753 if (rrsig_ptr->algorithm != dst_key_alg(keys[i])) {
6754 continue;
6755 }
6756
6757 ret = dst_key_getbool(keys[i], DST_BOOL_KSK, &ksk);
6758 if (ret != ISC_R_SUCCESS) {
6759 ksk = KSK(keys[i]);
6760 }
6761 ret = dst_key_getbool(keys[i], DST_BOOL_ZSK, &zsk);
6762 if (ret != ISC_R_SUCCESS) {
6763 zsk = !KSK(keys[i]);
6764 }
6765
6766 if (ksk) {
6767 have_ksk = true;
6768 if (dst_key_isprivate(keys[i])) {
6769 have_pksk = true;
6770 }
6771 }
6772 if (zsk) {
6773 have_zsk = true;
6774 if (dst_key_isprivate(keys[i])) {
6775 have_pzsk = true;
6776 }
6777 }
6778 }
6779
6780 if (have_zsk && have_ksk && !have_pzsk) {
6781 *warn = true;
6782 }
6783
6784 if (have_pksk && have_pzsk) {
6785 return true;
6786 }
6787
6788 /*
6789 * Deleting the SOA RRSIG is always okay.
6790 */
6791 if (rrsig_ptr->covered == dns_rdatatype_soa) {
6792 return true;
6793 }
6794
6795 /*
6796 * It's okay to delete a signature if there is an active key with the
6797 * same algorithm to replace it, unless that violates the DNSSEC
6798 * policy.
6799 */
6800 if (have_pksk || have_pzsk) {
6801 if (kasp && have_pzsk) {
6802 return true;
6803 }
6804 return !kasp;
6805 }
6806
6807 /*
6808 * Failing that, it is *not* okay to delete a signature
6809 * if the associated public key is still in the DNSKEY RRset
6810 */
6811 for (i = 0; i < nkeys; i++) {
6812 if ((rrsig_ptr->algorithm == dst_key_alg(keys[i])) &&
6813 (rrsig_ptr->keyid == dst_key_id(keys[i])))
6814 {
6815 return false;
6816 }
6817 }
6818
6819 /*
6820 * But if the key is gone, then go ahead.
6821 */
6822 return true;
6823 }
6824
6825 /*
6826 * Delete expired RRsigs and any RRsigs we are about to re-sign.
6827 * See also update.c:del_keysigs().
6828 */
6829 static isc_result_t
6830 del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
6831 dns_rdatatype_t type, dns__zonediff_t *zonediff, dst_key_t **keys,
6832 unsigned int nkeys, isc_stdtime_t now, bool incremental) {
6833 isc_result_t result;
6834 dns_dbnode_t *node = NULL;
6835 dns_rdataset_t rdataset;
6836 unsigned int i;
6837 dns_rdata_rrsig_t rrsig;
6838 dns_kasp_t *kasp = zone->kasp;
6839 bool found;
6840 bool offlineksk = false;
6841 int64_t timewarn = 0, timemaybe = 0;
6842
6843 dns_rdataset_init(&rdataset);
6844
6845 if (kasp != NULL) {
6846 offlineksk = dns_kasp_offlineksk(kasp);
6847 }
6848
6849 if (type == dns_rdatatype_nsec3) {
6850 result = dns_db_findnsec3node(db, name, false, &node);
6851 } else {
6852 result = dns_db_findnode(db, name, false, &node);
6853 }
6854 if (result == ISC_R_NOTFOUND) {
6855 return ISC_R_SUCCESS;
6856 }
6857 CHECK(result);
6858
6859 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig, type,
6860 (isc_stdtime_t)0, &rdataset, NULL);
6861 dns_db_detachnode(db, &node);
6862
6863 if (result == ISC_R_NOTFOUND) {
6864 INSIST(!dns_rdataset_isassociated(&rdataset));
6865 return ISC_R_SUCCESS;
6866 }
6867 if (result != ISC_R_SUCCESS) {
6868 INSIST(!dns_rdataset_isassociated(&rdataset));
6869 goto cleanup;
6870 }
6871
6872 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
6873 result = dns_rdataset_next(&rdataset))
6874 {
6875 dns_rdata_t rdata = DNS_RDATA_INIT;
6876
6877 dns_rdataset_current(&rdataset, &rdata);
6878 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
6879 RUNTIME_CHECK(result == ISC_R_SUCCESS);
6880
6881 if (!dns_rdatatype_iskeymaterial(type)) {
6882 bool warn = false, deleted = false;
6883 if (delsig_ok(&rrsig, keys, nkeys, kasp != NULL, &warn))
6884 {
6885 result = update_one_rr(db, ver, zonediff->diff,
6886 DNS_DIFFOP_DELRESIGN,
6887 name, rdataset.ttl,
6888 &rdata);
6889 if (result != ISC_R_SUCCESS) {
6890 break;
6891 }
6892 deleted = true;
6893 }
6894 if (warn && !deleted) {
6895 /*
6896 * At this point, we've got an RRSIG,
6897 * which is signed by an inactive key.
6898 * An administrator needs to provide a new
6899 * key/alg, but until that time, we want to
6900 * keep the old RRSIG. Marking the key as
6901 * offline will prevent us spinning waiting
6902 * for the private part.
6903 */
6904 if (incremental) {
6905 result = offline(db, ver, zonediff,
6906 name, rdataset.ttl,
6907 &rdata);
6908 if (result != ISC_R_SUCCESS) {
6909 break;
6910 }
6911 }
6912
6913 /*
6914 * Log the key id and algorithm of
6915 * the inactive key with no replacement
6916 */
6917 if (zone->log_key_expired_timer <= now) {
6918 char origin[DNS_NAME_FORMATSIZE];
6919 char algbuf[DNS_NAME_FORMATSIZE];
6920 dns_name_format(&zone->origin, origin,
6921 sizeof(origin));
6922 dns_secalg_format(rrsig.algorithm,
6923 algbuf,
6924 sizeof(algbuf));
6925 dns_zone_log(zone, ISC_LOG_WARNING,
6926 "Key %s/%s/%d "
6927 "missing or inactive "
6928 "and has no replacement: "
6929 "retaining signatures.",
6930 origin, algbuf,
6931 rrsig.keyid);
6932 zone->log_key_expired_timer = now +
6933 3600;
6934 }
6935 }
6936 continue;
6937 }
6938
6939 /*
6940 * KSK RRSIGs requires special processing.
6941 */
6942 found = false;
6943 for (i = 0; i < nkeys; i++) {
6944 if (rrsig.algorithm == dst_key_alg(keys[i]) &&
6945 rrsig.keyid == dst_key_id(keys[i]))
6946 {
6947 found = true;
6948 /*
6949 * Mark offline DNSKEY.
6950 * We want the earliest offline expire time
6951 * iff there is a new offline signature.
6952 */
6953 if (!dst_key_inactive(keys[i]) &&
6954 !dst_key_isprivate(keys[i]) && !offlineksk)
6955 {
6956 int64_t timeexpire = dns_time64_from32(
6957 rrsig.timeexpire);
6958 if (timewarn != 0 &&
6959 timewarn > timeexpire)
6960 {
6961 timewarn = timeexpire;
6962 }
6963 if (rdata.flags & DNS_RDATA_OFFLINE) {
6964 if (timemaybe == 0 ||
6965 timemaybe > timeexpire)
6966 {
6967 timemaybe = timeexpire;
6968 }
6969 break;
6970 }
6971 if (timewarn == 0) {
6972 timewarn = timemaybe;
6973 }
6974 if (timewarn == 0 ||
6975 timewarn > timeexpire)
6976 {
6977 timewarn = timeexpire;
6978 }
6979 result = offline(db, ver, zonediff,
6980 name, rdataset.ttl,
6981 &rdata);
6982 break;
6983 }
6984 result = update_one_rr(db, ver, zonediff->diff,
6985 DNS_DIFFOP_DELRESIGN,
6986 name, rdataset.ttl,
6987 &rdata);
6988 break;
6989 }
6990 }
6991
6992 /*
6993 * If there is not a matching DNSKEY then
6994 * delete the RRSIG.
6995 */
6996 if (!found) {
6997 result = update_one_rr(db, ver, zonediff->diff,
6998 DNS_DIFFOP_DELRESIGN, name,
6999 rdataset.ttl, &rdata);
7000 }
7001 if (result != ISC_R_SUCCESS) {
7002 break;
7003 }
7004 }
7005
7006 dns_rdataset_disassociate(&rdataset);
7007 if (result == ISC_R_NOMORE) {
7008 result = ISC_R_SUCCESS;
7009 }
7010 if (timewarn > 0) {
7011 isc_stdtime_t stdwarn = (isc_stdtime_t)timewarn;
7012 if (timewarn == stdwarn) {
7013 set_key_expiry_warning(zone, (isc_stdtime_t)timewarn,
7014 now);
7015 } else {
7016 dns_zone_log(zone, ISC_LOG_ERROR,
7017 "key expiry warning time out of range");
7018 }
7019 }
7020 cleanup:
7021 if (node != NULL) {
7022 dns_db_detachnode(db, &node);
7023 }
7024 return result;
7025 }
7026
7027 static isc_result_t
7028 add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_zone_t *zone,
7029 dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
7030 unsigned int nkeys, isc_mem_t *mctx, isc_stdtime_t now,
7031 isc_stdtime_t inception, isc_stdtime_t expire) {
7032 isc_result_t result;
7033 dns_dbnode_t *node = NULL;
7034 dns_stats_t *dnssecsignstats;
7035 dns_rdataset_t rdataset;
7036 dns_rdata_t sig_rdata = DNS_RDATA_INIT;
7037 unsigned char data[1024]; /* XXX */
7038 isc_buffer_t buffer;
7039 unsigned int i;
7040 bool use_kasp = false;
7041 bool offlineksk = false;
7042
7043 if (zone->kasp != NULL) {
7044 use_kasp = true;
7045 offlineksk = dns_kasp_offlineksk(zone->kasp);
7046 }
7047
7048 dns_rdataset_init(&rdataset);
7049 isc_buffer_init(&buffer, data, sizeof(data));
7050
7051 if (type == dns_rdatatype_nsec3) {
7052 result = dns_db_findnsec3node(db, name, false, &node);
7053 } else {
7054 result = dns_db_findnode(db, name, false, &node);
7055 }
7056 if (result == ISC_R_NOTFOUND) {
7057 return ISC_R_SUCCESS;
7058 }
7059 CHECK(result);
7060
7061 result = dns_db_findrdataset(db, node, ver, type, 0, (isc_stdtime_t)0,
7062 &rdataset, NULL);
7063 dns_db_detachnode(db, &node);
7064 if (result == ISC_R_NOTFOUND) {
7065 INSIST(!dns_rdataset_isassociated(&rdataset));
7066 return ISC_R_SUCCESS;
7067 }
7068 if (result != ISC_R_SUCCESS) {
7069 INSIST(!dns_rdataset_isassociated(&rdataset));
7070 goto cleanup;
7071 }
7072
7073 for (i = 0; i < nkeys; i++) {
7074 /* Don't add signatures for offline or inactive keys */
7075 if (!dst_key_isprivate(keys[i]) && !offlineksk) {
7076 continue;
7077 }
7078 if (dst_key_inactive(keys[i]) && !offlineksk) {
7079 continue;
7080 }
7081
7082 if (use_kasp) {
7083 /*
7084 * A dnssec-policy is found. Check what RRsets this
7085 * key should sign.
7086 */
7087 isc_result_t kresult;
7088 isc_stdtime_t when;
7089 bool ksk = false;
7090 bool zsk = false;
7091 bool have_zsk = false;
7092
7093 kresult = dst_key_getbool(keys[i], DST_BOOL_KSK, &ksk);
7094 if (kresult != ISC_R_SUCCESS) {
7095 if (KSK(keys[i])) {
7096 ksk = true;
7097 }
7098 }
7099 kresult = dst_key_getbool(keys[i], DST_BOOL_ZSK, &zsk);
7100 if (kresult != ISC_R_SUCCESS) {
7101 if (!KSK(keys[i])) {
7102 zsk = true;
7103 }
7104 }
7105
7106 /*
7107 * Don't consider inactive keys or offline keys.
7108 */
7109 if (!dst_key_isprivate(keys[i]) && offlineksk && zsk) {
7110 continue;
7111 }
7112 if (dst_key_inactive(keys[i]) && offlineksk && zsk) {
7113 continue;
7114 }
7115
7116 if (offlineksk) {
7117 have_zsk = true;
7118 } else {
7119 (void)dst_key_have_ksk_and_zsk(keys, nkeys, i,
7120 true, ksk, zsk,
7121 NULL, &have_zsk);
7122 }
7123
7124 if (dns_rdatatype_iskeymaterial(type)) {
7125 /*
7126 * DNSKEY RRset is signed with KSK.
7127 * CDS and CDNSKEY RRsets too (RFC 7344, 4.1).
7128 */
7129 if (!ksk) {
7130 continue;
7131 }
7132 } else if (!zsk) {
7133 /*
7134 * Other RRsets are signed with ZSK.
7135 */
7136 if (type != dns_rdatatype_soa &&
7137 type != zone->privatetype)
7138 {
7139 continue;
7140 }
7141 if (have_zsk) {
7142 continue;
7143 }
7144 } else if (!dst_key_is_signing(keys[i], DST_BOOL_ZSK,
7145 now, &when))
7146 {
7147 /*
7148 * This key is not active for zone-signing.
7149 */
7150 continue;
7151 }
7152 } else if (!REVOKE(keys[i])) {
7153 /*
7154 * Don't consider inactive keys, however the KSK may be
7155 * temporary offline, so do consider keys which private
7156 * key files are unavailable.
7157 */
7158 bool both = dst_key_have_ksk_and_zsk(
7159 keys, nkeys, i, false, KSK(keys[i]),
7160 !KSK(keys[i]), NULL, NULL);
7161 if (both) {
7162 /*
7163 * CDS and CDNSKEY are signed with KSK (RFC
7164 * 7344, 4.1).
7165 */
7166 if (dns_rdatatype_iskeymaterial(type)) {
7167 if (!KSK(keys[i])) {
7168 continue;
7169 }
7170 } else if (KSK(keys[i])) {
7171 continue;
7172 }
7173 }
7174 }
7175
7176 /*
7177 * If this key is revoked, it may only sign the DNSKEY RRset.
7178 */
7179 if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey) {
7180 continue;
7181 }
7182
7183 /* Calculate the signature, creating a RRSIG RDATA. */
7184 isc_buffer_clear(&buffer);
7185
7186 if (offlineksk && dns_rdatatype_iskeymaterial(type)) {
7187 /* Look up the signature in the SKR bundle */
7188 dns_skrbundle_t *bundle = dns_zone_getskrbundle(zone);
7189 if (bundle == NULL) {
7190 CHECK(DNS_R_NOSKRBUNDLE);
7191 }
7192 CHECK(dns_skrbundle_getsig(bundle, keys[i], type,
7193 &sig_rdata));
7194 } else {
7195 CHECK(dns_dnssec_sign(name, &rdataset, keys[i],
7196 &inception, &expire, mctx,
7197 &buffer, &sig_rdata));
7198 }
7199
7200 /* Update the database and journal with the RRSIG. */
7201 /* XXX inefficient - will cause dataset merging */
7202 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN, name,
7203 rdataset.ttl, &sig_rdata));
7204 dns_rdata_reset(&sig_rdata);
7205 isc_buffer_init(&buffer, data, sizeof(data));
7206
7207 /* Update DNSSEC sign statistics. */
7208 dnssecsignstats = dns_zone_getdnssecsignstats(zone);
7209 if (dnssecsignstats != NULL) {
7210 /* Generated a new signature. */
7211 dns_dnssecsignstats_increment(dnssecsignstats,
7212 ID(keys[i]),
7213 (uint8_t)ALG(keys[i]),
7214 dns_dnssecsignstats_sign);
7215 /* This is a refresh. */
7216 dns_dnssecsignstats_increment(
7217 dnssecsignstats, ID(keys[i]),
7218 (uint8_t)ALG(keys[i]),
7219 dns_dnssecsignstats_refresh);
7220 }
7221 }
7222
7223 cleanup:
7224 if (dns_rdataset_isassociated(&rdataset)) {
7225 dns_rdataset_disassociate(&rdataset);
7226 }
7227 if (node != NULL) {
7228 dns_db_detachnode(db, &node);
7229 }
7230 return result;
7231 }
7232
7233 static void
7234 calculate_rrsig_validity(dns_zone_t *zone, isc_stdtime_t now,
7235 isc_stdtime_t *inception, isc_stdtime_t *soaexpire,
7236 isc_stdtime_t *expire, isc_stdtime_t *fullexpire) {
7237 REQUIRE(inception != NULL);
7238 REQUIRE(soaexpire != NULL);
7239 /* expire and fullexpire are optional */
7240
7241 isc_stdtime_t jitter = DEFAULT_JITTER;
7242 isc_stdtime_t sigvalidity = dns_zone_getsigvalidityinterval(zone);
7243 isc_stdtime_t shortjitter = 0, fulljitter = 0;
7244
7245 if (zone->kasp != NULL) {
7246 jitter = dns_kasp_sigjitter(zone->kasp);
7247 sigvalidity = dns_kasp_sigvalidity(zone->kasp);
7248 INSIST(jitter <= sigvalidity);
7249 }
7250
7251 if (jitter > sigvalidity) {
7252 jitter = sigvalidity;
7253 }
7254
7255 *inception = now - 3600; /* Allow for clock skew. */
7256 *soaexpire = now + sigvalidity;
7257
7258 /*
7259 * Spread out signatures over time if they happen to be
7260 * clumped. We don't do this for each add_sigs() call as
7261 * we still want some clustering to occur. In normal operations
7262 * the records should be re-signed as they fall due and they should
7263 * already be spread out. However if the server is off for a
7264 * period we need to ensure that the clusters don't become
7265 * synchronised by using the full jitter range.
7266 */
7267 if (sigvalidity >= 3600U) {
7268 if (sigvalidity > 7200U) {
7269 shortjitter = isc_random_uniform(3600);
7270 fulljitter = isc_random_uniform(jitter);
7271 } else {
7272 shortjitter = fulljitter = isc_random_uniform(1200);
7273 }
7274 }
7275
7276 SET_IF_NOT_NULL(expire, *soaexpire - shortjitter - 1);
7277 SET_IF_NOT_NULL(fullexpire, *soaexpire - fulljitter - 1);
7278 }
7279
7280 static void
7281 zone_resigninc(dns_zone_t *zone) {
7282 dns_db_t *db = NULL;
7283 dns_dbversion_t *version = NULL;
7284 dns_diff_t _sig_diff;
7285 dns__zonediff_t zonediff;
7286 dns_fixedname_t fixed;
7287 dns_name_t *name;
7288 dns_typepair_t typepair;
7289 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
7290 isc_result_t result;
7291 isc_stdtime_t now, inception, soaexpire, expire, fullexpire, stop;
7292 unsigned int i;
7293 unsigned int nkeys = 0;
7294 isc_stdtime_t resign;
7295
7296 ENTER;
7297
7298 dns_diff_init(zone->mctx, &_sig_diff);
7299 zonediff_init(&zonediff, &_sig_diff);
7300
7301 /*
7302 * Zone is frozen. Pause for 5 minutes.
7303 */
7304 if (zone->update_disabled) {
7305 CHECK(ISC_R_FAILURE);
7306 }
7307
7308 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
7309 if (zone->db != NULL) {
7310 dns_db_attach(zone->db, &db);
7311 }
7312 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7313 if (db == NULL) {
7314 CHECK(ISC_R_FAILURE);
7315 }
7316
7317 result = dns_db_newversion(db, &version);
7318 if (result != ISC_R_SUCCESS) {
7319 dns_zone_log(zone, ISC_LOG_ERROR,
7320 "zone_resigninc:dns_db_newversion -> %s",
7321 isc_result_totext(result));
7322 goto cleanup;
7323 }
7324
7325 now = isc_stdtime_now();
7326
7327 result = dns_zone_findkeys(zone, db, version, now, zone->mctx,
7328 DNS_MAXZONEKEYS, zone_keys, &nkeys);
7329 if (result != ISC_R_SUCCESS) {
7330 dns_zone_log(zone, ISC_LOG_ERROR,
7331 "zone_resigninc:dns_zone_findkeys -> %s",
7332 isc_result_totext(result));
7333 goto cleanup;
7334 }
7335
7336 calculate_rrsig_validity(zone, now, &inception, &soaexpire, &expire,
7337 &fullexpire);
7338
7339 stop = now + 5;
7340
7341 name = dns_fixedname_initname(&fixed);
7342 result = dns_db_getsigningtime(db, &resign, name, &typepair);
7343 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
7344 dns_zone_log(zone, ISC_LOG_ERROR,
7345 "zone_resigninc:dns_db_getsigningtime -> %s",
7346 isc_result_totext(result));
7347 }
7348
7349 i = 0;
7350 while (result == ISC_R_SUCCESS) {
7351 dns_rdatatype_t covers = DNS_TYPEPAIR_COVERS(typepair);
7352
7353 resign -= dns_zone_getsigresigninginterval(zone);
7354
7355 /*
7356 * Stop if we hit the SOA as that means we have walked the
7357 * entire zone. The SOA record should always be the most
7358 * recent signature.
7359 */
7360 /* XXXMPA increase number of RRsets signed pre call */
7361 if ((covers == dns_rdatatype_soa &&
7362 dns_name_equal(name, &zone->origin)) ||
7363 i++ > zone->signatures || resign > stop)
7364 {
7365 break;
7366 }
7367
7368 result = del_sigs(zone, db, version, name, covers, &zonediff,
7369 zone_keys, nkeys, now, true);
7370 if (result != ISC_R_SUCCESS) {
7371 dns_zone_log(zone, ISC_LOG_ERROR,
7372 "zone_resigninc:del_sigs -> %s",
7373 isc_result_totext(result));
7374 break;
7375 }
7376
7377 /*
7378 * If re-signing is over 5 minutes late use 'fullexpire'
7379 * to redistribute the signature over the complete
7380 * re-signing window, otherwise only add a small amount
7381 * of jitter.
7382 */
7383 result = add_sigs(db, version, name, zone, covers,
7384 zonediff.diff, zone_keys, nkeys, zone->mctx,
7385 now, inception,
7386 resign > (now - 300) ? expire : fullexpire);
7387 if (result != ISC_R_SUCCESS) {
7388 dns_zone_log(zone, ISC_LOG_ERROR,
7389 "zone_resigninc:add_sigs -> %s",
7390 isc_result_totext(result));
7391 break;
7392 }
7393 result = dns_db_getsigningtime(db, &resign, name, &typepair);
7394 if (nkeys == 0 && result == ISC_R_NOTFOUND) {
7395 result = ISC_R_SUCCESS;
7396 break;
7397 }
7398 if (result != ISC_R_SUCCESS) {
7399 dns_zone_log(zone, ISC_LOG_ERROR,
7400 "zone_resigninc:dns_db_getsigningtime -> "
7401 "%s",
7402 isc_result_totext(result));
7403 }
7404 }
7405
7406 if (result != ISC_R_NOMORE) {
7407 CHECK(result);
7408 }
7409
7410 result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
7411 &zonediff, zone_keys, nkeys, now, true);
7412 if (result != ISC_R_SUCCESS) {
7413 dns_zone_log(zone, ISC_LOG_ERROR,
7414 "zone_resigninc:del_sigs -> %s",
7415 isc_result_totext(result));
7416 goto cleanup;
7417 }
7418
7419 /*
7420 * Did we change anything in the zone?
7421 */
7422 if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
7423 /*
7424 * Commit the changes if any key has been marked as offline.
7425 */
7426 if (zonediff.offline) {
7427 dns_db_closeversion(db, &version, true);
7428 }
7429 goto cleanup;
7430 }
7431
7432 /* Increment SOA serial if we have made changes */
7433 result = update_soa_serial(zone, db, version, zonediff.diff, zone->mctx,
7434 zone->updatemethod);
7435 if (result != ISC_R_SUCCESS) {
7436 dns_zone_log(zone, ISC_LOG_ERROR,
7437 "zone_resigninc:update_soa_serial -> %s",
7438 isc_result_totext(result));
7439 goto cleanup;
7440 }
7441
7442 /*
7443 * Generate maximum life time signatures so that the above loop
7444 * termination is sensible.
7445 */
7446 result = add_sigs(db, version, &zone->origin, zone, dns_rdatatype_soa,
7447 zonediff.diff, zone_keys, nkeys, zone->mctx, now,
7448 inception, soaexpire);
7449 if (result != ISC_R_SUCCESS) {
7450 dns_zone_log(zone, ISC_LOG_ERROR,
7451 "zone_resigninc:add_sigs -> %s",
7452 isc_result_totext(result));
7453 goto cleanup;
7454 }
7455
7456 /* Write changes to journal file. */
7457 CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_resigninc"));
7458
7459 /* Everything has succeeded. Commit the changes. */
7460 dns_db_closeversion(db, &version, true);
7461
7462 cleanup:
7463 dns_diff_clear(&_sig_diff);
7464 for (i = 0; i < nkeys; i++) {
7465 dst_key_free(&zone_keys[i]);
7466 }
7467 if (version != NULL) {
7468 dns_db_closeversion(db, &version, false);
7469 dns_db_detach(&db);
7470 } else if (db != NULL) {
7471 dns_db_detach(&db);
7472 }
7473
7474 LOCK_ZONE(zone);
7475 if (result == ISC_R_SUCCESS) {
7476 set_resigntime(zone);
7477 zone_needdump(zone, DNS_DUMP_DELAY);
7478 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
7479 } else {
7480 /*
7481 * Something failed. Retry in 5 minutes.
7482 */
7483 isc_interval_t ival;
7484 isc_interval_set(&ival, 300, 0);
7485 isc_time_nowplusinterval(&zone->resigntime, &ival);
7486 }
7487 UNLOCK_ZONE(zone);
7488
7489 INSIST(version == NULL);
7490 }
7491
7492 static isc_result_t
7493 next_active(dns_db_t *db, dns_dbversion_t *version, dns_name_t *oldname,
7494 dns_name_t *newname, bool bottom) {
7495 isc_result_t result;
7496 dns_dbiterator_t *dbit = NULL;
7497 dns_rdatasetiter_t *rdsit = NULL;
7498 dns_dbnode_t *node = NULL;
7499
7500 CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit));
7501 CHECK(dns_dbiterator_seek(dbit, oldname));
7502 do {
7503 result = dns_dbiterator_next(dbit);
7504 if (result == ISC_R_NOMORE) {
7505 CHECK(dns_dbiterator_first(dbit));
7506 }
7507 CHECK(dns_dbiterator_current(dbit, &node, newname));
7508 if (bottom && dns_name_issubdomain(newname, oldname) &&
7509 !dns_name_equal(newname, oldname))
7510 {
7511 dns_db_detachnode(db, &node);
7512 continue;
7513 }
7514 /*
7515 * Is this node empty?
7516 */
7517 CHECK(dns_db_allrdatasets(db, node, version, 0, 0, &rdsit));
7518 result = dns_rdatasetiter_first(rdsit);
7519 dns_db_detachnode(db, &node);
7520 dns_rdatasetiter_destroy(&rdsit);
7521 if (result != ISC_R_NOMORE) {
7522 break;
7523 }
7524 } while (1);
7525 cleanup:
7526 if (node != NULL) {
7527 dns_db_detachnode(db, &node);
7528 }
7529 if (dbit != NULL) {
7530 dns_dbiterator_destroy(&dbit);
7531 }
7532 return result;
7533 }
7534
7535 static bool
7536 signed_with_good_key(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
7537 dns_dbversion_t *version, dns_rdatatype_t type,
7538 dst_key_t *key, bool fullsign) {
7539 isc_result_t result;
7540 dns_rdataset_t rdataset;
7541 dns_rdata_t rdata = DNS_RDATA_INIT;
7542 dns_rdata_rrsig_t rrsig;
7543 int count = 0;
7544 dns_kasp_t *kasp = zone->kasp;
7545
7546 dns_rdataset_init(&rdataset);
7547 result = dns_db_findrdataset(db, node, version, dns_rdatatype_rrsig,
7548 type, 0, &rdataset, NULL);
7549 if (result != ISC_R_SUCCESS) {
7550 INSIST(!dns_rdataset_isassociated(&rdataset));
7551 return false;
7552 }
7553 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
7554 result = dns_rdataset_next(&rdataset))
7555 {
7556 dns_rdataset_current(&rdataset, &rdata);
7557 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
7558 INSIST(result == ISC_R_SUCCESS);
7559 if (rrsig.algorithm == dst_key_alg(key) &&
7560 rrsig.keyid == dst_key_id(key))
7561 {
7562 dns_rdataset_disassociate(&rdataset);
7563 return true;
7564 }
7565 if (rrsig.algorithm == dst_key_alg(key)) {
7566 count++;
7567 }
7568 dns_rdata_reset(&rdata);
7569 }
7570
7571 if (zone->kasp != NULL && !fullsign) {
7572 dns_kasp_key_t *kkey;
7573 int zsk_count = 0;
7574 bool approved;
7575
7576 KASP_LOCK(kasp);
7577 for (kkey = ISC_LIST_HEAD(dns_kasp_keys(kasp)); kkey != NULL;
7578 kkey = ISC_LIST_NEXT(kkey, link))
7579 {
7580 if (dns_kasp_key_algorithm(kkey) != dst_key_alg(key)) {
7581 continue;
7582 }
7583 if (dns_kasp_key_zsk(kkey)) {
7584 zsk_count++;
7585 }
7586 }
7587 KASP_UNLOCK(kasp);
7588
7589 if (dns_rdatatype_iskeymaterial(type)) {
7590 /*
7591 * CDS and CDNSKEY are signed with KSK like DNSKEY.
7592 * (RFC 7344, section 4.1 specifies that they must
7593 * be signed with a key in the current DS RRset,
7594 * which would only include KSK's.)
7595 */
7596 approved = false;
7597 } else {
7598 approved = (zsk_count == count);
7599 }
7600
7601 dns_rdataset_disassociate(&rdataset);
7602 return approved;
7603 }
7604
7605 dns_rdataset_disassociate(&rdataset);
7606 return false;
7607 }
7608
7609 static isc_result_t
7610 add_nsec(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
7611 dns_dbnode_t *node, dns_ttl_t ttl, bool bottom, dns_diff_t *diff) {
7612 dns_fixedname_t fixed;
7613 dns_name_t *next;
7614 dns_rdata_t rdata = DNS_RDATA_INIT;
7615 isc_result_t result;
7616 unsigned char nsecbuffer[DNS_NSEC_BUFFERSIZE];
7617
7618 next = dns_fixedname_initname(&fixed);
7619
7620 CHECK(next_active(db, version, name, next, bottom));
7621 CHECK(dns_nsec_buildrdata(db, version, node, next, nsecbuffer, &rdata));
7622 CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADD, name, ttl,
7623 &rdata));
7624 cleanup:
7625 return result;
7626 }
7627
7628 static isc_result_t
7629 check_if_bottom_of_zone(dns_db_t *db, dns_dbnode_t *node,
7630 dns_dbversion_t *version, bool *is_bottom_of_zone) {
7631 isc_result_t result;
7632 dns_rdatasetiter_t *iterator = NULL;
7633 dns_rdataset_t rdataset;
7634 bool seen_soa = false, seen_ns = false, seen_dname = false;
7635
7636 REQUIRE(is_bottom_of_zone != NULL);
7637
7638 result = dns_db_allrdatasets(db, node, version, 0, 0, &iterator);
7639 if (result != ISC_R_SUCCESS) {
7640 if (result == ISC_R_NOTFOUND) {
7641 result = ISC_R_SUCCESS;
7642 }
7643 return result;
7644 }
7645
7646 dns_rdataset_init(&rdataset);
7647 for (result = dns_rdatasetiter_first(iterator); result == ISC_R_SUCCESS;
7648 result = dns_rdatasetiter_next(iterator))
7649 {
7650 dns_rdatasetiter_current(iterator, &rdataset);
7651 switch (rdataset.type) {
7652 case dns_rdatatype_soa:
7653 seen_soa = true;
7654 break;
7655 case dns_rdatatype_ns:
7656 seen_ns = true;
7657 break;
7658 case dns_rdatatype_dname:
7659 seen_dname = true;
7660 break;
7661 }
7662 dns_rdataset_disassociate(&rdataset);
7663 }
7664 if (result != ISC_R_NOMORE) {
7665 goto cleanup;
7666 }
7667 if ((seen_ns && !seen_soa) || seen_dname) {
7668 *is_bottom_of_zone = true;
7669 }
7670 result = ISC_R_SUCCESS;
7671
7672 cleanup:
7673 dns_rdatasetiter_destroy(&iterator);
7674
7675 return result;
7676 }
7677
7678 typedef struct seen {
7679 bool rr;
7680 bool soa;
7681 bool ns;
7682 bool nsec;
7683 bool nsec3;
7684 bool ds;
7685 bool dname;
7686 } seen_t;
7687
7688 static isc_result_t
7689 allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
7690 dns_rdatasetiter_t **iterp, seen_t *seen) {
7691 isc_result_t result;
7692 dns_rdataset_t rdataset = DNS_RDATASET_INIT;
7693
7694 *seen = (seen_t){};
7695
7696 RETERR(dns_db_allrdatasets(db, node, version, 0, 0, iterp));
7697
7698 for (result = dns_rdatasetiter_first(*iterp); result == ISC_R_SUCCESS;
7699 result = dns_rdatasetiter_next(*iterp))
7700 {
7701 dns_rdatasetiter_current(*iterp, &rdataset);
7702
7703 if (rdataset.type == dns_rdatatype_rrsig) {
7704 dns_rdataset_disassociate(&rdataset);
7705 continue;
7706 }
7707
7708 (*seen).rr = true;
7709
7710 if (rdataset.type == dns_rdatatype_soa) {
7711 (*seen).soa = true;
7712 } else if (rdataset.type == dns_rdatatype_ns) {
7713 (*seen).ns = true;
7714 } else if (rdataset.type == dns_rdatatype_ds) {
7715 (*seen).ds = true;
7716 } else if (rdataset.type == dns_rdatatype_dname) {
7717 (*seen).dname = true;
7718 } else if (rdataset.type == dns_rdatatype_nsec) {
7719 (*seen).nsec = true;
7720 } else if (rdataset.type == dns_rdatatype_nsec3) {
7721 (*seen).nsec3 = true;
7722 }
7723
7724 dns_rdataset_disassociate(&rdataset);
7725 }
7726
7727 return ISC_R_SUCCESS;
7728 }
7729
7730 static isc_result_t
7731 sign_a_node(dns_db_t *db, dns_zone_t *zone, dns_name_t *name,
7732 dns_dbnode_t *node, dns_dbversion_t *version, bool build_nsec3,
7733 bool build_nsec, dst_key_t *key, isc_stdtime_t now,
7734 isc_stdtime_t inception, isc_stdtime_t expire, dns_ttl_t nsecttl,
7735 bool both, bool is_ksk, bool is_zsk, bool fullsign,
7736 bool is_bottom_of_zone, dns_diff_t *diff, int32_t *signatures,
7737 isc_mem_t *mctx) {
7738 isc_result_t result;
7739 dns_rdatasetiter_t *iterator = NULL;
7740 dns_rdataset_t rdataset;
7741 dns_rdata_t rdata = DNS_RDATA_INIT;
7742 dns_stats_t *dnssecsignstats;
7743 bool offlineksk = false;
7744 isc_buffer_t buffer;
7745 unsigned char data[1024];
7746 seen_t seen;
7747
7748 if (zone->kasp != NULL) {
7749 offlineksk = dns_kasp_offlineksk(zone->kasp);
7750 }
7751
7752 result = allrdatasets(db, node, version, &iterator, &seen);
7753 if (result != ISC_R_SUCCESS) {
7754 if (result == ISC_R_NOTFOUND) {
7755 result = ISC_R_SUCCESS;
7756 }
7757 return result;
7758 }
7759
7760 dns_rdataset_init(&rdataset);
7761 isc_buffer_init(&buffer, data, sizeof(data));
7762
7763 /*
7764 * Going from insecure to NSEC3.
7765 * Don't generate NSEC3 records for NSEC3 records.
7766 */
7767 if (build_nsec3 && !seen.nsec3 && seen.rr) {
7768 bool unsecure = !seen.ds && seen.ns && !seen.soa;
7769 CHECK(dns_nsec3_addnsec3s(db, version, name, nsecttl, unsecure,
7770 diff));
7771 (*signatures)--;
7772 }
7773 /*
7774 * Going from insecure to NSEC.
7775 * Don't generate NSEC records for NSEC3 records.
7776 */
7777 if (build_nsec && !seen.nsec3 && !seen.nsec && seen.rr) {
7778 /*
7779 * Build a NSEC record except at the origin.
7780 */
7781 if (!dns_name_equal(name, dns_db_origin(db))) {
7782 CHECK(add_nsec(db, version, name, node, nsecttl,
7783 is_bottom_of_zone, diff));
7784 /* Count a NSEC generation as a signature generation. */
7785 (*signatures)--;
7786 }
7787 }
7788 result = dns_rdatasetiter_first(iterator);
7789 while (result == ISC_R_SUCCESS) {
7790 isc_stdtime_t when;
7791
7792 dns_rdatasetiter_current(iterator, &rdataset);
7793 if (rdataset.type == dns_rdatatype_soa ||
7794 rdataset.type == dns_rdatatype_rrsig)
7795 {
7796 goto next_rdataset;
7797 }
7798 if (dns_rdatatype_iskeymaterial(rdataset.type)) {
7799 /*
7800 * CDS and CDNSKEY are signed with KSK like DNSKEY.
7801 * (RFC 7344, section 4.1 specifies that they must
7802 * be signed with a key in the current DS RRset,
7803 * which would only include KSK's.)
7804 */
7805 if (!is_ksk && both) {
7806 goto next_rdataset;
7807 }
7808 } else if (!is_zsk && both) {
7809 goto next_rdataset;
7810 } else if (is_zsk &&
7811 !dst_key_is_signing(key, DST_BOOL_ZSK, now, &when))
7812 {
7813 /* Only applies to dnssec-policy. */
7814 if (zone->kasp != NULL) {
7815 goto next_rdataset;
7816 }
7817 }
7818
7819 if (seen.ns && !seen.soa && rdataset.type != dns_rdatatype_ds &&
7820 rdataset.type != dns_rdatatype_nsec)
7821 {
7822 goto next_rdataset;
7823 }
7824 if (signed_with_good_key(zone, db, node, version, rdataset.type,
7825 key, fullsign))
7826 {
7827 goto next_rdataset;
7828 }
7829
7830 /* Calculate the signature, creating a RRSIG RDATA. */
7831 isc_buffer_clear(&buffer);
7832 if (offlineksk && dns_rdatatype_iskeymaterial(rdataset.type)) {
7833 /* Look up the signature in the SKR bundle */
7834 dns_skrbundle_t *bundle = dns_zone_getskrbundle(zone);
7835 if (bundle == NULL) {
7836 CHECK(DNS_R_NOSKRBUNDLE);
7837 }
7838 CHECK(dns_skrbundle_getsig(bundle, key, rdataset.type,
7839 &rdata));
7840 } else {
7841 CHECK(dns_dnssec_sign(name, &rdataset, key, &inception,
7842 &expire, mctx, &buffer, &rdata));
7843 }
7844
7845 /* Update the database and journal with the RRSIG. */
7846 /* XXX inefficient - will cause dataset merging */
7847 CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADDRESIGN,
7848 name, rdataset.ttl, &rdata));
7849 dns_rdata_reset(&rdata);
7850
7851 /* Update DNSSEC sign statistics. */
7852 dnssecsignstats = dns_zone_getdnssecsignstats(zone);
7853 if (dnssecsignstats != NULL) {
7854 /* Generated a new signature. */
7855 dns_dnssecsignstats_increment(dnssecsignstats, ID(key),
7856 ALG(key),
7857 dns_dnssecsignstats_sign);
7858 /* This is a refresh. */
7859 dns_dnssecsignstats_increment(
7860 dnssecsignstats, ID(key), ALG(key),
7861 dns_dnssecsignstats_refresh);
7862 }
7863
7864 (*signatures)--;
7865 next_rdataset:
7866 dns_rdataset_disassociate(&rdataset);
7867 result = dns_rdatasetiter_next(iterator);
7868 }
7869 if (result == ISC_R_NOMORE) {
7870 result = ISC_R_SUCCESS;
7871 }
7872
7873 cleanup:
7874 if (dns_rdataset_isassociated(&rdataset)) {
7875 dns_rdataset_disassociate(&rdataset);
7876 }
7877 if (iterator != NULL) {
7878 dns_rdatasetiter_destroy(&iterator);
7879 }
7880 return result;
7881 }
7882
7883 /*
7884 * If 'update_only' is set then don't create a NSEC RRset if it doesn't exist.
7885 */
7886 static isc_result_t
7887 updatesecure(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
7888 dns_ttl_t nsecttl, bool update_only, dns_diff_t *diff) {
7889 isc_result_t result;
7890 dns_rdataset_t rdataset;
7891 dns_dbnode_t *node = NULL;
7892
7893 CHECK(dns_db_getoriginnode(db, &node));
7894 if (update_only) {
7895 dns_rdataset_init(&rdataset);
7896 result = dns_db_findrdataset(
7897 db, node, version, dns_rdatatype_nsec,
7898 dns_rdatatype_none, 0, &rdataset, NULL);
7899 if (dns_rdataset_isassociated(&rdataset)) {
7900 dns_rdataset_disassociate(&rdataset);
7901 }
7902 if (result == ISC_R_NOTFOUND) {
7903 goto success;
7904 }
7905 CHECK(result);
7906 }
7907 CHECK(delete_nsec(db, version, node, name, diff));
7908 CHECK(add_nsec(db, version, name, node, nsecttl, false, diff));
7909 success:
7910 result = ISC_R_SUCCESS;
7911 cleanup:
7912 if (node != NULL) {
7913 dns_db_detachnode(db, &node);
7914 }
7915 return result;
7916 }
7917
7918 static isc_result_t
7919 updatesignwithkey(dns_zone_t *zone, dns_signing_t *signing,
7920 dns_dbversion_t *version, bool build_nsec3, dns_ttl_t nsecttl,
7921 dns_diff_t *diff) {
7922 isc_result_t result;
7923 dns_dbnode_t *node = NULL;
7924 dns_rdataset_t rdataset;
7925 dns_rdata_t rdata = DNS_RDATA_INIT;
7926 unsigned char data[5];
7927 bool seen_done = false;
7928 bool have_rr = false;
7929
7930 dns_rdataset_init(&rdataset);
7931 CHECK(dns_db_getoriginnode(signing->db, &node));
7932
7933 result = dns_db_findrdataset(signing->db, node, version,
7934 zone->privatetype, dns_rdatatype_none, 0,
7935 &rdataset, NULL);
7936 if (result == ISC_R_NOTFOUND) {
7937 INSIST(!dns_rdataset_isassociated(&rdataset));
7938 result = ISC_R_SUCCESS;
7939 goto cleanup;
7940 }
7941 if (result != ISC_R_SUCCESS) {
7942 INSIST(!dns_rdataset_isassociated(&rdataset));
7943 goto cleanup;
7944 }
7945 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
7946 result = dns_rdataset_next(&rdataset))
7947 {
7948 dns_rdataset_current(&rdataset, &rdata);
7949 /*
7950 * If we don't match the algorithm or keyid skip the record.
7951 */
7952 if (rdata.length != 5 || rdata.data[0] != signing->algorithm ||
7953 rdata.data[1] != ((signing->keyid >> 8) & 0xff) ||
7954 rdata.data[2] != (signing->keyid & 0xff))
7955 {
7956 have_rr = true;
7957 dns_rdata_reset(&rdata);
7958 continue;
7959 }
7960 /*
7961 * We have a match. If we were signing (!signing->deleteit)
7962 * and we already have a record indicating that we have
7963 * finished signing (rdata.data[4] != 0) then keep it.
7964 * Otherwise it needs to be deleted as we have removed all
7965 * the signatures (signing->deleteit), so any record indicating
7966 * completion is now out of date, or we have finished signing
7967 * with the new record so we no longer need to remember that
7968 * we need to sign the zone with the matching key across a
7969 * nameserver re-start.
7970 */
7971 if (!signing->deleteit && rdata.data[4] != 0) {
7972 seen_done = true;
7973 have_rr = true;
7974 } else {
7975 CHECK(update_one_rr(signing->db, version, diff,
7976 DNS_DIFFOP_DEL, &zone->origin,
7977 rdataset.ttl, &rdata));
7978 }
7979 dns_rdata_reset(&rdata);
7980 }
7981 if (result == ISC_R_NOMORE) {
7982 result = ISC_R_SUCCESS;
7983 }
7984 if (!signing->deleteit && !seen_done) {
7985 /*
7986 * If we were signing then we need to indicate that we have
7987 * finished signing the zone with this key. If it is already
7988 * there we don't need to add it a second time.
7989 */
7990 data[0] = signing->algorithm;
7991 data[1] = (signing->keyid >> 8) & 0xff;
7992 data[2] = signing->keyid & 0xff;
7993 data[3] = 0;
7994 data[4] = 1;
7995 rdata.length = sizeof(data);
7996 rdata.data = data;
7997 rdata.type = zone->privatetype;
7998 rdata.rdclass = dns_db_class(signing->db);
7999 CHECK(update_one_rr(signing->db, version, diff, DNS_DIFFOP_ADD,
8000 &zone->origin, rdataset.ttl, &rdata));
8001 } else if (!have_rr) {
8002 dns_name_t *origin = dns_db_origin(signing->db);
8003 /*
8004 * Rebuild the NSEC/NSEC3 record for the origin as we no
8005 * longer have any private records.
8006 */
8007 if (build_nsec3) {
8008 CHECK(dns_nsec3_addnsec3s(signing->db, version, origin,
8009 nsecttl, false, diff));
8010 }
8011 CHECK(updatesecure(signing->db, version, origin, nsecttl, true,
8012 diff));
8013 }
8014
8015 cleanup:
8016 if (dns_rdataset_isassociated(&rdataset)) {
8017 dns_rdataset_disassociate(&rdataset);
8018 }
8019 if (node != NULL) {
8020 dns_db_detachnode(signing->db, &node);
8021 }
8022 return result;
8023 }
8024
8025 /*
8026 * Called from zone_nsec3chain() in order to update zone records indicating
8027 * processing status of given NSEC3 chain:
8028 *
8029 * - If the supplied dns_nsec3chain_t structure has been fully processed
8030 * (which is indicated by "active" being set to false):
8031 *
8032 * - remove all NSEC3PARAM records matching the relevant NSEC3 chain,
8033 *
8034 * - remove all private-type records containing NSEC3PARAM RDATA matching
8035 * the relevant NSEC3 chain.
8036 *
8037 * - If the supplied dns_nsec3chain_t structure has not been fully processed
8038 * (which is indicated by "active" being set to true), only remove the
8039 * NSEC3PARAM record which matches the relevant NSEC3 chain and has the
8040 * "flags" field set to 0.
8041 *
8042 * - If given NSEC3 chain is being added, add an NSEC3PARAM record contained
8043 * in the relevant private-type record, but with the "flags" field set to
8044 * 0, indicating that this NSEC3 chain is now complete for this zone.
8045 *
8046 * Note that this function is called at different processing stages for NSEC3
8047 * chain additions vs. removals and needs to handle all cases properly.
8048 */
8049 static isc_result_t
8050 fixup_nsec3param(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3chain_t *chain,
8051 bool active, dns_rdatatype_t privatetype, dns_diff_t *diff) {
8052 dns_dbnode_t *node = NULL;
8053 dns_name_t *name = dns_db_origin(db);
8054 dns_rdata_t rdata = DNS_RDATA_INIT;
8055 dns_rdataset_t rdataset;
8056 dns_rdata_nsec3param_t nsec3param;
8057 dns_rdata_soa_t soa;
8058 isc_result_t result;
8059 isc_buffer_t buffer;
8060 unsigned char parambuf[DNS_NSEC3PARAM_BUFFERSIZE];
8061 dns_ttl_t ttl = 0;
8062 bool nseconly = false, nsec3ok = false;
8063
8064 dns_rdataset_init(&rdataset);
8065
8066 result = dns_db_getoriginnode(db, &node);
8067 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8068
8069 /* Default TTL is SOA MINIMUM */
8070 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_soa, 0, 0,
8071 &rdataset, NULL);
8072 if (result == ISC_R_SUCCESS) {
8073 CHECK(dns_rdataset_first(&rdataset));
8074 dns_rdataset_current(&rdataset, &rdata);
8075 CHECK(dns_rdata_tostruct(&rdata, &soa, NULL));
8076 ttl = soa.minimum;
8077 dns_rdata_reset(&rdata);
8078 }
8079 if (dns_rdataset_isassociated(&rdataset)) {
8080 dns_rdataset_disassociate(&rdataset);
8081 }
8082
8083 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param, 0,
8084 0, &rdataset, NULL);
8085 if (result == ISC_R_NOTFOUND) {
8086 goto try_private;
8087 }
8088 if (result != ISC_R_SUCCESS) {
8089 goto cleanup;
8090 }
8091
8092 /*
8093 * Delete all NSEC3PARAM records which match that in nsec3chain.
8094 */
8095 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
8096 result = dns_rdataset_next(&rdataset))
8097 {
8098 dns_rdataset_current(&rdataset, &rdata);
8099 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
8100
8101 if (nsec3param.hash != chain->nsec3param.hash ||
8102 (active && nsec3param.flags != 0) ||
8103 nsec3param.iterations != chain->nsec3param.iterations ||
8104 nsec3param.salt_length != chain->nsec3param.salt_length ||
8105 memcmp(nsec3param.salt, chain->nsec3param.salt,
8106 nsec3param.salt_length))
8107 {
8108 /*
8109 * If the SOA minimum is different to the current TTL,
8110 * delete the record. We will re-add it with the new
8111 * TTL below.
8112 */
8113 if (rdataset.ttl != ttl) {
8114 CHECK(update_one_rr(db, ver, diff,
8115 DNS_DIFFOP_DEL, name,
8116 rdataset.ttl, &rdata));
8117 }
8118 dns_rdata_reset(&rdata);
8119 continue;
8120 }
8121
8122 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
8123 rdataset.ttl, &rdata));
8124 dns_rdata_reset(&rdata);
8125 }
8126 if (result != ISC_R_NOMORE) {
8127 goto cleanup;
8128 }
8129
8130 /*
8131 * Restore any NSEC3PARAM records that we deleted to change the TTL.
8132 */
8133 if (rdataset.ttl != ttl) {
8134 for (result = dns_rdataset_first(&rdataset);
8135 result == ISC_R_SUCCESS;
8136 result = dns_rdataset_next(&rdataset))
8137 {
8138 dns_rdataset_current(&rdataset, &rdata);
8139 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
8140
8141 if (nsec3param.hash != chain->nsec3param.hash ||
8142 (active && nsec3param.flags != 0) ||
8143 nsec3param.iterations !=
8144 chain->nsec3param.iterations ||
8145 nsec3param.salt_length !=
8146 chain->nsec3param.salt_length ||
8147 memcmp(nsec3param.salt, chain->nsec3param.salt,
8148 nsec3param.salt_length))
8149 {
8150 CHECK(update_one_rr(db, ver, diff,
8151 DNS_DIFFOP_ADD, name, ttl,
8152 &rdata));
8153 }
8154 dns_rdata_reset(&rdata);
8155 }
8156 }
8157
8158 dns_rdataset_disassociate(&rdataset);
8159
8160 try_private:
8161
8162 if (active) {
8163 goto add;
8164 }
8165
8166 result = dns_nsec_nseconly(db, ver, diff, &nseconly);
8167 nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
8168
8169 /*
8170 * Delete all private records which match that in nsec3chain.
8171 */
8172 result = dns_db_findrdataset(db, node, ver, privatetype, 0, 0,
8173 &rdataset, NULL);
8174 if (result == ISC_R_NOTFOUND) {
8175 goto add;
8176 }
8177 CHECK(result);
8178
8179 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
8180 result = dns_rdataset_next(&rdataset))
8181 {
8182 dns_rdata_t private = DNS_RDATA_INIT;
8183 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
8184
8185 dns_rdataset_current(&rdataset, &private);
8186 if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
8187 sizeof(buf)))
8188 {
8189 continue;
8190 }
8191 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
8192
8193 if ((!nsec3ok &&
8194 (nsec3param.flags & DNS_NSEC3FLAG_INITIAL) != 0) ||
8195 nsec3param.hash != chain->nsec3param.hash ||
8196 nsec3param.iterations != chain->nsec3param.iterations ||
8197 nsec3param.salt_length != chain->nsec3param.salt_length ||
8198 memcmp(nsec3param.salt, chain->nsec3param.salt,
8199 nsec3param.salt_length))
8200 {
8201 dns_rdata_reset(&rdata);
8202 continue;
8203 }
8204
8205 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
8206 rdataset.ttl, &private));
8207 dns_rdata_reset(&rdata);
8208 }
8209 if (result != ISC_R_NOMORE) {
8210 goto cleanup;
8211 }
8212
8213 add:
8214 if ((chain->nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
8215 result = ISC_R_SUCCESS;
8216 goto cleanup;
8217 }
8218
8219 /*
8220 * Add a NSEC3PARAM record which matches that in nsec3chain but
8221 * with all flags bits cleared.
8222 *
8223 * Note: we do not clear chain->nsec3param.flags as this change
8224 * may be reversed.
8225 */
8226 isc_buffer_init(&buffer, ¶mbuf, sizeof(parambuf));
8227 CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db),
8228 dns_rdatatype_nsec3param, &chain->nsec3param,
8229 &buffer));
8230 rdata.data[1] = 0; /* Clear flag bits. */
8231 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, name, ttl, &rdata));
8232
8233 cleanup:
8234 dns_db_detachnode(db, &node);
8235 if (dns_rdataset_isassociated(&rdataset)) {
8236 dns_rdataset_disassociate(&rdataset);
8237 }
8238 return result;
8239 }
8240
8241 static isc_result_t
8242 delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
8243 dns_name_t *name, dns_diff_t *diff) {
8244 dns_rdataset_t rdataset;
8245 isc_result_t result;
8246
8247 dns_rdataset_init(&rdataset);
8248
8249 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec, 0, 0,
8250 &rdataset, NULL);
8251 if (result == ISC_R_NOTFOUND) {
8252 return ISC_R_SUCCESS;
8253 }
8254 if (result != ISC_R_SUCCESS) {
8255 return result;
8256 }
8257 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
8258 result = dns_rdataset_next(&rdataset))
8259 {
8260 dns_rdata_t rdata = DNS_RDATA_INIT;
8261
8262 dns_rdataset_current(&rdataset, &rdata);
8263 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
8264 rdataset.ttl, &rdata));
8265 }
8266 if (result == ISC_R_NOMORE) {
8267 result = ISC_R_SUCCESS;
8268 }
8269
8270 cleanup:
8271 dns_rdataset_disassociate(&rdataset);
8272 return result;
8273 }
8274
8275 static isc_result_t
8276 deletematchingnsec3(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
8277 dns_name_t *name, const dns_rdata_nsec3param_t *param,
8278 dns_diff_t *diff) {
8279 dns_rdataset_t rdataset;
8280 dns_rdata_nsec3_t nsec3;
8281 isc_result_t result;
8282
8283 dns_rdataset_init(&rdataset);
8284 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3, 0, 0,
8285 &rdataset, NULL);
8286 if (result == ISC_R_NOTFOUND) {
8287 return ISC_R_SUCCESS;
8288 }
8289 if (result != ISC_R_SUCCESS) {
8290 return result;
8291 }
8292
8293 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
8294 result = dns_rdataset_next(&rdataset))
8295 {
8296 dns_rdata_t rdata = DNS_RDATA_INIT;
8297
8298 dns_rdataset_current(&rdataset, &rdata);
8299 CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
8300 if (nsec3.hash != param->hash ||
8301 nsec3.iterations != param->iterations ||
8302 nsec3.salt_length != param->salt_length ||
8303 memcmp(nsec3.salt, param->salt, nsec3.salt_length))
8304 {
8305 continue;
8306 }
8307 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
8308 rdataset.ttl, &rdata));
8309 }
8310 if (result == ISC_R_NOMORE) {
8311 result = ISC_R_SUCCESS;
8312 }
8313
8314 cleanup:
8315 dns_rdataset_disassociate(&rdataset);
8316 return result;
8317 }
8318
8319 static isc_result_t
8320 need_nsec_chain(dns_db_t *db, dns_dbversion_t *ver,
8321 const dns_rdata_nsec3param_t *param, bool *answer) {
8322 dns_dbnode_t *node = NULL;
8323 dns_rdata_t rdata = DNS_RDATA_INIT;
8324 dns_rdata_nsec3param_t myparam;
8325 dns_rdataset_t rdataset;
8326 isc_result_t result;
8327
8328 *answer = false;
8329
8330 result = dns_db_getoriginnode(db, &node);
8331 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8332
8333 dns_rdataset_init(&rdataset);
8334
8335 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec, 0, 0,
8336 &rdataset, NULL);
8337 if (result == ISC_R_SUCCESS) {
8338 dns_rdataset_disassociate(&rdataset);
8339 dns_db_detachnode(db, &node);
8340 return result;
8341 }
8342 if (result != ISC_R_NOTFOUND) {
8343 dns_db_detachnode(db, &node);
8344 return result;
8345 }
8346
8347 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param, 0,
8348 0, &rdataset, NULL);
8349 if (result == ISC_R_NOTFOUND) {
8350 *answer = true;
8351 dns_db_detachnode(db, &node);
8352 return ISC_R_SUCCESS;
8353 }
8354 if (result != ISC_R_SUCCESS) {
8355 dns_db_detachnode(db, &node);
8356 return result;
8357 }
8358
8359 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
8360 result = dns_rdataset_next(&rdataset))
8361 {
8362 dns_rdataset_current(&rdataset, &rdata);
8363 CHECK(dns_rdata_tostruct(&rdata, &myparam, NULL));
8364 dns_rdata_reset(&rdata);
8365 /*
8366 * Ignore any NSEC3PARAM removals.
8367 */
8368 if (NSEC3REMOVE(myparam.flags)) {
8369 continue;
8370 }
8371 /*
8372 * Ignore the chain that we are in the process of deleting.
8373 */
8374 if (myparam.hash == param->hash &&
8375 myparam.iterations == param->iterations &&
8376 myparam.salt_length == param->salt_length &&
8377 !memcmp(myparam.salt, param->salt, myparam.salt_length))
8378 {
8379 continue;
8380 }
8381 /*
8382 * Found an active NSEC3 chain.
8383 */
8384 break;
8385 }
8386 if (result == ISC_R_NOMORE) {
8387 *answer = true;
8388 result = ISC_R_SUCCESS;
8389 }
8390
8391 cleanup:
8392 if (dns_rdataset_isassociated(&rdataset)) {
8393 dns_rdataset_disassociate(&rdataset);
8394 }
8395 dns_db_detachnode(db, &node);
8396 return result;
8397 }
8398
8399 /*%
8400 * Given a tuple which is part of a diff, return a pointer to the next tuple in
8401 * that diff which has the same name and type (or NULL if no such tuple is
8402 * found).
8403 */
8404 static dns_difftuple_t *
8405 find_next_matching_tuple(dns_difftuple_t *cur) {
8406 dns_difftuple_t *next = cur;
8407
8408 while ((next = ISC_LIST_NEXT(next, link)) != NULL) {
8409 if (cur->rdata.type == next->rdata.type &&
8410 dns_name_equal(&cur->name, &next->name))
8411 {
8412 return next;
8413 }
8414 }
8415
8416 return NULL;
8417 }
8418
8419 /*%
8420 * Remove all tuples with the same name and type as 'cur' from 'src' and append
8421 * them to 'dst'.
8422 */
8423 static void
8424 move_matching_tuples(dns_difftuple_t *cur, dns_diff_t *src, dns_diff_t *dst) {
8425 do {
8426 dns_difftuple_t *next = find_next_matching_tuple(cur);
8427 ISC_LIST_UNLINK(src->tuples, cur, link);
8428 dns_diff_appendminimal(dst, &cur);
8429 cur = next;
8430 } while (cur != NULL);
8431 }
8432
8433 /*%
8434 * Add/remove DNSSEC signatures for the list of "raw" zone changes supplied in
8435 * 'diff'. Gradually remove tuples from 'diff' and append them to 'zonediff'
8436 * along with tuples representing relevant signature changes.
8437 */
8438 isc_result_t
8439 dns__zone_updatesigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version,
8440 dst_key_t *zone_keys[], unsigned int nkeys,
8441 dns_zone_t *zone, isc_stdtime_t inception,
8442 isc_stdtime_t expire, isc_stdtime_t keyexpire,
8443 isc_stdtime_t now, dns__zonediff_t *zonediff) {
8444 dns_difftuple_t *tuple;
8445 isc_result_t result;
8446
8447 while ((tuple = ISC_LIST_HEAD(diff->tuples)) != NULL) {
8448 isc_stdtime_t exp = expire;
8449
8450 if (keyexpire != 0 &&
8451 dns_rdatatype_iskeymaterial(tuple->rdata.type))
8452 {
8453 exp = keyexpire;
8454 }
8455
8456 result = del_sigs(zone, db, version, &tuple->name,
8457 tuple->rdata.type, zonediff, zone_keys, nkeys,
8458 now, false);
8459 if (result != ISC_R_SUCCESS) {
8460 dns_zone_log(zone, ISC_LOG_ERROR,
8461 "dns__zone_updatesigs:del_sigs -> %s",
8462 isc_result_totext(result));
8463 return result;
8464 }
8465 result = add_sigs(db, version, &tuple->name, zone,
8466 tuple->rdata.type, zonediff->diff, zone_keys,
8467 nkeys, zone->mctx, now, inception, exp);
8468 if (result != ISC_R_SUCCESS) {
8469 dns_zone_log(zone, ISC_LOG_ERROR,
8470 "dns__zone_updatesigs:add_sigs -> %s",
8471 isc_result_totext(result));
8472 return result;
8473 }
8474
8475 /*
8476 * Signature changes for all RRs with name tuple->name and type
8477 * tuple->rdata.type were appended to zonediff->diff. Now we
8478 * remove all the "raw" changes with the same name and type
8479 * from diff (so that they are not processed by this loop
8480 * again) and append them to zonediff so that they get applied.
8481 */
8482 move_matching_tuples(tuple, diff, zonediff->diff);
8483 }
8484 return ISC_R_SUCCESS;
8485 }
8486
8487 /*
8488 * Incrementally build and sign a new NSEC3 chain using the parameters
8489 * requested.
8490 */
8491 static void
8492 zone_nsec3chain(dns_zone_t *zone) {
8493 dns_db_t *db = NULL;
8494 dns_dbnode_t *node = NULL;
8495 dns_dbversion_t *version = NULL;
8496 dns_diff_t _sig_diff;
8497 dns_diff_t nsec_diff;
8498 dns_diff_t nsec3_diff;
8499 dns_diff_t param_diff;
8500 dns__zonediff_t zonediff;
8501 dns_fixedname_t fixed;
8502 dns_fixedname_t nextfixed;
8503 dns_name_t *name, *nextname;
8504 dns_rdataset_t rdataset;
8505 dns_nsec3chain_t *nsec3chain = NULL, *nextnsec3chain;
8506 dns_nsec3chainlist_t cleanup;
8507 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
8508 int32_t signatures;
8509 bool delegation;
8510 bool first;
8511 isc_result_t result;
8512 isc_stdtime_t now, inception, soaexpire, expire;
8513 unsigned int i;
8514 unsigned int nkeys = 0;
8515 uint32_t nodes;
8516 bool unsecure = false;
8517 seen_t seen;
8518 dns_rdatasetiter_t *iterator = NULL;
8519 bool buildnsecchain;
8520 bool updatensec = false;
8521 dns_rdatatype_t privatetype = zone->privatetype;
8522
8523 ENTER;
8524
8525 dns_rdataset_init(&rdataset);
8526 name = dns_fixedname_initname(&fixed);
8527 nextname = dns_fixedname_initname(&nextfixed);
8528 dns_diff_init(zone->mctx, ¶m_diff);
8529 dns_diff_init(zone->mctx, &nsec3_diff);
8530 dns_diff_init(zone->mctx, &nsec_diff);
8531 dns_diff_init(zone->mctx, &_sig_diff);
8532 zonediff_init(&zonediff, &_sig_diff);
8533 ISC_LIST_INIT(cleanup);
8534
8535 /*
8536 * Updates are disabled. Pause for 5 minutes.
8537 */
8538 if (zone->update_disabled) {
8539 CHECK(ISC_R_FAILURE);
8540 }
8541
8542 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8543 /*
8544 * This function is called when zone timer fires, after the latter gets
8545 * set by zone_addnsec3chain(). If the action triggering the call to
8546 * zone_addnsec3chain() is closely followed by a zone deletion request,
8547 * it might turn out that the timer thread will not be woken up until
8548 * after the zone is deleted by rmzone(), which calls dns_db_detach()
8549 * for zone->db, causing the latter to become NULL. Return immediately
8550 * if that happens.
8551 */
8552 if (zone->db != NULL) {
8553 dns_db_attach(zone->db, &db);
8554 }
8555 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8556 if (db == NULL) {
8557 return;
8558 }
8559
8560 result = dns_db_newversion(db, &version);
8561 if (result != ISC_R_SUCCESS) {
8562 dnssec_log(zone, ISC_LOG_ERROR,
8563 "zone_nsec3chain:dns_db_newversion -> %s",
8564 isc_result_totext(result));
8565 goto cleanup;
8566 }
8567
8568 now = isc_stdtime_now();
8569
8570 result = dns_zone_findkeys(zone, db, version, now, zone->mctx,
8571 DNS_MAXZONEKEYS, zone_keys, &nkeys);
8572 if (result != ISC_R_SUCCESS) {
8573 dnssec_log(zone, ISC_LOG_ERROR,
8574 "zone_nsec3chain:dns_zone_findkeys -> %s",
8575 isc_result_totext(result));
8576 goto cleanup;
8577 }
8578
8579 calculate_rrsig_validity(zone, now, &inception, &soaexpire, NULL,
8580 &expire);
8581
8582 /*
8583 * We keep pulling nodes off each iterator in turn until
8584 * we have no more nodes to pull off or we reach the limits
8585 * for this quantum.
8586 */
8587 nodes = zone->nodes;
8588 signatures = zone->signatures;
8589 LOCK_ZONE(zone);
8590 nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
8591 UNLOCK_ZONE(zone);
8592 first = true;
8593
8594 if (nsec3chain != NULL) {
8595 nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
8596 }
8597 /*
8598 * Generate new NSEC3 chains first.
8599 *
8600 * The following while loop iterates over nodes in the zone database,
8601 * updating the NSEC3 chain by calling dns_nsec3_addnsec3() for each of
8602 * them. Once all nodes are processed, the "delete_nsec" field is
8603 * consulted to check whether we are supposed to remove NSEC records
8604 * from the zone database; if so, the database iterator is reset to
8605 * point to the first node and the loop traverses all of them again,
8606 * this time removing NSEC records. If we hit a node which is obscured
8607 * by a delegation or a DNAME, nodes are skipped over until we find one
8608 * that is not obscured by the same obscuring name and then normal
8609 * processing is resumed.
8610 *
8611 * The above is repeated until all requested NSEC3 chain changes are
8612 * applied or when we reach the limits for this quantum, whichever
8613 * happens first.
8614 *
8615 * Note that the "signatures" variable is only used here to limit the
8616 * amount of work performed. Actual DNSSEC signatures are only
8617 * generated by dns__zone_updatesigs() calls later in this function.
8618 */
8619 while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
8620 dns_dbiterator_pause(nsec3chain->dbiterator);
8621
8622 LOCK_ZONE(zone);
8623 nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
8624
8625 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8626 if (nsec3chain->done || nsec3chain->db != zone->db) {
8627 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
8628 ISC_LIST_APPEND(cleanup, nsec3chain, link);
8629 }
8630 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8631 UNLOCK_ZONE(zone);
8632 if (ISC_LIST_TAIL(cleanup) == nsec3chain) {
8633 goto next_addchain;
8634 }
8635
8636 /*
8637 * Possible future db.
8638 */
8639 if (nsec3chain->db != db) {
8640 goto next_addchain;
8641 }
8642
8643 if (NSEC3REMOVE(nsec3chain->nsec3param.flags)) {
8644 goto next_addchain;
8645 }
8646
8647 dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
8648
8649 if (nsec3chain->delete_nsec) {
8650 delegation = false;
8651 dns_dbiterator_pause(nsec3chain->dbiterator);
8652 CHECK(delete_nsec(db, version, node, name, &nsec_diff));
8653 goto next_addnode;
8654 }
8655 /*
8656 * On the first pass we need to check if the current node
8657 * has not been obscured.
8658 */
8659 delegation = false;
8660 unsecure = false;
8661 if (first) {
8662 dns_fixedname_t ffound;
8663 dns_name_t *found;
8664 found = dns_fixedname_initname(&ffound);
8665 result = dns_db_find(
8666 db, name, version, dns_rdatatype_soa,
8667 DNS_DBFIND_NOWILD, 0, NULL, found, NULL, NULL);
8668 if ((result == DNS_R_DELEGATION ||
8669 result == DNS_R_DNAME) &&
8670 !dns_name_equal(name, found))
8671 {
8672 /*
8673 * Remember the obscuring name so that
8674 * we skip all obscured names.
8675 */
8676 dns_name_copy(found, name);
8677 delegation = true;
8678 goto next_addnode;
8679 }
8680 }
8681
8682 /*
8683 * Check to see if this is a bottom of zone node.
8684 */
8685 result = allrdatasets(db, node, version, &iterator, &seen);
8686 if (result == ISC_R_NOTFOUND) {
8687 /* Empty node? */
8688 goto next_addnode;
8689 }
8690 CHECK(result);
8691
8692 INSIST(!seen.nsec3);
8693
8694 dns_rdatasetiter_destroy(&iterator);
8695 /*
8696 * Is there a NSEC chain than needs to be cleaned up?
8697 */
8698 if (seen.nsec) {
8699 nsec3chain->seen_nsec = true;
8700 }
8701
8702 if (seen.ns && !seen.soa && !seen.ds) {
8703 unsecure = true;
8704 }
8705 if ((seen.ns && !seen.soa) || seen.dname) {
8706 delegation = true;
8707 }
8708
8709 /*
8710 * Process one node.
8711 */
8712 dns_dbiterator_pause(nsec3chain->dbiterator);
8713 result = dns_nsec3_addnsec3(
8714 db, version, name, &nsec3chain->nsec3param,
8715 zone_nsecttl(zone), unsecure, &nsec3_diff);
8716 if (result != ISC_R_SUCCESS) {
8717 dnssec_log(zone, ISC_LOG_ERROR,
8718 "zone_nsec3chain:"
8719 "dns_nsec3_addnsec3 -> %s",
8720 isc_result_totext(result));
8721 goto cleanup;
8722 }
8723
8724 /*
8725 * Treat each call to dns_nsec3_addnsec3() as if it's cost is
8726 * two signatures. Additionally there will, in general, be
8727 * two signature generated below.
8728 *
8729 * If we are only changing the optout flag the cost is half
8730 * that of the cost of generating a completely new chain.
8731 */
8732 signatures -= 4;
8733
8734 /*
8735 * Go onto next node.
8736 */
8737 next_addnode:
8738 first = false;
8739 dns_db_detachnode(db, &node);
8740 do {
8741 result = dns_dbiterator_next(nsec3chain->dbiterator);
8742
8743 if (result == ISC_R_NOMORE && nsec3chain->delete_nsec) {
8744 dns_dbiterator_pause(nsec3chain->dbiterator);
8745 CHECK(fixup_nsec3param(db, version, nsec3chain,
8746 false, privatetype,
8747 ¶m_diff));
8748 LOCK_ZONE(zone);
8749 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
8750 link);
8751 UNLOCK_ZONE(zone);
8752 ISC_LIST_APPEND(cleanup, nsec3chain, link);
8753 goto next_addchain;
8754 }
8755 if (result == ISC_R_NOMORE) {
8756 dns_dbiterator_pause(nsec3chain->dbiterator);
8757 if (nsec3chain->seen_nsec) {
8758 CHECK(fixup_nsec3param(
8759 db, version, nsec3chain, true,
8760 privatetype, ¶m_diff));
8761 nsec3chain->delete_nsec = true;
8762 goto same_addchain;
8763 }
8764 CHECK(fixup_nsec3param(db, version, nsec3chain,
8765 false, privatetype,
8766 ¶m_diff));
8767 LOCK_ZONE(zone);
8768 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
8769 link);
8770 UNLOCK_ZONE(zone);
8771 ISC_LIST_APPEND(cleanup, nsec3chain, link);
8772 goto next_addchain;
8773 } else if (result != ISC_R_SUCCESS) {
8774 dnssec_log(zone, ISC_LOG_ERROR,
8775 "zone_nsec3chain:"
8776 "dns_dbiterator_next -> %s",
8777 isc_result_totext(result));
8778 goto cleanup;
8779 } else if (delegation) {
8780 dns_dbiterator_current(nsec3chain->dbiterator,
8781 &node, nextname);
8782 dns_db_detachnode(db, &node);
8783 if (!dns_name_issubdomain(nextname, name)) {
8784 break;
8785 }
8786 } else {
8787 break;
8788 }
8789 } while (1);
8790 continue;
8791
8792 same_addchain:
8793 CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
8794 first = true;
8795 continue;
8796
8797 next_addchain:
8798 dns_dbiterator_pause(nsec3chain->dbiterator);
8799 nsec3chain = nextnsec3chain;
8800 first = true;
8801 if (nsec3chain != NULL) {
8802 nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
8803 }
8804 }
8805
8806 if (nsec3chain != NULL) {
8807 goto skip_removals;
8808 }
8809
8810 /*
8811 * Process removals.
8812 *
8813 * This is a counterpart of the above while loop which takes care of
8814 * removing an NSEC3 chain. It starts with determining whether the
8815 * zone needs to switch from NSEC3 to NSEC; if so, it first builds an
8816 * NSEC chain by iterating over all nodes in the zone database and only
8817 * then goes on to remove NSEC3 records be iterating over all nodes
8818 * again and calling deletematchingnsec3() for each of them; otherwise,
8819 * it starts removing NSEC3 records immediately. Rules for processing
8820 * obscured nodes and interrupting work are the same as for the while
8821 * loop above.
8822 */
8823 LOCK_ZONE(zone);
8824 nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
8825 UNLOCK_ZONE(zone);
8826 first = true;
8827 buildnsecchain = false;
8828 while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
8829 dns_dbiterator_pause(nsec3chain->dbiterator);
8830
8831 LOCK_ZONE(zone);
8832 nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
8833 UNLOCK_ZONE(zone);
8834
8835 if (nsec3chain->db != db) {
8836 goto next_removechain;
8837 }
8838
8839 if (!NSEC3REMOVE(nsec3chain->nsec3param.flags)) {
8840 goto next_removechain;
8841 }
8842
8843 /*
8844 * Work out if we need to build a NSEC chain as a consequence
8845 * of removing this NSEC3 chain.
8846 */
8847 if (first && !updatensec &&
8848 (nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_NONSEC) == 0)
8849 {
8850 result = need_nsec_chain(db, version,
8851 &nsec3chain->nsec3param,
8852 &buildnsecchain);
8853 if (result != ISC_R_SUCCESS) {
8854 dnssec_log(zone, ISC_LOG_ERROR,
8855 "zone_nsec3chain:"
8856 "need_nsec_chain -> %s",
8857 isc_result_totext(result));
8858 goto cleanup;
8859 }
8860 }
8861
8862 if (first) {
8863 dnssec_log(zone, ISC_LOG_DEBUG(3),
8864 "zone_nsec3chain:buildnsecchain = %u",
8865 buildnsecchain);
8866 }
8867
8868 dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
8869 dns_dbiterator_pause(nsec3chain->dbiterator);
8870 delegation = false;
8871
8872 if (!buildnsecchain) {
8873 /*
8874 * Delete the NSEC3PARAM record matching this chain.
8875 */
8876 if (first) {
8877 result = fixup_nsec3param(
8878 db, version, nsec3chain, true,
8879 privatetype, ¶m_diff);
8880 if (result != ISC_R_SUCCESS) {
8881 dnssec_log(zone, ISC_LOG_ERROR,
8882 "zone_nsec3chain:"
8883 "fixup_nsec3param -> %s",
8884 isc_result_totext(result));
8885 goto cleanup;
8886 }
8887 }
8888
8889 /*
8890 * Delete the NSEC3 records.
8891 */
8892 result = deletematchingnsec3(db, version, node, name,
8893 &nsec3chain->nsec3param,
8894 &nsec3_diff);
8895 if (result != ISC_R_SUCCESS) {
8896 dnssec_log(zone, ISC_LOG_ERROR,
8897 "zone_nsec3chain:"
8898 "deletematchingnsec3 -> %s",
8899 isc_result_totext(result));
8900 goto cleanup;
8901 }
8902 goto next_removenode;
8903 }
8904
8905 if (first) {
8906 dns_fixedname_t ffound;
8907 dns_name_t *found;
8908 found = dns_fixedname_initname(&ffound);
8909 result = dns_db_find(
8910 db, name, version, dns_rdatatype_soa,
8911 DNS_DBFIND_NOWILD, 0, NULL, found, NULL, NULL);
8912 if ((result == DNS_R_DELEGATION ||
8913 result == DNS_R_DNAME) &&
8914 !dns_name_equal(name, found))
8915 {
8916 /*
8917 * Remember the obscuring name so that
8918 * we skip all obscured names.
8919 */
8920 dns_name_copy(found, name);
8921 delegation = true;
8922 goto next_removenode;
8923 }
8924 }
8925
8926 /*
8927 * Check to see if this is a bottom of zone node.
8928 */
8929 result = allrdatasets(db, node, version, &iterator, &seen);
8930 if (result == ISC_R_NOTFOUND) {
8931 /* Empty node? */
8932 goto next_removenode;
8933 }
8934 CHECK(result);
8935
8936 dns_rdatasetiter_destroy(&iterator);
8937
8938 if (!seen.rr || seen.nsec3 || seen.nsec) {
8939 goto next_removenode;
8940 }
8941 if ((seen.ns && !seen.soa) || seen.dname) {
8942 delegation = true;
8943 }
8944
8945 /*
8946 * Add a NSEC record except at the origin.
8947 */
8948 if (!dns_name_equal(name, dns_db_origin(db))) {
8949 dns_dbiterator_pause(nsec3chain->dbiterator);
8950 CHECK(add_nsec(db, version, name, node,
8951 zone_nsecttl(zone), delegation,
8952 &nsec_diff));
8953 signatures--;
8954 }
8955
8956 next_removenode:
8957 first = false;
8958 dns_db_detachnode(db, &node);
8959 do {
8960 result = dns_dbiterator_next(nsec3chain->dbiterator);
8961 if (result == ISC_R_NOMORE && buildnsecchain) {
8962 /*
8963 * The NSEC chain should now be built.
8964 * We can now remove the NSEC3 chain.
8965 */
8966 updatensec = true;
8967 goto same_removechain;
8968 }
8969 if (result == ISC_R_NOMORE) {
8970 dns_dbiterator_pause(nsec3chain->dbiterator);
8971 LOCK_ZONE(zone);
8972 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
8973 link);
8974 UNLOCK_ZONE(zone);
8975 ISC_LIST_APPEND(cleanup, nsec3chain, link);
8976 result = fixup_nsec3param(
8977 db, version, nsec3chain, false,
8978 privatetype, ¶m_diff);
8979 if (result != ISC_R_SUCCESS) {
8980 dnssec_log(zone, ISC_LOG_ERROR,
8981 "zone_nsec3chain:"
8982 "fixup_nsec3param -> %s",
8983 isc_result_totext(result));
8984 goto cleanup;
8985 }
8986 goto next_removechain;
8987 } else if (result != ISC_R_SUCCESS) {
8988 dnssec_log(zone, ISC_LOG_ERROR,
8989 "zone_nsec3chain:"
8990 "dns_dbiterator_next -> %s",
8991 isc_result_totext(result));
8992 goto cleanup;
8993 } else if (delegation) {
8994 dns_dbiterator_current(nsec3chain->dbiterator,
8995 &node, nextname);
8996 dns_db_detachnode(db, &node);
8997 if (!dns_name_issubdomain(nextname, name)) {
8998 break;
8999 }
9000 } else {
9001 break;
9002 }
9003 } while (1);
9004 continue;
9005
9006 same_removechain:
9007 CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
9008 buildnsecchain = false;
9009 first = true;
9010 continue;
9011
9012 next_removechain:
9013 dns_dbiterator_pause(nsec3chain->dbiterator);
9014 nsec3chain = nextnsec3chain;
9015 first = true;
9016 }
9017
9018 skip_removals:
9019 /*
9020 * We may need to update the NSEC/NSEC3 records for the zone apex.
9021 */
9022 if (!ISC_LIST_EMPTY(param_diff.tuples)) {
9023 bool rebuild_nsec = false, rebuild_nsec3 = false;
9024 result = dns_db_getoriginnode(db, &node);
9025 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9026 result = dns_db_allrdatasets(db, node, version, 0, 0,
9027 &iterator);
9028 if (result != ISC_R_SUCCESS) {
9029 dnssec_log(zone, ISC_LOG_ERROR,
9030 "zone_nsec3chain:dns_db_allrdatasets -> %s",
9031 isc_result_totext(result));
9032 goto cleanup;
9033 }
9034 for (result = dns_rdatasetiter_first(iterator);
9035 result == ISC_R_SUCCESS;
9036 result = dns_rdatasetiter_next(iterator))
9037 {
9038 dns_rdatasetiter_current(iterator, &rdataset);
9039 if (rdataset.type == dns_rdatatype_nsec) {
9040 rebuild_nsec = true;
9041 } else if (rdataset.type == dns_rdatatype_nsec3param) {
9042 rebuild_nsec3 = true;
9043 }
9044 dns_rdataset_disassociate(&rdataset);
9045 }
9046 dns_rdatasetiter_destroy(&iterator);
9047 dns_db_detachnode(db, &node);
9048
9049 if (rebuild_nsec) {
9050 if (nsec3chain != NULL) {
9051 dns_dbiterator_pause(nsec3chain->dbiterator);
9052 }
9053
9054 result = updatesecure(db, version, &zone->origin,
9055 zone_nsecttl(zone), true,
9056 &nsec_diff);
9057 if (result != ISC_R_SUCCESS) {
9058 dnssec_log(zone, ISC_LOG_ERROR,
9059 "zone_nsec3chain:updatesecure -> %s",
9060 isc_result_totext(result));
9061 goto cleanup;
9062 }
9063 }
9064
9065 if (rebuild_nsec3) {
9066 if (nsec3chain != NULL) {
9067 dns_dbiterator_pause(nsec3chain->dbiterator);
9068 }
9069
9070 result = dns_nsec3_addnsec3s(
9071 db, version, dns_db_origin(db),
9072 zone_nsecttl(zone), false, &nsec3_diff);
9073 if (result != ISC_R_SUCCESS) {
9074 dnssec_log(zone, ISC_LOG_ERROR,
9075 "zone_nsec3chain:"
9076 "dns_nsec3_addnsec3s -> %s",
9077 isc_result_totext(result));
9078 goto cleanup;
9079 }
9080 }
9081 }
9082
9083 /*
9084 * Add / update signatures for the NSEC3 records.
9085 */
9086 if (nsec3chain != NULL) {
9087 dns_dbiterator_pause(nsec3chain->dbiterator);
9088 }
9089 result = dns__zone_updatesigs(&nsec3_diff, db, version, zone_keys,
9090 nkeys, zone, inception, expire, 0, now,
9091 &zonediff);
9092 if (result != ISC_R_SUCCESS) {
9093 dnssec_log(zone, ISC_LOG_ERROR,
9094 "zone_nsec3chain:dns__zone_updatesigs -> %s",
9095 isc_result_totext(result));
9096 goto cleanup;
9097 }
9098
9099 /*
9100 * We have changed the NSEC3PARAM or private RRsets
9101 * above so we need to update the signatures.
9102 */
9103 result = dns__zone_updatesigs(¶m_diff, db, version, zone_keys,
9104 nkeys, zone, inception, expire, 0, now,
9105 &zonediff);
9106 if (result != ISC_R_SUCCESS) {
9107 dnssec_log(zone, ISC_LOG_ERROR,
9108 "zone_nsec3chain:dns__zone_updatesigs -> %s",
9109 isc_result_totext(result));
9110 goto cleanup;
9111 }
9112
9113 if (updatensec) {
9114 result = updatesecure(db, version, &zone->origin,
9115 zone_nsecttl(zone), false, &nsec_diff);
9116 if (result != ISC_R_SUCCESS) {
9117 dnssec_log(zone, ISC_LOG_ERROR,
9118 "zone_nsec3chain:updatesecure -> %s",
9119 isc_result_totext(result));
9120 goto cleanup;
9121 }
9122 }
9123
9124 result = dns__zone_updatesigs(&nsec_diff, db, version, zone_keys, nkeys,
9125 zone, inception, expire, 0, now,
9126 &zonediff);
9127 if (result != ISC_R_SUCCESS) {
9128 dnssec_log(zone, ISC_LOG_ERROR,
9129 "zone_nsec3chain:dns__zone_updatesigs -> %s",
9130 isc_result_totext(result));
9131 goto cleanup;
9132 }
9133
9134 /*
9135 * If we made no effective changes to the zone then we can just
9136 * cleanup otherwise we need to increment the serial.
9137 */
9138 if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
9139 /*
9140 * No need to call dns_db_closeversion() here as it is
9141 * called with commit = true below.
9142 */
9143 goto closeversion;
9144 }
9145
9146 result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
9147 &zonediff, zone_keys, nkeys, now, false);
9148 if (result != ISC_R_SUCCESS) {
9149 dnssec_log(zone, ISC_LOG_ERROR,
9150 "zone_nsec3chain:del_sigs -> %s",
9151 isc_result_totext(result));
9152 goto cleanup;
9153 }
9154
9155 result = update_soa_serial(zone, db, version, zonediff.diff, zone->mctx,
9156 zone->updatemethod);
9157 if (result != ISC_R_SUCCESS) {
9158 dnssec_log(zone, ISC_LOG_ERROR,
9159 "zone_nsec3chain:update_soa_serial -> %s",
9160 isc_result_totext(result));
9161 goto cleanup;
9162 }
9163
9164 result = add_sigs(db, version, &zone->origin, zone, dns_rdatatype_soa,
9165 zonediff.diff, zone_keys, nkeys, zone->mctx, now,
9166 inception, soaexpire);
9167 if (result != ISC_R_SUCCESS) {
9168 dnssec_log(zone, ISC_LOG_ERROR,
9169 "zone_nsec3chain:add_sigs -> %s",
9170 isc_result_totext(result));
9171 goto cleanup;
9172 }
9173
9174 /* Write changes to journal file. */
9175 CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_nsec3chain"));
9176
9177 LOCK_ZONE(zone);
9178 zone_needdump(zone, DNS_DUMP_DELAY);
9179 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
9180 UNLOCK_ZONE(zone);
9181
9182 closeversion:
9183 /*
9184 * Pause all iterators so that dns_db_closeversion() can succeed.
9185 */
9186 LOCK_ZONE(zone);
9187 for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain); nsec3chain != NULL;
9188 nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
9189 {
9190 dns_dbiterator_pause(nsec3chain->dbiterator);
9191 }
9192 UNLOCK_ZONE(zone);
9193
9194 /*
9195 * Everything has succeeded. Commit the changes.
9196 * Unconditionally commit as zonediff.offline not checked above.
9197 */
9198 dns_db_closeversion(db, &version, true);
9199
9200 /*
9201 * Everything succeeded so we can clean these up now.
9202 */
9203 nsec3chain = ISC_LIST_HEAD(cleanup);
9204 while (nsec3chain != NULL) {
9205 ISC_LIST_UNLINK(cleanup, nsec3chain, link);
9206 dns_db_detach(&nsec3chain->db);
9207 dns_dbiterator_destroy(&nsec3chain->dbiterator);
9208 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
9209 nsec3chain = ISC_LIST_HEAD(cleanup);
9210 }
9211
9212 LOCK_ZONE(zone);
9213 set_resigntime(zone);
9214 UNLOCK_ZONE(zone);
9215
9216 cleanup:
9217 if (result != ISC_R_SUCCESS) {
9218 dnssec_log(zone, ISC_LOG_ERROR, "zone_nsec3chain: %s",
9219 isc_result_totext(result));
9220 }
9221
9222 /*
9223 * On error roll back the current nsec3chain.
9224 */
9225 if (result != ISC_R_SUCCESS && nsec3chain != NULL) {
9226 if (nsec3chain->done) {
9227 dns_db_detach(&nsec3chain->db);
9228 dns_dbiterator_destroy(&nsec3chain->dbiterator);
9229 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
9230 } else {
9231 result = dns_dbiterator_first(nsec3chain->dbiterator);
9232 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9233 dns_dbiterator_pause(nsec3chain->dbiterator);
9234 nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
9235 }
9236 }
9237
9238 /*
9239 * Rollback the cleanup list.
9240 */
9241 nsec3chain = ISC_LIST_TAIL(cleanup);
9242 while (nsec3chain != NULL) {
9243 ISC_LIST_UNLINK(cleanup, nsec3chain, link);
9244 if (nsec3chain->done) {
9245 dns_db_detach(&nsec3chain->db);
9246 dns_dbiterator_destroy(&nsec3chain->dbiterator);
9247 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
9248 } else {
9249 LOCK_ZONE(zone);
9250 ISC_LIST_PREPEND(zone->nsec3chain, nsec3chain, link);
9251 UNLOCK_ZONE(zone);
9252 result = dns_dbiterator_first(nsec3chain->dbiterator);
9253 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9254 dns_dbiterator_pause(nsec3chain->dbiterator);
9255 nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
9256 }
9257 nsec3chain = ISC_LIST_TAIL(cleanup);
9258 }
9259
9260 LOCK_ZONE(zone);
9261 for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain); nsec3chain != NULL;
9262 nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
9263 {
9264 dns_dbiterator_pause(nsec3chain->dbiterator);
9265 }
9266 UNLOCK_ZONE(zone);
9267
9268 dns_diff_clear(¶m_diff);
9269 dns_diff_clear(&nsec3_diff);
9270 dns_diff_clear(&nsec_diff);
9271 dns_diff_clear(&_sig_diff);
9272
9273 if (iterator != NULL) {
9274 dns_rdatasetiter_destroy(&iterator);
9275 }
9276
9277 for (i = 0; i < nkeys; i++) {
9278 dst_key_free(&zone_keys[i]);
9279 }
9280
9281 if (node != NULL) {
9282 dns_db_detachnode(db, &node);
9283 }
9284 if (version != NULL) {
9285 dns_db_closeversion(db, &version, false);
9286 dns_db_detach(&db);
9287 } else if (db != NULL) {
9288 dns_db_detach(&db);
9289 }
9290
9291 LOCK_ZONE(zone);
9292 if (ISC_LIST_HEAD(zone->nsec3chain) != NULL) {
9293 isc_interval_t interval;
9294 if (zone->update_disabled || result != ISC_R_SUCCESS) {
9295 isc_interval_set(&interval, 60, 0); /* 1 minute */
9296 } else {
9297 isc_interval_set(&interval, 0, 10000000); /* 10 ms */
9298 }
9299 isc_time_nowplusinterval(&zone->nsec3chaintime, &interval);
9300 } else {
9301 isc_time_settoepoch(&zone->nsec3chaintime);
9302 }
9303 UNLOCK_ZONE(zone);
9304
9305 INSIST(version == NULL);
9306 }
9307
9308 /*%
9309 * Delete all RRSIG records with the given algorithm and keyid.
9310 * Remove the NSEC record and RRSIGs if nkeys is zero.
9311 * If all remaining RRsets are signed with the given algorithm
9312 * set *has_algp to true.
9313 */
9314 static isc_result_t
9315 del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
9316 dns_dbnode_t *node, unsigned int nkeys, dns_secalg_t algorithm,
9317 uint16_t keyid, bool *has_algp, dns_diff_t *diff) {
9318 dns_rdata_rrsig_t rrsig;
9319 dns_rdataset_t rdataset;
9320 dns_rdatasetiter_t *iterator = NULL;
9321 isc_result_t result;
9322 bool alg_missed = false;
9323 bool alg_found = false;
9324
9325 char namebuf[DNS_NAME_FORMATSIZE];
9326 dns_name_format(name, namebuf, sizeof(namebuf));
9327
9328 result = dns_db_allrdatasets(db, node, version, 0, 0, &iterator);
9329 if (result != ISC_R_SUCCESS) {
9330 if (result == ISC_R_NOTFOUND) {
9331 result = ISC_R_SUCCESS;
9332 }
9333 return result;
9334 }
9335
9336 dns_rdataset_init(&rdataset);
9337 for (result = dns_rdatasetiter_first(iterator); result == ISC_R_SUCCESS;
9338 result = dns_rdatasetiter_next(iterator))
9339 {
9340 bool has_alg = false;
9341 dns_rdatasetiter_current(iterator, &rdataset);
9342 if (nkeys == 0 && rdataset.type == dns_rdatatype_nsec) {
9343 for (result = dns_rdataset_first(&rdataset);
9344 result == ISC_R_SUCCESS;
9345 result = dns_rdataset_next(&rdataset))
9346 {
9347 dns_rdata_t rdata = DNS_RDATA_INIT;
9348 dns_rdataset_current(&rdataset, &rdata);
9349 CHECK(update_one_rr(db, version, diff,
9350 DNS_DIFFOP_DEL, name,
9351 rdataset.ttl, &rdata));
9352 }
9353 if (result != ISC_R_NOMORE) {
9354 goto cleanup;
9355 }
9356 dns_rdataset_disassociate(&rdataset);
9357 continue;
9358 }
9359 if (rdataset.type != dns_rdatatype_rrsig) {
9360 dns_rdataset_disassociate(&rdataset);
9361 continue;
9362 }
9363 for (result = dns_rdataset_first(&rdataset);
9364 result == ISC_R_SUCCESS;
9365 result = dns_rdataset_next(&rdataset))
9366 {
9367 dns_rdata_t rdata = DNS_RDATA_INIT;
9368 dns_rdataset_current(&rdataset, &rdata);
9369 CHECK(dns_rdata_tostruct(&rdata, &rrsig, NULL));
9370 if (nkeys != 0 && (rrsig.algorithm != algorithm ||
9371 rrsig.keyid != keyid))
9372 {
9373 if (rrsig.algorithm == algorithm) {
9374 has_alg = true;
9375 }
9376 continue;
9377 }
9378 CHECK(update_one_rr(db, version, diff,
9379 DNS_DIFFOP_DELRESIGN, name,
9380 rdataset.ttl, &rdata));
9381 }
9382 dns_rdataset_disassociate(&rdataset);
9383 if (result != ISC_R_NOMORE) {
9384 break;
9385 }
9386
9387 /*
9388 * After deleting, if there's still a signature for
9389 * 'algorithm', set alg_found; if not, set alg_missed.
9390 */
9391 if (has_alg) {
9392 alg_found = true;
9393 } else {
9394 alg_missed = true;
9395 }
9396 }
9397 if (result == ISC_R_NOMORE) {
9398 result = ISC_R_SUCCESS;
9399 }
9400
9401 /*
9402 * Set `has_algp` if the algorithm was found in every RRset:
9403 * i.e., found in at least one, and not missing from any.
9404 */
9405 *has_algp = (alg_found && !alg_missed);
9406 cleanup:
9407 if (dns_rdataset_isassociated(&rdataset)) {
9408 dns_rdataset_disassociate(&rdataset);
9409 }
9410 dns_rdatasetiter_destroy(&iterator);
9411 return result;
9412 }
9413
9414 /*
9415 * Prevent the zone entering a inconsistent state where
9416 * NSEC only DNSKEYs are present with NSEC3 chains.
9417 */
9418 bool
9419 dns_zone_check_dnskey_nsec3(dns_zone_t *zone, dns_db_t *db,
9420 dns_dbversion_t *ver, dns_diff_t *diff,
9421 dst_key_t **keys, unsigned int numkeys) {
9422 uint8_t alg;
9423 dns_rdatatype_t privatetype;
9424 ;
9425 bool nseconly = false, nsec3 = false;
9426 isc_result_t result;
9427
9428 REQUIRE(DNS_ZONE_VALID(zone));
9429 REQUIRE(db != NULL);
9430
9431 privatetype = dns_zone_getprivatetype(zone);
9432
9433 /* Scan the tuples for an NSEC-only DNSKEY */
9434 if (diff != NULL) {
9435 for (dns_difftuple_t *tuple = ISC_LIST_HEAD(diff->tuples);
9436 tuple != NULL; tuple = ISC_LIST_NEXT(tuple, link))
9437 {
9438 if (nseconly && nsec3) {
9439 break;
9440 }
9441
9442 if (tuple->op != DNS_DIFFOP_ADD) {
9443 continue;
9444 }
9445
9446 if (tuple->rdata.type == dns_rdatatype_nsec3param) {
9447 nsec3 = true;
9448 }
9449
9450 if (tuple->rdata.type != dns_rdatatype_dnskey) {
9451 continue;
9452 }
9453
9454 alg = tuple->rdata.data[3];
9455 if (alg == DNS_KEYALG_RSAMD5 || alg == DNS_KEYALG_DSA ||
9456 alg == DNS_KEYALG_RSASHA1)
9457 {
9458 nseconly = true;
9459 }
9460 }
9461 }
9462 /* Scan the zone keys for an NSEC-only DNSKEY */
9463 if (keys != NULL && !nseconly) {
9464 for (unsigned int i = 0; i < numkeys; i++) {
9465 alg = dst_key_alg(keys[i]);
9466 if (alg == DNS_KEYALG_RSAMD5 || alg == DNS_KEYALG_DSA ||
9467 alg == DNS_KEYALG_RSASHA1)
9468 {
9469 nseconly = true;
9470 break;
9471 }
9472 }
9473 }
9474
9475 /* Check DB for NSEC-only DNSKEY */
9476 if (!nseconly) {
9477 result = dns_nsec_nseconly(db, ver, diff, &nseconly);
9478 /*
9479 * Adding an NSEC3PARAM record can proceed without a
9480 * DNSKEY (it will trigger a delayed change), so we can
9481 * ignore ISC_R_NOTFOUND here.
9482 */
9483 if (result == ISC_R_NOTFOUND) {
9484 result = ISC_R_SUCCESS;
9485 }
9486 CHECK(result);
9487 }
9488
9489 /* Check existing DB for NSEC3 */
9490 if (!nsec3) {
9491 CHECK(dns_nsec3_activex(db, ver, false, privatetype, &nsec3));
9492 }
9493
9494 /* Check kasp for NSEC3PARAM settings */
9495 if (!nsec3) {
9496 dns_kasp_t *kasp = zone->kasp;
9497 if (kasp != NULL) {
9498 nsec3 = dns_kasp_nsec3(kasp);
9499 }
9500 }
9501
9502 /* Refuse to allow NSEC3 with NSEC-only keys */
9503 if (nseconly && nsec3) {
9504 goto cleanup;
9505 }
9506
9507 return true;
9508
9509 cleanup:
9510 return false;
9511 }
9512
9513 /*
9514 * Incrementally sign the zone using the keys requested.
9515 * Builds the NSEC chain if required.
9516 */
9517 static void
9518 zone_sign(dns_zone_t *zone) {
9519 dns_db_t *db = NULL;
9520 dns_dbnode_t *node = NULL;
9521 dns_dbversion_t *version = NULL;
9522 dns_diff_t _sig_diff;
9523 dns_diff_t post_diff;
9524 dns__zonediff_t zonediff;
9525 dns_fixedname_t fixed;
9526 dns_fixedname_t nextfixed;
9527 dns_kasp_t *kasp;
9528 dns_name_t *name, *nextname;
9529 dns_rdataset_t rdataset;
9530 dns_signing_t *signing, *nextsigning;
9531 dns_signinglist_t cleanup;
9532 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
9533 int32_t signatures;
9534 bool is_ksk, is_zsk;
9535 bool with_ksk, with_zsk;
9536 bool commit = false;
9537 bool is_bottom_of_zone;
9538 bool build_nsec = false;
9539 bool build_nsec3 = false;
9540 bool use_kasp = false;
9541 bool first;
9542 isc_result_t result;
9543 isc_stdtime_t now, inception, soaexpire, expire;
9544 unsigned int i, j;
9545 unsigned int nkeys = 0;
9546 uint32_t nodes;
9547
9548 ENTER;
9549
9550 dns_rdataset_init(&rdataset);
9551 name = dns_fixedname_initname(&fixed);
9552 nextname = dns_fixedname_initname(&nextfixed);
9553 dns_diff_init(zone->mctx, &_sig_diff);
9554 dns_diff_init(zone->mctx, &post_diff);
9555 zonediff_init(&zonediff, &_sig_diff);
9556 ISC_LIST_INIT(cleanup);
9557
9558 /*
9559 * Updates are disabled. Pause for 1 minute.
9560 */
9561 if (zone->update_disabled) {
9562 result = ISC_R_FAILURE;
9563 goto done;
9564 }
9565
9566 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9567 if (zone->db != NULL) {
9568 dns_db_attach(zone->db, &db);
9569 }
9570 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9571 if (db == NULL) {
9572 result = ISC_R_FAILURE;
9573 goto done;
9574 }
9575
9576 result = dns_db_newversion(db, &version);
9577 if (result != ISC_R_SUCCESS) {
9578 dnssec_log(zone, ISC_LOG_ERROR,
9579 "zone_sign:dns_db_newversion -> %s",
9580 isc_result_totext(result));
9581 goto done;
9582 }
9583
9584 now = isc_stdtime_now();
9585
9586 result = dns_zone_findkeys(zone, db, version, now, zone->mctx,
9587 DNS_MAXZONEKEYS, zone_keys, &nkeys);
9588 if (result != ISC_R_SUCCESS) {
9589 dnssec_log(zone, ISC_LOG_ERROR,
9590 "zone_sign:dns_zone_findkeys -> %s",
9591 isc_result_totext(result));
9592 goto done;
9593 }
9594
9595 kasp = zone->kasp;
9596
9597 calculate_rrsig_validity(zone, now, &inception, &soaexpire, NULL,
9598 &expire);
9599
9600 /*
9601 * We keep pulling nodes off each iterator in turn until
9602 * we have no more nodes to pull off or we reach the limits
9603 * for this quantum.
9604 */
9605 nodes = zone->nodes;
9606 signatures = zone->signatures;
9607 signing = ISC_LIST_HEAD(zone->signing);
9608 first = true;
9609
9610 if (kasp != NULL) {
9611 use_kasp = true;
9612 }
9613 dnssec_log(zone, ISC_LOG_DEBUG(3), "zone_sign:use kasp -> %s",
9614 use_kasp ? "yes" : "no");
9615
9616 /* Determine which type of chain to build */
9617 CHECK(dns_private_chains(db, version, zone->privatetype, &build_nsec,
9618 &build_nsec3));
9619 if (!build_nsec && !build_nsec3) {
9620 if (use_kasp) {
9621 build_nsec3 = dns_kasp_nsec3(kasp);
9622 if (!dns_zone_check_dnskey_nsec3(
9623 zone, db, version, NULL,
9624 (dst_key_t **)&zone_keys, nkeys))
9625 {
9626 dnssec_log(zone, ISC_LOG_INFO,
9627 "wait building NSEC3 chain until "
9628 "NSEC only DNSKEYs are removed");
9629 build_nsec3 = false;
9630 }
9631 build_nsec = !build_nsec3;
9632 } else {
9633 /* If neither chain is found, default to NSEC */
9634 build_nsec = true;
9635 }
9636 }
9637
9638 while (signing != NULL && nodes-- > 0 && signatures > 0) {
9639 bool has_alg = false;
9640
9641 dns_dbiterator_pause(signing->dbiterator);
9642 nextsigning = ISC_LIST_NEXT(signing, link);
9643
9644 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9645 if (signing->done || signing->db != zone->db) {
9646 /*
9647 * The zone has been reloaded. We will have to
9648 * created new signings as part of the reload
9649 * process so we can destroy this one.
9650 */
9651 ISC_LIST_UNLINK(zone->signing, signing, link);
9652 ISC_LIST_APPEND(cleanup, signing, link);
9653 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9654 goto next_signing;
9655 }
9656 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9657
9658 if (signing->db != db) {
9659 goto next_signing;
9660 }
9661
9662 is_bottom_of_zone = false;
9663
9664 if (first && signing->deleteit) {
9665 /*
9666 * Remove the key we are deleting from consideration.
9667 */
9668 for (i = 0, j = 0; i < nkeys; i++) {
9669 /*
9670 * Find the key we want to remove.
9671 */
9672 if (ALG(zone_keys[i]) == signing->algorithm &&
9673 dst_key_id(zone_keys[i]) == signing->keyid)
9674 {
9675 dst_key_free(&zone_keys[i]);
9676 continue;
9677 }
9678 zone_keys[j] = zone_keys[i];
9679 j++;
9680 }
9681 for (i = j; i < nkeys; i++) {
9682 zone_keys[i] = NULL;
9683 }
9684 nkeys = j;
9685 }
9686
9687 dns_dbiterator_current(signing->dbiterator, &node, name);
9688
9689 if (signing->deleteit) {
9690 dns_dbiterator_pause(signing->dbiterator);
9691 CHECK(del_sig(db, version, name, node, nkeys,
9692 signing->algorithm, signing->keyid,
9693 &has_alg, zonediff.diff));
9694 }
9695
9696 /*
9697 * On the first pass we need to check if the current node
9698 * has not been obscured.
9699 */
9700 if (first) {
9701 dns_fixedname_t ffound;
9702 dns_name_t *found;
9703 found = dns_fixedname_initname(&ffound);
9704 result = dns_db_find(
9705 db, name, version, dns_rdatatype_soa,
9706 DNS_DBFIND_NOWILD, 0, NULL, found, NULL, NULL);
9707 if ((result == DNS_R_DELEGATION ||
9708 result == DNS_R_DNAME) &&
9709 !dns_name_equal(name, found))
9710 {
9711 /*
9712 * Remember the obscuring name so that
9713 * we skip all obscured names.
9714 */
9715 dns_name_copy(found, name);
9716 is_bottom_of_zone = true;
9717 goto next_node;
9718 }
9719 }
9720
9721 /*
9722 * Process one node.
9723 */
9724 with_ksk = false;
9725 with_zsk = false;
9726 dns_dbiterator_pause(signing->dbiterator);
9727
9728 CHECK(check_if_bottom_of_zone(db, node, version,
9729 &is_bottom_of_zone));
9730
9731 for (i = 0; !has_alg && i < nkeys; i++) {
9732 bool both = false;
9733 /*
9734 * Find the keys we want to sign with.
9735 */
9736 if (!dst_key_isprivate(zone_keys[i])) {
9737 continue;
9738 }
9739 if (dst_key_inactive(zone_keys[i])) {
9740 continue;
9741 }
9742
9743 /*
9744 * When adding look for the specific key.
9745 */
9746 if (!signing->deleteit &&
9747 (dst_key_alg(zone_keys[i]) != signing->algorithm ||
9748 dst_key_id(zone_keys[i]) != signing->keyid))
9749 {
9750 continue;
9751 }
9752
9753 /*
9754 * When deleting make sure we are properly signed
9755 * with the algorithm that was being removed.
9756 */
9757 if (signing->deleteit &&
9758 ALG(zone_keys[i]) != signing->algorithm)
9759 {
9760 continue;
9761 }
9762
9763 /*
9764 * We do KSK processing.
9765 */
9766 if (use_kasp) {
9767 /*
9768 * A dnssec-policy is found. Check what
9769 * RRsets this key can sign.
9770 */
9771 isc_result_t kresult;
9772 is_ksk = false;
9773 kresult = dst_key_getbool(
9774 zone_keys[i], DST_BOOL_KSK, &is_ksk);
9775 if (kresult != ISC_R_SUCCESS) {
9776 if (KSK(zone_keys[i])) {
9777 is_ksk = true;
9778 }
9779 }
9780
9781 is_zsk = false;
9782 kresult = dst_key_getbool(
9783 zone_keys[i], DST_BOOL_ZSK, &is_zsk);
9784 if (kresult != ISC_R_SUCCESS) {
9785 if (!KSK(zone_keys[i])) {
9786 is_zsk = true;
9787 }
9788 }
9789 both = true;
9790 } else {
9791 is_ksk = KSK(zone_keys[i]);
9792 is_zsk = !is_ksk;
9793
9794 /*
9795 * Don't consider inactive keys, however the key
9796 * may be temporary offline, so do consider KSKs
9797 * which private key files are unavailable.
9798 */
9799 both = dst_key_have_ksk_and_zsk(
9800 zone_keys, nkeys, i, false, is_ksk,
9801 is_zsk, NULL, NULL);
9802 if (both || REVOKE(zone_keys[i])) {
9803 is_ksk = KSK(zone_keys[i]);
9804 is_zsk = !KSK(zone_keys[i]);
9805 } else {
9806 is_ksk = false;
9807 is_zsk = false;
9808 }
9809 }
9810
9811 /*
9812 * If deleting signatures, we need to ensure that
9813 * the RRset is still signed at least once by a
9814 * KSK and a ZSK.
9815 */
9816 if (signing->deleteit && is_zsk && with_zsk) {
9817 continue;
9818 }
9819
9820 if (signing->deleteit && is_ksk && with_ksk) {
9821 continue;
9822 }
9823
9824 CHECK(sign_a_node(
9825 db, zone, name, node, version, build_nsec3,
9826 build_nsec, zone_keys[i], now, inception,
9827 expire, zone_nsecttl(zone), both, is_ksk,
9828 is_zsk, signing->fullsign, is_bottom_of_zone,
9829 zonediff.diff, &signatures, zone->mctx));
9830 /*
9831 * If we are adding we are done. Look for other keys
9832 * of the same algorithm if deleting.
9833 */
9834 if (!signing->deleteit) {
9835 break;
9836 }
9837 if (is_zsk) {
9838 with_zsk = true;
9839 }
9840 if (is_ksk) {
9841 with_ksk = true;
9842 }
9843 }
9844
9845 /*
9846 * Go onto next node.
9847 */
9848 next_node:
9849 first = false;
9850 dns_db_detachnode(db, &node);
9851 do {
9852 result = dns_dbiterator_next(signing->dbiterator);
9853 if (result == ISC_R_NOMORE) {
9854 ISC_LIST_UNLINK(zone->signing, signing, link);
9855 ISC_LIST_APPEND(cleanup, signing, link);
9856 dns_dbiterator_pause(signing->dbiterator);
9857 if (nkeys != 0 && build_nsec) {
9858 /*
9859 * We have finished regenerating the
9860 * zone with a zone signing key.
9861 * The NSEC chain is now complete and
9862 * there is a full set of signatures
9863 * for the zone. We can now clear the
9864 * OPT bit from the NSEC record.
9865 */
9866 result = updatesecure(
9867 db, version, &zone->origin,
9868 zone_nsecttl(zone), false,
9869 &post_diff);
9870 if (result != ISC_R_SUCCESS) {
9871 dnssec_log(zone, ISC_LOG_ERROR,
9872 "updatesecure -> %s",
9873 isc_result_totext(
9874 result));
9875 goto done;
9876 }
9877 }
9878 result = updatesignwithkey(
9879 zone, signing, version, build_nsec3,
9880 zone_nsecttl(zone), &post_diff);
9881 if (result != ISC_R_SUCCESS) {
9882 dnssec_log(zone, ISC_LOG_ERROR,
9883 "updatesignwithkey -> %s",
9884 isc_result_totext(result));
9885 goto done;
9886 }
9887 build_nsec = false;
9888 goto next_signing;
9889 } else if (result != ISC_R_SUCCESS) {
9890 dnssec_log(zone, ISC_LOG_ERROR,
9891 "zone_sign:"
9892 "dns_dbiterator_next -> %s",
9893 isc_result_totext(result));
9894 goto done;
9895 } else if (is_bottom_of_zone) {
9896 dns_dbiterator_current(signing->dbiterator,
9897 &node, nextname);
9898 dns_db_detachnode(db, &node);
9899 if (!dns_name_issubdomain(nextname, name)) {
9900 break;
9901 }
9902 } else {
9903 break;
9904 }
9905 } while (1);
9906 continue;
9907
9908 next_signing:
9909 dns_dbiterator_pause(signing->dbiterator);
9910 signing = nextsigning;
9911 first = true;
9912 }
9913
9914 if (ISC_LIST_HEAD(post_diff.tuples) != NULL) {
9915 result = dns__zone_updatesigs(&post_diff, db, version,
9916 zone_keys, nkeys, zone, inception,
9917 expire, 0, now, &zonediff);
9918 if (result != ISC_R_SUCCESS) {
9919 dnssec_log(zone, ISC_LOG_ERROR,
9920 "zone_sign:dns__zone_updatesigs -> %s",
9921 isc_result_totext(result));
9922 goto done;
9923 }
9924 }
9925
9926 /*
9927 * Have we changed anything?
9928 */
9929 if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
9930 if (zonediff.offline) {
9931 commit = true;
9932 }
9933 result = ISC_R_SUCCESS;
9934 goto pauseall;
9935 }
9936
9937 commit = true;
9938
9939 result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
9940 &zonediff, zone_keys, nkeys, now, false);
9941 if (result != ISC_R_SUCCESS) {
9942 dnssec_log(zone, ISC_LOG_ERROR, "zone_sign:del_sigs -> %s",
9943 isc_result_totext(result));
9944 goto done;
9945 }
9946
9947 result = update_soa_serial(zone, db, version, zonediff.diff, zone->mctx,
9948 zone->updatemethod);
9949 if (result != ISC_R_SUCCESS) {
9950 dnssec_log(zone, ISC_LOG_ERROR,
9951 "zone_sign:update_soa_serial -> %s",
9952 isc_result_totext(result));
9953 goto done;
9954 }
9955
9956 /*
9957 * Generate maximum life time signatures so that the above loop
9958 * termination is sensible.
9959 */
9960 result = add_sigs(db, version, &zone->origin, zone, dns_rdatatype_soa,
9961 zonediff.diff, zone_keys, nkeys, zone->mctx, now,
9962 inception, soaexpire);
9963 if (result != ISC_R_SUCCESS) {
9964 dnssec_log(zone, ISC_LOG_ERROR, "zone_sign:add_sigs -> %s",
9965 isc_result_totext(result));
9966 goto done;
9967 }
9968
9969 /*
9970 * Write changes to journal file.
9971 */
9972 CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_sign"));
9973
9974 pauseall:
9975 /*
9976 * Pause all iterators so that dns_db_closeversion() can succeed.
9977 */
9978 for (signing = ISC_LIST_HEAD(zone->signing); signing != NULL;
9979 signing = ISC_LIST_NEXT(signing, link))
9980 {
9981 dns_dbiterator_pause(signing->dbiterator);
9982 }
9983
9984 for (signing = ISC_LIST_HEAD(cleanup); signing != NULL;
9985 signing = ISC_LIST_NEXT(signing, link))
9986 {
9987 dns_dbiterator_pause(signing->dbiterator);
9988 }
9989
9990 /*
9991 * Everything has succeeded. Commit the changes.
9992 */
9993 dns_db_closeversion(db, &version, commit);
9994
9995 /*
9996 * Everything succeeded so we can clean these up now.
9997 */
9998 signing = ISC_LIST_HEAD(cleanup);
9999 while (signing != NULL) {
10000 ISC_LIST_UNLINK(cleanup, signing, link);
10001 dns_db_detach(&signing->db);
10002 dns_dbiterator_destroy(&signing->dbiterator);
10003 isc_mem_put(zone->mctx, signing, sizeof *signing);
10004 signing = ISC_LIST_HEAD(cleanup);
10005 }
10006
10007 LOCK_ZONE(zone);
10008 set_resigntime(zone);
10009 if (commit) {
10010 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
10011 zone_needdump(zone, DNS_DUMP_DELAY);
10012 }
10013 UNLOCK_ZONE(zone);
10014
10015 cleanup:
10016 if (result != ISC_R_SUCCESS) {
10017 dnssec_log(zone, ISC_LOG_ERROR, "zone_sign: failed: %s",
10018 isc_result_totext(result));
10019 }
10020
10021 done:
10022 /*
10023 * Pause all dbiterators.
10024 */
10025 for (signing = ISC_LIST_HEAD(zone->signing); signing != NULL;
10026 signing = ISC_LIST_NEXT(signing, link))
10027 {
10028 dns_dbiterator_pause(signing->dbiterator);
10029 }
10030
10031 /*
10032 * Rollback the cleanup list.
10033 */
10034 signing = ISC_LIST_HEAD(cleanup);
10035 while (signing != NULL) {
10036 ISC_LIST_UNLINK(cleanup, signing, link);
10037 ISC_LIST_PREPEND(zone->signing, signing, link);
10038 dns_dbiterator_first(signing->dbiterator);
10039 dns_dbiterator_pause(signing->dbiterator);
10040 signing = ISC_LIST_HEAD(cleanup);
10041 }
10042
10043 dns_diff_clear(&_sig_diff);
10044 dns_diff_clear(&post_diff);
10045
10046 for (i = 0; i < nkeys; i++) {
10047 dst_key_free(&zone_keys[i]);
10048 }
10049
10050 if (node != NULL) {
10051 dns_db_detachnode(db, &node);
10052 }
10053
10054 if (version != NULL) {
10055 dns_db_closeversion(db, &version, false);
10056 dns_db_detach(&db);
10057 } else if (db != NULL) {
10058 dns_db_detach(&db);
10059 }
10060
10061 LOCK_ZONE(zone);
10062 if (ISC_LIST_HEAD(zone->signing) != NULL) {
10063 isc_interval_t interval;
10064 if (zone->update_disabled || result != ISC_R_SUCCESS) {
10065 isc_interval_set(&interval, 60, 0); /* 1 minute */
10066 } else {
10067 isc_interval_set(&interval, 0, 10000000); /* 10 ms */
10068 }
10069 isc_time_nowplusinterval(&zone->signingtime, &interval);
10070 } else {
10071 isc_time_settoepoch(&zone->signingtime);
10072 }
10073 UNLOCK_ZONE(zone);
10074
10075 INSIST(version == NULL);
10076 }
10077
10078 static isc_result_t
10079 normalize_key(dns_rdata_t *rr, dns_rdata_t *target, unsigned char *data,
10080 int size) {
10081 dns_rdata_dnskey_t dnskey;
10082 dns_rdata_keydata_t keydata;
10083 isc_buffer_t buf;
10084 isc_result_t result;
10085
10086 dns_rdata_reset(target);
10087 isc_buffer_init(&buf, data, size);
10088
10089 switch (rr->type) {
10090 case dns_rdatatype_dnskey:
10091 result = dns_rdata_tostruct(rr, &dnskey, NULL);
10092 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10093 dnskey.flags &= ~DNS_KEYFLAG_REVOKE;
10094 dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
10095 &dnskey, &buf);
10096 break;
10097 case dns_rdatatype_keydata:
10098 result = dns_rdata_tostruct(rr, &keydata, NULL);
10099 if (result == ISC_R_UNEXPECTEDEND) {
10100 return result;
10101 }
10102 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10103 dns_keydata_todnskey(&keydata, &dnskey, NULL);
10104 dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
10105 &dnskey, &buf);
10106 break;
10107 default:
10108 UNREACHABLE();
10109 }
10110 return ISC_R_SUCCESS;
10111 }
10112
10113 /*
10114 * 'rdset' contains either a DNSKEY rdataset from the zone apex, or
10115 * a KEYDATA rdataset from the key zone.
10116 *
10117 * 'rr' contains either a DNSKEY record, or a KEYDATA record
10118 *
10119 * After normalizing keys to the same format (DNSKEY, with revoke bit
10120 * cleared), return true if a key that matches 'rr' is found in
10121 * 'rdset', or false if not.
10122 */
10123
10124 static bool
10125 matchkey(dns_rdataset_t *rdset, dns_rdata_t *rr) {
10126 unsigned char data1[4096], data2[4096];
10127 dns_rdata_t rdata, rdata1, rdata2;
10128 isc_result_t result;
10129
10130 dns_rdata_init(&rdata);
10131 dns_rdata_init(&rdata1);
10132 dns_rdata_init(&rdata2);
10133
10134 result = normalize_key(rr, &rdata1, data1, sizeof(data1));
10135 if (result != ISC_R_SUCCESS) {
10136 return false;
10137 }
10138
10139 for (result = dns_rdataset_first(rdset); result == ISC_R_SUCCESS;
10140 result = dns_rdataset_next(rdset))
10141 {
10142 dns_rdata_reset(&rdata);
10143 dns_rdataset_current(rdset, &rdata);
10144 result = normalize_key(&rdata, &rdata2, data2, sizeof(data2));
10145 if (result != ISC_R_SUCCESS) {
10146 continue;
10147 }
10148 if (dns_rdata_compare(&rdata1, &rdata2) == 0) {
10149 return true;
10150 }
10151 }
10152
10153 return false;
10154 }
10155
10156 /*
10157 * Calculate the refresh interval for a keydata zone, per
10158 * RFC5011: MAX(1 hr,
10159 * MIN(15 days,
10160 * 1/2 * OrigTTL,
10161 * 1/2 * RRSigExpirationInterval))
10162 * or for retries: MAX(1 hr,
10163 * MIN(1 day,
10164 * 1/10 * OrigTTL,
10165 * 1/10 * RRSigExpirationInterval))
10166 */
10167 static isc_stdtime_t
10168 refresh_time(dns_keyfetch_t *kfetch, bool retry) {
10169 isc_result_t result;
10170 uint32_t t;
10171 dns_rdataset_t *rdset;
10172 dns_rdata_t sigrr = DNS_RDATA_INIT;
10173 dns_rdata_sig_t sig;
10174 isc_stdtime_t now = isc_stdtime_now();
10175
10176 if (dns_rdataset_isassociated(&kfetch->dnskeysigset)) {
10177 rdset = &kfetch->dnskeysigset;
10178 } else {
10179 return now + dns_zone_mkey_hour;
10180 }
10181
10182 result = dns_rdataset_first(rdset);
10183 if (result != ISC_R_SUCCESS) {
10184 return now + dns_zone_mkey_hour;
10185 }
10186
10187 dns_rdataset_current(rdset, &sigrr);
10188 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
10189 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10190
10191 if (!retry) {
10192 t = sig.originalttl / 2;
10193
10194 if (isc_serial_gt(sig.timeexpire, now)) {
10195 uint32_t exp = (sig.timeexpire - now) / 2;
10196 if (t > exp) {
10197 t = exp;
10198 }
10199 }
10200
10201 if (t > (15 * dns_zone_mkey_day)) {
10202 t = (15 * dns_zone_mkey_day);
10203 }
10204
10205 if (t < dns_zone_mkey_hour) {
10206 t = dns_zone_mkey_hour;
10207 }
10208 } else {
10209 t = sig.originalttl / 10;
10210
10211 if (isc_serial_gt(sig.timeexpire, now)) {
10212 uint32_t exp = (sig.timeexpire - now) / 10;
10213 if (t > exp) {
10214 t = exp;
10215 }
10216 }
10217
10218 if (t > dns_zone_mkey_day) {
10219 t = dns_zone_mkey_day;
10220 }
10221
10222 if (t < dns_zone_mkey_hour) {
10223 t = dns_zone_mkey_hour;
10224 }
10225 }
10226
10227 return now + t;
10228 }
10229
10230 /*
10231 * This routine is called when no changes are needed in a KEYDATA
10232 * record except to simply update the refresh timer. Caller should
10233 * hold zone lock.
10234 */
10235 static isc_result_t
10236 minimal_update(dns_keyfetch_t *kfetch, dns_dbversion_t *ver, dns_diff_t *diff) {
10237 isc_result_t result;
10238 isc_buffer_t keyb;
10239 unsigned char key_buf[4096];
10240 dns_rdata_t rdata = DNS_RDATA_INIT;
10241 dns_rdata_keydata_t keydata;
10242 dns_name_t *name;
10243 dns_zone_t *zone = kfetch->zone;
10244 isc_stdtime_t now = isc_stdtime_now();
10245
10246 name = dns_fixedname_name(&kfetch->name);
10247
10248 for (result = dns_rdataset_first(&kfetch->keydataset);
10249 result == ISC_R_SUCCESS;
10250 result = dns_rdataset_next(&kfetch->keydataset))
10251 {
10252 dns_rdata_reset(&rdata);
10253 dns_rdataset_current(&kfetch->keydataset, &rdata);
10254
10255 /* Delete old version */
10256 CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_DEL, name,
10257 0, &rdata));
10258
10259 /* Update refresh timer */
10260 result = dns_rdata_tostruct(&rdata, &keydata, NULL);
10261 if (result == ISC_R_UNEXPECTEDEND) {
10262 continue;
10263 }
10264 CHECK(result);
10265
10266 keydata.refresh = refresh_time(kfetch, true);
10267 set_refreshkeytimer(zone, &keydata, now, false);
10268
10269 dns_rdata_reset(&rdata);
10270 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10271 CHECK(dns_rdata_fromstruct(&rdata, zone->rdclass,
10272 dns_rdatatype_keydata, &keydata,
10273 &keyb));
10274
10275 /* Insert updated version */
10276 CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_ADD, name,
10277 0, &rdata));
10278 }
10279 result = ISC_R_SUCCESS;
10280 cleanup:
10281 return result;
10282 }
10283
10284 /*
10285 * Verify that DNSKEY set is signed by the key specified in 'keydata'.
10286 */
10287 static bool
10288 revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) {
10289 isc_result_t result;
10290 dns_name_t *keyname;
10291 isc_mem_t *mctx;
10292 dns_rdata_t sigrr = DNS_RDATA_INIT;
10293 dns_rdata_t rr = DNS_RDATA_INIT;
10294 dns_rdata_rrsig_t sig;
10295 dns_rdata_dnskey_t dnskey;
10296 dst_key_t *dstkey = NULL;
10297 unsigned char key_buf[4096];
10298 isc_buffer_t keyb;
10299 bool answer = false;
10300
10301 REQUIRE(kfetch != NULL && keydata != NULL);
10302 REQUIRE(dns_rdataset_isassociated(&kfetch->dnskeysigset));
10303
10304 keyname = dns_fixedname_name(&kfetch->name);
10305 mctx = kfetch->zone->view->mctx;
10306
10307 /* Generate a key from keydata */
10308 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10309 dns_keydata_todnskey(keydata, &dnskey, NULL);
10310 dns_rdata_fromstruct(&rr, keydata->common.rdclass, dns_rdatatype_dnskey,
10311 &dnskey, &keyb);
10312 result = dns_dnssec_keyfromrdata(keyname, &rr, mctx, &dstkey);
10313 if (result != ISC_R_SUCCESS) {
10314 return false;
10315 }
10316
10317 /* See if that key generated any of the signatures */
10318 for (result = dns_rdataset_first(&kfetch->dnskeysigset);
10319 result == ISC_R_SUCCESS;
10320 result = dns_rdataset_next(&kfetch->dnskeysigset))
10321 {
10322 dns_fixedname_t fixed;
10323 dns_fixedname_init(&fixed);
10324
10325 dns_rdata_reset(&sigrr);
10326 dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
10327 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
10328 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10329
10330 if (dst_key_alg(dstkey) == sig.algorithm &&
10331 dst_key_rid(dstkey) == sig.keyid)
10332 {
10333 result = dns_dnssec_verify(
10334 keyname, &kfetch->dnskeyset, dstkey, false, 0,
10335 mctx, &sigrr, dns_fixedname_name(&fixed));
10336
10337 dnssec_log(kfetch->zone, ISC_LOG_DEBUG(3),
10338 "Confirm revoked DNSKEY is self-signed: %s",
10339 isc_result_totext(result));
10340
10341 if (result == ISC_R_SUCCESS) {
10342 answer = true;
10343 break;
10344 }
10345 }
10346 }
10347
10348 dst_key_free(&dstkey);
10349 return answer;
10350 }
10351
10352 /*
10353 * A DNSKEY set has been fetched from the zone apex of a zone whose trust
10354 * anchors are being managed; scan the keyset, and update the key zone and the
10355 * local trust anchors according to RFC5011.
10356 */
10357 static void
10358 keyfetch_done(void *arg) {
10359 dns_fetchresponse_t *resp = (dns_fetchresponse_t *)arg;
10360 isc_result_t result, eresult;
10361 dns_keyfetch_t *kfetch = NULL;
10362 dns_zone_t *zone = NULL;
10363 isc_mem_t *mctx = NULL;
10364 dns_keytable_t *secroots = NULL;
10365 dns_dbversion_t *ver = NULL;
10366 dns_diff_t diff;
10367 bool alldone = false;
10368 bool commit = false;
10369 dns_name_t *keyname = NULL;
10370 dns_rdata_t sigrr = DNS_RDATA_INIT;
10371 dns_rdata_t dnskeyrr = DNS_RDATA_INIT;
10372 dns_rdata_t keydatarr = DNS_RDATA_INIT;
10373 dns_rdata_rrsig_t sig;
10374 dns_rdata_dnskey_t dnskey;
10375 dns_rdata_keydata_t keydata;
10376 bool initializing;
10377 char namebuf[DNS_NAME_FORMATSIZE];
10378 unsigned char key_buf[4096];
10379 isc_buffer_t keyb;
10380 dst_key_t *dstkey = NULL;
10381 isc_stdtime_t now;
10382 int pending = 0;
10383 bool secure = false, initial = false;
10384 bool free_needed;
10385 dns_keynode_t *keynode = NULL;
10386 dns_rdataset_t *dnskeys = NULL, *dnskeysigs = NULL;
10387 dns_rdataset_t *keydataset = NULL, dsset;
10388
10389 INSIST(resp != NULL);
10390
10391 kfetch = resp->arg;
10392
10393 INSIST(kfetch != NULL);
10394
10395 zone = kfetch->zone;
10396 mctx = kfetch->mctx;
10397 keyname = dns_fixedname_name(&kfetch->name);
10398 dnskeys = &kfetch->dnskeyset;
10399 dnskeysigs = &kfetch->dnskeysigset;
10400 keydataset = &kfetch->keydataset;
10401
10402 eresult = resp->result;
10403
10404 /* Free resources which are not of interest */
10405 if (resp->node != NULL) {
10406 dns_db_detachnode(resp->db, &resp->node);
10407 }
10408 if (resp->db != NULL) {
10409 dns_db_detach(&resp->db);
10410 }
10411
10412 dns_resolver_destroyfetch(&kfetch->fetch);
10413
10414 LOCK_ZONE(zone);
10415 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || zone->view == NULL) {
10416 goto out;
10417 }
10418
10419 now = isc_stdtime_now();
10420 dns_name_format(keyname, namebuf, sizeof(namebuf));
10421
10422 result = dns_view_getsecroots(zone->view, &secroots);
10423 INSIST(result == ISC_R_SUCCESS);
10424
10425 dns_diff_init(mctx, &diff);
10426
10427 CHECK(dns_db_newversion(kfetch->db, &ver));
10428
10429 zone->refreshkeycount--;
10430 alldone = (zone->refreshkeycount == 0);
10431
10432 if (alldone) {
10433 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
10434 }
10435
10436 dnssec_log(zone, ISC_LOG_DEBUG(3),
10437 "Returned from key fetch in keyfetch_done() for '%s': %s",
10438 namebuf, isc_result_totext(eresult));
10439
10440 /* Fetch failed */
10441 if (eresult != ISC_R_SUCCESS || !dns_rdataset_isassociated(dnskeys)) {
10442 dnssec_log(zone, ISC_LOG_WARNING,
10443 "Unable to fetch DNSKEY set '%s': %s", namebuf,
10444 isc_result_totext(eresult));
10445 CHECK(minimal_update(kfetch, ver, &diff));
10446 goto done;
10447 }
10448
10449 /* No RRSIGs found */
10450 if (!dns_rdataset_isassociated(dnskeysigs)) {
10451 dnssec_log(zone, ISC_LOG_WARNING,
10452 "No DNSKEY RRSIGs found for '%s': %s", namebuf,
10453 isc_result_totext(eresult));
10454 CHECK(minimal_update(kfetch, ver, &diff));
10455 goto done;
10456 }
10457
10458 /*
10459 * Clear any cached trust level, as we need to run validation
10460 * over again; trusted keys might have changed.
10461 */
10462 dnskeys->trust = dnskeysigs->trust = dns_trust_none;
10463
10464 /* Look up the trust anchor */
10465 result = dns_keytable_find(secroots, keyname, &keynode);
10466 if (result != ISC_R_SUCCESS) {
10467 goto anchors_done;
10468 }
10469
10470 /*
10471 * If the keynode has a DS trust anchor, use it for verification.
10472 */
10473 dns_rdataset_init(&dsset);
10474 if (dns_keynode_dsset(keynode, &dsset)) {
10475 for (result = dns_rdataset_first(dnskeysigs);
10476 result == ISC_R_SUCCESS;
10477 result = dns_rdataset_next(dnskeysigs))
10478 {
10479 isc_result_t tresult;
10480 dns_rdata_t keyrdata = DNS_RDATA_INIT;
10481
10482 dns_rdata_reset(&sigrr);
10483 dns_rdataset_current(dnskeysigs, &sigrr);
10484 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
10485 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10486
10487 for (tresult = dns_rdataset_first(&dsset);
10488 tresult == ISC_R_SUCCESS;
10489 tresult = dns_rdataset_next(&dsset))
10490 {
10491 dns_rdata_t dsrdata = DNS_RDATA_INIT;
10492 dns_rdata_ds_t ds;
10493
10494 dns_rdata_reset(&dsrdata);
10495 dns_rdataset_current(&dsset, &dsrdata);
10496 tresult = dns_rdata_tostruct(&dsrdata, &ds,
10497 NULL);
10498 RUNTIME_CHECK(tresult == ISC_R_SUCCESS);
10499
10500 if (ds.key_tag != sig.keyid ||
10501 ds.algorithm != sig.algorithm)
10502 {
10503 continue;
10504 }
10505
10506 result = dns_dnssec_matchdskey(
10507 keyname, &dsrdata, dnskeys, &keyrdata);
10508 if (result == ISC_R_SUCCESS) {
10509 break;
10510 }
10511 }
10512
10513 if (tresult == ISC_R_NOMORE) {
10514 continue;
10515 }
10516
10517 result = dns_dnssec_keyfromrdata(keyname, &keyrdata,
10518 mctx, &dstkey);
10519 if (result != ISC_R_SUCCESS) {
10520 continue;
10521 }
10522
10523 result = dns_dnssec_verify(keyname, dnskeys, dstkey,
10524 false, 0, mctx, &sigrr,
10525 NULL);
10526 dst_key_free(&dstkey);
10527
10528 dnssec_log(zone, ISC_LOG_DEBUG(3),
10529 "Verifying DNSKEY set for zone "
10530 "'%s' using DS %d/%d: %s",
10531 namebuf, sig.keyid, sig.algorithm,
10532 isc_result_totext(result));
10533
10534 if (result == ISC_R_SUCCESS) {
10535 dnskeys->trust = dns_trust_secure;
10536 dnskeysigs->trust = dns_trust_secure;
10537 initial = dns_keynode_initial(keynode);
10538 dns_keynode_trust(keynode);
10539 secure = true;
10540 break;
10541 }
10542 }
10543 dns_rdataset_disassociate(&dsset);
10544 }
10545
10546 anchors_done:
10547 if (keynode != NULL) {
10548 dns_keynode_detach(&keynode);
10549 }
10550
10551 /*
10552 * If we were not able to verify the answer using the current
10553 * trusted keys then all we can do is look at any revoked keys.
10554 */
10555 if (!secure) {
10556 dnssec_log(zone, ISC_LOG_INFO,
10557 "DNSKEY set for zone '%s' could not be verified "
10558 "with current keys",
10559 namebuf);
10560 }
10561
10562 /*
10563 * First scan keydataset to find keys that are not in dnskeyset
10564 * - Missing keys which are not scheduled for removal,
10565 * log a warning
10566 * - Missing keys which are scheduled for removal and
10567 * the remove hold-down timer has completed should
10568 * be removed from the key zone
10569 * - Missing keys whose acceptance timers have not yet
10570 * completed, log a warning and reset the acceptance
10571 * timer to 30 days in the future
10572 * - All keys not being removed have their refresh timers
10573 * updated
10574 */
10575 initializing = true;
10576 for (result = dns_rdataset_first(keydataset); result == ISC_R_SUCCESS;
10577 result = dns_rdataset_next(keydataset))
10578 {
10579 dns_keytag_t keytag;
10580
10581 dns_rdata_reset(&keydatarr);
10582 dns_rdataset_current(keydataset, &keydatarr);
10583 result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
10584 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10585
10586 dns_keydata_todnskey(&keydata, &dnskey, NULL);
10587 result = compute_tag(keyname, &dnskey, mctx, &keytag);
10588 if (result != ISC_R_SUCCESS) {
10589 /*
10590 * Skip if we cannot compute the key tag.
10591 * This may happen if the algorithm is unsupported
10592 */
10593 dns_zone_log(zone, ISC_LOG_ERROR,
10594 "Cannot compute tag for key in zone %s: "
10595 "%s "
10596 "(skipping)",
10597 namebuf, isc_result_totext(result));
10598 continue;
10599 }
10600 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10601
10602 /*
10603 * If any keydata record has a nonzero add holddown, then
10604 * there was a pre-existing trust anchor for this domain;
10605 * that means we are *not* initializing it and shouldn't
10606 * automatically trust all the keys we find at the zone apex.
10607 */
10608 initializing = initializing && (keydata.addhd == 0);
10609
10610 if (!matchkey(dnskeys, &keydatarr)) {
10611 bool deletekey = false;
10612
10613 if (!secure) {
10614 if (keydata.removehd != 0 &&
10615 keydata.removehd <= now)
10616 {
10617 deletekey = true;
10618 }
10619 } else if (keydata.addhd == 0) {
10620 deletekey = true;
10621 } else if (keydata.addhd > now) {
10622 dnssec_log(zone, ISC_LOG_INFO,
10623 "Pending key %d for zone %s "
10624 "unexpectedly missing from DNSKEY "
10625 "RRset: restarting 30-day "
10626 "acceptance timer",
10627 keytag, namebuf);
10628 if (keydata.addhd < now + dns_zone_mkey_month) {
10629 keydata.addhd = now +
10630 dns_zone_mkey_month;
10631 }
10632 keydata.refresh = refresh_time(kfetch, false);
10633 } else if (keydata.removehd == 0) {
10634 dnssec_log(zone, ISC_LOG_INFO,
10635 "Active key %d for zone %s "
10636 "unexpectedly missing from DNSKEY "
10637 "RRset",
10638 keytag, namebuf);
10639 keydata.refresh = now + dns_zone_mkey_hour;
10640 } else if (keydata.removehd <= now) {
10641 deletekey = true;
10642 dnssec_log(
10643 zone, ISC_LOG_INFO,
10644 "Revoked key %d for zone %s no longer "
10645 "present in DNSKEY RRset: deleting "
10646 "from managed keys database",
10647 keytag, namebuf);
10648 } else {
10649 keydata.refresh = refresh_time(kfetch, false);
10650 }
10651
10652 if (secure || deletekey) {
10653 /* Delete old version */
10654 CHECK(update_one_rr(kfetch->db, ver, &diff,
10655 DNS_DIFFOP_DEL, keyname, 0,
10656 &keydatarr));
10657 }
10658
10659 if (!secure || deletekey) {
10660 continue;
10661 }
10662
10663 dns_rdata_reset(&keydatarr);
10664 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10665 dns_rdata_fromstruct(&keydatarr, zone->rdclass,
10666 dns_rdatatype_keydata, &keydata,
10667 &keyb);
10668
10669 /* Insert updated version */
10670 CHECK(update_one_rr(kfetch->db, ver, &diff,
10671 DNS_DIFFOP_ADD, keyname, 0,
10672 &keydatarr));
10673
10674 set_refreshkeytimer(zone, &keydata, now, false);
10675 }
10676 }
10677
10678 /*
10679 * Next scan dnskeyset:
10680 * - If new keys are found (i.e., lacking a match in keydataset)
10681 * add them to the key zone and set the acceptance timer
10682 * to 30 days in the future (or to immediately if we've
10683 * determined that we're initializing the zone for the
10684 * first time)
10685 * - Previously-known keys that have been revoked
10686 * must be scheduled for removal from the key zone (or,
10687 * if they hadn't been accepted as trust anchors yet
10688 * anyway, removed at once)
10689 * - Previously-known unrevoked keys whose acceptance timers
10690 * have completed are promoted to trust anchors
10691 * - All keys not being removed have their refresh
10692 * timers updated
10693 */
10694 for (result = dns_rdataset_first(dnskeys); result == ISC_R_SUCCESS;
10695 result = dns_rdataset_next(dnskeys))
10696 {
10697 bool revoked = false;
10698 bool newkey = false;
10699 bool updatekey = false;
10700 bool deletekey = false;
10701 bool trustkey = false;
10702 dns_keytag_t keytag;
10703
10704 dns_rdata_reset(&dnskeyrr);
10705 dns_rdataset_current(dnskeys, &dnskeyrr);
10706 result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
10707 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10708
10709 /* Skip ZSK's */
10710 if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0) {
10711 continue;
10712 }
10713
10714 result = compute_tag(keyname, &dnskey, mctx, &keytag);
10715 if (result != ISC_R_SUCCESS) {
10716 /*
10717 * Skip if we cannot compute the key tag.
10718 * This may happen if the algorithm is unsupported
10719 */
10720 dns_zone_log(zone, ISC_LOG_ERROR,
10721 "Cannot compute tag for key in zone %s: "
10722 "%s "
10723 "(skipping)",
10724 namebuf, isc_result_totext(result));
10725 continue;
10726 }
10727 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10728
10729 revoked = ((dnskey.flags & DNS_KEYFLAG_REVOKE) != 0);
10730
10731 if (matchkey(keydataset, &dnskeyrr)) {
10732 dns_rdata_reset(&keydatarr);
10733 dns_rdataset_current(keydataset, &keydatarr);
10734 result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
10735 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10736
10737 if (revoked && revocable(kfetch, &keydata)) {
10738 if (keydata.addhd > now) {
10739 /*
10740 * Key wasn't trusted yet, and now
10741 * it's been revoked? Just remove it
10742 */
10743 deletekey = true;
10744 dnssec_log(zone, ISC_LOG_INFO,
10745 "Pending key %d for "
10746 "zone %s is now revoked: "
10747 "deleting from the "
10748 "managed keys database",
10749 keytag, namebuf);
10750 } else if (keydata.removehd == 0) {
10751 /*
10752 * Remove key from secroots.
10753 */
10754 dns_view_untrust(zone->view, keyname,
10755 &dnskey);
10756
10757 /* If initializing, delete now */
10758 if (keydata.addhd == 0) {
10759 deletekey = true;
10760 } else {
10761 keydata.removehd =
10762 now +
10763 dns_zone_mkey_month;
10764 keydata.flags |=
10765 DNS_KEYFLAG_REVOKE;
10766 }
10767
10768 dnssec_log(zone, ISC_LOG_INFO,
10769 "Trusted key %d for "
10770 "zone %s is now revoked",
10771 keytag, namebuf);
10772 } else if (keydata.removehd < now) {
10773 /* Scheduled for removal */
10774 deletekey = true;
10775
10776 dnssec_log(zone, ISC_LOG_INFO,
10777 "Revoked key %d for "
10778 "zone %s removal timer "
10779 "complete: deleting from "
10780 "the managed keys database",
10781 keytag, namebuf);
10782 }
10783 } else if (revoked && keydata.removehd == 0) {
10784 dnssec_log(zone, ISC_LOG_WARNING,
10785 "Active key %d for zone "
10786 "%s is revoked but "
10787 "did not self-sign; "
10788 "ignoring",
10789 keytag, namebuf);
10790 continue;
10791 } else if (secure) {
10792 if (keydata.removehd != 0) {
10793 /*
10794 * Key isn't revoked--but it
10795 * seems it used to be.
10796 * Remove it now and add it
10797 * back as if it were a fresh key,
10798 * with a 30-day acceptance timer.
10799 */
10800 deletekey = true;
10801 newkey = true;
10802 keydata.removehd = 0;
10803 keydata.addhd = now +
10804 dns_zone_mkey_month;
10805
10806 dnssec_log(zone, ISC_LOG_INFO,
10807 "Revoked key %d for "
10808 "zone %s has returned: "
10809 "starting 30-day "
10810 "acceptance timer",
10811 keytag, namebuf);
10812 } else if (keydata.addhd > now) {
10813 pending++;
10814 } else if (keydata.addhd == 0) {
10815 keydata.addhd = now;
10816 }
10817
10818 if (keydata.addhd <= now) {
10819 trustkey = true;
10820 dnssec_log(zone, ISC_LOG_INFO,
10821 "Key %d for zone %s "
10822 "is now trusted (%s)",
10823 keytag, namebuf,
10824 initial ? "initializing key "
10825 "verified"
10826 : "acceptance timer "
10827 "complete");
10828 }
10829 } else if (keydata.addhd > now) {
10830 /*
10831 * Not secure, and key is pending:
10832 * reset the acceptance timer
10833 */
10834 pending++;
10835 keydata.addhd = now + dns_zone_mkey_month;
10836 dnssec_log(zone, ISC_LOG_INFO,
10837 "Pending key %d "
10838 "for zone %s was "
10839 "not validated: restarting "
10840 "30-day acceptance timer",
10841 keytag, namebuf);
10842 }
10843
10844 if (!deletekey && !newkey) {
10845 updatekey = true;
10846 }
10847 } else if (secure) {
10848 /*
10849 * Key wasn't in the key zone but it's
10850 * revoked now anyway, so just skip it
10851 */
10852 if (revoked) {
10853 continue;
10854 }
10855
10856 /* Key wasn't in the key zone: add it */
10857 newkey = true;
10858
10859 if (initializing) {
10860 dnssec_log(zone, ISC_LOG_WARNING,
10861 "Initializing automatic trust "
10862 "anchor management for zone '%s'; "
10863 "DNSKEY ID %d is now trusted, "
10864 "waiving the normal 30-day "
10865 "waiting period.",
10866 namebuf, keytag);
10867 trustkey = true;
10868 } else {
10869 dnssec_log(zone, ISC_LOG_INFO,
10870 "New key %d observed "
10871 "for zone '%s': "
10872 "starting 30-day "
10873 "acceptance timer",
10874 keytag, namebuf);
10875 }
10876 } else {
10877 /*
10878 * No previously known key, and the key is not
10879 * secure, so skip it.
10880 */
10881 continue;
10882 }
10883
10884 /* Delete old version */
10885 if (deletekey || !newkey) {
10886 CHECK(update_one_rr(kfetch->db, ver, &diff,
10887 DNS_DIFFOP_DEL, keyname, 0,
10888 &keydatarr));
10889 }
10890
10891 if (updatekey) {
10892 /* Set refresh timer */
10893 keydata.refresh = refresh_time(kfetch, false);
10894 dns_rdata_reset(&keydatarr);
10895 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10896 dns_rdata_fromstruct(&keydatarr, zone->rdclass,
10897 dns_rdatatype_keydata, &keydata,
10898 &keyb);
10899
10900 /* Insert updated version */
10901 CHECK(update_one_rr(kfetch->db, ver, &diff,
10902 DNS_DIFFOP_ADD, keyname, 0,
10903 &keydatarr));
10904 } else if (newkey) {
10905 /* Convert DNSKEY to KEYDATA */
10906 result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
10907 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10908 dns_keydata_fromdnskey(&keydata, &dnskey, 0, 0, 0,
10909 NULL);
10910 keydata.addhd = initializing
10911 ? now
10912 : now + dns_zone_mkey_month;
10913 keydata.refresh = refresh_time(kfetch, false);
10914 dns_rdata_reset(&keydatarr);
10915 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10916 dns_rdata_fromstruct(&keydatarr, zone->rdclass,
10917 dns_rdatatype_keydata, &keydata,
10918 &keyb);
10919
10920 /* Insert into key zone */
10921 CHECK(update_one_rr(kfetch->db, ver, &diff,
10922 DNS_DIFFOP_ADD, keyname, 0,
10923 &keydatarr));
10924 }
10925
10926 if (trustkey) {
10927 /* Trust this key. */
10928 result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
10929 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10930 trust_key(zone, keyname, &dnskey, false);
10931 }
10932
10933 if (secure && !deletekey) {
10934 INSIST(newkey || updatekey);
10935 set_refreshkeytimer(zone, &keydata, now, false);
10936 }
10937 }
10938
10939 /*
10940 * RFC5011 says, "A trust point that has all of its trust anchors
10941 * revoked is considered deleted and is treated as if the trust
10942 * point was never configured." But if someone revoked their
10943 * active key before the standby was trusted, that would mean the
10944 * zone would suddenly be nonsecured. We avoid this by checking to
10945 * see if there's pending keydata. If so, we put a null key in
10946 * the security roots; then all queries to the zone will fail.
10947 */
10948 if (pending != 0) {
10949 fail_secure(zone, keyname);
10950 }
10951
10952 done:
10953 if (!ISC_LIST_EMPTY(diff.tuples)) {
10954 /* Write changes to journal file. */
10955 CHECK(update_soa_serial(zone, kfetch->db, ver, &diff, mctx,
10956 zone->updatemethod));
10957 CHECK(zone_journal(zone, &diff, NULL, "keyfetch_done"));
10958 commit = true;
10959
10960 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
10961 zone_needdump(zone, 30);
10962 } else if (result == ISC_R_NOMORE) {
10963 /*
10964 * If "updatekey" was true for all keys found in the DNSKEY
10965 * response and the previous update of those keys happened
10966 * during the same second (only possible if a key refresh was
10967 * externally triggered), it may happen that all relevant
10968 * update_one_rr() calls will return ISC_R_SUCCESS, but
10969 * diff.tuples will remain empty. Reset result to
10970 * ISC_R_SUCCESS to prevent a bogus warning from being logged.
10971 */
10972 result = ISC_R_SUCCESS;
10973 }
10974
10975 cleanup:
10976 if (result != ISC_R_SUCCESS) {
10977 dnssec_log(zone, ISC_LOG_ERROR,
10978 "error during managed-keys processing (%s): "
10979 "DNSSEC validation may be at risk",
10980 isc_result_totext(result));
10981 }
10982 dns_diff_clear(&diff);
10983 if (ver != NULL) {
10984 dns_db_closeversion(kfetch->db, &ver, commit);
10985 }
10986
10987 out:
10988 dns_db_detach(&kfetch->db);
10989
10990 isc_refcount_decrement(&zone->irefs);
10991
10992 if (dns_rdataset_isassociated(keydataset)) {
10993 dns_rdataset_disassociate(keydataset);
10994 }
10995 if (dns_rdataset_isassociated(dnskeys)) {
10996 dns_rdataset_disassociate(dnskeys);
10997 }
10998 if (dns_rdataset_isassociated(dnskeysigs)) {
10999 dns_rdataset_disassociate(dnskeysigs);
11000 }
11001
11002 dns_resolver_freefresp(&resp);
11003 dns_name_free(keyname, mctx);
11004 isc_mem_putanddetach(&kfetch->mctx, kfetch, sizeof(dns_keyfetch_t));
11005
11006 if (secroots != NULL) {
11007 dns_keytable_detach(&secroots);
11008 }
11009
11010 free_needed = exit_check(zone);
11011 UNLOCK_ZONE(zone);
11012
11013 if (free_needed) {
11014 zone_free(zone);
11015 }
11016
11017 INSIST(ver == NULL);
11018 }
11019
11020 static void
11021 retry_keyfetch(dns_keyfetch_t *kfetch, dns_name_t *kname) {
11022 isc_time_t timenow, timethen;
11023 dns_zone_t *zone = kfetch->zone;
11024 bool free_needed;
11025 char namebuf[DNS_NAME_FORMATSIZE];
11026
11027 dns_name_format(kname, namebuf, sizeof(namebuf));
11028 dnssec_log(zone, ISC_LOG_WARNING,
11029 "Failed to create fetch for %s DNSKEY update", namebuf);
11030
11031 /*
11032 * Error during a key fetch; cancel and retry in an hour.
11033 */
11034 LOCK_ZONE(zone);
11035 zone->refreshkeycount--;
11036 isc_refcount_decrement(&zone->irefs);
11037 dns_db_detach(&kfetch->db);
11038 dns_rdataset_disassociate(&kfetch->keydataset);
11039 dns_name_free(kname, zone->mctx);
11040 isc_mem_putanddetach(&kfetch->mctx, kfetch, sizeof(*kfetch));
11041
11042 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
11043 /* Don't really retry if we are exiting */
11044 char timebuf[80];
11045
11046 timenow = isc_time_now();
11047 DNS_ZONE_TIME_ADD(&timenow, dns_zone_mkey_hour, &timethen);
11048 zone->refreshkeytime = timethen;
11049 zone_settimer(zone, &timenow);
11050
11051 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
11052 dnssec_log(zone, ISC_LOG_DEBUG(1), "retry key refresh: %s",
11053 timebuf);
11054 }
11055
11056 free_needed = exit_check(zone);
11057 UNLOCK_ZONE(zone);
11058
11059 if (free_needed) {
11060 zone_free(zone);
11061 }
11062 }
11063
11064 static void
11065 do_keyfetch(void *arg) {
11066 isc_result_t result;
11067 dns_keyfetch_t *kfetch = (dns_keyfetch_t *)arg;
11068 dns_name_t *kname = dns_fixedname_name(&kfetch->name);
11069 dns_resolver_t *resolver = NULL;
11070 dns_zone_t *zone = kfetch->zone;
11071 unsigned int options = DNS_FETCHOPT_NOVALIDATE | DNS_FETCHOPT_UNSHARED |
11072 DNS_FETCHOPT_NOCACHED;
11073
11074 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
11075 goto retry;
11076 }
11077
11078 result = dns_view_getresolver(zone->view, &resolver);
11079 if (result != ISC_R_SUCCESS) {
11080 goto retry;
11081 }
11082
11083 /*
11084 * Use of DNS_FETCHOPT_NOCACHED is essential here. If it is not
11085 * set and the cache still holds a non-expired, validated version
11086 * of the RRset being queried for by the time the response is
11087 * received, the cached RRset will be passed to keyfetch_done()
11088 * instead of the one received in the response as the latter will
11089 * have a lower trust level due to not being validated until
11090 * keyfetch_done() is called.
11091 */
11092 result = dns_resolver_createfetch(
11093 resolver, kname, dns_rdatatype_dnskey, NULL, NULL, NULL, NULL,
11094 0, options, 0, NULL, NULL, NULL, zone->loop, keyfetch_done,
11095 kfetch, NULL, &kfetch->dnskeyset, &kfetch->dnskeysigset,
11096 &kfetch->fetch);
11097
11098 dns_resolver_detach(&resolver);
11099 if (result == ISC_R_SUCCESS) {
11100 return;
11101 }
11102 retry:
11103 retry_keyfetch(kfetch, kname);
11104 }
11105
11106 /*
11107 * Refresh the data in the key zone. Initiate a fetch to look up
11108 * DNSKEY records at the trust anchor name.
11109 */
11110 static void
11111 zone_refreshkeys(dns_zone_t *zone) {
11112 isc_result_t result;
11113 dns_rriterator_t rrit;
11114 dns_db_t *db = NULL;
11115 dns_dbversion_t *ver = NULL;
11116 dns_diff_t diff;
11117 dns_rdata_t rdata = DNS_RDATA_INIT;
11118 dns_rdata_keydata_t kd;
11119 isc_stdtime_t now = isc_stdtime_now();
11120 bool commit = false;
11121 bool fetching = false;
11122 bool timerset = false;
11123
11124 ENTER;
11125 REQUIRE(zone->db != NULL);
11126
11127 LOCK_ZONE(zone);
11128 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
11129 isc_time_settoepoch(&zone->refreshkeytime);
11130 UNLOCK_ZONE(zone);
11131 return;
11132 }
11133
11134 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11135 dns_db_attach(zone->db, &db);
11136 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11137
11138 dns_diff_init(zone->mctx, &diff);
11139
11140 CHECK(dns_db_newversion(db, &ver));
11141
11142 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESHING);
11143
11144 dns_rriterator_init(&rrit, db, ver, 0);
11145 for (result = dns_rriterator_first(&rrit); result == ISC_R_SUCCESS;
11146 result = dns_rriterator_nextrrset(&rrit))
11147 {
11148 isc_stdtime_t timer = 0xffffffff;
11149 dns_name_t *name = NULL, *kname = NULL;
11150 dns_rdataset_t *kdset = NULL;
11151 uint32_t ttl;
11152
11153 dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL);
11154 if (kdset == NULL || kdset->type != dns_rdatatype_keydata ||
11155 !dns_rdataset_isassociated(kdset))
11156 {
11157 continue;
11158 }
11159
11160 /*
11161 * Scan the stored keys looking for ones that need
11162 * removal or refreshing
11163 */
11164 for (result = dns_rdataset_first(kdset);
11165 result == ISC_R_SUCCESS; result = dns_rdataset_next(kdset))
11166 {
11167 dns_rdata_reset(&rdata);
11168 dns_rdataset_current(kdset, &rdata);
11169 result = dns_rdata_tostruct(&rdata, &kd, NULL);
11170 RUNTIME_CHECK(result == ISC_R_SUCCESS);
11171
11172 /* Removal timer expired? */
11173 if (kd.removehd != 0 && kd.removehd < now) {
11174 dns_rriterator_pause(&rrit);
11175 CHECK(update_one_rr(db, ver, &diff,
11176 DNS_DIFFOP_DEL, name, ttl,
11177 &rdata));
11178 continue;
11179 }
11180
11181 /* Acceptance timer expired? */
11182 if (kd.addhd <= now) {
11183 timer = kd.addhd;
11184 }
11185
11186 /* Or do we just need to refresh the keyset? */
11187 if (timer > kd.refresh) {
11188 timer = kd.refresh;
11189 }
11190
11191 dns_rriterator_pause(&rrit);
11192 set_refreshkeytimer(zone, &kd, now, false);
11193 timerset = true;
11194 }
11195
11196 if (timer > now) {
11197 continue;
11198 }
11199
11200 dns_rriterator_pause(&rrit);
11201
11202 #ifdef ENABLE_AFL
11203 if (!dns_fuzzing_resolver) {
11204 #endif /* ifdef ENABLE_AFL */
11205 dns_keyfetch_t *kfetch = NULL;
11206
11207 kfetch = isc_mem_get(zone->mctx,
11208 sizeof(dns_keyfetch_t));
11209 *kfetch = (dns_keyfetch_t){ .zone = zone };
11210 isc_mem_attach(zone->mctx, &kfetch->mctx);
11211
11212 zone->refreshkeycount++;
11213 isc_refcount_increment0(&zone->irefs);
11214 kname = dns_fixedname_initname(&kfetch->name);
11215 dns_name_dup(name, zone->mctx, kname);
11216 dns_rdataset_init(&kfetch->dnskeyset);
11217 dns_rdataset_init(&kfetch->dnskeysigset);
11218 dns_rdataset_init(&kfetch->keydataset);
11219 dns_rdataset_clone(kdset, &kfetch->keydataset);
11220 dns_db_attach(db, &kfetch->db);
11221
11222 if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
11223 char namebuf[DNS_NAME_FORMATSIZE];
11224 dns_name_format(kname, namebuf,
11225 sizeof(namebuf));
11226 dnssec_log(zone, ISC_LOG_DEBUG(3),
11227 "Creating key fetch in "
11228 "zone_refreshkeys() for '%s'",
11229 namebuf);
11230 }
11231
11232 isc_async_run(zone->loop, do_keyfetch, kfetch);
11233 fetching = true;
11234 #ifdef ENABLE_AFL
11235 }
11236 #endif /* ifdef ENABLE_AFL */
11237 }
11238 if (!ISC_LIST_EMPTY(diff.tuples)) {
11239 CHECK(update_soa_serial(zone, db, ver, &diff, zone->mctx,
11240 zone->updatemethod));
11241 CHECK(zone_journal(zone, &diff, NULL, "zone_refreshkeys"));
11242 commit = true;
11243 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
11244 zone_needdump(zone, 30);
11245 }
11246
11247 cleanup:
11248 if (!timerset) {
11249 isc_time_settoepoch(&zone->refreshkeytime);
11250 }
11251
11252 if (!fetching) {
11253 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
11254 }
11255
11256 dns_diff_clear(&diff);
11257 if (ver != NULL) {
11258 dns_rriterator_destroy(&rrit);
11259 dns_db_closeversion(db, &ver, commit);
11260 }
11261 dns_db_detach(&db);
11262
11263 UNLOCK_ZONE(zone);
11264
11265 INSIST(ver == NULL);
11266 }
11267
11268 static void
11269 zone_maintenance(dns_zone_t *zone) {
11270 isc_time_t now;
11271 isc_result_t result;
11272 bool load_pending, exiting, dumping, viewok = false, notify;
11273 bool refreshkeys, sign, resign, rekey, chain, warn_expire;
11274
11275 REQUIRE(DNS_ZONE_VALID(zone));
11276 ENTER;
11277
11278 /*
11279 * Are we pending load/reload, exiting, or unconfigured
11280 * (e.g. because of a syntax failure in the config file)?
11281 * If so, don't attempt maintenance.
11282 */
11283 LOCK_ZONE(zone);
11284 load_pending = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING);
11285 exiting = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING);
11286 if (!load_pending && !exiting && zone->view != NULL) {
11287 dns_adb_t *adb = NULL;
11288 dns_view_getadb(zone->view, &adb);
11289 if (adb != NULL) {
11290 dns_adb_detach(&adb);
11291 viewok = true;
11292 }
11293 }
11294 UNLOCK_ZONE(zone);
11295
11296 if (load_pending || exiting || !viewok) {
11297 return;
11298 }
11299
11300 now = isc_time_now();
11301
11302 /*
11303 * Expire check.
11304 */
11305 switch (zone->type) {
11306 case dns_zone_redirect:
11307 if (dns_remote_addresses(&zone->primaries) == NULL) {
11308 break;
11309 }
11310 FALLTHROUGH;
11311 case dns_zone_secondary:
11312 case dns_zone_mirror:
11313 case dns_zone_stub:
11314 LOCK_ZONE(zone);
11315 if (isc_time_compare(&now, &zone->expiretime) >= 0 &&
11316 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
11317 {
11318 zone_expire(zone);
11319 zone->refreshtime = now;
11320 }
11321 UNLOCK_ZONE(zone);
11322 break;
11323 default:
11324 break;
11325 }
11326
11327 /*
11328 * Up to date check.
11329 */
11330 switch (zone->type) {
11331 case dns_zone_redirect:
11332 if (dns_remote_addresses(&zone->primaries) == NULL) {
11333 break;
11334 }
11335 FALLTHROUGH;
11336 case dns_zone_secondary:
11337 case dns_zone_mirror:
11338 case dns_zone_stub:
11339 LOCK_ZONE(zone);
11340 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
11341 isc_time_compare(&now, &zone->refreshtime) >= 0)
11342 {
11343 zone_refresh(zone);
11344 }
11345 UNLOCK_ZONE(zone);
11346 break;
11347 default:
11348 break;
11349 }
11350
11351 /*
11352 * Secondaries send notifies before backing up to disk,
11353 * primaries after.
11354 */
11355 LOCK_ZONE(zone);
11356 if (zone->notifydefer != 0 &&
11357 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOTIFYNODEFER) &&
11358 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOTIFYDEFERRED))
11359 {
11360 if (isc_time_compare(&now, &zone->notifytime) > 0) {
11361 zone->notifytime = now;
11362 }
11363 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOTIFYDEFERRED);
11364 DNS_ZONE_TIME_ADD(&zone->notifytime, zone->notifydefer,
11365 &zone->notifytime);
11366 }
11367 notify = (zone->type == dns_zone_secondary ||
11368 zone->type == dns_zone_mirror) &&
11369 (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
11370 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY)) &&
11371 isc_time_compare(&now, &zone->notifytime) >= 0;
11372 UNLOCK_ZONE(zone);
11373
11374 if (notify) {
11375 zone_notify(zone, &now);
11376 }
11377
11378 /*
11379 * Do we need to consolidate the backing store?
11380 */
11381 switch (zone->type) {
11382 case dns_zone_primary:
11383 case dns_zone_secondary:
11384 case dns_zone_mirror:
11385 case dns_zone_key:
11386 case dns_zone_redirect:
11387 case dns_zone_stub:
11388 LOCK_ZONE(zone);
11389 if (zone->masterfile != NULL &&
11390 isc_time_compare(&now, &zone->dumptime) >= 0 &&
11391 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
11392 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP))
11393 {
11394 dumping = was_dumping(zone);
11395 } else {
11396 dumping = true;
11397 }
11398 UNLOCK_ZONE(zone);
11399 if (!dumping) {
11400 result = zone_dump(zone, true); /* loop locked */
11401 if (result != ISC_R_SUCCESS) {
11402 dns_zone_log(zone, ISC_LOG_WARNING,
11403 "dump failed: %s",
11404 isc_result_totext(result));
11405 }
11406 }
11407 break;
11408 default:
11409 break;
11410 }
11411
11412 /*
11413 * Primary/redirect zones send notifies now, if needed
11414 */
11415 switch (zone->type) {
11416 case dns_zone_primary:
11417 case dns_zone_redirect:
11418 LOCK_ZONE(zone);
11419 notify = (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
11420 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY)) &&
11421 isc_time_compare(&now, &zone->notifytime) >= 0;
11422 UNLOCK_ZONE(zone);
11423 if (notify) {
11424 zone_notify(zone, &now);
11425 }
11426 default:
11427 break;
11428 }
11429
11430 /*
11431 * Do we need to refresh keys?
11432 */
11433 switch (zone->type) {
11434 case dns_zone_key:
11435 LOCK_ZONE(zone);
11436 refreshkeys = isc_time_compare(&now, &zone->refreshkeytime) >=
11437 0 &&
11438 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
11439 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING);
11440 UNLOCK_ZONE(zone);
11441 if (refreshkeys) {
11442 zone_refreshkeys(zone);
11443 }
11444 break;
11445 case dns_zone_primary:
11446 LOCK_ZONE(zone);
11447 if (zone->rss != NULL) {
11448 isc_time_settoepoch(&zone->refreshkeytime);
11449 UNLOCK_ZONE(zone);
11450 break;
11451 }
11452 rekey = (!isc_time_isepoch(&zone->refreshkeytime) &&
11453 isc_time_compare(&now, &zone->refreshkeytime) >= 0);
11454 UNLOCK_ZONE(zone);
11455 if (rekey) {
11456 zone_rekey(zone);
11457 }
11458 default:
11459 break;
11460 }
11461
11462 switch (zone->type) {
11463 case dns_zone_primary:
11464 case dns_zone_redirect:
11465 case dns_zone_secondary:
11466 /*
11467 * Do we need to sign/resign some RRsets?
11468 */
11469 LOCK_ZONE(zone);
11470 if (zone->rss != NULL) {
11471 isc_time_settoepoch(&zone->signingtime);
11472 isc_time_settoepoch(&zone->resigntime);
11473 isc_time_settoepoch(&zone->nsec3chaintime);
11474 isc_time_settoepoch(&zone->keywarntime);
11475 UNLOCK_ZONE(zone);
11476 break;
11477 }
11478 sign = !isc_time_isepoch(&zone->signingtime) &&
11479 isc_time_compare(&now, &zone->signingtime) >= 0;
11480 resign = !isc_time_isepoch(&zone->resigntime) &&
11481 isc_time_compare(&now, &zone->resigntime) >= 0;
11482 chain = !isc_time_isepoch(&zone->nsec3chaintime) &&
11483 isc_time_compare(&now, &zone->nsec3chaintime) >= 0;
11484 warn_expire = !isc_time_isepoch(&zone->keywarntime) &&
11485 isc_time_compare(&now, &zone->keywarntime) >= 0;
11486 UNLOCK_ZONE(zone);
11487
11488 if (sign) {
11489 zone_sign(zone);
11490 } else if (resign) {
11491 zone_resigninc(zone);
11492 } else if (chain) {
11493 zone_nsec3chain(zone);
11494 }
11495
11496 /*
11497 * Do we need to issue a key expiry warning?
11498 */
11499 if (warn_expire) {
11500 set_key_expiry_warning(zone, zone->key_expiry,
11501 isc_time_seconds(&now));
11502 }
11503 break;
11504
11505 default:
11506 break;
11507 }
11508 LOCK_ZONE(zone);
11509 zone_settimer(zone, &now);
11510 UNLOCK_ZONE(zone);
11511 }
11512
11513 void
11514 dns_zone_markdirty(dns_zone_t *zone) {
11515 uint32_t serial;
11516 isc_result_t result = ISC_R_SUCCESS;
11517 dns_zone_t *secure = NULL;
11518
11519 /*
11520 * Obtaining a lock on the zone->secure (see zone_send_secureserial)
11521 * could result in a deadlock due to a LOR so we will spin if we
11522 * can't obtain the both locks.
11523 */
11524 again:
11525 LOCK_ZONE(zone);
11526 if (zone->type == dns_zone_primary) {
11527 if (inline_raw(zone)) {
11528 unsigned int soacount;
11529 secure = zone->secure;
11530 INSIST(secure != zone);
11531 TRYLOCK_ZONE(result, secure);
11532 if (result != ISC_R_SUCCESS) {
11533 UNLOCK_ZONE(zone);
11534 secure = NULL;
11535 isc_thread_yield();
11536 goto again;
11537 }
11538
11539 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11540 if (zone->db != NULL) {
11541 result = zone_get_from_db(
11542 zone, zone->db, NULL, &soacount, NULL,
11543 &serial, NULL, NULL, NULL, NULL, NULL);
11544 } else {
11545 result = DNS_R_NOTLOADED;
11546 }
11547 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11548 if (result == ISC_R_SUCCESS && soacount > 0U) {
11549 zone_send_secureserial(zone, serial);
11550 }
11551 }
11552
11553 /* XXXMPA make separate call back */
11554 if (result == ISC_R_SUCCESS) {
11555 set_resigntime(zone);
11556 if (zone->loop != NULL) {
11557 isc_time_t now;
11558 now = isc_time_now();
11559 zone_settimer(zone, &now);
11560 }
11561 }
11562 }
11563 if (secure != NULL) {
11564 UNLOCK_ZONE(secure);
11565 }
11566 zone_needdump(zone, DNS_DUMP_DELAY);
11567 UNLOCK_ZONE(zone);
11568 }
11569
11570 void
11571 dns_zone_expire(dns_zone_t *zone) {
11572 REQUIRE(DNS_ZONE_VALID(zone));
11573
11574 LOCK_ZONE(zone);
11575 zone_expire(zone);
11576 UNLOCK_ZONE(zone);
11577 }
11578
11579 static void
11580 zone_expire(dns_zone_t *zone) {
11581 dns_db_t *db = NULL;
11582
11583 /*
11584 * 'zone' locked by caller.
11585 */
11586
11587 REQUIRE(LOCKED_ZONE(zone));
11588
11589 dns_zone_log(zone, ISC_LOG_WARNING, "expired");
11590
11591 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXPIRED);
11592 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
11593 zone->retry = DNS_ZONE_DEFAULTRETRY;
11594 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
11595
11596 /*
11597 * An RPZ zone has expired; before unloading it, we must
11598 * first remove it from the RPZ summary database. The
11599 * easiest way to do this is "update" it with an empty
11600 * database so that the update callback synchronizes
11601 * the diff automatically.
11602 */
11603 if (zone->rpzs != NULL && zone->rpz_num != DNS_RPZ_INVALID_NUM) {
11604 isc_result_t result;
11605 dns_rpz_zone_t *rpz = zone->rpzs->zones[zone->rpz_num];
11606
11607 CHECK(dns_db_create(zone->mctx, ZONEDB_DEFAULT, &zone->origin,
11608 dns_dbtype_zone, zone->rdclass, 0, NULL,
11609 &db));
11610 CHECK(dns_rpz_dbupdate_callback(db, rpz));
11611 dns_zone_log(zone, ISC_LOG_WARNING,
11612 "response-policy zone expired; "
11613 "policies unloaded");
11614 }
11615
11616 cleanup:
11617 if (db != NULL) {
11618 dns_db_detach(&db);
11619 }
11620
11621 zone_unload(zone);
11622 }
11623
11624 static void
11625 zone_refresh(dns_zone_t *zone) {
11626 isc_interval_t i;
11627 uint32_t oldflags;
11628 isc_result_t result;
11629
11630 REQUIRE(DNS_ZONE_VALID(zone));
11631 REQUIRE(LOCKED_ZONE(zone));
11632
11633 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
11634 return;
11635 }
11636
11637 /*
11638 * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation
11639 * in progress at a time.
11640 */
11641
11642 oldflags = ISC_ZONE_GET(zone, flags);
11643 if (dns_remote_addresses(&zone->primaries) == NULL) {
11644 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOPRIMARIES);
11645 if ((oldflags & DNS_ZONEFLG_NOPRIMARIES) == 0) {
11646 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
11647 ISC_LOG_ERROR,
11648 "cannot refresh: no primaries");
11649 }
11650 return;
11651 }
11652 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
11653 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
11654 if ((oldflags & (DNS_ZONEFLG_REFRESH | DNS_ZONEFLG_LOADING)) != 0) {
11655 return;
11656 }
11657
11658 /*
11659 * Set the next refresh time as if refresh check has failed.
11660 * Setting this to the retry time will do that. XXXMLG
11661 * If we are successful it will be reset using zone->refresh.
11662 */
11663 isc_interval_set(&i, zone->retry - isc_random_uniform(zone->retry / 4),
11664 0);
11665 result = isc_time_nowplusinterval(&zone->refreshtime, &i);
11666 if (result != ISC_R_SUCCESS) {
11667 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_WARNING,
11668 "isc_time_nowplusinterval() failed: %s",
11669 isc_result_totext(result));
11670 }
11671
11672 /*
11673 * When lacking user-specified timer values from the SOA,
11674 * do exponential backoff of the retry time up to a
11675 * maximum of six hours.
11676 */
11677 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS)) {
11678 zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
11679 }
11680
11681 dns_remote_reset(&zone->primaries, true);
11682
11683 /* initiate soa query */
11684 queue_soa_query(zone);
11685 }
11686
11687 static void
11688 zone_refresh_async(void *arg) {
11689 dns_zone_t *zone = arg;
11690
11691 LOCK_ZONE(zone);
11692 zone_refresh(zone);
11693 UNLOCK_ZONE(zone);
11694
11695 dns_zone_detach(&zone);
11696 }
11697
11698 void
11699 dns_zone_refresh(dns_zone_t *zone) {
11700 REQUIRE(DNS_ZONE_VALID(zone));
11701
11702 dns_zone_ref(zone);
11703 isc_async_run(zone->loop, zone_refresh_async, zone);
11704 }
11705
11706 static isc_result_t
11707 zone_journal_rollforward(dns_zone_t *zone, dns_db_t *db, bool *needdump,
11708 bool *fixjournal) {
11709 dns_journal_t *journal = NULL;
11710 unsigned int options;
11711 isc_result_t result;
11712
11713 if (zone->type == dns_zone_primary &&
11714 (inline_secure(zone) ||
11715 (zone->update_acl != NULL || zone->ssutable != NULL)))
11716 {
11717 options = DNS_JOURNALOPT_RESIGN;
11718 } else {
11719 options = 0;
11720 }
11721
11722 result = dns_journal_open(zone->mctx, zone->journal, DNS_JOURNAL_READ,
11723 &journal);
11724 if (result == ISC_R_NOTFOUND) {
11725 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(3),
11726 "no journal file, but that's OK ");
11727 return ISC_R_SUCCESS;
11728 } else if (result != ISC_R_SUCCESS) {
11729 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
11730 "journal open failed: %s",
11731 isc_result_totext(result));
11732 return result;
11733 }
11734
11735 if (dns_journal_empty(journal)) {
11736 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
11737 "journal empty");
11738 dns_journal_destroy(&journal);
11739 return ISC_R_SUCCESS;
11740 }
11741
11742 result = dns_journal_rollforward(journal, db, options);
11743 switch (result) {
11744 case ISC_R_SUCCESS:
11745 *needdump = true;
11746 FALLTHROUGH;
11747 case DNS_R_UPTODATE:
11748 if (dns_journal_recovered(journal)) {
11749 *fixjournal = true;
11750 dns_zone_logc(
11751 zone, DNS_LOGCATEGORY_ZONELOAD,
11752 ISC_LOG_DEBUG(1),
11753 "journal rollforward completed successfully "
11754 "using old journal format: %s",
11755 isc_result_totext(result));
11756 } else {
11757 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
11758 ISC_LOG_DEBUG(1),
11759 "journal rollforward completed "
11760 "successfully: %s",
11761 isc_result_totext(result));
11762 }
11763
11764 dns_journal_destroy(&journal);
11765 return ISC_R_SUCCESS;
11766 case ISC_R_NOTFOUND:
11767 case ISC_R_RANGE:
11768 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
11769 "journal rollforward failed: journal out of sync "
11770 "with zone");
11771 dns_journal_destroy(&journal);
11772 return result;
11773 default:
11774 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
11775 "journal rollforward failed: %s",
11776 isc_result_totext(result));
11777 dns_journal_destroy(&journal);
11778 return result;
11779 }
11780 }
11781
11782 static void
11783 zone_journal_compact(dns_zone_t *zone, dns_db_t *db, uint32_t serial) {
11784 isc_result_t result;
11785 int32_t journalsize;
11786 dns_dbversion_t *ver = NULL;
11787 uint64_t dbsize;
11788 uint32_t options = 0;
11789
11790 INSIST(LOCKED_ZONE(zone));
11791 if (inline_raw(zone)) {
11792 INSIST(LOCKED_ZONE(zone->secure));
11793 }
11794
11795 journalsize = zone->journalsize;
11796 if (journalsize == -1) {
11797 journalsize = DNS_JOURNAL_SIZE_MAX;
11798 dns_db_currentversion(db, &ver);
11799 result = dns_db_getsize(db, ver, NULL, &dbsize);
11800 dns_db_closeversion(db, &ver, false);
11801 if (result != ISC_R_SUCCESS) {
11802 dns_zone_log(zone, ISC_LOG_ERROR,
11803 "zone_journal_compact: "
11804 "could not get zone size: %s",
11805 isc_result_totext(result));
11806 } else if (dbsize < DNS_JOURNAL_SIZE_MAX / 2) {
11807 journalsize = (int32_t)dbsize * 2;
11808 }
11809 }
11810 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FIXJOURNAL)) {
11811 options |= DNS_JOURNAL_COMPACTALL;
11812 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FIXJOURNAL);
11813 zone_debuglog(zone, __func__, 1, "repair full journal");
11814 } else {
11815 zone_debuglog(zone, __func__, 1, "target journal size %d",
11816 journalsize);
11817 }
11818 result = dns_journal_compact(zone->mctx, zone->journal, serial, options,
11819 journalsize);
11820 switch (result) {
11821 case ISC_R_SUCCESS:
11822 case ISC_R_NOSPACE:
11823 case ISC_R_NOTFOUND:
11824 dns_zone_log(zone, ISC_LOG_DEBUG(3), "dns_journal_compact: %s",
11825 isc_result_totext(result));
11826 break;
11827 default:
11828 dns_zone_log(zone, ISC_LOG_ERROR,
11829 "dns_journal_compact failed: %s",
11830 isc_result_totext(result));
11831 break;
11832 }
11833 }
11834
11835 isc_result_t
11836 dns_zone_flush(dns_zone_t *zone) {
11837 isc_result_t result = ISC_R_SUCCESS;
11838 bool dumping;
11839
11840 REQUIRE(DNS_ZONE_VALID(zone));
11841
11842 LOCK_ZONE(zone);
11843 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FLUSH);
11844 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
11845 zone->masterfile != NULL)
11846 {
11847 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
11848 result = ISC_R_ALREADYRUNNING;
11849 dumping = was_dumping(zone);
11850 } else {
11851 dumping = true;
11852 }
11853 UNLOCK_ZONE(zone);
11854 if (!dumping) {
11855 result = zone_dump(zone, true);
11856 }
11857 return result;
11858 }
11859
11860 isc_result_t
11861 dns_zone_dump(dns_zone_t *zone) {
11862 isc_result_t result = ISC_R_ALREADYRUNNING;
11863 bool dumping;
11864
11865 REQUIRE(DNS_ZONE_VALID(zone));
11866
11867 LOCK_ZONE(zone);
11868 dumping = was_dumping(zone);
11869 UNLOCK_ZONE(zone);
11870 if (!dumping) {
11871 result = zone_dump(zone, false);
11872 }
11873 return result;
11874 }
11875
11876 static void
11877 zone_needdump(dns_zone_t *zone, unsigned int delay) {
11878 isc_time_t dumptime;
11879 isc_time_t now;
11880
11881 /*
11882 * 'zone' locked by caller
11883 */
11884
11885 REQUIRE(DNS_ZONE_VALID(zone));
11886 REQUIRE(LOCKED_ZONE(zone));
11887 ENTER;
11888
11889 /*
11890 * Do we have a place to dump to and are we loaded?
11891 */
11892 if (zone->masterfile == NULL ||
11893 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
11894 {
11895 return;
11896 }
11897
11898 now = isc_time_now();
11899 /* add some noise */
11900 DNS_ZONE_JITTER_ADD(&now, delay, &dumptime);
11901
11902 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
11903 if (isc_time_isepoch(&zone->dumptime) ||
11904 isc_time_compare(&zone->dumptime, &dumptime) > 0)
11905 {
11906 zone->dumptime = dumptime;
11907 }
11908 if (zone->loop != NULL) {
11909 zone_settimer(zone, &now);
11910 }
11911 }
11912
11913 static void
11914 dump_done(void *arg, isc_result_t result) {
11915 dns_zone_t *zone = arg;
11916 dns_zone_t *secure = NULL;
11917 dns_db_t *db;
11918 dns_dbversion_t *version;
11919 bool again = false;
11920 bool compact = false;
11921 uint32_t serial;
11922 isc_result_t tresult;
11923
11924 REQUIRE(DNS_ZONE_VALID(zone));
11925
11926 ENTER;
11927
11928 /*
11929 * Adjust modification time of zone file to preserve expire timing.
11930 */
11931 if ((zone->type == dns_zone_secondary ||
11932 zone->type == dns_zone_mirror ||
11933 zone->type == dns_zone_redirect) &&
11934 result == ISC_R_SUCCESS)
11935 {
11936 LOCK_ZONE(zone);
11937 isc_time_t when;
11938 isc_interval_t i;
11939 isc_interval_set(&i, zone->expire, 0);
11940 result = isc_time_subtract(&zone->expiretime, &i, &when);
11941 if (result == ISC_R_SUCCESS) {
11942 (void)isc_file_settime(zone->masterfile, &when);
11943 } else {
11944 result = ISC_R_SUCCESS;
11945 }
11946 UNLOCK_ZONE(zone);
11947 }
11948
11949 if (result == ISC_R_SUCCESS && zone->journal != NULL) {
11950 /*
11951 * We don't own these, zone->dctx must stay valid.
11952 */
11953 db = dns_dumpctx_db(zone->dumpctx);
11954 version = dns_dumpctx_version(zone->dumpctx);
11955 tresult = dns_db_getsoaserial(db, version, &serial);
11956
11957 /*
11958 * Handle lock order inversion.
11959 */
11960 again:
11961 LOCK_ZONE(zone);
11962 if (inline_raw(zone)) {
11963 secure = zone->secure;
11964 INSIST(secure != zone);
11965 TRYLOCK_ZONE(result, secure);
11966 if (result != ISC_R_SUCCESS) {
11967 UNLOCK_ZONE(zone);
11968 secure = NULL;
11969 isc_thread_yield();
11970 goto again;
11971 }
11972 }
11973
11974 /*
11975 * If there is a secure version of this zone
11976 * use its serial if it is less than ours.
11977 */
11978 if (tresult == ISC_R_SUCCESS && secure != NULL) {
11979 uint32_t sserial;
11980 isc_result_t mresult;
11981
11982 ZONEDB_LOCK(&secure->dblock, isc_rwlocktype_read);
11983 if (secure->db != NULL) {
11984 mresult = dns_db_getsoaserial(zone->secure->db,
11985 NULL, &sserial);
11986 if (mresult == ISC_R_SUCCESS &&
11987 isc_serial_lt(sserial, serial))
11988 {
11989 serial = sserial;
11990 }
11991 }
11992 ZONEDB_UNLOCK(&secure->dblock, isc_rwlocktype_read);
11993 }
11994 if (tresult == ISC_R_SUCCESS && zone->xfr == NULL) {
11995 dns_db_t *zdb = NULL;
11996 if (dns_zone_getdb(zone, &zdb) == ISC_R_SUCCESS) {
11997 zone_journal_compact(zone, zdb, serial);
11998 dns_db_detach(&zdb);
11999 }
12000 } else if (tresult == ISC_R_SUCCESS) {
12001 compact = true;
12002 zone->compact_serial = serial;
12003 }
12004 if (secure != NULL) {
12005 UNLOCK_ZONE(secure);
12006 }
12007 UNLOCK_ZONE(zone);
12008 }
12009
12010 LOCK_ZONE(zone);
12011 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
12012 if (compact) {
12013 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
12014 }
12015 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN)) {
12016 /*
12017 * If DNS_ZONEFLG_SHUTDOWN is set, all external references to
12018 * the zone are gone, which means it is in the process of being
12019 * cleaned up, so do not reschedule dumping.
12020 *
12021 * Detach from the raw version of the zone in case this
12022 * operation has been deferred in zone_shutdown().
12023 */
12024 if (zone->raw != NULL) {
12025 dns_zone_detach(&zone->raw);
12026 }
12027 if (result == ISC_R_SUCCESS) {
12028 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
12029 }
12030 } else if (result != ISC_R_SUCCESS && result != ISC_R_CANCELED) {
12031 /*
12032 * Try again in a short while.
12033 */
12034 zone_needdump(zone, DNS_DUMP_DELAY);
12035 } else if (result == ISC_R_SUCCESS &&
12036 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
12037 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
12038 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
12039 {
12040 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
12041 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
12042 isc_time_settoepoch(&zone->dumptime);
12043 again = true;
12044 } else if (result == ISC_R_SUCCESS) {
12045 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
12046 }
12047
12048 if (zone->dumpctx != NULL) {
12049 dns_dumpctx_detach(&zone->dumpctx);
12050 }
12051 UNLOCK_ZONE(zone);
12052 if (again) {
12053 (void)zone_dump(zone, false);
12054 }
12055 dns_zone_idetach(&zone);
12056 }
12057
12058 static isc_result_t
12059 zone_dump(dns_zone_t *zone, bool compact) {
12060 isc_result_t result;
12061 dns_dbversion_t *version = NULL;
12062 bool again = false;
12063 dns_db_t *db = NULL;
12064 char *masterfile = NULL;
12065 dns_masterformat_t masterformat = dns_masterformat_none;
12066 const dns_master_style_t *masterstyle = NULL;
12067 dns_masterrawheader_t rawdata;
12068
12069 /*
12070 * 'compact' MUST only be set if we are loop locked.
12071 */
12072
12073 REQUIRE(DNS_ZONE_VALID(zone));
12074 ENTER;
12075
12076 redo:
12077 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
12078 if (zone->db != NULL) {
12079 dns_db_attach(zone->db, &db);
12080 }
12081 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12082 LOCK_ZONE(zone);
12083 if (zone->masterfile != NULL) {
12084 masterfile = isc_mem_strdup(zone->mctx, zone->masterfile);
12085 masterformat = zone->masterformat;
12086 }
12087 if (zone->type == dns_zone_key) {
12088 masterstyle = &dns_master_style_keyzone;
12089 } else if (zone->masterstyle != NULL) {
12090 masterstyle = zone->masterstyle;
12091 } else {
12092 masterstyle = &dns_master_style_default;
12093 }
12094 UNLOCK_ZONE(zone);
12095 if (db == NULL) {
12096 result = DNS_R_NOTLOADED;
12097 goto fail;
12098 }
12099 if (masterfile == NULL) {
12100 result = DNS_R_NOMASTERFILE;
12101 goto fail;
12102 }
12103
12104 dns_db_currentversion(db, &version);
12105
12106 dns_master_initrawheader(&rawdata);
12107
12108 if (inline_secure(zone)) {
12109 get_raw_serial(zone->raw, &rawdata);
12110 }
12111
12112 if (compact && zone->type != dns_zone_stub) {
12113 LOCK_ZONE(zone);
12114 zone_iattach(zone, &(dns_zone_t *){ NULL });
12115
12116 INSIST(zone != zone->raw);
12117
12118 result = dns_master_dumpasync(
12119 zone->mctx, db, version, masterstyle, masterfile,
12120 zone->loop, dump_done, zone, &zone->dumpctx,
12121 masterformat, &rawdata);
12122
12123 UNLOCK_ZONE(zone);
12124 if (result != ISC_R_SUCCESS) {
12125 dns_zone_idetach(&(dns_zone_t *){ zone });
12126 goto fail;
12127 }
12128 result = DNS_R_CONTINUE;
12129 } else {
12130 result = dns_master_dump(zone->mctx, db, version, masterstyle,
12131 masterfile, masterformat, &rawdata);
12132 if ((zone->type == dns_zone_secondary ||
12133 zone->type == dns_zone_mirror ||
12134 zone->type == dns_zone_redirect) &&
12135 result == ISC_R_SUCCESS)
12136 {
12137 isc_time_t when;
12138 isc_interval_t i;
12139 isc_interval_set(&i, zone->expire, 0);
12140 result = isc_time_subtract(&zone->expiretime, &i,
12141 &when);
12142 if (result == ISC_R_SUCCESS) {
12143 (void)isc_file_settime(zone->masterfile, &when);
12144 } else {
12145 result = ISC_R_SUCCESS;
12146 }
12147 }
12148 }
12149 fail:
12150 if (version != NULL) {
12151 dns_db_closeversion(db, &version, false);
12152 }
12153 if (db != NULL) {
12154 dns_db_detach(&db);
12155 }
12156 if (masterfile != NULL) {
12157 isc_mem_free(zone->mctx, masterfile);
12158 masterfile = NULL;
12159 }
12160
12161 if (result == DNS_R_CONTINUE) {
12162 /*
12163 * Asyncronous write is in progress. Zone flags will get
12164 * updated on completion. Cleanup is complete. We are done.
12165 */
12166 return ISC_R_SUCCESS;
12167 }
12168
12169 again = false;
12170 LOCK_ZONE(zone);
12171 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
12172 if (result != ISC_R_SUCCESS) {
12173 /*
12174 * Try again in a short while.
12175 */
12176 zone_needdump(zone, DNS_DUMP_DELAY);
12177 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
12178 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
12179 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
12180 {
12181 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
12182 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
12183 isc_time_settoepoch(&zone->dumptime);
12184 again = true;
12185 } else {
12186 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
12187 }
12188 UNLOCK_ZONE(zone);
12189 if (again) {
12190 goto redo;
12191 }
12192
12193 return result;
12194 }
12195
12196 static isc_result_t
12197 dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style,
12198 dns_masterformat_t format, const uint32_t rawversion) {
12199 isc_result_t result;
12200 dns_dbversion_t *version = NULL;
12201 dns_db_t *db = NULL;
12202 dns_masterrawheader_t rawdata;
12203
12204 REQUIRE(DNS_ZONE_VALID(zone));
12205
12206 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
12207 if (zone->db != NULL) {
12208 dns_db_attach(zone->db, &db);
12209 }
12210 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12211 if (db == NULL) {
12212 return DNS_R_NOTLOADED;
12213 }
12214
12215 dns_db_currentversion(db, &version);
12216 dns_master_initrawheader(&rawdata);
12217 if (rawversion == 0) {
12218 rawdata.flags |= DNS_MASTERRAW_COMPAT;
12219 } else if (inline_secure(zone)) {
12220 get_raw_serial(zone->raw, &rawdata);
12221 } else if (zone->sourceserialset) {
12222 rawdata.flags = DNS_MASTERRAW_SOURCESERIALSET;
12223 rawdata.sourceserial = zone->sourceserial;
12224 }
12225 result = dns_master_dumptostream(zone->mctx, db, version, style, format,
12226 &rawdata, fd);
12227 dns_db_closeversion(db, &version, false);
12228 dns_db_detach(&db);
12229 return result;
12230 }
12231
12232 isc_result_t
12233 dns_zone_dumptostream(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
12234 const dns_master_style_t *style,
12235 const uint32_t rawversion) {
12236 return dumptostream(zone, fd, style, format, rawversion);
12237 }
12238
12239 void
12240 dns_zone_unload(dns_zone_t *zone) {
12241 REQUIRE(DNS_ZONE_VALID(zone));
12242
12243 LOCK_ZONE(zone);
12244 zone_unload(zone);
12245 UNLOCK_ZONE(zone);
12246 }
12247
12248 static void
12249 notify_cancel(dns_zone_t *zone) {
12250 dns_notify_t *notify;
12251
12252 /*
12253 * 'zone' locked by caller.
12254 */
12255
12256 REQUIRE(LOCKED_ZONE(zone));
12257
12258 for (notify = ISC_LIST_HEAD(zone->notifies); notify != NULL;
12259 notify = ISC_LIST_NEXT(notify, link))
12260 {
12261 if (notify->find != NULL) {
12262 dns_adb_cancelfind(notify->find);
12263 }
12264 if (notify->request != NULL) {
12265 dns_request_cancel(notify->request);
12266 }
12267 }
12268 }
12269
12270 static void
12271 checkds_cancel(dns_zone_t *zone) {
12272 dns_checkds_t *checkds;
12273
12274 /*
12275 * 'zone' locked by caller.
12276 */
12277
12278 REQUIRE(LOCKED_ZONE(zone));
12279
12280 for (checkds = ISC_LIST_HEAD(zone->checkds_requests); checkds != NULL;
12281 checkds = ISC_LIST_NEXT(checkds, link))
12282 {
12283 if (checkds->find != NULL) {
12284 dns_adb_cancelfind(checkds->find);
12285 }
12286 if (checkds->request != NULL) {
12287 dns_request_cancel(checkds->request);
12288 }
12289 }
12290 }
12291
12292 static void
12293 forward_cancel(dns_zone_t *zone) {
12294 dns_forward_t *forward;
12295
12296 /*
12297 * 'zone' locked by caller.
12298 */
12299
12300 REQUIRE(LOCKED_ZONE(zone));
12301
12302 for (forward = ISC_LIST_HEAD(zone->forwards); forward != NULL;
12303 forward = ISC_LIST_NEXT(forward, link))
12304 {
12305 if (forward->request != NULL) {
12306 dns_request_cancel(forward->request);
12307 }
12308 }
12309 }
12310
12311 static void
12312 zone_unload(dns_zone_t *zone) {
12313 /*
12314 * 'zone' locked by caller.
12315 */
12316
12317 REQUIRE(LOCKED_ZONE(zone));
12318
12319 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
12320 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
12321 {
12322 if (zone->dumpctx != NULL) {
12323 dns_dumpctx_cancel(zone->dumpctx);
12324 }
12325 }
12326 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
12327 zone_detachdb(zone);
12328 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
12329 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
12330 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
12331
12332 if (zone->type == dns_zone_mirror) {
12333 dns_zone_log(zone, ISC_LOG_INFO,
12334 "mirror zone is no longer in use; "
12335 "reverting to normal recursion");
12336 }
12337 }
12338
12339 void
12340 dns_zone_setminrefreshtime(dns_zone_t *zone, uint32_t val) {
12341 REQUIRE(DNS_ZONE_VALID(zone));
12342 REQUIRE(val > 0);
12343
12344 zone->minrefresh = val;
12345 }
12346
12347 void
12348 dns_zone_setmaxrefreshtime(dns_zone_t *zone, uint32_t val) {
12349 REQUIRE(DNS_ZONE_VALID(zone));
12350 REQUIRE(val > 0);
12351
12352 zone->maxrefresh = val;
12353 }
12354
12355 void
12356 dns_zone_setminretrytime(dns_zone_t *zone, uint32_t val) {
12357 REQUIRE(DNS_ZONE_VALID(zone));
12358 REQUIRE(val > 0);
12359
12360 zone->minretry = val;
12361 }
12362
12363 void
12364 dns_zone_setmaxretrytime(dns_zone_t *zone, uint32_t val) {
12365 REQUIRE(DNS_ZONE_VALID(zone));
12366 REQUIRE(val > 0);
12367
12368 zone->maxretry = val;
12369 }
12370
12371 uint32_t
12372 dns_zone_getmaxrecords(dns_zone_t *zone) {
12373 REQUIRE(DNS_ZONE_VALID(zone));
12374
12375 return zone->maxrecords;
12376 }
12377
12378 void
12379 dns_zone_setmaxrecords(dns_zone_t *zone, uint32_t val) {
12380 REQUIRE(DNS_ZONE_VALID(zone));
12381
12382 zone->maxrecords = val;
12383 }
12384
12385 void
12386 dns_zone_setmaxrrperset(dns_zone_t *zone, uint32_t val) {
12387 REQUIRE(DNS_ZONE_VALID(zone));
12388
12389 zone->maxrrperset = val;
12390 if (zone->db != NULL) {
12391 dns_db_setmaxrrperset(zone->db, val);
12392 }
12393 }
12394
12395 void
12396 dns_zone_setmaxtypepername(dns_zone_t *zone, uint32_t val) {
12397 REQUIRE(DNS_ZONE_VALID(zone));
12398
12399 zone->maxtypepername = val;
12400 if (zone->db != NULL) {
12401 dns_db_setmaxtypepername(zone->db, val);
12402 }
12403 }
12404
12405 static bool
12406 notify_isqueued(dns_zone_t *zone, unsigned int flags, dns_name_t *name,
12407 isc_sockaddr_t *addr, dns_tsigkey_t *key,
12408 dns_transport_t *transport) {
12409 dns_notify_t *notify;
12410 dns_zonemgr_t *zmgr;
12411 isc_result_t result;
12412
12413 for (notify = ISC_LIST_HEAD(zone->notifies); notify != NULL;
12414 notify = ISC_LIST_NEXT(notify, link))
12415 {
12416 if (notify->request != NULL) {
12417 continue;
12418 }
12419 if (name != NULL && dns_name_dynamic(¬ify->ns) &&
12420 dns_name_equal(name, ¬ify->ns))
12421 {
12422 goto requeue;
12423 }
12424 if (addr != NULL && isc_sockaddr_equal(addr, ¬ify->dst) &&
12425 notify->key == key && notify->transport == transport)
12426 {
12427 goto requeue;
12428 }
12429 }
12430 return false;
12431
12432 requeue:
12433 /*
12434 * If we are enqueued on the startup ratelimiter and this is
12435 * not a startup notify, re-enqueue on the normal notify
12436 * ratelimiter.
12437 */
12438 if (notify->rlevent != NULL && (flags & DNS_NOTIFY_STARTUP) == 0 &&
12439 (notify->flags & DNS_NOTIFY_STARTUP) != 0)
12440 {
12441 zmgr = notify->zone->zmgr;
12442 result = isc_ratelimiter_dequeue(zmgr->startupnotifyrl,
12443 ¬ify->rlevent);
12444 if (result != ISC_R_SUCCESS) {
12445 return true;
12446 }
12447
12448 notify->flags &= ~DNS_NOTIFY_STARTUP;
12449 result = isc_ratelimiter_enqueue(
12450 notify->zone->zmgr->notifyrl, notify->zone->loop,
12451 notify_send_toaddr, notify, ¬ify->rlevent);
12452 if (result != ISC_R_SUCCESS) {
12453 return false;
12454 }
12455 }
12456
12457 return true;
12458 }
12459
12460 static bool
12461 notify_isself(dns_zone_t *zone, isc_sockaddr_t *dst) {
12462 dns_tsigkey_t *key = NULL;
12463 isc_sockaddr_t src;
12464 isc_sockaddr_t any;
12465 bool isself;
12466 isc_netaddr_t dstaddr;
12467 isc_result_t result;
12468
12469 if (zone->view == NULL || zone->isself == NULL) {
12470 return false;
12471 }
12472
12473 switch (isc_sockaddr_pf(dst)) {
12474 case PF_INET:
12475 src = zone->notifysrc4;
12476 isc_sockaddr_any(&any);
12477 break;
12478 case PF_INET6:
12479 src = zone->notifysrc6;
12480 isc_sockaddr_any6(&any);
12481 break;
12482 default:
12483 return false;
12484 }
12485
12486 /*
12487 * When sending from any the kernel will assign a source address
12488 * that matches the destination address.
12489 */
12490 if (isc_sockaddr_eqaddr(&any, &src)) {
12491 src = *dst;
12492 }
12493
12494 isc_netaddr_fromsockaddr(&dstaddr, dst);
12495 result = dns_view_getpeertsig(zone->view, &dstaddr, &key);
12496 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
12497 return false;
12498 }
12499 isself = (zone->isself)(zone->view, key, &src, dst, zone->rdclass,
12500 zone->isselfarg);
12501 if (key != NULL) {
12502 dns_tsigkey_detach(&key);
12503 }
12504 return isself;
12505 }
12506
12507 static void
12508 notify_destroy(dns_notify_t *notify, bool locked) {
12509 isc_mem_t *mctx;
12510
12511 REQUIRE(DNS_NOTIFY_VALID(notify));
12512
12513 if (notify->zone != NULL) {
12514 if (!locked) {
12515 LOCK_ZONE(notify->zone);
12516 }
12517 REQUIRE(LOCKED_ZONE(notify->zone));
12518 if (ISC_LINK_LINKED(notify, link)) {
12519 ISC_LIST_UNLINK(notify->zone->notifies, notify, link);
12520 }
12521 if (!locked) {
12522 UNLOCK_ZONE(notify->zone);
12523 }
12524 if (locked) {
12525 zone_idetach(¬ify->zone);
12526 } else {
12527 dns_zone_idetach(¬ify->zone);
12528 }
12529 }
12530 if (notify->find != NULL) {
12531 dns_adb_destroyfind(¬ify->find);
12532 }
12533 if (notify->request != NULL) {
12534 dns_request_destroy(¬ify->request);
12535 }
12536 if (dns_name_dynamic(¬ify->ns)) {
12537 dns_name_free(¬ify->ns, notify->mctx);
12538 }
12539 if (notify->key != NULL) {
12540 dns_tsigkey_detach(¬ify->key);
12541 }
12542 if (notify->transport != NULL) {
12543 dns_transport_detach(¬ify->transport);
12544 }
12545 mctx = notify->mctx;
12546 isc_mem_put(notify->mctx, notify, sizeof(*notify));
12547 isc_mem_detach(&mctx);
12548 }
12549
12550 static isc_result_t
12551 notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
12552 dns_notify_t *notify;
12553
12554 REQUIRE(notifyp != NULL && *notifyp == NULL);
12555
12556 notify = isc_mem_get(mctx, sizeof(*notify));
12557 *notify = (dns_notify_t){
12558 .flags = flags,
12559 };
12560
12561 isc_mem_attach(mctx, ¬ify->mctx);
12562 isc_sockaddr_any(¬ify->src);
12563 isc_sockaddr_any(¬ify->dst);
12564 dns_name_init(¬ify->ns, NULL);
12565 ISC_LINK_INIT(notify, link);
12566 notify->magic = NOTIFY_MAGIC;
12567 *notifyp = notify;
12568 return ISC_R_SUCCESS;
12569 }
12570
12571 /*
12572 * XXXAG should check for DNS_ZONEFLG_EXITING
12573 */
12574 static void
12575 process_notify_adb_event(void *arg) {
12576 dns_adbfind_t *find = (dns_adbfind_t *)arg;
12577 dns_notify_t *notify = (dns_notify_t *)find->cbarg;
12578 dns_adbstatus_t astat = find->status;
12579
12580 REQUIRE(DNS_NOTIFY_VALID(notify));
12581 REQUIRE(find == notify->find);
12582
12583 switch (astat) {
12584 case DNS_ADB_MOREADDRESSES:
12585 dns_adb_destroyfind(¬ify->find);
12586 notify_find_address(notify);
12587 return;
12588
12589 case DNS_ADB_NOMOREADDRESSES:
12590 LOCK_ZONE(notify->zone);
12591 notify_send(notify);
12592 UNLOCK_ZONE(notify->zone);
12593 break;
12594
12595 default:
12596 break;
12597 }
12598
12599 notify_destroy(notify, false);
12600 }
12601
12602 static void
12603 notify_find_address(dns_notify_t *notify) {
12604 isc_result_t result;
12605 unsigned int options;
12606 dns_adb_t *adb = NULL;
12607
12608 REQUIRE(DNS_NOTIFY_VALID(notify));
12609
12610 options = DNS_ADBFIND_WANTEVENT;
12611 if (isc_net_probeipv4() != ISC_R_DISABLED) {
12612 options |= DNS_ADBFIND_INET;
12613 }
12614 if (isc_net_probeipv6() != ISC_R_DISABLED) {
12615 options |= DNS_ADBFIND_INET6;
12616 }
12617
12618 dns_view_getadb(notify->zone->view, &adb);
12619 if (adb == NULL) {
12620 goto destroy;
12621 }
12622
12623 result = dns_adb_createfind(adb, notify->zone->loop,
12624 process_notify_adb_event, notify,
12625 ¬ify->ns, dns_rootname, 0, options, 0,
12626 NULL, notify->zone->view->dstport, 0, NULL,
12627 NULL, NULL, ¬ify->find);
12628 dns_adb_detach(&adb);
12629
12630 /* Something failed? */
12631 if (result != ISC_R_SUCCESS) {
12632 goto destroy;
12633 }
12634
12635 /* More addresses pending? */
12636 if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0) {
12637 return;
12638 }
12639
12640 /* We have as many addresses as we can get. */
12641 LOCK_ZONE(notify->zone);
12642 notify_send(notify);
12643 UNLOCK_ZONE(notify->zone);
12644
12645 destroy:
12646 notify_destroy(notify, false);
12647 }
12648
12649 static isc_result_t
12650 notify_send_queue(dns_notify_t *notify, bool startup) {
12651 return isc_ratelimiter_enqueue(
12652 startup ? notify->zone->zmgr->startupnotifyrl
12653 : notify->zone->zmgr->notifyrl,
12654 notify->zone->loop, notify_send_toaddr, notify,
12655 ¬ify->rlevent);
12656 }
12657
12658 static void
12659 notify_send_toaddr(void *arg) {
12660 dns_notify_t *notify = (dns_notify_t *)arg;
12661 isc_result_t result;
12662 dns_message_t *message = NULL;
12663 isc_netaddr_t dstip;
12664 dns_tsigkey_t *key = NULL;
12665 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
12666 isc_sockaddr_t src;
12667 unsigned int options, timeout, udptimeout;
12668 bool have_notifysource = false;
12669 isc_tlsctx_cache_t *zmgr_tlsctx_cache = NULL;
12670
12671 REQUIRE(DNS_NOTIFY_VALID(notify));
12672
12673 LOCK_ZONE(notify->zone);
12674
12675 isc_sockaddr_format(¬ify->dst, addrbuf, sizeof(addrbuf));
12676
12677 if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0 ||
12678 notify->rlevent->canceled ||
12679 DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) ||
12680 notify->zone->view->requestmgr == NULL || notify->zone->db == NULL)
12681 {
12682 result = ISC_R_CANCELED;
12683 goto cleanup;
12684 }
12685
12686 /*
12687 * The raw IPv4 address should also exist. Don't send to the
12688 * mapped form.
12689 */
12690 if (isc_sockaddr_pf(¬ify->dst) == PF_INET6 &&
12691 IN6_IS_ADDR_V4MAPPED(¬ify->dst.type.sin6.sin6_addr))
12692 {
12693 notify_log(notify->zone, ISC_LOG_DEBUG(3),
12694 "notify: ignoring IPv6 mapped IPV4 address: %s",
12695 addrbuf);
12696 result = ISC_R_CANCELED;
12697 goto cleanup;
12698 }
12699
12700 result = notify_createmessage(notify->zone, notify->flags, &message);
12701 if (result != ISC_R_SUCCESS) {
12702 goto cleanup;
12703 }
12704
12705 if (notify->key != NULL) {
12706 /* Transfer ownership of key */
12707 key = notify->key;
12708 notify->key = NULL;
12709 } else {
12710 isc_netaddr_fromsockaddr(&dstip, ¬ify->dst);
12711 result = dns_view_getpeertsig(notify->zone->view, &dstip, &key);
12712 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
12713 notify_log(notify->zone, ISC_LOG_ERROR,
12714 "NOTIFY to %s not sent. "
12715 "Peer TSIG key lookup failure.",
12716 addrbuf);
12717 goto cleanup_message;
12718 }
12719 }
12720
12721 if (key != NULL) {
12722 char namebuf[DNS_NAME_FORMATSIZE];
12723
12724 dns_name_format(key->name, namebuf, sizeof(namebuf));
12725 notify_log(notify->zone, ISC_LOG_INFO,
12726 "sending notify to %s : TSIG (%s)", addrbuf,
12727 namebuf);
12728 } else {
12729 notify_log(notify->zone, ISC_LOG_INFO, "sending notify to %s",
12730 addrbuf);
12731 }
12732 options = 0;
12733 if (notify->zone->view->peers != NULL) {
12734 dns_peer_t *peer = NULL;
12735 bool usetcp = false;
12736 result = dns_peerlist_peerbyaddr(notify->zone->view->peers,
12737 &dstip, &peer);
12738 if (result == ISC_R_SUCCESS) {
12739 result = dns_peer_getnotifysource(peer, &src);
12740 if (result == ISC_R_SUCCESS) {
12741 have_notifysource = true;
12742 }
12743 result = dns_peer_getforcetcp(peer, &usetcp);
12744 if (result == ISC_R_SUCCESS && usetcp) {
12745 options |= DNS_FETCHOPT_TCP;
12746 }
12747 }
12748 }
12749 switch (isc_sockaddr_pf(¬ify->dst)) {
12750 case PF_INET:
12751 if (!have_notifysource) {
12752 isc_sockaddr_t any;
12753 isc_sockaddr_any(&any);
12754
12755 src = notify->src;
12756 if (isc_sockaddr_equal(&src, &any)) {
12757 src = notify->zone->notifysrc4;
12758 }
12759 }
12760 break;
12761 case PF_INET6:
12762 if (!have_notifysource) {
12763 isc_sockaddr_t any;
12764 isc_sockaddr_any6(&any);
12765
12766 src = notify->src;
12767 if (isc_sockaddr_equal(&src, &any)) {
12768 src = notify->zone->notifysrc6;
12769 }
12770 }
12771 break;
12772 default:
12773 result = ISC_R_NOTIMPLEMENTED;
12774 goto cleanup_key;
12775 }
12776 udptimeout = 5;
12777 if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY)) {
12778 udptimeout = 30;
12779 }
12780 timeout = 3 * udptimeout + 1;
12781 again:
12782 if ((notify->flags & DNS_NOTIFY_TCP) != 0) {
12783 options |= DNS_REQUESTOPT_TCP;
12784 udptimeout = 0;
12785 timeout = 15;
12786 }
12787
12788 zmgr_tlsctx_attach(notify->zone->zmgr, &zmgr_tlsctx_cache);
12789
12790 result = dns_request_create(notify->zone->view->requestmgr, message,
12791 &src, ¬ify->dst, notify->transport,
12792 zmgr_tlsctx_cache, options, key, timeout,
12793 udptimeout, 2, notify->zone->loop,
12794 notify_done, notify, ¬ify->request);
12795
12796 isc_tlsctx_cache_detach(&zmgr_tlsctx_cache);
12797
12798 if (result == ISC_R_SUCCESS) {
12799 if (isc_sockaddr_pf(¬ify->dst) == AF_INET) {
12800 inc_stats(notify->zone,
12801 dns_zonestatscounter_notifyoutv4);
12802 } else {
12803 inc_stats(notify->zone,
12804 dns_zonestatscounter_notifyoutv6);
12805 }
12806 } else if (result == ISC_R_SHUTTINGDOWN || result == ISC_R_CANCELED) {
12807 goto cleanup_key;
12808 } else if ((notify->flags & DNS_NOTIFY_TCP) == 0) {
12809 notify_log(notify->zone, ISC_LOG_NOTICE,
12810 "notify to %s failed: %s: retrying over TCP",
12811 addrbuf, isc_result_totext(result));
12812 notify->flags |= DNS_NOTIFY_TCP;
12813 goto again;
12814 }
12815
12816 cleanup_key:
12817 if (key != NULL) {
12818 dns_tsigkey_detach(&key);
12819 }
12820 cleanup_message:
12821 dns_message_detach(&message);
12822 cleanup:
12823 UNLOCK_ZONE(notify->zone);
12824 if (notify->rlevent != NULL) {
12825 isc_rlevent_free(¬ify->rlevent);
12826 }
12827
12828 if (result != ISC_R_SUCCESS) {
12829 isc_sockaddr_format(¬ify->dst, addrbuf, sizeof(addrbuf));
12830 notify_log(notify->zone, ISC_LOG_WARNING,
12831 "notify to %s failed: %s", addrbuf,
12832 isc_result_totext(result));
12833 notify_destroy(notify, false);
12834 }
12835 }
12836
12837 static void
12838 notify_send(dns_notify_t *notify) {
12839 dns_adbaddrinfo_t *ai;
12840 isc_sockaddr_t dst;
12841 isc_result_t result;
12842 dns_notify_t *newnotify = NULL;
12843 unsigned int flags;
12844 bool startup;
12845
12846 /*
12847 * Zone lock held by caller.
12848 */
12849 REQUIRE(DNS_NOTIFY_VALID(notify));
12850 REQUIRE(LOCKED_ZONE(notify->zone));
12851
12852 if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING)) {
12853 return;
12854 }
12855
12856 for (ai = ISC_LIST_HEAD(notify->find->list); ai != NULL;
12857 ai = ISC_LIST_NEXT(ai, publink))
12858 {
12859 dst = ai->sockaddr;
12860 if (notify_isqueued(notify->zone, notify->flags, NULL, &dst,
12861 NULL, NULL))
12862 {
12863 continue;
12864 }
12865 if (notify_isself(notify->zone, &dst)) {
12866 continue;
12867 }
12868 newnotify = NULL;
12869 flags = notify->flags & DNS_NOTIFY_NOSOA;
12870 result = notify_create(notify->mctx, flags, &newnotify);
12871 if (result != ISC_R_SUCCESS) {
12872 goto cleanup;
12873 }
12874 zone_iattach(notify->zone, &newnotify->zone);
12875 ISC_LIST_APPEND(newnotify->zone->notifies, newnotify, link);
12876 newnotify->dst = dst;
12877 if (isc_sockaddr_pf(&dst) == AF_INET6) {
12878 isc_sockaddr_any6(&newnotify->src);
12879 }
12880 startup = ((notify->flags & DNS_NOTIFY_STARTUP) != 0);
12881 result = notify_send_queue(newnotify, startup);
12882 if (result != ISC_R_SUCCESS) {
12883 goto cleanup;
12884 }
12885 newnotify = NULL;
12886 }
12887
12888 cleanup:
12889 if (newnotify != NULL) {
12890 notify_destroy(newnotify, true);
12891 }
12892 }
12893
12894 void
12895 dns_zone_notify(dns_zone_t *zone, bool nodefer) {
12896 isc_time_t now;
12897
12898 REQUIRE(DNS_ZONE_VALID(zone));
12899
12900 LOCK_ZONE(zone);
12901 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
12902 if (nodefer) {
12903 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOTIFYDEFERRED)) {
12904 /*
12905 * We have previously deferred the notify, but we have a
12906 * new request not to defer it. Reverse the deferring
12907 * operation.
12908 */
12909 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOTIFYDEFERRED);
12910 DNS_ZONE_TIME_SUBTRACT(&zone->notifytime,
12911 zone->notifydefer,
12912 &zone->notifytime);
12913 }
12914 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOTIFYNODEFER);
12915 }
12916 now = isc_time_now();
12917 zone_settimer(zone, &now);
12918 UNLOCK_ZONE(zone);
12919 }
12920
12921 static void
12922 zone_notify(dns_zone_t *zone, isc_time_t *now) {
12923 dns_dbnode_t *node = NULL;
12924 dns_db_t *zonedb = NULL;
12925 dns_dbversion_t *version = NULL;
12926 dns_name_t *origin = NULL;
12927 dns_name_t primary;
12928 dns_rdata_ns_t ns;
12929 dns_rdata_soa_t soa;
12930 uint32_t serial;
12931 dns_rdata_t rdata = DNS_RDATA_INIT;
12932 dns_rdataset_t nsrdset;
12933 dns_rdataset_t soardset;
12934 isc_result_t result;
12935 isc_sockaddr_t src;
12936 isc_sockaddr_t dst;
12937 bool isqueued;
12938 dns_notifytype_t notifytype;
12939 unsigned int flags = 0;
12940 bool loggednotify = false;
12941 bool startup;
12942
12943 REQUIRE(DNS_ZONE_VALID(zone));
12944
12945 LOCK_ZONE(zone);
12946 startup = !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
12947 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY |
12948 DNS_ZONEFLG_NEEDSTARTUPNOTIFY |
12949 DNS_ZONEFLG_NOTIFYNODEFER |
12950 DNS_ZONEFLG_NOTIFYDEFERRED);
12951 notifytype = zone->notifytype;
12952 DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime);
12953 UNLOCK_ZONE(zone);
12954
12955 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
12956 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
12957 {
12958 return;
12959 }
12960
12961 if (notifytype == dns_notifytype_no) {
12962 return;
12963 }
12964
12965 if (notifytype == dns_notifytype_masteronly &&
12966 zone->type != dns_zone_primary)
12967 {
12968 return;
12969 }
12970
12971 origin = &zone->origin;
12972
12973 /*
12974 * If the zone is dialup we are done as we don't want to send
12975 * the current soa so as to force a refresh query.
12976 */
12977 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY)) {
12978 flags |= DNS_NOTIFY_NOSOA;
12979 }
12980
12981 /*
12982 * Record that this was a notify due to starting up.
12983 */
12984 if (startup) {
12985 flags |= DNS_NOTIFY_STARTUP;
12986 }
12987
12988 /*
12989 * Get SOA RRset.
12990 */
12991 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
12992 if (zone->db != NULL) {
12993 dns_db_attach(zone->db, &zonedb);
12994 }
12995 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12996 if (zonedb == NULL) {
12997 return;
12998 }
12999 dns_db_currentversion(zonedb, &version);
13000 result = dns_db_findnode(zonedb, origin, false, &node);
13001 if (result != ISC_R_SUCCESS) {
13002 goto cleanup1;
13003 }
13004
13005 dns_rdataset_init(&soardset);
13006 result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
13007 dns_rdatatype_none, 0, &soardset, NULL);
13008 if (result != ISC_R_SUCCESS) {
13009 goto cleanup2;
13010 }
13011
13012 /*
13013 * Find serial and primary server's name.
13014 */
13015 dns_name_init(&primary, NULL);
13016 result = dns_rdataset_first(&soardset);
13017 if (result != ISC_R_SUCCESS) {
13018 goto cleanup3;
13019 }
13020 dns_rdataset_current(&soardset, &rdata);
13021 result = dns_rdata_tostruct(&rdata, &soa, NULL);
13022 RUNTIME_CHECK(result == ISC_R_SUCCESS);
13023 dns_rdata_reset(&rdata);
13024 dns_name_dup(&soa.origin, zone->mctx, &primary);
13025 serial = soa.serial;
13026 dns_rdataset_disassociate(&soardset);
13027
13028 /*
13029 * Enqueue notify requests for 'also-notify' servers.
13030 */
13031 LOCK_ZONE(zone);
13032
13033 dns_remote_reset(&zone->notify, false);
13034 while (!dns_remote_done(&zone->notify)) {
13035 dns_tsigkey_t *key = NULL;
13036 dns_transport_t *transport = NULL;
13037 dns_notify_t *notify = NULL;
13038 dns_view_t *view = dns_zone_getview(zone);
13039
13040 if (dns_remote_keyname(&zone->notify) != NULL) {
13041 dns_name_t *keyname = dns_remote_keyname(&zone->notify);
13042 (void)dns_view_gettsig(view, keyname, &key);
13043 }
13044
13045 if (dns_remote_tlsname(&zone->notify) != NULL) {
13046 dns_name_t *tlsname = dns_remote_tlsname(&zone->notify);
13047 result = dns_view_gettransport(view, DNS_TRANSPORT_TLS,
13048 tlsname, &transport);
13049
13050 if (result == ISC_R_SUCCESS) {
13051 notify_log(
13052 zone, ISC_LOG_INFO,
13053 "got TLS configuration for a notify");
13054 } else {
13055 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
13056 ISC_LOG_ERROR,
13057 "could not get TLS configuration "
13058 "for zone transfer: %s",
13059 isc_result_totext(result));
13060 goto next;
13061 }
13062
13063 flags |= DNS_NOTIFY_TCP;
13064 }
13065
13066 /* TODO: glue the transport to the notify */
13067
13068 dst = dns_remote_curraddr(&zone->notify);
13069 src = dns_remote_sourceaddr(&zone->notify);
13070 INSIST(isc_sockaddr_pf(&src) == isc_sockaddr_pf(&dst));
13071
13072 if (isc_sockaddr_disabled(&dst)) {
13073 goto next;
13074 }
13075
13076 if (notify_isqueued(zone, flags, NULL, &dst, key, transport)) {
13077 if (key != NULL) {
13078 dns_tsigkey_detach(&key);
13079 }
13080 if (transport != NULL) {
13081 dns_transport_detach(&transport);
13082 }
13083 goto next;
13084 }
13085
13086 result = notify_create(zone->mctx, flags, ¬ify);
13087 if (result != ISC_R_SUCCESS) {
13088 if (key != NULL) {
13089 dns_tsigkey_detach(&key);
13090 }
13091 if (transport != NULL) {
13092 dns_transport_detach(&transport);
13093 }
13094 goto next;
13095 }
13096
13097 zone_iattach(zone, ¬ify->zone);
13098 notify->src = src;
13099 notify->dst = dst;
13100
13101 INSIST(notify->key == NULL);
13102
13103 if (key != NULL) {
13104 notify->key = key;
13105 key = NULL;
13106 }
13107
13108 INSIST(notify->transport == NULL);
13109 if (transport != NULL) {
13110 notify->transport = transport;
13111 transport = NULL;
13112 }
13113
13114 ISC_LIST_APPEND(zone->notifies, notify, link);
13115 result = notify_send_queue(notify, startup);
13116 if (result != ISC_R_SUCCESS) {
13117 notify_destroy(notify, true);
13118 }
13119 if (!loggednotify) {
13120 notify_log(zone, ISC_LOG_INFO,
13121 "sending notifies (serial %u)", serial);
13122 loggednotify = true;
13123 }
13124 next:
13125 flags &= ~DNS_NOTIFY_TCP;
13126 dns_remote_next(&zone->notify, false);
13127 }
13128 UNLOCK_ZONE(zone);
13129
13130 if (notifytype == dns_notifytype_explicit) {
13131 goto cleanup3;
13132 }
13133
13134 /*
13135 * Process NS RRset to generate notifies.
13136 */
13137
13138 dns_rdataset_init(&nsrdset);
13139 result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_ns,
13140 dns_rdatatype_none, 0, &nsrdset, NULL);
13141 if (result != ISC_R_SUCCESS) {
13142 goto cleanup3;
13143 }
13144
13145 result = dns_rdataset_first(&nsrdset);
13146 while (result == ISC_R_SUCCESS) {
13147 dns_notify_t *notify = NULL;
13148
13149 dns_rdataset_current(&nsrdset, &rdata);
13150 result = dns_rdata_tostruct(&rdata, &ns, NULL);
13151 RUNTIME_CHECK(result == ISC_R_SUCCESS);
13152 dns_rdata_reset(&rdata);
13153 /*
13154 * Don't notify the primary server unless explicitly
13155 * configured to do so.
13156 */
13157 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOTIFYTOSOA) &&
13158 dns_name_compare(&primary, &ns.name) == 0)
13159 {
13160 result = dns_rdataset_next(&nsrdset);
13161 continue;
13162 }
13163
13164 if (!loggednotify) {
13165 notify_log(zone, ISC_LOG_INFO,
13166 "sending notifies (serial %u)", serial);
13167 loggednotify = true;
13168 }
13169
13170 LOCK_ZONE(zone);
13171 isqueued = notify_isqueued(zone, flags, &ns.name, NULL, NULL,
13172 NULL);
13173 UNLOCK_ZONE(zone);
13174 if (isqueued) {
13175 result = dns_rdataset_next(&nsrdset);
13176 continue;
13177 }
13178 result = notify_create(zone->mctx, flags, ¬ify);
13179 if (result != ISC_R_SUCCESS) {
13180 continue;
13181 }
13182 dns_zone_iattach(zone, ¬ify->zone);
13183 dns_name_dup(&ns.name, zone->mctx, ¬ify->ns);
13184 LOCK_ZONE(zone);
13185 ISC_LIST_APPEND(zone->notifies, notify, link);
13186 UNLOCK_ZONE(zone);
13187 notify_find_address(notify);
13188 result = dns_rdataset_next(&nsrdset);
13189 }
13190 dns_rdataset_disassociate(&nsrdset);
13191
13192 cleanup3:
13193 if (dns_name_dynamic(&primary)) {
13194 dns_name_free(&primary, zone->mctx);
13195 }
13196 cleanup2:
13197 dns_db_detachnode(zonedb, &node);
13198 cleanup1:
13199 dns_db_closeversion(zonedb, &version, false);
13200 dns_db_detach(&zonedb);
13201 }
13202
13203 /***
13204 *** Private
13205 ***/
13206 static void
13207 create_query(dns_zone_t *zone, dns_rdatatype_t rdtype, dns_name_t *name,
13208 dns_message_t **messagep) {
13209 dns_message_t *message = NULL;
13210 dns_name_t *qname = NULL;
13211 dns_rdataset_t *qrdataset = NULL;
13212
13213 dns_message_create(zone->mctx, NULL, NULL, DNS_MESSAGE_INTENTRENDER,
13214 &message);
13215
13216 message->opcode = dns_opcode_query;
13217 message->rdclass = zone->rdclass;
13218
13219 dns_message_gettempname(message, &qname);
13220
13221 dns_message_gettemprdataset(message, &qrdataset);
13222
13223 /*
13224 * Make question.
13225 */
13226 dns_name_clone(name, qname);
13227 dns_rdataset_makequestion(qrdataset, zone->rdclass, rdtype);
13228 ISC_LIST_APPEND(qname->list, qrdataset, link);
13229 dns_message_addname(message, qname, DNS_SECTION_QUESTION);
13230
13231 *messagep = message;
13232 }
13233
13234 static isc_result_t
13235 add_opt(dns_message_t *message, uint16_t udpsize, bool reqnsid,
13236 bool reqexpire) {
13237 isc_result_t result;
13238 dns_rdataset_t *rdataset = NULL;
13239 dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS];
13240 int count = 0;
13241
13242 /* Set EDNS options if applicable. */
13243 if (reqnsid) {
13244 INSIST(count < DNS_EDNSOPTIONS);
13245 ednsopts[count].code = DNS_OPT_NSID;
13246 ednsopts[count].length = 0;
13247 ednsopts[count].value = NULL;
13248 count++;
13249 }
13250 if (reqexpire) {
13251 INSIST(count < DNS_EDNSOPTIONS);
13252 ednsopts[count].code = DNS_OPT_EXPIRE;
13253 ednsopts[count].length = 0;
13254 ednsopts[count].value = NULL;
13255 count++;
13256 }
13257 result = dns_message_buildopt(message, &rdataset, 0, udpsize, 0,
13258 ednsopts, count);
13259 if (result != ISC_R_SUCCESS) {
13260 return result;
13261 }
13262
13263 return dns_message_setopt(message, rdataset);
13264 }
13265
13266 /*
13267 * Called when stub zone update is finished.
13268 * Update zone refresh, retry, expire values accordingly with
13269 * SOA received from primary, sync database to file, restart
13270 * zone management timer.
13271 */
13272 static void
13273 stub_finish_zone_update(dns_stub_t *stub, isc_time_t now) {
13274 uint32_t refresh, retry, expire;
13275 isc_result_t result;
13276 isc_interval_t i;
13277 unsigned int soacount;
13278 dns_zone_t *zone = stub->zone;
13279
13280 /*
13281 * Tidy up.
13282 */
13283 dns_db_closeversion(stub->db, &stub->version, true);
13284 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
13285 if (zone->db == NULL) {
13286 zone_attachdb(zone, stub->db);
13287 }
13288 result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL, NULL,
13289 &refresh, &retry, &expire, NULL, NULL);
13290 if (result == ISC_R_SUCCESS && soacount > 0U) {
13291 zone->refresh = RANGE(refresh, zone->minrefresh,
13292 zone->maxrefresh);
13293 zone->retry = RANGE(retry, zone->minretry, zone->maxretry);
13294 zone->expire = RANGE(expire, zone->refresh + zone->retry,
13295 DNS_MAX_EXPIRE);
13296 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
13297 }
13298 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
13299 dns_db_detach(&stub->db);
13300
13301 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
13302 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
13303 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
13304 isc_interval_set(&i, zone->expire, 0);
13305 DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
13306
13307 if (zone->masterfile != NULL) {
13308 zone_needdump(zone, 0);
13309 }
13310
13311 zone_settimer(zone, &now);
13312 }
13313
13314 /*
13315 * Process answers for A and AAAA queries when
13316 * resolving nameserver addresses for which glue
13317 * was missing in a previous answer for a NS query.
13318 */
13319 static void
13320 stub_glue_response(void *arg) {
13321 dns_request_t *request = (dns_request_t *)arg;
13322 struct stub_glue_request *sgr = dns_request_getarg(request);
13323 struct stub_cb_args *cb_args = sgr->args;
13324 dns_stub_t *stub = cb_args->stub;
13325 dns_message_t *msg = NULL;
13326 dns_zone_t *zone = NULL;
13327 char primary[ISC_SOCKADDR_FORMATSIZE];
13328 char source[ISC_SOCKADDR_FORMATSIZE];
13329 uint32_t addr_count, cnamecnt;
13330 isc_result_t result;
13331 isc_sockaddr_t curraddr;
13332 isc_time_t now;
13333 dns_rdataset_t *addr_rdataset = NULL;
13334 dns_dbnode_t *node = NULL;
13335
13336 INSIST(DNS_STUB_VALID(stub));
13337
13338 zone = stub->zone;
13339
13340 ENTER;
13341
13342 now = isc_time_now();
13343
13344 LOCK_ZONE(zone);
13345
13346 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
13347 zone_debuglog(zone, __func__, 1, "exiting");
13348 goto cleanup;
13349 }
13350
13351 curraddr = dns_remote_curraddr(&zone->primaries);
13352 isc_sockaddr_format(&curraddr, primary, sizeof(primary));
13353 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
13354
13355 if (dns_request_getresult(request) != ISC_R_SUCCESS) {
13356 dns_zonemgr_unreachableadd(zone->zmgr, &curraddr,
13357 &zone->sourceaddr, &now);
13358 dns_zone_log(zone, ISC_LOG_INFO,
13359 "could not refresh stub from primary %s"
13360 " (source %s): %s",
13361 primary, source,
13362 isc_result_totext(dns_request_getresult(request)));
13363 goto cleanup;
13364 }
13365
13366 dns_message_create(zone->mctx, NULL, NULL, DNS_MESSAGE_INTENTPARSE,
13367 &msg);
13368 result = dns_request_getresponse(request, msg, 0);
13369 if (result != ISC_R_SUCCESS) {
13370 dns_zone_log(zone, ISC_LOG_INFO,
13371 "refreshing stub: unable to parse response (%s)",
13372 isc_result_totext(result));
13373 goto cleanup;
13374 }
13375
13376 /*
13377 * Unexpected opcode.
13378 */
13379 if (msg->opcode != dns_opcode_query) {
13380 char opcode[128];
13381 isc_buffer_t rb;
13382
13383 isc_buffer_init(&rb, opcode, sizeof(opcode));
13384 (void)dns_opcode_totext(msg->opcode, &rb);
13385
13386 dns_zone_log(zone, ISC_LOG_INFO,
13387 "refreshing stub: "
13388 "unexpected opcode (%.*s) from %s (source %s)",
13389 (int)rb.used, opcode, primary, source);
13390 goto cleanup;
13391 }
13392
13393 /*
13394 * Unexpected rcode.
13395 */
13396 if (msg->rcode != dns_rcode_noerror) {
13397 char rcode[128];
13398 isc_buffer_t rb;
13399
13400 isc_buffer_init(&rb, rcode, sizeof(rcode));
13401 (void)dns_rcode_totext(msg->rcode, &rb);
13402
13403 dns_zone_log(zone, ISC_LOG_INFO,
13404 "refreshing stub: "
13405 "unexpected rcode (%.*s) from %s (source %s)",
13406 (int)rb.used, rcode, primary, source);
13407 goto cleanup;
13408 }
13409
13410 /*
13411 * We need complete messages.
13412 */
13413 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
13414 if (dns_request_usedtcp(request)) {
13415 dns_zone_log(zone, ISC_LOG_INFO,
13416 "refreshing stub: truncated TCP "
13417 "response from primary %s (source %s)",
13418 primary, source);
13419 }
13420 goto cleanup;
13421 }
13422
13423 /*
13424 * If non-auth log.
13425 */
13426 if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
13427 dns_zone_log(zone, ISC_LOG_INFO,
13428 "refreshing stub: "
13429 "non-authoritative answer from "
13430 "primary %s (source %s)",
13431 primary, source);
13432 goto cleanup;
13433 }
13434
13435 /*
13436 * Sanity checks.
13437 */
13438 cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
13439 addr_count = message_count(msg, DNS_SECTION_ANSWER,
13440 sgr->ipv4 ? dns_rdatatype_a
13441 : dns_rdatatype_aaaa);
13442
13443 if (cnamecnt != 0) {
13444 dns_zone_log(zone, ISC_LOG_INFO,
13445 "refreshing stub: unexpected CNAME response "
13446 "from primary %s (source %s)",
13447 primary, source);
13448 goto cleanup;
13449 }
13450
13451 if (addr_count == 0) {
13452 dns_zone_log(zone, ISC_LOG_INFO,
13453 "refreshing stub: no %s records in response "
13454 "from primary %s (source %s)",
13455 sgr->ipv4 ? "A" : "AAAA", primary, source);
13456 goto cleanup;
13457 }
13458 /*
13459 * Extract A or AAAA RRset from message.
13460 */
13461 result = dns_message_findname(msg, DNS_SECTION_ANSWER, &sgr->name,
13462 sgr->ipv4 ? dns_rdatatype_a
13463 : dns_rdatatype_aaaa,
13464 dns_rdatatype_none, NULL, &addr_rdataset);
13465 if (result != ISC_R_SUCCESS) {
13466 if (result != DNS_R_NXDOMAIN && result != DNS_R_NXRRSET) {
13467 char namebuf[DNS_NAME_FORMATSIZE];
13468 dns_name_format(&sgr->name, namebuf, sizeof(namebuf));
13469 dns_zone_log(
13470 zone, ISC_LOG_INFO,
13471 "refreshing stub: dns_message_findname(%s/%s) "
13472 "failed (%s)",
13473 namebuf, sgr->ipv4 ? "A" : "AAAA",
13474 isc_result_totext(result));
13475 }
13476 goto cleanup;
13477 }
13478
13479 result = dns_db_findnode(stub->db, &sgr->name, true, &node);
13480 if (result != ISC_R_SUCCESS) {
13481 dns_zone_log(zone, ISC_LOG_INFO,
13482 "refreshing stub: "
13483 "dns_db_findnode() failed: %s",
13484 isc_result_totext(result));
13485 goto cleanup;
13486 }
13487
13488 result = dns_db_addrdataset(stub->db, node, stub->version, 0,
13489 addr_rdataset, 0, NULL);
13490 if (result != ISC_R_SUCCESS) {
13491 dns_zone_log(zone, ISC_LOG_INFO,
13492 "refreshing stub: "
13493 "dns_db_addrdataset() failed: %s",
13494 isc_result_totext(result));
13495 }
13496 dns_db_detachnode(stub->db, &node);
13497
13498 cleanup:
13499 if (msg != NULL) {
13500 dns_message_detach(&msg);
13501 }
13502
13503 dns_name_free(&sgr->name, zone->mctx);
13504 dns_request_destroy(&sgr->request);
13505 isc_mem_put(zone->mctx, sgr, sizeof(*sgr));
13506
13507 /* If last request, release all related resources */
13508 if (atomic_fetch_sub_release(&stub->pending_requests, 1) == 1) {
13509 isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
13510 stub_finish_zone_update(stub, now);
13511 UNLOCK_ZONE(zone);
13512 stub->magic = 0;
13513 dns_zone_idetach(&stub->zone);
13514 INSIST(stub->db == NULL);
13515 INSIST(stub->version == NULL);
13516 isc_mem_put(stub->mctx, stub, sizeof(*stub));
13517 } else {
13518 UNLOCK_ZONE(zone);
13519 }
13520 }
13521
13522 /*
13523 * Create and send an A or AAAA query to the primary
13524 * server of the stub zone given.
13525 */
13526 static isc_result_t
13527 stub_request_nameserver_address(struct stub_cb_args *args, bool ipv4,
13528 const dns_name_t *name) {
13529 dns_message_t *message = NULL;
13530 dns_zone_t *zone;
13531 isc_result_t result;
13532 struct stub_glue_request *sgr;
13533 isc_sockaddr_t curraddr;
13534
13535 zone = args->stub->zone;
13536 sgr = isc_mem_get(zone->mctx, sizeof(*sgr));
13537 *sgr = (struct stub_glue_request){
13538 .args = args,
13539 .name = (dns_name_t)DNS_NAME_INITEMPTY,
13540 .ipv4 = ipv4,
13541 };
13542
13543 dns_name_dup(name, zone->mctx, &sgr->name);
13544
13545 create_query(zone, ipv4 ? dns_rdatatype_a : dns_rdatatype_aaaa,
13546 &sgr->name, &message);
13547
13548 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
13549 result = add_opt(message, args->udpsize, args->reqnsid, false);
13550 if (result != ISC_R_SUCCESS) {
13551 zone_debuglog(zone, __func__, 1,
13552 "unable to add opt record: %s",
13553 isc_result_totext(result));
13554 goto fail;
13555 }
13556 }
13557
13558 atomic_fetch_add_release(&args->stub->pending_requests, 1);
13559
13560 curraddr = dns_remote_curraddr(&zone->primaries);
13561 result = dns_request_create(
13562 zone->view->requestmgr, message, &zone->sourceaddr, &curraddr,
13563 NULL, NULL, DNS_REQUESTOPT_TCP, args->tsig_key,
13564 args->timeout * 3, args->timeout, 2, zone->loop,
13565 stub_glue_response, sgr, &sgr->request);
13566
13567 if (result != ISC_R_SUCCESS) {
13568 uint_fast32_t pr;
13569 pr = atomic_fetch_sub_release(&args->stub->pending_requests, 1);
13570 INSIST(pr > 1);
13571 zone_debuglog(zone, __func__, 1,
13572 "dns_request_create() failed: %s",
13573 isc_result_totext(result));
13574 goto fail;
13575 }
13576
13577 dns_message_detach(&message);
13578
13579 return ISC_R_SUCCESS;
13580
13581 fail:
13582 dns_name_free(&sgr->name, zone->mctx);
13583 isc_mem_put(zone->mctx, sgr, sizeof(*sgr));
13584
13585 if (message != NULL) {
13586 dns_message_detach(&message);
13587 }
13588
13589 return result;
13590 }
13591
13592 static isc_result_t
13593 save_nsrrset(dns_message_t *message, dns_name_t *name,
13594 struct stub_cb_args *cb_args, dns_db_t *db,
13595 dns_dbversion_t *version) {
13596 dns_rdataset_t *nsrdataset = NULL;
13597 dns_rdataset_t *rdataset = NULL;
13598 dns_dbnode_t *node = NULL;
13599 dns_rdata_ns_t ns;
13600 isc_result_t result;
13601 dns_rdata_t rdata = DNS_RDATA_INIT;
13602 bool has_glue = false;
13603 dns_name_t *ns_name;
13604 /*
13605 * List of NS entries in answer, keep names that will be used
13606 * to resolve missing A/AAAA glue for each entry.
13607 */
13608 dns_namelist_t ns_list;
13609 ISC_LIST_INIT(ns_list);
13610
13611 /*
13612 * Extract NS RRset from message.
13613 */
13614 result = dns_message_findname(message, DNS_SECTION_ANSWER, name,
13615 dns_rdatatype_ns, dns_rdatatype_none,
13616 NULL, &nsrdataset);
13617 if (result != ISC_R_SUCCESS) {
13618 goto done;
13619 }
13620
13621 /*
13622 * Add NS rdataset.
13623 */
13624 result = dns_db_findnode(db, name, true, &node);
13625 if (result != ISC_R_SUCCESS) {
13626 goto done;
13627 }
13628 result = dns_db_addrdataset(db, node, version, 0, nsrdataset, 0, NULL);
13629 dns_db_detachnode(db, &node);
13630 if (result != ISC_R_SUCCESS) {
13631 goto done;
13632 }
13633 /*
13634 * Add glue rdatasets.
13635 */
13636 for (result = dns_rdataset_first(nsrdataset); result == ISC_R_SUCCESS;
13637 result = dns_rdataset_next(nsrdataset))
13638 {
13639 dns_rdataset_current(nsrdataset, &rdata);
13640 result = dns_rdata_tostruct(&rdata, &ns, NULL);
13641 RUNTIME_CHECK(result == ISC_R_SUCCESS);
13642 dns_rdata_reset(&rdata);
13643
13644 if (!dns_name_issubdomain(&ns.name, name)) {
13645 continue;
13646 }
13647 rdataset = NULL;
13648 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
13649 &ns.name, dns_rdatatype_aaaa,
13650 dns_rdatatype_none, NULL,
13651 &rdataset);
13652 if (result == ISC_R_SUCCESS) {
13653 has_glue = true;
13654 result = dns_db_findnode(db, &ns.name, true, &node);
13655 if (result != ISC_R_SUCCESS) {
13656 goto done;
13657 }
13658 result = dns_db_addrdataset(db, node, version, 0,
13659 rdataset, 0, NULL);
13660 dns_db_detachnode(db, &node);
13661 if (result != ISC_R_SUCCESS) {
13662 goto done;
13663 }
13664 }
13665
13666 rdataset = NULL;
13667 result = dns_message_findname(
13668 message, DNS_SECTION_ADDITIONAL, &ns.name,
13669 dns_rdatatype_a, dns_rdatatype_none, NULL, &rdataset);
13670 if (result == ISC_R_SUCCESS) {
13671 has_glue = true;
13672 result = dns_db_findnode(db, &ns.name, true, &node);
13673 if (result != ISC_R_SUCCESS) {
13674 goto done;
13675 }
13676 result = dns_db_addrdataset(db, node, version, 0,
13677 rdataset, 0, NULL);
13678 dns_db_detachnode(db, &node);
13679 if (result != ISC_R_SUCCESS) {
13680 goto done;
13681 }
13682 }
13683
13684 /*
13685 * If no glue is found so far, we add the name to the list to
13686 * resolve the A/AAAA glue later. If any glue is found in any
13687 * iteration step, this list will be discarded and only the glue
13688 * provided in this message will be used.
13689 */
13690 if (!has_glue && dns_name_issubdomain(&ns.name, name)) {
13691 dns_name_t *tmp_name;
13692 tmp_name = isc_mem_get(cb_args->stub->mctx,
13693 sizeof(*tmp_name));
13694 dns_name_init(tmp_name, NULL);
13695 dns_name_dup(&ns.name, cb_args->stub->mctx, tmp_name);
13696 ISC_LIST_APPEND(ns_list, tmp_name, link);
13697 }
13698 }
13699
13700 if (result != ISC_R_NOMORE) {
13701 goto done;
13702 }
13703
13704 /*
13705 * If no glue records were found, we attempt to resolve A/AAAA
13706 * for each NS entry found in the answer.
13707 */
13708 if (!has_glue) {
13709 for (ns_name = ISC_LIST_HEAD(ns_list); ns_name != NULL;
13710 ns_name = ISC_LIST_NEXT(ns_name, link))
13711 {
13712 /*
13713 * Resolve NS IPv4 address/A.
13714 */
13715 result = stub_request_nameserver_address(cb_args, true,
13716 ns_name);
13717 if (result != ISC_R_SUCCESS) {
13718 goto done;
13719 }
13720 /*
13721 * Resolve NS IPv6 address/AAAA.
13722 */
13723 result = stub_request_nameserver_address(cb_args, false,
13724 ns_name);
13725 if (result != ISC_R_SUCCESS) {
13726 goto done;
13727 }
13728 }
13729 }
13730
13731 result = ISC_R_SUCCESS;
13732
13733 done:
13734 while ((ns_name = ISC_LIST_HEAD(ns_list)) != NULL) {
13735 ISC_LIST_UNLINK(ns_list, ns_name, link);
13736 dns_name_free(ns_name, cb_args->stub->mctx);
13737 isc_mem_put(cb_args->stub->mctx, ns_name, sizeof(*ns_name));
13738 }
13739 return result;
13740 }
13741
13742 static void
13743 stub_callback(void *arg) {
13744 dns_request_t *request = (dns_request_t *)arg;
13745 struct stub_cb_args *cb_args = dns_request_getarg(request);
13746 dns_stub_t *stub = cb_args->stub;
13747 dns_message_t *msg = NULL;
13748 dns_zone_t *zone = NULL;
13749 char primary[ISC_SOCKADDR_FORMATSIZE];
13750 char source[ISC_SOCKADDR_FORMATSIZE];
13751 uint32_t nscnt, cnamecnt;
13752 isc_result_t result;
13753 isc_sockaddr_t curraddr;
13754 isc_time_t now;
13755 bool exiting = false;
13756
13757 INSIST(DNS_STUB_VALID(stub));
13758
13759 zone = stub->zone;
13760
13761 ENTER;
13762
13763 now = isc_time_now();
13764
13765 LOCK_ZONE(zone);
13766
13767 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
13768 goto exiting;
13769 }
13770
13771 curraddr = dns_remote_curraddr(&zone->primaries);
13772 isc_sockaddr_format(&curraddr, primary, sizeof(primary));
13773 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
13774
13775 result = dns_request_getresult(request);
13776 switch (result) {
13777 case ISC_R_SUCCESS:
13778 break;
13779 case ISC_R_SHUTTINGDOWN:
13780 case ISC_R_CANCELED:
13781 goto exiting;
13782 case ISC_R_TIMEDOUT:
13783 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
13784 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
13785 dns_zone_log(zone, ISC_LOG_DEBUG(1),
13786 "refreshing stub: timeout retrying "
13787 "without EDNS primary %s (source %s)",
13788 primary, source);
13789 goto same_primary;
13790 }
13791 FALLTHROUGH;
13792 default:
13793 dns_zonemgr_unreachableadd(zone->zmgr, &curraddr,
13794 &zone->sourceaddr, &now);
13795 dns_zone_log(zone, ISC_LOG_INFO,
13796 "could not refresh stub from primary "
13797 "%s (source %s): %s",
13798 primary, source, isc_result_totext(result));
13799 goto next_primary;
13800 }
13801
13802 dns_message_create(zone->mctx, NULL, NULL, DNS_MESSAGE_INTENTPARSE,
13803 &msg);
13804
13805 result = dns_request_getresponse(request, msg, 0);
13806 if (result != ISC_R_SUCCESS) {
13807 goto next_primary;
13808 }
13809
13810 /*
13811 * Unexpected opcode.
13812 */
13813 if (msg->opcode != dns_opcode_query) {
13814 char opcode[128];
13815 isc_buffer_t rb;
13816
13817 isc_buffer_init(&rb, opcode, sizeof(opcode));
13818 (void)dns_opcode_totext(msg->opcode, &rb);
13819
13820 dns_zone_log(zone, ISC_LOG_INFO,
13821 "refreshing stub: "
13822 "unexpected opcode (%.*s) from %s (source %s)",
13823 (int)rb.used, opcode, primary, source);
13824 goto next_primary;
13825 }
13826
13827 /*
13828 * Unexpected rcode.
13829 */
13830 if (msg->rcode != dns_rcode_noerror) {
13831 char rcode[128];
13832 isc_buffer_t rb;
13833
13834 isc_buffer_init(&rb, rcode, sizeof(rcode));
13835 (void)dns_rcode_totext(msg->rcode, &rb);
13836
13837 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
13838 (msg->rcode == dns_rcode_servfail ||
13839 msg->rcode == dns_rcode_notimp ||
13840 (msg->rcode == dns_rcode_formerr && msg->opt == NULL)))
13841 {
13842 dns_zone_log(zone, ISC_LOG_DEBUG(1),
13843 "refreshing stub: rcode (%.*s) retrying "
13844 "without EDNS primary %s (source %s)",
13845 (int)rb.used, rcode, primary, source);
13846 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
13847 goto same_primary;
13848 }
13849
13850 dns_zone_log(zone, ISC_LOG_INFO,
13851 "refreshing stub: "
13852 "unexpected rcode (%.*s) from %s (source %s)",
13853 (int)rb.used, rcode, primary, source);
13854 goto next_primary;
13855 }
13856
13857 /*
13858 * We need complete messages.
13859 */
13860 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
13861 if (dns_request_usedtcp(request)) {
13862 dns_zone_log(zone, ISC_LOG_INFO,
13863 "refreshing stub: truncated TCP "
13864 "response from primary %s (source %s)",
13865 primary, source);
13866 goto next_primary;
13867 }
13868 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
13869 goto same_primary;
13870 }
13871
13872 /*
13873 * If non-auth log and next primary.
13874 */
13875 if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
13876 dns_zone_log(zone, ISC_LOG_INFO,
13877 "refreshing stub: "
13878 "non-authoritative answer from "
13879 "primary %s (source %s)",
13880 primary, source);
13881 goto next_primary;
13882 }
13883
13884 /*
13885 * Sanity checks.
13886 */
13887 cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
13888 nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns);
13889
13890 if (cnamecnt != 0) {
13891 dns_zone_log(zone, ISC_LOG_INFO,
13892 "refreshing stub: unexpected CNAME response "
13893 "from primary %s (source %s)",
13894 primary, source);
13895 goto next_primary;
13896 }
13897
13898 if (nscnt == 0) {
13899 dns_zone_log(zone, ISC_LOG_INFO,
13900 "refreshing stub: no NS records in response "
13901 "from primary %s (source %s)",
13902 primary, source);
13903 goto next_primary;
13904 }
13905
13906 atomic_fetch_add(&stub->pending_requests, 1);
13907
13908 /*
13909 * Save answer.
13910 */
13911 result = save_nsrrset(msg, &zone->origin, cb_args, stub->db,
13912 stub->version);
13913 if (result != ISC_R_SUCCESS) {
13914 dns_zone_log(zone, ISC_LOG_INFO,
13915 "refreshing stub: unable to save NS records "
13916 "from primary %s (source %s)",
13917 primary, source);
13918 goto next_primary;
13919 }
13920
13921 dns_message_detach(&msg);
13922 dns_request_destroy(&zone->request);
13923
13924 /*
13925 * Check to see if there are no outstanding requests and
13926 * finish off if that is so.
13927 */
13928 if (atomic_fetch_sub(&stub->pending_requests, 1) == 1) {
13929 isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
13930 stub_finish_zone_update(stub, now);
13931 goto free_stub;
13932 }
13933
13934 UNLOCK_ZONE(zone);
13935 return;
13936
13937 exiting:
13938 zone_debuglog(zone, __func__, 1, "exiting");
13939 exiting = true;
13940
13941 next_primary:
13942 isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
13943 if (stub->version != NULL) {
13944 dns_db_closeversion(stub->db, &stub->version, false);
13945 }
13946 if (stub->db != NULL) {
13947 dns_db_detach(&stub->db);
13948 }
13949 if (msg != NULL) {
13950 dns_message_detach(&msg);
13951 }
13952 dns_request_destroy(&zone->request);
13953 /*
13954 * Skip to next failed / untried primary.
13955 */
13956 dns_remote_next(&zone->primaries, true);
13957 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
13958 if (exiting || dns_remote_done(&zone->primaries)) {
13959 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
13960 zone_settimer(zone, &now);
13961 goto free_stub;
13962 }
13963 queue_soa_query(zone);
13964 goto free_stub;
13965
13966 same_primary:
13967 isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
13968 if (msg != NULL) {
13969 dns_message_detach(&msg);
13970 }
13971 dns_request_destroy(&zone->request);
13972 ns_query(zone, NULL, stub);
13973 UNLOCK_ZONE(zone);
13974 return;
13975
13976 free_stub:
13977 UNLOCK_ZONE(zone);
13978 stub->magic = 0;
13979 dns_zone_idetach(&stub->zone);
13980 INSIST(stub->db == NULL);
13981 INSIST(stub->version == NULL);
13982 isc_mem_put(stub->mctx, stub, sizeof(*stub));
13983 }
13984
13985 /*
13986 * Get the EDNS EXPIRE option from the response and if it exists trim
13987 * expire to be not more than it.
13988 */
13989 static void
13990 get_edns_expire(dns_zone_t *zone, dns_message_t *message, uint32_t *expirep) {
13991 isc_result_t result;
13992 uint32_t expire;
13993 dns_rdata_t rdata = DNS_RDATA_INIT;
13994 isc_buffer_t optbuf;
13995 uint16_t optcode;
13996 uint16_t optlen;
13997
13998 REQUIRE(expirep != NULL);
13999 REQUIRE(message != NULL);
14000
14001 if (message->opt == NULL) {
14002 return;
14003 }
14004
14005 result = dns_rdataset_first(message->opt);
14006 if (result == ISC_R_SUCCESS) {
14007 dns_rdataset_current(message->opt, &rdata);
14008 isc_buffer_init(&optbuf, rdata.data, rdata.length);
14009 isc_buffer_add(&optbuf, rdata.length);
14010 while (isc_buffer_remaininglength(&optbuf) >= 4) {
14011 optcode = isc_buffer_getuint16(&optbuf);
14012 optlen = isc_buffer_getuint16(&optbuf);
14013 /*
14014 * A EDNS EXPIRE response has a length of 4.
14015 */
14016 if (optcode != DNS_OPT_EXPIRE || optlen != 4) {
14017 isc_buffer_forward(&optbuf, optlen);
14018 continue;
14019 }
14020 expire = isc_buffer_getuint32(&optbuf);
14021 dns_zone_log(zone, ISC_LOG_DEBUG(1),
14022 "got EDNS EXPIRE of %u", expire);
14023 /*
14024 * Trim *expirep?
14025 */
14026 if (expire < *expirep) {
14027 *expirep = expire;
14028 }
14029 break;
14030 }
14031 }
14032 }
14033
14034 /*
14035 * Set the file modification time zone->expire seconds before expiretime.
14036 */
14037 static void
14038 setmodtime(dns_zone_t *zone, isc_time_t *expiretime) {
14039 isc_result_t result;
14040 isc_time_t when;
14041 isc_interval_t i;
14042
14043 isc_interval_set(&i, zone->expire, 0);
14044 result = isc_time_subtract(expiretime, &i, &when);
14045 if (result != ISC_R_SUCCESS) {
14046 return;
14047 }
14048
14049 result = ISC_R_FAILURE;
14050 if (zone->journal != NULL) {
14051 result = isc_file_settime(zone->journal, &when);
14052 }
14053 if (result == ISC_R_SUCCESS &&
14054 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
14055 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
14056 {
14057 result = isc_file_settime(zone->masterfile, &when);
14058 } else if (result != ISC_R_SUCCESS) {
14059 result = isc_file_settime(zone->masterfile, &when);
14060 }
14061
14062 /*
14063 * Someone removed the file from underneath us!
14064 */
14065 if (result == ISC_R_FILENOTFOUND) {
14066 zone_needdump(zone, DNS_DUMP_DELAY);
14067 } else if (result != ISC_R_SUCCESS) {
14068 dns_zone_log(zone, ISC_LOG_ERROR,
14069 "refresh: could not set "
14070 "file modification time of '%s': %s",
14071 zone->masterfile, isc_result_totext(result));
14072 }
14073 }
14074
14075 /*
14076 * An SOA query has finished (successfully or not).
14077 */
14078 static void
14079 refresh_callback(void *arg) {
14080 dns_request_t *request = (dns_request_t *)arg;
14081 dns_zone_t *zone = dns_request_getarg(request);
14082 dns_message_t *msg = NULL;
14083 uint32_t soacnt, cnamecnt, soacount, nscount;
14084 isc_time_t now;
14085 char primary[ISC_SOCKADDR_FORMATSIZE];
14086 char source[ISC_SOCKADDR_FORMATSIZE];
14087 dns_rdataset_t *rdataset = NULL;
14088 dns_rdata_t rdata = DNS_RDATA_INIT;
14089 dns_rdata_soa_t soa;
14090 isc_result_t result;
14091 const isc_result_t eresult = dns_request_getresult(request);
14092 isc_sockaddr_t curraddr;
14093 uint32_t serial, oldserial = 0;
14094 bool do_queue_xfrin = false;
14095
14096 INSIST(DNS_ZONE_VALID(zone));
14097
14098 ENTER;
14099
14100 if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
14101 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(3),
14102 "refresh: request result: %s",
14103 isc_result_totext(eresult));
14104 }
14105
14106 now = isc_time_now();
14107
14108 LOCK_ZONE(zone);
14109
14110 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
14111 goto exiting;
14112 }
14113
14114 /*
14115 * If timeout, log and try the next primary
14116 */
14117 curraddr = dns_remote_curraddr(&zone->primaries);
14118 isc_sockaddr_format(&curraddr, primary, sizeof(primary));
14119 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
14120
14121 switch (eresult) {
14122 case ISC_R_SUCCESS:
14123 break;
14124 case ISC_R_SHUTTINGDOWN:
14125 case ISC_R_CANCELED:
14126 goto exiting;
14127 case ISC_R_TIMEDOUT:
14128 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
14129 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
14130 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
14131 ISC_LOG_DEBUG(1),
14132 "refresh: timeout retrying without EDNS "
14133 "primary %s (source %s)",
14134 primary, source);
14135 goto same_primary;
14136 } else if (!dns_request_usedtcp(request)) {
14137 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
14138 ISC_LOG_INFO,
14139 "refresh: retry limit for "
14140 "primary %s exceeded (source %s)",
14141 primary, source);
14142 /* Try with secondary with TCP. */
14143 if ((zone->type == dns_zone_secondary ||
14144 zone->type == dns_zone_mirror ||
14145 zone->type == dns_zone_redirect) &&
14146 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH))
14147 {
14148 if (!dns_zonemgr_unreachable(
14149 zone->zmgr, &curraddr,
14150 &zone->sourceaddr, &now))
14151 {
14152 DNS_ZONE_SETFLAG(
14153 zone,
14154 DNS_ZONEFLG_SOABEFOREAXFR);
14155 goto tcp_transfer;
14156 }
14157 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
14158 ISC_LOG_DEBUG(1),
14159 "refresh: skipped tcp fallback "
14160 "as primary %s (source %s) is "
14161 "unreachable (cached)",
14162 primary, source);
14163 }
14164 goto next_primary;
14165 }
14166 FALLTHROUGH;
14167 default:
14168 result = eresult;
14169 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
14170 "refresh: failure trying primary "
14171 "%s (source %s): %s",
14172 primary, source, isc_result_totext(result));
14173 goto next_primary;
14174 }
14175
14176 dns_message_create(zone->mctx, NULL, NULL, DNS_MESSAGE_INTENTPARSE,
14177 &msg);
14178 result = dns_request_getresponse(request, msg, 0);
14179 if (result != ISC_R_SUCCESS) {
14180 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
14181 "refresh: failure trying primary "
14182 "%s (source %s): %s",
14183 primary, source, isc_result_totext(result));
14184 goto next_primary;
14185 }
14186
14187 /*
14188 * Unexpected opcode.
14189 */
14190 if (msg->opcode != dns_opcode_query) {
14191 char opcode[128];
14192 isc_buffer_t rb;
14193
14194 isc_buffer_init(&rb, opcode, sizeof(opcode));
14195 (void)dns_opcode_totext(msg->opcode, &rb);
14196
14197 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
14198 "refresh: "
14199 "unexpected opcode (%.*s) from %s (source %s)",
14200 (int)rb.used, opcode, primary, source);
14201 goto next_primary;
14202 }
14203
14204 /*
14205 * Unexpected rcode.
14206 */
14207 if (msg->rcode != dns_rcode_noerror) {
14208 char rcode[128];
14209 isc_buffer_t rb;
14210
14211 isc_buffer_init(&rb, rcode, sizeof(rcode));
14212 (void)dns_rcode_totext(msg->rcode, &rb);
14213
14214 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
14215 (msg->rcode == dns_rcode_servfail ||
14216 msg->rcode == dns_rcode_notimp ||
14217 (msg->rcode == dns_rcode_formerr && msg->opt == NULL)))
14218 {
14219 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
14220 ISC_LOG_DEBUG(1),
14221 "refresh: rcode (%.*s) retrying without "
14222 "EDNS primary %s (source %s)",
14223 (int)rb.used, rcode, primary, source);
14224 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
14225 goto same_primary;
14226 }
14227 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
14228 msg->rcode == dns_rcode_badvers)
14229 {
14230 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
14231 ISC_LOG_DEBUG(1),
14232 "refresh: rcode (%.*s) retrying without "
14233 "EDNS EXPIRE OPTION primary %s "
14234 "(source %s)",
14235 (int)rb.used, rcode, primary, source);
14236 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
14237 goto same_primary;
14238 }
14239 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
14240 "refresh: unexpected rcode (%.*s) from "
14241 "primary %s (source %s)",
14242 (int)rb.used, rcode, primary, source);
14243 /*
14244 * Perhaps AXFR/IXFR is allowed even if SOA queries aren't.
14245 */
14246 if (msg->rcode == dns_rcode_refused &&
14247 (zone->type == dns_zone_secondary ||
14248 zone->type == dns_zone_mirror ||
14249 zone->type == dns_zone_redirect))
14250 {
14251 goto tcp_transfer;
14252 }
14253 goto next_primary;
14254 }
14255
14256 /*
14257 * If truncated punt to zone transfer which will query again.
14258 */
14259 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
14260 if (zone->type == dns_zone_secondary ||
14261 zone->type == dns_zone_mirror ||
14262 zone->type == dns_zone_redirect)
14263 {
14264 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
14265 ISC_LOG_INFO,
14266 "refresh: truncated UDP answer, "
14267 "initiating TCP zone xfer "
14268 "for primary %s (source %s)",
14269 primary, source);
14270 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
14271 goto tcp_transfer;
14272 } else {
14273 INSIST(zone->type == dns_zone_stub);
14274 if (dns_request_usedtcp(request)) {
14275 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
14276 ISC_LOG_INFO,
14277 "refresh: truncated TCP response "
14278 "from primary %s (source %s)",
14279 primary, source);
14280 goto next_primary;
14281 }
14282 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
14283 goto same_primary;
14284 }
14285 }
14286
14287 /*
14288 * If non-auth, log and try the next primary
14289 */
14290 if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
14291 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
14292 "refresh: non-authoritative answer from "
14293 "primary %s (source %s)",
14294 primary, source);
14295 goto next_primary;
14296 }
14297
14298 cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
14299 soacnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_soa);
14300 nscount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_ns);
14301 soacount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_soa);
14302
14303 /*
14304 * There should not be a CNAME record at top of zone.
14305 */
14306 if (cnamecnt != 0) {
14307 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
14308 "refresh: CNAME at top of zone "
14309 "in primary %s (source %s)",
14310 primary, source);
14311 goto next_primary;
14312 }
14313
14314 /*
14315 * If referral, log and try the next primary;
14316 */
14317 if (soacnt == 0 && soacount == 0 && nscount != 0) {
14318 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
14319 "refresh: referral response "
14320 "from primary %s (source %s)",
14321 primary, source);
14322 goto next_primary;
14323 }
14324
14325 /*
14326 * If nodata, log and try the next primary;
14327 */
14328 if (soacnt == 0 && (nscount == 0 || soacount != 0)) {
14329 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
14330 "refresh: NODATA response "
14331 "from primary %s (source %s)",
14332 primary, source);
14333 goto next_primary;
14334 }
14335
14336 /*
14337 * Only one soa at top of zone.
14338 */
14339 if (soacnt != 1) {
14340 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
14341 "refresh: answer SOA count (%d) != 1 "
14342 "from primary %s (source %s)",
14343 soacnt, primary, source);
14344 goto next_primary;
14345 }
14346
14347 /*
14348 * Extract serial
14349 */
14350 rdataset = NULL;
14351 result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin,
14352 dns_rdatatype_soa, dns_rdatatype_none,
14353 NULL, &rdataset);
14354 if (result != ISC_R_SUCCESS) {
14355 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
14356 "refresh: unable to get SOA record "
14357 "from primary %s (source %s)",
14358 primary, source);
14359 goto next_primary;
14360 }
14361
14362 result = dns_rdataset_first(rdataset);
14363 if (result != ISC_R_SUCCESS) {
14364 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
14365 "refresh: dns_rdataset_first() failed");
14366 goto next_primary;
14367 }
14368
14369 dns_rdataset_current(rdataset, &rdata);
14370 result = dns_rdata_tostruct(&rdata, &soa, NULL);
14371 RUNTIME_CHECK(result == ISC_R_SUCCESS);
14372
14373 serial = soa.serial;
14374 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
14375 unsigned int dbsoacount;
14376 result = zone_get_from_db(zone, zone->db, NULL, &dbsoacount,
14377 NULL, &oldserial, NULL, NULL, NULL,
14378 NULL, NULL);
14379 RUNTIME_CHECK(result == ISC_R_SUCCESS);
14380 RUNTIME_CHECK(dbsoacount > 0U);
14381 zone_debuglogc(zone, DNS_LOGCATEGORY_XFER_IN, __func__, 1,
14382 "serial: new %u, old %u", serial, oldserial);
14383 } else {
14384 zone_debuglogc(zone, DNS_LOGCATEGORY_XFER_IN, __func__, 1,
14385 "serial: new %u, old not loaded", serial);
14386 }
14387
14388 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
14389 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
14390 isc_serial_gt(serial, oldserial))
14391 {
14392 if (dns_zonemgr_unreachable(zone->zmgr, &curraddr,
14393 &zone->sourceaddr, &now))
14394 {
14395 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
14396 ISC_LOG_INFO,
14397 "refresh: skipping %s as primary %s "
14398 "(source %s) is unreachable (cached)",
14399 (zone->type == dns_zone_secondary ||
14400 zone->type == dns_zone_mirror ||
14401 zone->type == dns_zone_redirect)
14402 ? "zone transfer"
14403 : "NS query",
14404 primary, source);
14405 goto next_primary;
14406 }
14407 tcp_transfer:
14408 dns_request_destroy(&zone->request);
14409 if (zone->type == dns_zone_secondary ||
14410 zone->type == dns_zone_mirror ||
14411 zone->type == dns_zone_redirect)
14412 {
14413 do_queue_xfrin = true;
14414 } else {
14415 INSIST(zone->type == dns_zone_stub);
14416 ns_query(zone, rdataset, NULL);
14417 }
14418 if (msg != NULL) {
14419 dns_message_detach(&msg);
14420 }
14421 } else if (isc_serial_eq(soa.serial, oldserial)) {
14422 isc_time_t expiretime;
14423 uint32_t expire;
14424
14425 /*
14426 * Compute the new expire time based on this response.
14427 */
14428 expire = zone->expire;
14429 get_edns_expire(zone, msg, &expire);
14430 DNS_ZONE_TIME_ADD(&now, expire, &expiretime);
14431
14432 /*
14433 * Has the expire time improved?
14434 */
14435 if (isc_time_compare(&expiretime, &zone->expiretime) > 0) {
14436 zone->expiretime = expiretime;
14437 if (zone->masterfile != NULL) {
14438 setmodtime(zone, &expiretime);
14439 }
14440 }
14441
14442 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
14443 dns_remote_mark(&zone->primaries, true);
14444 goto next_primary;
14445 } else {
14446 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER)) {
14447 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
14448 ISC_LOG_INFO,
14449 "serial number (%u) "
14450 "received from primary %s < ours (%u)",
14451 soa.serial, primary, oldserial);
14452 } else {
14453 zone_debuglogc(zone, DNS_LOGCATEGORY_XFER_IN, __func__,
14454 1, "ahead");
14455 }
14456 dns_remote_mark(&zone->primaries, true);
14457 goto next_primary;
14458 }
14459 if (msg != NULL) {
14460 dns_message_detach(&msg);
14461 }
14462 goto detach;
14463
14464 next_primary:
14465 if (msg != NULL) {
14466 dns_message_detach(&msg);
14467 }
14468 dns_request_destroy(&zone->request);
14469 /*
14470 * Skip to next failed / untried primary.
14471 */
14472 dns_remote_next(&zone->primaries, true);
14473 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
14474 if (dns_remote_done(&zone->primaries)) {
14475 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
14476 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
14477 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
14478 zone->refreshtime = now;
14479 }
14480 zone_settimer(zone, &now);
14481 goto detach;
14482 }
14483
14484 queue_soa_query(zone);
14485 goto detach;
14486
14487 exiting:
14488 /*
14489 * We can get here not only during shutdown, but also when the refresh
14490 * is canceled during reconfiguration. In that case, make sure to clear
14491 * the DNS_ZONEFLG_REFRESH flag so that future zone refreshes don't get
14492 * stuck, and make sure a new refresh attempt is made again soon after
14493 * the reconfiguration is complete.
14494 */
14495 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
14496 zone->refreshtime = now;
14497 zone_settimer(zone, &now);
14498
14499 dns_request_destroy(&zone->request);
14500 goto detach;
14501
14502 same_primary:
14503 if (msg != NULL) {
14504 dns_message_detach(&msg);
14505 }
14506 dns_request_destroy(&zone->request);
14507 queue_soa_query(zone);
14508
14509 detach:
14510 if (do_queue_xfrin) {
14511 /* Shows in the statistics channel the duration of the step. */
14512 zone->xfrintime = isc_time_now();
14513 }
14514 UNLOCK_ZONE(zone);
14515 if (do_queue_xfrin) {
14516 queue_xfrin(zone);
14517 }
14518 dns_zone_idetach(&zone);
14519 return;
14520 }
14521
14522 struct soaquery {
14523 dns_zone_t *zone;
14524 isc_rlevent_t *rlevent;
14525 };
14526
14527 static void
14528 queue_soa_query(dns_zone_t *zone) {
14529 isc_result_t result;
14530 struct soaquery *sq = NULL;
14531
14532 ENTER;
14533 /*
14534 * Locked by caller
14535 */
14536 REQUIRE(LOCKED_ZONE(zone));
14537
14538 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
14539 cancel_refresh(zone);
14540 return;
14541 }
14542
14543 sq = isc_mem_get(zone->mctx, sizeof(*sq));
14544 *sq = (struct soaquery){ .zone = NULL };
14545
14546 /* Shows in the statistics channel the duration of the current step. */
14547 zone->xfrintime = isc_time_now();
14548
14549 /*
14550 * Attach so that we won't clean up until the event is delivered.
14551 */
14552 zone_iattach(zone, &sq->zone);
14553 result = isc_ratelimiter_enqueue(zone->zmgr->refreshrl, zone->loop,
14554 soa_query, sq, &sq->rlevent);
14555 if (result != ISC_R_SUCCESS) {
14556 zone_idetach(&sq->zone);
14557 isc_mem_put(zone->mctx, sq, sizeof(*sq));
14558 cancel_refresh(zone);
14559 }
14560 }
14561
14562 static void
14563 soa_query(void *arg) {
14564 struct soaquery *sq = (struct soaquery *)arg;
14565 dns_zone_t *zone = sq->zone;
14566 isc_result_t result = ISC_R_FAILURE;
14567 dns_message_t *message = NULL;
14568 isc_netaddr_t primaryip;
14569 dns_tsigkey_t *key = NULL;
14570 dns_transport_t *transport = NULL;
14571 uint32_t options;
14572 bool cancel = true;
14573 int timeout;
14574 bool have_xfrsource = false, reqnsid, reqexpire;
14575 uint16_t udpsize = SEND_BUFFER_SIZE;
14576 isc_sockaddr_t curraddr, sourceaddr;
14577 bool do_queue_xfrin = false;
14578
14579 REQUIRE(DNS_ZONE_VALID(zone));
14580
14581 ENTER;
14582
14583 LOCK_ZONE(zone);
14584 if (sq->rlevent->canceled || DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
14585 zone->view->requestmgr == NULL)
14586 {
14587 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
14588 cancel = false;
14589 }
14590 goto cleanup;
14591 }
14592
14593 again:
14594 dns_zone_logc(
14595 zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(3),
14596 "soa_query: remote server current address index %d count %d",
14597 zone->primaries.curraddr, zone->primaries.addrcnt);
14598 INSIST(dns_remote_count(&zone->primaries) > 0);
14599 INSIST(!dns_remote_done(&zone->primaries));
14600
14601 sourceaddr = dns_remote_sourceaddr(&zone->primaries);
14602 curraddr = dns_remote_curraddr(&zone->primaries);
14603 isc_netaddr_fromsockaddr(&primaryip, &curraddr);
14604
14605 if (isc_sockaddr_disabled(&curraddr)) {
14606 goto skip_primary;
14607 }
14608
14609 /*
14610 * First, look for a tsig key in the primaries statement, then
14611 * try for a server key.
14612 */
14613 if (dns_remote_keyname(&zone->primaries) != NULL) {
14614 dns_view_t *view = dns_zone_getview(zone);
14615 dns_name_t *keyname = dns_remote_keyname(&zone->primaries);
14616 result = dns_view_gettsig(view, keyname, &key);
14617 if (result != ISC_R_SUCCESS) {
14618 char namebuf[DNS_NAME_FORMATSIZE];
14619 dns_name_format(keyname, namebuf, sizeof(namebuf));
14620 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
14621 ISC_LOG_ERROR, "unable to find key: %s",
14622 namebuf);
14623 goto skip_primary;
14624 }
14625 }
14626 if (key == NULL) {
14627 result = dns_view_getpeertsig(zone->view, &primaryip, &key);
14628 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
14629 char addrbuf[ISC_NETADDR_FORMATSIZE];
14630 isc_netaddr_format(&primaryip, addrbuf,
14631 sizeof(addrbuf));
14632 dns_zone_logc(
14633 zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
14634 "unable to find TSIG key for %s", addrbuf);
14635 goto skip_primary;
14636 }
14637 }
14638
14639 if (dns_remote_tlsname(&zone->primaries) != NULL) {
14640 dns_view_t *view = dns_zone_getview(zone);
14641 dns_name_t *tlsname = dns_remote_tlsname(&zone->primaries);
14642 result = dns_view_gettransport(view, DNS_TRANSPORT_TLS, tlsname,
14643 &transport);
14644 if (result != ISC_R_SUCCESS) {
14645 char namebuf[DNS_NAME_FORMATSIZE];
14646 dns_name_format(tlsname, namebuf, sizeof(namebuf));
14647 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
14648 ISC_LOG_ERROR,
14649 "unable to find TLS configuration: %s",
14650 namebuf);
14651 goto skip_primary;
14652 }
14653 }
14654
14655 options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ? DNS_REQUESTOPT_TCP
14656 : 0;
14657 reqnsid = zone->view->requestnsid;
14658 reqexpire = zone->requestexpire;
14659 if (zone->view->peers != NULL) {
14660 dns_peer_t *peer = NULL;
14661 bool edns, usetcp;
14662 result = dns_peerlist_peerbyaddr(zone->view->peers, &primaryip,
14663 &peer);
14664 if (result == ISC_R_SUCCESS) {
14665 result = dns_peer_getsupportedns(peer, &edns);
14666 if (result == ISC_R_SUCCESS && !edns) {
14667 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
14668 }
14669 result = dns_peer_gettransfersource(peer,
14670 &zone->sourceaddr);
14671 if (result == ISC_R_SUCCESS) {
14672 have_xfrsource = true;
14673 }
14674 udpsize = dns_view_getudpsize(zone->view);
14675 (void)dns_peer_getudpsize(peer, &udpsize);
14676 (void)dns_peer_getrequestnsid(peer, &reqnsid);
14677 (void)dns_peer_getrequestexpire(peer, &reqexpire);
14678 result = dns_peer_getforcetcp(peer, &usetcp);
14679 if (result == ISC_R_SUCCESS && usetcp) {
14680 options |= DNS_REQUESTOPT_TCP;
14681 }
14682 }
14683 }
14684
14685 switch (isc_sockaddr_pf(&curraddr)) {
14686 case PF_INET:
14687 if (!have_xfrsource) {
14688 isc_sockaddr_t any;
14689 isc_sockaddr_any(&any);
14690
14691 zone->sourceaddr = sourceaddr;
14692 if (isc_sockaddr_equal(&sourceaddr, &any)) {
14693 zone->sourceaddr = zone->xfrsource4;
14694 }
14695 }
14696 break;
14697 case PF_INET6:
14698 if (!have_xfrsource) {
14699 isc_sockaddr_t any;
14700 isc_sockaddr_any6(&any);
14701
14702 zone->sourceaddr = sourceaddr;
14703 if (isc_sockaddr_equal(&zone->sourceaddr, &any)) {
14704 zone->sourceaddr = zone->xfrsource6;
14705 }
14706 }
14707 break;
14708 default:
14709 result = ISC_R_NOTIMPLEMENTED;
14710 goto cleanup;
14711 }
14712
14713 /*
14714 * FIXME(OS): This is a bit hackish, but it enforces the SOA query to go
14715 * through the XFR channel instead of doing dns_request that doesn't
14716 * have DoT support yet.
14717 */
14718 if (transport != NULL) {
14719 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
14720 do_queue_xfrin = true;
14721 cancel = false;
14722 result = ISC_R_SUCCESS;
14723 goto cleanup;
14724 }
14725
14726 create_query(zone, dns_rdatatype_soa, &zone->origin, &message);
14727
14728 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
14729 result = add_opt(message, udpsize, reqnsid, reqexpire);
14730 if (result != ISC_R_SUCCESS) {
14731 zone_debuglogc(zone, DNS_LOGCATEGORY_XFER_IN, __func__,
14732 1, "unable to add opt record: %s",
14733 isc_result_totext(result));
14734 }
14735 }
14736
14737 zone_iattach(zone, &(dns_zone_t *){ NULL });
14738 timeout = 5;
14739 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH)) {
14740 timeout = 30;
14741 }
14742 result = dns_request_create(
14743 zone->view->requestmgr, message, &zone->sourceaddr, &curraddr,
14744 NULL, NULL, options, key, timeout * 3 + 1, timeout, 2,
14745 zone->loop, refresh_callback, zone, &zone->request);
14746 if (result != ISC_R_SUCCESS) {
14747 zone_idetach(&(dns_zone_t *){ zone });
14748 zone_debuglogc(zone, DNS_LOGCATEGORY_XFER_IN, __func__, 1,
14749 "dns_request_create() failed: %s",
14750 isc_result_totext(result));
14751 goto skip_primary;
14752 } else {
14753 /* Shows in the statistics channel the duration of the query. */
14754 zone->xfrintime = isc_time_now();
14755
14756 if (isc_sockaddr_pf(&curraddr) == PF_INET) {
14757 inc_stats(zone, dns_zonestatscounter_soaoutv4);
14758 } else {
14759 inc_stats(zone, dns_zonestatscounter_soaoutv6);
14760 }
14761 }
14762 cancel = false;
14763 cleanup:
14764 if (transport != NULL) {
14765 dns_transport_detach(&transport);
14766 }
14767 if (key != NULL) {
14768 dns_tsigkey_detach(&key);
14769 }
14770 if (result != ISC_R_SUCCESS) {
14771 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
14772 }
14773 if (message != NULL) {
14774 dns_message_detach(&message);
14775 }
14776 if (cancel) {
14777 cancel_refresh(zone);
14778 }
14779 if (do_queue_xfrin) {
14780 /* Shows in the statistics channel the duration of the step. */
14781 zone->xfrintime = isc_time_now();
14782 }
14783 UNLOCK_ZONE(zone);
14784 if (do_queue_xfrin) {
14785 queue_xfrin(zone);
14786 }
14787 isc_rlevent_free(&sq->rlevent);
14788 isc_mem_put(zone->mctx, sq, sizeof(*sq));
14789 dns_zone_idetach(&zone);
14790 return;
14791
14792 skip_primary:
14793 if (transport != NULL) {
14794 dns_transport_detach(&transport);
14795 }
14796 if (key != NULL) {
14797 dns_tsigkey_detach(&key);
14798 }
14799 if (message != NULL) {
14800 dns_message_detach(&message);
14801 }
14802 /*
14803 * Skip to next failed / untried primary.
14804 */
14805 dns_remote_next(&zone->primaries, true);
14806 if (!dns_remote_done(&zone->primaries)) {
14807 goto again;
14808 }
14809 dns_remote_reset(&zone->primaries, false);
14810 goto cleanup;
14811 }
14812
14813 static void
14814 ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
14815 isc_result_t result;
14816 dns_message_t *message = NULL;
14817 isc_netaddr_t primaryip;
14818 dns_tsigkey_t *key = NULL;
14819 dns_dbnode_t *node = NULL;
14820 int timeout;
14821 bool have_xfrsource = false;
14822 bool reqnsid;
14823 uint16_t udpsize = SEND_BUFFER_SIZE;
14824 isc_sockaddr_t curraddr, sourceaddr;
14825 struct stub_cb_args *cb_args;
14826
14827 REQUIRE(DNS_ZONE_VALID(zone));
14828 REQUIRE(LOCKED_ZONE(zone));
14829 REQUIRE((soardataset != NULL && stub == NULL) ||
14830 (soardataset == NULL && stub != NULL));
14831 REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
14832
14833 ENTER;
14834
14835 if (stub == NULL) {
14836 stub = isc_mem_get(zone->mctx, sizeof(*stub));
14837 stub->magic = STUB_MAGIC;
14838 stub->mctx = zone->mctx;
14839 stub->zone = NULL;
14840 stub->db = NULL;
14841 stub->version = NULL;
14842 atomic_init(&stub->pending_requests, 0);
14843
14844 /*
14845 * Attach so that the zone won't disappear from under us.
14846 */
14847 zone_iattach(zone, &stub->zone);
14848
14849 /*
14850 * If a db exists we will update it, otherwise we create a
14851 * new one and attach it to the zone once we have the NS
14852 * RRset and glue.
14853 */
14854 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
14855 if (zone->db != NULL) {
14856 dns_db_attach(zone->db, &stub->db);
14857 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
14858 } else {
14859 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
14860
14861 INSIST(zone->db_argc >= 1);
14862 result = dns_db_create(zone->mctx, zone->db_argv[0],
14863 &zone->origin, dns_dbtype_stub,
14864 zone->rdclass, zone->db_argc - 1,
14865 zone->db_argv + 1, &stub->db);
14866 if (result != ISC_R_SUCCESS) {
14867 dns_zone_log(zone, ISC_LOG_ERROR,
14868 "refreshing stub: "
14869 "could not create "
14870 "database: %s",
14871 isc_result_totext(result));
14872 goto cleanup;
14873 }
14874 dns_db_setloop(stub->db, zone->loop);
14875 dns_db_setmaxrrperset(stub->db, zone->maxrrperset);
14876 dns_db_setmaxtypepername(stub->db,
14877 zone->maxtypepername);
14878 }
14879
14880 result = dns_db_newversion(stub->db, &stub->version);
14881 if (result != ISC_R_SUCCESS) {
14882 dns_zone_log(zone, ISC_LOG_INFO,
14883 "refreshing stub: "
14884 "dns_db_newversion() failed: %s",
14885 isc_result_totext(result));
14886 goto cleanup;
14887 }
14888
14889 /*
14890 * Update SOA record.
14891 */
14892 result = dns_db_findnode(stub->db, &zone->origin, true, &node);
14893 if (result != ISC_R_SUCCESS) {
14894 dns_zone_log(zone, ISC_LOG_INFO,
14895 "refreshing stub: "
14896 "dns_db_findnode() failed: %s",
14897 isc_result_totext(result));
14898 goto cleanup;
14899 }
14900
14901 result = dns_db_addrdataset(stub->db, node, stub->version, 0,
14902 soardataset, 0, NULL);
14903 dns_db_detachnode(stub->db, &node);
14904 if (result != ISC_R_SUCCESS) {
14905 dns_zone_log(zone, ISC_LOG_INFO,
14906 "refreshing stub: "
14907 "dns_db_addrdataset() failed: %s",
14908 isc_result_totext(result));
14909 goto cleanup;
14910 }
14911 }
14912
14913 /*
14914 * XXX Optimisation: Create message when zone is setup and reuse.
14915 */
14916 create_query(zone, dns_rdatatype_ns, &zone->origin, &message);
14917
14918 INSIST(dns_remote_count(&zone->primaries) > 0);
14919 INSIST(!dns_remote_done(&zone->primaries));
14920
14921 sourceaddr = dns_remote_sourceaddr(&zone->primaries);
14922 curraddr = dns_remote_curraddr(&zone->primaries);
14923 isc_netaddr_fromsockaddr(&primaryip, &curraddr);
14924 /*
14925 * First, look for a tsig key in the primaries statement, then
14926 * try for a server key.
14927 */
14928 if (dns_remote_keyname(&zone->primaries) != NULL) {
14929 dns_view_t *view = dns_zone_getview(zone);
14930 dns_name_t *keyname = dns_remote_keyname(&zone->primaries);
14931 result = dns_view_gettsig(view, keyname, &key);
14932 if (result != ISC_R_SUCCESS) {
14933 char namebuf[DNS_NAME_FORMATSIZE];
14934 dns_name_format(keyname, namebuf, sizeof(namebuf));
14935 dns_zone_log(zone, ISC_LOG_ERROR,
14936 "unable to find key: %s", namebuf);
14937 }
14938 }
14939 if (key == NULL) {
14940 (void)dns_view_getpeertsig(zone->view, &primaryip, &key);
14941 }
14942
14943 /* FIXME(OS): Do we need the transport here too? Most probably yes */
14944
14945 reqnsid = zone->view->requestnsid;
14946 if (zone->view->peers != NULL) {
14947 dns_peer_t *peer = NULL;
14948 bool edns;
14949 result = dns_peerlist_peerbyaddr(zone->view->peers, &primaryip,
14950 &peer);
14951 if (result == ISC_R_SUCCESS) {
14952 result = dns_peer_getsupportedns(peer, &edns);
14953 if (result == ISC_R_SUCCESS && !edns) {
14954 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
14955 }
14956 result = dns_peer_gettransfersource(peer,
14957 &zone->sourceaddr);
14958 if (result == ISC_R_SUCCESS) {
14959 have_xfrsource = true;
14960 }
14961 udpsize = dns_view_getudpsize(zone->view);
14962 (void)dns_peer_getudpsize(peer, &udpsize);
14963 (void)dns_peer_getrequestnsid(peer, &reqnsid);
14964 }
14965 }
14966 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
14967 result = add_opt(message, udpsize, reqnsid, false);
14968 if (result != ISC_R_SUCCESS) {
14969 zone_debuglog(zone, __func__, 1,
14970 "unable to add opt record: %s",
14971 isc_result_totext(result));
14972 }
14973 }
14974
14975 /*
14976 * Always use TCP so that we shouldn't truncate in additional section.
14977 */
14978 switch (isc_sockaddr_pf(&curraddr)) {
14979 case PF_INET:
14980 if (!have_xfrsource) {
14981 isc_sockaddr_t any;
14982 isc_sockaddr_any(&any);
14983
14984 zone->sourceaddr = sourceaddr;
14985 if (isc_sockaddr_equal(&zone->sourceaddr, &any)) {
14986 zone->sourceaddr = zone->xfrsource4;
14987 }
14988 }
14989 break;
14990 case PF_INET6:
14991 if (!have_xfrsource) {
14992 isc_sockaddr_t any;
14993 isc_sockaddr_any6(&any);
14994
14995 zone->sourceaddr = sourceaddr;
14996 if (isc_sockaddr_equal(&zone->sourceaddr, &any)) {
14997 zone->sourceaddr = zone->xfrsource6;
14998 }
14999 }
15000 break;
15001 default:
15002 result = ISC_R_NOTIMPLEMENTED;
15003 POST(result);
15004 goto cleanup;
15005 }
15006 timeout = 5;
15007 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH)) {
15008 timeout = 30;
15009 }
15010
15011 /*
15012 * Save request parameters so we can reuse them later on
15013 * for resolving missing glue A/AAAA records.
15014 */
15015 cb_args = isc_mem_get(zone->mctx, sizeof(*cb_args));
15016 cb_args->stub = stub;
15017 cb_args->tsig_key = key;
15018 cb_args->udpsize = udpsize;
15019 cb_args->timeout = timeout;
15020 cb_args->reqnsid = reqnsid;
15021
15022 result = dns_request_create(
15023 zone->view->requestmgr, message, &zone->sourceaddr, &curraddr,
15024 NULL, NULL, DNS_REQUESTOPT_TCP, key, timeout * 3 + 1, timeout,
15025 2, zone->loop, stub_callback, cb_args, &zone->request);
15026 if (result != ISC_R_SUCCESS) {
15027 zone_debuglog(zone, __func__, 1,
15028 "dns_request_create() failed: %s",
15029 isc_result_totext(result));
15030 goto cleanup;
15031 }
15032 dns_message_detach(&message);
15033 goto unlock;
15034
15035 cleanup:
15036 cancel_refresh(zone);
15037 stub->magic = 0;
15038 if (stub->version != NULL) {
15039 dns_db_closeversion(stub->db, &stub->version, false);
15040 }
15041 if (stub->db != NULL) {
15042 dns_db_detach(&stub->db);
15043 }
15044 if (stub->zone != NULL) {
15045 zone_idetach(&stub->zone);
15046 }
15047 isc_mem_put(stub->mctx, stub, sizeof(*stub));
15048 if (message != NULL) {
15049 dns_message_detach(&message);
15050 }
15051 unlock:
15052 if (key != NULL) {
15053 dns_tsigkey_detach(&key);
15054 }
15055 return;
15056 }
15057
15058 /*
15059 * Shut the zone down.
15060 */
15061 static void
15062 zone_shutdown(void *arg) {
15063 dns_zone_t *zone = (dns_zone_t *)arg;
15064 bool free_needed, linked = false;
15065 dns_zone_t *raw = NULL, *secure = NULL;
15066 dns_view_t *view = NULL, *prev_view = NULL;
15067
15068 REQUIRE(DNS_ZONE_VALID(zone));
15069 INSIST(isc_refcount_current(&zone->references) == 0);
15070
15071 zone_debuglog(zone, __func__, 3, "shutting down");
15072
15073 /*
15074 * If we were waiting for xfrin quota, step out of
15075 * the queue.
15076 * If there's no zone manager, we can't be waiting for the
15077 * xfrin quota
15078 */
15079 if (zone->zmgr != NULL) {
15080 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
15081 if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
15082 ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone,
15083 statelink);
15084 linked = true;
15085 zone->statelist = NULL;
15086 }
15087 if (zone->statelist == &zone->zmgr->xfrin_in_progress) {
15088 ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone,
15089 statelink);
15090 zone->statelist = NULL;
15091 zmgr_resume_xfrs(zone->zmgr, false);
15092 }
15093 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
15094 }
15095
15096 /*
15097 * In loop context, no locking required. See zone_xfrdone().
15098 */
15099 if (zone->xfr != NULL) {
15100 /* The final detach will happen in zone_xfrdone() */
15101 dns_xfrin_shutdown(zone->xfr);
15102 }
15103
15104 /* Safe to release the zone now */
15105 if (zone->zmgr != NULL) {
15106 dns_zonemgr_releasezone(zone->zmgr, zone);
15107 }
15108
15109 LOCK_ZONE(zone);
15110 INSIST(zone != zone->raw);
15111
15112 /*
15113 * Detach the views early, we don't need them anymore. However, we need
15114 * to detach them outside of the zone lock to break the lock loop
15115 * between view, adb and zone locks.
15116 */
15117 view = zone->view;
15118 zone->view = NULL;
15119 prev_view = zone->prev_view;
15120 zone->prev_view = NULL;
15121
15122 if (linked) {
15123 isc_refcount_decrement(&zone->irefs);
15124 }
15125 if (zone->request != NULL) {
15126 dns_request_cancel(zone->request);
15127 }
15128
15129 if (zone->loadctx != NULL) {
15130 dns_loadctx_cancel(zone->loadctx);
15131 }
15132
15133 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
15134 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
15135 {
15136 if (zone->dumpctx != NULL) {
15137 dns_dumpctx_cancel(zone->dumpctx);
15138 }
15139 }
15140
15141 checkds_cancel(zone);
15142
15143 notify_cancel(zone);
15144
15145 forward_cancel(zone);
15146
15147 if (zone->timer != NULL) {
15148 isc_refcount_decrement(&zone->irefs);
15149 isc_timer_destroy(&zone->timer);
15150 }
15151
15152 /*
15153 * We have now canceled everything set the flag to allow exit_check()
15154 * to succeed. We must not unlock between setting this flag and
15155 * calling exit_check().
15156 */
15157 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN);
15158 free_needed = exit_check(zone);
15159 /*
15160 * If a dump is in progress for the secure zone, defer detaching from
15161 * the raw zone as it may prevent the unsigned serial number from being
15162 * stored in the raw-format dump of the secure zone. In this scenario,
15163 * dump_done() takes care of cleaning up the zone->raw reference.
15164 */
15165 if (inline_secure(zone) && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
15166 raw = zone->raw;
15167 zone->raw = NULL;
15168 }
15169 if (inline_raw(zone)) {
15170 secure = zone->secure;
15171 zone->secure = NULL;
15172 }
15173 UNLOCK_ZONE(zone);
15174
15175 if (view != NULL) {
15176 dns_view_weakdetach(&view);
15177 }
15178 if (prev_view != NULL) {
15179 dns_view_weakdetach(&prev_view);
15180 }
15181
15182 if (raw != NULL) {
15183 dns_zone_detach(&raw);
15184 }
15185 if (secure != NULL) {
15186 dns_zone_idetach(&secure);
15187 }
15188 if (free_needed) {
15189 zone_free(zone);
15190 }
15191 }
15192
15193 static void
15194 zone_timer(void *arg) {
15195 dns_zone_t *zone = (dns_zone_t *)arg;
15196
15197 REQUIRE(DNS_ZONE_VALID(zone));
15198
15199 zone_maintenance(zone);
15200 }
15201
15202 static void
15203 zone_timer_stop(dns_zone_t *zone) {
15204 zone_debuglog(zone, __func__, 10, "stop zone timer");
15205 if (zone->timer != NULL) {
15206 isc_timer_stop(zone->timer);
15207 }
15208 }
15209
15210 static void
15211 zone_timer_set(dns_zone_t *zone, isc_time_t *next, isc_time_t *now) {
15212 isc_interval_t interval;
15213
15214 if (isc_time_compare(next, now) <= 0) {
15215 isc_interval_set(&interval, 0, 0);
15216 } else {
15217 isc_time_subtract(next, now, &interval);
15218 }
15219
15220 if (zone->loop == NULL) {
15221 zone_debuglog(zone, __func__, 10, "zone is not managed");
15222 } else if (zone->timer == NULL) {
15223 isc_refcount_increment0(&zone->irefs);
15224 isc_timer_create(zone->loop, zone_timer, zone, &zone->timer);
15225 }
15226 if (zone->timer != NULL) {
15227 isc_timer_start(zone->timer, isc_timertype_once, &interval);
15228 }
15229 }
15230
15231 static void
15232 zone__settimer(void *arg) {
15233 zone_settimer_t *data = arg;
15234 dns_zone_t *zone = data->zone;
15235 isc_time_t *now = &data->now;
15236 isc_time_t next;
15237 bool free_needed = false;
15238
15239 REQUIRE(DNS_ZONE_VALID(zone));
15240 ENTER;
15241
15242 LOCK_ZONE(zone);
15243 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
15244 goto free;
15245 }
15246 isc_time_settoepoch(&next);
15247
15248 switch (zone->type) {
15249 case dns_zone_redirect:
15250 if (dns_remote_addresses(&zone->primaries) != NULL) {
15251 goto treat_as_secondary;
15252 }
15253 FALLTHROUGH;
15254 case dns_zone_primary:
15255 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
15256 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))
15257 {
15258 next = zone->notifytime;
15259 }
15260 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
15261 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
15262 {
15263 INSIST(!isc_time_isepoch(&zone->dumptime));
15264 if (isc_time_isepoch(&next) ||
15265 isc_time_compare(&zone->dumptime, &next) < 0)
15266 {
15267 next = zone->dumptime;
15268 }
15269 }
15270 if (zone->type == dns_zone_redirect) {
15271 break;
15272 }
15273 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING) &&
15274 !isc_time_isepoch(&zone->refreshkeytime))
15275 {
15276 if (isc_time_isepoch(&next) ||
15277 isc_time_compare(&zone->refreshkeytime, &next) < 0)
15278 {
15279 next = zone->refreshkeytime;
15280 }
15281 }
15282 if (!isc_time_isepoch(&zone->resigntime)) {
15283 if (isc_time_isepoch(&next) ||
15284 isc_time_compare(&zone->resigntime, &next) < 0)
15285 {
15286 next = zone->resigntime;
15287 }
15288 }
15289 if (!isc_time_isepoch(&zone->keywarntime)) {
15290 if (isc_time_isepoch(&next) ||
15291 isc_time_compare(&zone->keywarntime, &next) < 0)
15292 {
15293 next = zone->keywarntime;
15294 }
15295 }
15296 if (!isc_time_isepoch(&zone->signingtime)) {
15297 if (isc_time_isepoch(&next) ||
15298 isc_time_compare(&zone->signingtime, &next) < 0)
15299 {
15300 next = zone->signingtime;
15301 }
15302 }
15303 if (!isc_time_isepoch(&zone->nsec3chaintime)) {
15304 if (isc_time_isepoch(&next) ||
15305 isc_time_compare(&zone->nsec3chaintime, &next) < 0)
15306 {
15307 next = zone->nsec3chaintime;
15308 }
15309 }
15310 break;
15311
15312 case dns_zone_secondary:
15313 case dns_zone_mirror:
15314 treat_as_secondary:
15315 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
15316 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))
15317 {
15318 next = zone->notifytime;
15319 }
15320 FALLTHROUGH;
15321 case dns_zone_stub:
15322 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) &&
15323 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOPRIMARIES) &&
15324 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH) &&
15325 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING) &&
15326 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING) &&
15327 !isc_time_isepoch(&zone->refreshtime) &&
15328 (isc_time_isepoch(&next) ||
15329 isc_time_compare(&zone->refreshtime, &next) < 0))
15330 {
15331 next = zone->refreshtime;
15332 }
15333 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
15334 !isc_time_isepoch(&zone->expiretime))
15335 {
15336 if (isc_time_isepoch(&next) ||
15337 isc_time_compare(&zone->expiretime, &next) < 0)
15338 {
15339 next = zone->expiretime;
15340 }
15341 }
15342 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
15343 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
15344 {
15345 INSIST(!isc_time_isepoch(&zone->dumptime));
15346 if (isc_time_isepoch(&next) ||
15347 isc_time_compare(&zone->dumptime, &next) < 0)
15348 {
15349 next = zone->dumptime;
15350 }
15351 }
15352 break;
15353
15354 case dns_zone_key:
15355 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
15356 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
15357 {
15358 INSIST(!isc_time_isepoch(&zone->dumptime));
15359 if (isc_time_isepoch(&next) ||
15360 isc_time_compare(&zone->dumptime, &next) < 0)
15361 {
15362 next = zone->dumptime;
15363 }
15364 }
15365 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
15366 if (isc_time_isepoch(&next) ||
15367 (!isc_time_isepoch(&zone->refreshkeytime) &&
15368 isc_time_compare(&zone->refreshkeytime, &next) <
15369 0))
15370 {
15371 next = zone->refreshkeytime;
15372 }
15373 }
15374 break;
15375
15376 default:
15377 break;
15378 }
15379
15380 if (isc_time_isepoch(&next)) {
15381 zone_timer_stop(zone);
15382 } else {
15383 zone_timer_set(zone, &next, now);
15384 }
15385
15386 free:
15387 isc_mem_put(zone->mctx, data, sizeof(*data));
15388 isc_refcount_decrement(&zone->irefs);
15389 free_needed = exit_check(zone);
15390 UNLOCK_ZONE(zone);
15391 if (free_needed) {
15392 zone_free(zone);
15393 }
15394 }
15395
15396 static void
15397 zone_settimer(dns_zone_t *zone, isc_time_t *now) {
15398 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
15399 return;
15400 }
15401
15402 zone_settimer_t *arg = isc_mem_get(zone->mctx, sizeof(*arg));
15403 *arg = (zone_settimer_t){
15404 .zone = zone,
15405 .now = *now,
15406 };
15407 isc_refcount_increment0(&zone->irefs);
15408 isc_async_run(zone->loop, zone__settimer, arg);
15409 }
15410
15411 static void
15412 cancel_refresh(dns_zone_t *zone) {
15413 isc_time_t now;
15414
15415 /*
15416 * 'zone' locked by caller.
15417 */
15418
15419 REQUIRE(DNS_ZONE_VALID(zone));
15420 REQUIRE(LOCKED_ZONE(zone));
15421
15422 ENTER;
15423
15424 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
15425 now = isc_time_now();
15426 zone_settimer(zone, &now);
15427 }
15428
15429 static isc_result_t
15430 notify_createmessage(dns_zone_t *zone, unsigned int flags,
15431 dns_message_t **messagep) {
15432 dns_db_t *zonedb = NULL;
15433 dns_dbnode_t *node = NULL;
15434 dns_dbversion_t *version = NULL;
15435 dns_message_t *message = NULL;
15436 dns_rdataset_t rdataset;
15437 dns_rdata_t rdata = DNS_RDATA_INIT;
15438
15439 dns_name_t *tempname = NULL;
15440 dns_rdata_t *temprdata = NULL;
15441 dns_rdatalist_t *temprdatalist = NULL;
15442 dns_rdataset_t *temprdataset = NULL;
15443
15444 isc_result_t result;
15445 isc_region_t r;
15446 isc_buffer_t *b = NULL;
15447
15448 REQUIRE(DNS_ZONE_VALID(zone));
15449 REQUIRE(messagep != NULL && *messagep == NULL);
15450
15451 dns_message_create(zone->mctx, NULL, NULL, DNS_MESSAGE_INTENTRENDER,
15452 &message);
15453
15454 message->opcode = dns_opcode_notify;
15455 message->flags |= DNS_MESSAGEFLAG_AA;
15456 message->rdclass = zone->rdclass;
15457
15458 dns_message_gettempname(message, &tempname);
15459
15460 dns_message_gettemprdataset(message, &temprdataset);
15461
15462 /*
15463 * Make question.
15464 */
15465 dns_name_clone(&zone->origin, tempname);
15466 dns_rdataset_makequestion(temprdataset, zone->rdclass,
15467 dns_rdatatype_soa);
15468 ISC_LIST_APPEND(tempname->list, temprdataset, link);
15469 dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
15470 tempname = NULL;
15471 temprdataset = NULL;
15472
15473 if ((flags & DNS_NOTIFY_NOSOA) != 0) {
15474 goto done;
15475 }
15476
15477 dns_message_gettempname(message, &tempname);
15478 dns_message_gettemprdata(message, &temprdata);
15479 dns_message_gettemprdataset(message, &temprdataset);
15480 dns_message_gettemprdatalist(message, &temprdatalist);
15481
15482 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
15483 INSIST(zone->db != NULL); /* XXXJT: is this assumption correct? */
15484 dns_db_attach(zone->db, &zonedb);
15485 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
15486
15487 dns_name_clone(&zone->origin, tempname);
15488 dns_db_currentversion(zonedb, &version);
15489 result = dns_db_findnode(zonedb, tempname, false, &node);
15490 if (result != ISC_R_SUCCESS) {
15491 goto soa_cleanup;
15492 }
15493
15494 dns_rdataset_init(&rdataset);
15495 result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
15496 dns_rdatatype_none, 0, &rdataset, NULL);
15497 if (result != ISC_R_SUCCESS) {
15498 goto soa_cleanup;
15499 }
15500 result = dns_rdataset_first(&rdataset);
15501 if (result != ISC_R_SUCCESS) {
15502 goto soa_cleanup;
15503 }
15504 dns_rdataset_current(&rdataset, &rdata);
15505 dns_rdata_toregion(&rdata, &r);
15506 isc_buffer_allocate(zone->mctx, &b, r.length);
15507 isc_buffer_putmem(b, r.base, r.length);
15508 isc_buffer_usedregion(b, &r);
15509 dns_rdata_init(temprdata);
15510 dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r);
15511 dns_message_takebuffer(message, &b);
15512 result = dns_rdataset_next(&rdataset);
15513 dns_rdataset_disassociate(&rdataset);
15514 if (result != ISC_R_NOMORE) {
15515 goto soa_cleanup;
15516 }
15517 temprdatalist->rdclass = rdata.rdclass;
15518 temprdatalist->type = rdata.type;
15519 temprdatalist->ttl = rdataset.ttl;
15520 ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link);
15521
15522 dns_rdatalist_tordataset(temprdatalist, temprdataset);
15523
15524 ISC_LIST_APPEND(tempname->list, temprdataset, link);
15525 dns_message_addname(message, tempname, DNS_SECTION_ANSWER);
15526 temprdatalist = NULL;
15527 temprdataset = NULL;
15528 temprdata = NULL;
15529 tempname = NULL;
15530
15531 soa_cleanup:
15532 if (node != NULL) {
15533 dns_db_detachnode(zonedb, &node);
15534 }
15535 if (version != NULL) {
15536 dns_db_closeversion(zonedb, &version, false);
15537 }
15538 if (zonedb != NULL) {
15539 dns_db_detach(&zonedb);
15540 }
15541 if (tempname != NULL) {
15542 dns_message_puttempname(message, &tempname);
15543 }
15544 if (temprdata != NULL) {
15545 dns_message_puttemprdata(message, &temprdata);
15546 }
15547 if (temprdataset != NULL) {
15548 dns_message_puttemprdataset(message, &temprdataset);
15549 }
15550 if (temprdatalist != NULL) {
15551 dns_message_puttemprdatalist(message, &temprdatalist);
15552 }
15553
15554 done:
15555 *messagep = message;
15556 return ISC_R_SUCCESS;
15557 }
15558
15559 isc_result_t
15560 dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
15561 isc_sockaddr_t *to, dns_message_t *msg) {
15562 unsigned int i;
15563 dns_rdata_soa_t soa;
15564 dns_rdataset_t *rdataset = NULL;
15565 dns_rdata_t rdata = DNS_RDATA_INIT;
15566 isc_result_t result;
15567 char fromtext[ISC_SOCKADDR_FORMATSIZE];
15568 int match = 0;
15569 isc_netaddr_t netaddr;
15570 uint32_t serial = 0;
15571 bool have_serial = false;
15572 dns_tsigkey_t *tsigkey;
15573 const dns_name_t *tsig;
15574
15575 REQUIRE(DNS_ZONE_VALID(zone));
15576
15577 /*
15578 * If type != T_SOA return DNS_R_NOTIMP. We don't yet support
15579 * ROLLOVER.
15580 *
15581 * SOA: RFC1996
15582 * Check that 'from' is a valid notify source, (zone->primaries).
15583 * Return DNS_R_REFUSED if not.
15584 *
15585 * If the notify message contains a serial number check it
15586 * against the zones serial and return if <= current serial
15587 *
15588 * If a refresh check is progress, if so just record the
15589 * fact we received a NOTIFY and from where and return.
15590 * We will perform a new refresh check when the current one
15591 * completes. Return ISC_R_SUCCESS.
15592 *
15593 * Otherwise initiate a refresh check using 'from' as the
15594 * first address to check. Return ISC_R_SUCCESS.
15595 */
15596
15597 isc_sockaddr_format(from, fromtext, sizeof(fromtext));
15598
15599 /*
15600 * Notify messages are processed by the raw zone.
15601 */
15602 LOCK_ZONE(zone);
15603 INSIST(zone != zone->raw);
15604 if (inline_secure(zone)) {
15605 result = dns_zone_notifyreceive(zone->raw, from, to, msg);
15606 UNLOCK_ZONE(zone);
15607 return result;
15608 }
15609 /*
15610 * We only handle NOTIFY (SOA) at the present.
15611 */
15612 if (isc_sockaddr_pf(from) == PF_INET) {
15613 inc_stats(zone, dns_zonestatscounter_notifyinv4);
15614 } else {
15615 inc_stats(zone, dns_zonestatscounter_notifyinv6);
15616 }
15617 if (msg->counts[DNS_SECTION_QUESTION] == 0 ||
15618 dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin,
15619 dns_rdatatype_soa, dns_rdatatype_none, NULL,
15620 NULL) != ISC_R_SUCCESS)
15621 {
15622 UNLOCK_ZONE(zone);
15623 if (msg->counts[DNS_SECTION_QUESTION] == 0) {
15624 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
15625 ISC_LOG_NOTICE,
15626 "NOTIFY with no question "
15627 "section from: %s",
15628 fromtext);
15629 return DNS_R_FORMERR;
15630 }
15631 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_NOTICE,
15632 "NOTIFY zone does not match");
15633 return DNS_R_NOTIMP;
15634 }
15635
15636 /*
15637 * If we are a primary zone just succeed.
15638 */
15639 if (zone->type == dns_zone_primary) {
15640 UNLOCK_ZONE(zone);
15641 return ISC_R_SUCCESS;
15642 }
15643
15644 isc_netaddr_fromsockaddr(&netaddr, from);
15645 for (i = 0; i < dns_remote_count(&zone->primaries); i++) {
15646 isc_sockaddr_t sockaddr = dns_remote_addr(&zone->primaries, i);
15647 if (isc_sockaddr_eqaddr(from, &sockaddr)) {
15648 break;
15649 }
15650 if (zone->view->aclenv->match_mapped &&
15651 IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) &&
15652 isc_sockaddr_pf(&sockaddr) == AF_INET)
15653 {
15654 isc_netaddr_t na1, na2;
15655 isc_netaddr_fromv4mapped(&na1, &netaddr);
15656 isc_netaddr_fromsockaddr(&na2, &sockaddr);
15657 if (isc_netaddr_equal(&na1, &na2)) {
15658 break;
15659 }
15660 }
15661 }
15662
15663 /*
15664 * Accept notify requests from non primaries if they are on
15665 * 'zone->notify_acl'.
15666 */
15667 tsigkey = dns_message_gettsigkey(msg);
15668 tsig = dns_tsigkey_identity(tsigkey);
15669 if (i >= dns_remote_count(&zone->primaries) &&
15670 zone->notify_acl != NULL &&
15671 (dns_acl_match(&netaddr, tsig, zone->notify_acl, zone->view->aclenv,
15672 &match, NULL) == ISC_R_SUCCESS) &&
15673 match > 0)
15674 {
15675 /* Accept notify. */
15676 } else if (i >= dns_remote_count(&zone->primaries)) {
15677 UNLOCK_ZONE(zone);
15678 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
15679 "refused notify from non-primary: %s", fromtext);
15680 inc_stats(zone, dns_zonestatscounter_notifyrej);
15681 return DNS_R_REFUSED;
15682 }
15683
15684 /*
15685 * If the zone is loaded and there are answers check the serial
15686 * to see if we need to do a refresh. Do not worry about this
15687 * check if we are a dialup zone as we use the notify request
15688 * to trigger a refresh check.
15689 */
15690 if (msg->counts[DNS_SECTION_ANSWER] > 0 &&
15691 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
15692 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH))
15693 {
15694 result = dns_message_findname(
15695 msg, DNS_SECTION_ANSWER, &zone->origin,
15696 dns_rdatatype_soa, dns_rdatatype_none, NULL, &rdataset);
15697 if (result == ISC_R_SUCCESS) {
15698 result = dns_rdataset_first(rdataset);
15699 }
15700 if (result == ISC_R_SUCCESS) {
15701 uint32_t oldserial;
15702 unsigned int soacount;
15703
15704 dns_rdataset_current(rdataset, &rdata);
15705 result = dns_rdata_tostruct(&rdata, &soa, NULL);
15706 RUNTIME_CHECK(result == ISC_R_SUCCESS);
15707 serial = soa.serial;
15708 have_serial = true;
15709 /*
15710 * The following should safely be performed without DB
15711 * lock and succeed in this context.
15712 */
15713 result = zone_get_from_db(zone, zone->db, NULL,
15714 &soacount, NULL, &oldserial,
15715 NULL, NULL, NULL, NULL, NULL);
15716 RUNTIME_CHECK(result == ISC_R_SUCCESS);
15717 RUNTIME_CHECK(soacount > 0U);
15718 if (isc_serial_le(serial, oldserial)) {
15719 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
15720 ISC_LOG_INFO,
15721 "notify from %s: "
15722 "zone is up to date",
15723 fromtext);
15724 UNLOCK_ZONE(zone);
15725 return ISC_R_SUCCESS;
15726 }
15727 }
15728 }
15729
15730 /*
15731 * If we got this far and there was a refresh in progress just
15732 * let it complete. Record where we got the notify from so we
15733 * can perform a refresh check when the current one completes
15734 */
15735 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
15736 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
15737 zone->notifyfrom = *from;
15738 UNLOCK_ZONE(zone);
15739 if (have_serial) {
15740 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
15741 ISC_LOG_INFO,
15742 "notify from %s: "
15743 "serial %u: refresh in progress, "
15744 "refresh check queued",
15745 fromtext, serial);
15746 } else {
15747 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
15748 ISC_LOG_INFO,
15749 "notify from %s: "
15750 "refresh in progress, "
15751 "refresh check queued",
15752 fromtext);
15753 }
15754 return ISC_R_SUCCESS;
15755 }
15756 if (have_serial) {
15757 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
15758 "notify from %s: serial %u", fromtext, serial);
15759 } else {
15760 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
15761 "notify from %s: no serial", fromtext);
15762 }
15763 zone->notifyfrom = *from;
15764 UNLOCK_ZONE(zone);
15765
15766 if (to != NULL) {
15767 dns_zonemgr_unreachabledel(zone->zmgr, from, to);
15768 }
15769 dns_zone_refresh(zone);
15770 return ISC_R_SUCCESS;
15771 }
15772
15773 void
15774 dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
15775 REQUIRE(DNS_ZONE_VALID(zone));
15776
15777 LOCK_ZONE(zone);
15778 if (zone->notify_acl != NULL) {
15779 dns_acl_detach(&zone->notify_acl);
15780 }
15781 dns_acl_attach(acl, &zone->notify_acl);
15782 UNLOCK_ZONE(zone);
15783 }
15784
15785 void
15786 dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
15787 REQUIRE(DNS_ZONE_VALID(zone));
15788
15789 LOCK_ZONE(zone);
15790 if (zone->query_acl != NULL) {
15791 dns_acl_detach(&zone->query_acl);
15792 }
15793 dns_acl_attach(acl, &zone->query_acl);
15794 UNLOCK_ZONE(zone);
15795 }
15796
15797 void
15798 dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl) {
15799 REQUIRE(DNS_ZONE_VALID(zone));
15800
15801 LOCK_ZONE(zone);
15802 if (zone->queryon_acl != NULL) {
15803 dns_acl_detach(&zone->queryon_acl);
15804 }
15805 dns_acl_attach(acl, &zone->queryon_acl);
15806 UNLOCK_ZONE(zone);
15807 }
15808
15809 void
15810 dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
15811 REQUIRE(DNS_ZONE_VALID(zone));
15812
15813 LOCK_ZONE(zone);
15814 if (zone->update_acl != NULL) {
15815 dns_acl_detach(&zone->update_acl);
15816 }
15817 dns_acl_attach(acl, &zone->update_acl);
15818 UNLOCK_ZONE(zone);
15819 }
15820
15821 void
15822 dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
15823 REQUIRE(DNS_ZONE_VALID(zone));
15824
15825 LOCK_ZONE(zone);
15826 if (zone->forward_acl != NULL) {
15827 dns_acl_detach(&zone->forward_acl);
15828 }
15829 dns_acl_attach(acl, &zone->forward_acl);
15830 UNLOCK_ZONE(zone);
15831 }
15832
15833 void
15834 dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
15835 REQUIRE(DNS_ZONE_VALID(zone));
15836
15837 LOCK_ZONE(zone);
15838 if (zone->xfr_acl != NULL) {
15839 dns_acl_detach(&zone->xfr_acl);
15840 }
15841 dns_acl_attach(acl, &zone->xfr_acl);
15842 UNLOCK_ZONE(zone);
15843 }
15844
15845 dns_acl_t *
15846 dns_zone_getnotifyacl(dns_zone_t *zone) {
15847 REQUIRE(DNS_ZONE_VALID(zone));
15848
15849 return zone->notify_acl;
15850 }
15851
15852 dns_acl_t *
15853 dns_zone_getqueryacl(dns_zone_t *zone) {
15854 REQUIRE(DNS_ZONE_VALID(zone));
15855
15856 return zone->query_acl;
15857 }
15858
15859 dns_acl_t *
15860 dns_zone_getqueryonacl(dns_zone_t *zone) {
15861 REQUIRE(DNS_ZONE_VALID(zone));
15862
15863 return zone->queryon_acl;
15864 }
15865
15866 dns_acl_t *
15867 dns_zone_getupdateacl(dns_zone_t *zone) {
15868 REQUIRE(DNS_ZONE_VALID(zone));
15869
15870 return zone->update_acl;
15871 }
15872
15873 dns_acl_t *
15874 dns_zone_getforwardacl(dns_zone_t *zone) {
15875 REQUIRE(DNS_ZONE_VALID(zone));
15876
15877 return zone->forward_acl;
15878 }
15879
15880 dns_acl_t *
15881 dns_zone_getxfracl(dns_zone_t *zone) {
15882 REQUIRE(DNS_ZONE_VALID(zone));
15883
15884 return zone->xfr_acl;
15885 }
15886
15887 void
15888 dns_zone_clearupdateacl(dns_zone_t *zone) {
15889 REQUIRE(DNS_ZONE_VALID(zone));
15890
15891 LOCK_ZONE(zone);
15892 if (zone->update_acl != NULL) {
15893 dns_acl_detach(&zone->update_acl);
15894 }
15895 UNLOCK_ZONE(zone);
15896 }
15897
15898 void
15899 dns_zone_clearforwardacl(dns_zone_t *zone) {
15900 REQUIRE(DNS_ZONE_VALID(zone));
15901
15902 LOCK_ZONE(zone);
15903 if (zone->forward_acl != NULL) {
15904 dns_acl_detach(&zone->forward_acl);
15905 }
15906 UNLOCK_ZONE(zone);
15907 }
15908
15909 void
15910 dns_zone_clearnotifyacl(dns_zone_t *zone) {
15911 REQUIRE(DNS_ZONE_VALID(zone));
15912
15913 LOCK_ZONE(zone);
15914 if (zone->notify_acl != NULL) {
15915 dns_acl_detach(&zone->notify_acl);
15916 }
15917 UNLOCK_ZONE(zone);
15918 }
15919
15920 void
15921 dns_zone_clearqueryacl(dns_zone_t *zone) {
15922 REQUIRE(DNS_ZONE_VALID(zone));
15923
15924 LOCK_ZONE(zone);
15925 if (zone->query_acl != NULL) {
15926 dns_acl_detach(&zone->query_acl);
15927 }
15928 UNLOCK_ZONE(zone);
15929 }
15930
15931 void
15932 dns_zone_clearqueryonacl(dns_zone_t *zone) {
15933 REQUIRE(DNS_ZONE_VALID(zone));
15934
15935 LOCK_ZONE(zone);
15936 if (zone->queryon_acl != NULL) {
15937 dns_acl_detach(&zone->queryon_acl);
15938 }
15939 UNLOCK_ZONE(zone);
15940 }
15941
15942 void
15943 dns_zone_clearxfracl(dns_zone_t *zone) {
15944 REQUIRE(DNS_ZONE_VALID(zone));
15945
15946 LOCK_ZONE(zone);
15947 if (zone->xfr_acl != NULL) {
15948 dns_acl_detach(&zone->xfr_acl);
15949 }
15950 UNLOCK_ZONE(zone);
15951 }
15952
15953 bool
15954 dns_zone_getupdatedisabled(dns_zone_t *zone) {
15955 REQUIRE(DNS_ZONE_VALID(zone));
15956 return zone->update_disabled;
15957 }
15958
15959 void
15960 dns_zone_setupdatedisabled(dns_zone_t *zone, bool state) {
15961 REQUIRE(DNS_ZONE_VALID(zone));
15962 zone->update_disabled = state;
15963 }
15964
15965 bool
15966 dns_zone_getzeronosoattl(dns_zone_t *zone) {
15967 REQUIRE(DNS_ZONE_VALID(zone));
15968 return zone->zero_no_soa_ttl;
15969 }
15970
15971 void
15972 dns_zone_setzeronosoattl(dns_zone_t *zone, bool state) {
15973 REQUIRE(DNS_ZONE_VALID(zone));
15974 zone->zero_no_soa_ttl = state;
15975 }
15976
15977 void
15978 dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
15979 REQUIRE(DNS_ZONE_VALID(zone));
15980
15981 zone->check_names = severity;
15982 }
15983
15984 dns_severity_t
15985 dns_zone_getchecknames(dns_zone_t *zone) {
15986 REQUIRE(DNS_ZONE_VALID(zone));
15987
15988 return zone->check_names;
15989 }
15990
15991 void
15992 dns_zone_setjournalsize(dns_zone_t *zone, int32_t size) {
15993 REQUIRE(DNS_ZONE_VALID(zone));
15994
15995 zone->journalsize = size;
15996 }
15997
15998 int32_t
15999 dns_zone_getjournalsize(dns_zone_t *zone) {
16000 REQUIRE(DNS_ZONE_VALID(zone));
16001
16002 return zone->journalsize;
16003 }
16004
16005 static void
16006 zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) {
16007 isc_result_t result = ISC_R_FAILURE;
16008 isc_buffer_t buffer;
16009
16010 REQUIRE(buf != NULL);
16011 REQUIRE(length > 1U);
16012
16013 /*
16014 * Leave space for terminating '\0'.
16015 */
16016 isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
16017 if (zone->type != dns_zone_redirect && zone->type != dns_zone_key) {
16018 if (dns_name_dynamic(&zone->origin)) {
16019 result = dns_name_totext(
16020 &zone->origin, DNS_NAME_OMITFINALDOT, &buffer);
16021 }
16022 if (result != ISC_R_SUCCESS &&
16023 isc_buffer_availablelength(&buffer) >=
16024 (sizeof("<UNKNOWN>") - 1))
16025 {
16026 isc_buffer_putstr(&buffer, "<UNKNOWN>");
16027 }
16028
16029 if (isc_buffer_availablelength(&buffer) > 0) {
16030 isc_buffer_putstr(&buffer, "/");
16031 }
16032 (void)dns_rdataclass_totext(zone->rdclass, &buffer);
16033 }
16034
16035 if (zone->view != NULL && strcmp(zone->view->name, "_bind") != 0 &&
16036 strcmp(zone->view->name, "_default") != 0 &&
16037 strlen(zone->view->name) < isc_buffer_availablelength(&buffer))
16038 {
16039 isc_buffer_putstr(&buffer, "/");
16040 isc_buffer_putstr(&buffer, zone->view->name);
16041 }
16042 if (inline_secure(zone) && 9U < isc_buffer_availablelength(&buffer)) {
16043 isc_buffer_putstr(&buffer, " (signed)");
16044 }
16045 if (inline_raw(zone) && 11U < isc_buffer_availablelength(&buffer)) {
16046 isc_buffer_putstr(&buffer, " (unsigned)");
16047 }
16048
16049 buf[isc_buffer_usedlength(&buffer)] = '\0';
16050 }
16051
16052 static void
16053 zone_name_tostr(dns_zone_t *zone, char *buf, size_t length) {
16054 isc_result_t result = ISC_R_FAILURE;
16055 isc_buffer_t buffer;
16056
16057 REQUIRE(buf != NULL);
16058 REQUIRE(length > 1U);
16059
16060 /*
16061 * Leave space for terminating '\0'.
16062 */
16063 isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
16064 if (dns_name_dynamic(&zone->origin)) {
16065 result = dns_name_totext(&zone->origin, DNS_NAME_OMITFINALDOT,
16066 &buffer);
16067 }
16068 if (result != ISC_R_SUCCESS &&
16069 isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
16070 {
16071 isc_buffer_putstr(&buffer, "<UNKNOWN>");
16072 }
16073
16074 buf[isc_buffer_usedlength(&buffer)] = '\0';
16075 }
16076
16077 static void
16078 zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length) {
16079 isc_buffer_t buffer;
16080
16081 REQUIRE(buf != NULL);
16082 REQUIRE(length > 1U);
16083
16084 /*
16085 * Leave space for terminating '\0'.
16086 */
16087 isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
16088 (void)dns_rdataclass_totext(zone->rdclass, &buffer);
16089
16090 buf[isc_buffer_usedlength(&buffer)] = '\0';
16091 }
16092
16093 static void
16094 zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length) {
16095 isc_buffer_t buffer;
16096
16097 REQUIRE(buf != NULL);
16098 REQUIRE(length > 1U);
16099
16100 /*
16101 * Leave space for terminating '\0'.
16102 */
16103 isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
16104
16105 if (zone->view == NULL) {
16106 isc_buffer_putstr(&buffer, "_none");
16107 } else if (strlen(zone->view->name) <
16108 isc_buffer_availablelength(&buffer))
16109 {
16110 isc_buffer_putstr(&buffer, zone->view->name);
16111 } else {
16112 isc_buffer_putstr(&buffer, "_toolong");
16113 }
16114
16115 buf[isc_buffer_usedlength(&buffer)] = '\0';
16116 }
16117
16118 void
16119 dns_zone_name(dns_zone_t *zone, char *buf, size_t length) {
16120 REQUIRE(DNS_ZONE_VALID(zone));
16121 REQUIRE(buf != NULL);
16122
16123 LOCK_ZONE(zone);
16124 zone_namerd_tostr(zone, buf, length);
16125 UNLOCK_ZONE(zone);
16126 }
16127
16128 void
16129 dns_zone_nameonly(dns_zone_t *zone, char *buf, size_t length) {
16130 REQUIRE(DNS_ZONE_VALID(zone));
16131 REQUIRE(buf != NULL);
16132 zone_name_tostr(zone, buf, length);
16133 }
16134
16135 void
16136 dns_zone_logv(dns_zone_t *zone, isc_logcategory_t *category, int level,
16137 const char *prefix, const char *fmt, va_list ap) {
16138 char message[4096];
16139 const char *zstr;
16140
16141 REQUIRE(DNS_ZONE_VALID(zone));
16142
16143 if (!isc_log_wouldlog(dns_lctx, level)) {
16144 return;
16145 }
16146
16147 vsnprintf(message, sizeof(message), fmt, ap);
16148
16149 switch (zone->type) {
16150 case dns_zone_key:
16151 zstr = "managed-keys-zone";
16152 break;
16153 case dns_zone_redirect:
16154 zstr = "redirect-zone";
16155 break;
16156 default:
16157 zstr = "zone ";
16158 }
16159
16160 isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE, level,
16161 "%s%s%s%s: %s", prefix != NULL ? prefix : "",
16162 prefix != NULL ? ": " : "", zstr, zone->strnamerd,
16163 message);
16164 }
16165
16166 static void
16167 notify_log(dns_zone_t *zone, int level, const char *fmt, ...) {
16168 va_list ap;
16169
16170 va_start(ap, fmt);
16171 dns_zone_logv(zone, DNS_LOGCATEGORY_NOTIFY, level, NULL, fmt, ap);
16172 va_end(ap);
16173 }
16174
16175 void
16176 dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category, int level,
16177 const char *fmt, ...) {
16178 va_list ap;
16179
16180 va_start(ap, fmt);
16181 dns_zone_logv(zone, category, level, NULL, fmt, ap);
16182 va_end(ap);
16183 }
16184
16185 void
16186 dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) {
16187 va_list ap;
16188
16189 va_start(ap, fmt);
16190 dns_zone_logv(zone, DNS_LOGCATEGORY_GENERAL, level, NULL, fmt, ap);
16191 va_end(ap);
16192 }
16193
16194 static void
16195 zone_debuglogc(dns_zone_t *zone, isc_logcategory_t *category, const char *me,
16196 int debuglevel, const char *fmt, ...) {
16197 int level = ISC_LOG_DEBUG(debuglevel);
16198 va_list ap;
16199
16200 va_start(ap, fmt);
16201 dns_zone_logv(zone, category, level, me, fmt, ap);
16202 va_end(ap);
16203 }
16204
16205 static void
16206 zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel, const char *fmt,
16207 ...) {
16208 int level = ISC_LOG_DEBUG(debuglevel);
16209 va_list ap;
16210
16211 va_start(ap, fmt);
16212 dns_zone_logv(zone, DNS_LOGCATEGORY_GENERAL, level, me, fmt, ap);
16213 va_end(ap);
16214 }
16215
16216 static void
16217 dnssec_log(dns_zone_t *zone, int level, const char *fmt, ...) {
16218 va_list ap;
16219
16220 va_start(ap, fmt);
16221 dns_zone_logv(zone, DNS_LOGCATEGORY_DNSSEC, level, NULL, fmt, ap);
16222 va_end(ap);
16223 }
16224
16225 static int
16226 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type) {
16227 isc_result_t result;
16228 dns_name_t *name;
16229 dns_rdataset_t *curr;
16230 int count = 0;
16231
16232 result = dns_message_firstname(msg, section);
16233 while (result == ISC_R_SUCCESS) {
16234 name = NULL;
16235 dns_message_currentname(msg, section, &name);
16236
16237 for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
16238 curr = ISC_LIST_PREV(curr, link))
16239 {
16240 if (curr->type == type) {
16241 count++;
16242 }
16243 }
16244 result = dns_message_nextname(msg, section);
16245 }
16246
16247 return count;
16248 }
16249
16250 void
16251 dns_zone_setminxfrratein(dns_zone_t *zone, uint32_t bytes, uint32_t seconds) {
16252 REQUIRE(DNS_ZONE_VALID(zone));
16253
16254 zone->minxfrratebytesin = bytes;
16255 zone->minxfrratesecondsin = seconds;
16256 }
16257
16258 uint32_t
16259 dns_zone_getminxfrratebytesin(dns_zone_t *zone) {
16260 REQUIRE(DNS_ZONE_VALID(zone));
16261
16262 return zone->minxfrratebytesin;
16263 }
16264
16265 uint32_t
16266 dns_zone_getminxfrratesecondsin(dns_zone_t *zone) {
16267 REQUIRE(DNS_ZONE_VALID(zone));
16268
16269 return zone->minxfrratesecondsin;
16270 }
16271
16272 void
16273 dns_zone_setmaxxfrin(dns_zone_t *zone, uint32_t maxxfrin) {
16274 REQUIRE(DNS_ZONE_VALID(zone));
16275
16276 zone->maxxfrin = maxxfrin;
16277 }
16278
16279 uint32_t
16280 dns_zone_getmaxxfrin(dns_zone_t *zone) {
16281 REQUIRE(DNS_ZONE_VALID(zone));
16282
16283 return zone->maxxfrin;
16284 }
16285
16286 void
16287 dns_zone_setmaxxfrout(dns_zone_t *zone, uint32_t maxxfrout) {
16288 REQUIRE(DNS_ZONE_VALID(zone));
16289 zone->maxxfrout = maxxfrout;
16290 }
16291
16292 uint32_t
16293 dns_zone_getmaxxfrout(dns_zone_t *zone) {
16294 REQUIRE(DNS_ZONE_VALID(zone));
16295
16296 return zone->maxxfrout;
16297 }
16298
16299 dns_zonetype_t
16300 dns_zone_gettype(dns_zone_t *zone) {
16301 REQUIRE(DNS_ZONE_VALID(zone));
16302
16303 return zone->type;
16304 }
16305
16306 const char *
16307 dns_zonetype_name(dns_zonetype_t type) {
16308 switch (type) {
16309 case dns_zone_none:
16310 return "none";
16311 case dns_zone_primary:
16312 return "primary";
16313 case dns_zone_secondary:
16314 return "secondary";
16315 case dns_zone_mirror:
16316 return "mirror";
16317 case dns_zone_stub:
16318 return "stub";
16319 case dns_zone_staticstub:
16320 return "static-stub";
16321 case dns_zone_key:
16322 return "key";
16323 case dns_zone_dlz:
16324 return "dlz";
16325 case dns_zone_redirect:
16326 return "redirect";
16327 default:
16328 return "unknown";
16329 }
16330 }
16331
16332 dns_zonetype_t
16333 dns_zone_getredirecttype(dns_zone_t *zone) {
16334 REQUIRE(DNS_ZONE_VALID(zone));
16335 REQUIRE(zone->type == dns_zone_redirect);
16336
16337 return dns_remote_addresses(&zone->primaries) == NULL
16338 ? dns_zone_primary
16339 : dns_zone_secondary;
16340 }
16341
16342 dns_name_t *
16343 dns_zone_getorigin(dns_zone_t *zone) {
16344 REQUIRE(DNS_ZONE_VALID(zone));
16345
16346 return &zone->origin;
16347 }
16348
16349 void
16350 dns_zone_setidlein(dns_zone_t *zone, uint32_t idlein) {
16351 REQUIRE(DNS_ZONE_VALID(zone));
16352
16353 if (idlein == 0) {
16354 idlein = DNS_DEFAULT_IDLEIN;
16355 }
16356 zone->idlein = idlein;
16357 }
16358
16359 uint32_t
16360 dns_zone_getidlein(dns_zone_t *zone) {
16361 REQUIRE(DNS_ZONE_VALID(zone));
16362
16363 return zone->idlein;
16364 }
16365
16366 void
16367 dns_zone_setidleout(dns_zone_t *zone, uint32_t idleout) {
16368 REQUIRE(DNS_ZONE_VALID(zone));
16369
16370 zone->idleout = idleout;
16371 }
16372
16373 uint32_t
16374 dns_zone_getidleout(dns_zone_t *zone) {
16375 REQUIRE(DNS_ZONE_VALID(zone));
16376
16377 return zone->idleout;
16378 }
16379
16380 static void
16381 notify_done(void *arg) {
16382 dns_request_t *request = (dns_request_t *)arg;
16383 dns_notify_t *notify = dns_request_getarg(request);
16384 isc_result_t result;
16385 dns_message_t *message = NULL;
16386 isc_buffer_t buf;
16387 char rcode[128];
16388 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
16389
16390 REQUIRE(DNS_NOTIFY_VALID(notify));
16391
16392 isc_buffer_init(&buf, rcode, sizeof(rcode));
16393 isc_sockaddr_format(¬ify->dst, addrbuf, sizeof(addrbuf));
16394 dns_message_create(notify->zone->mctx, NULL, NULL,
16395 DNS_MESSAGE_INTENTPARSE, &message);
16396
16397 result = dns_request_getresult(request);
16398 if (result != ISC_R_SUCCESS) {
16399 goto fail;
16400 }
16401
16402 result = dns_request_getresponse(request, message,
16403 DNS_MESSAGEPARSE_PRESERVEORDER);
16404 if (result != ISC_R_SUCCESS) {
16405 goto fail;
16406 }
16407
16408 result = dns_rcode_totext(message->rcode, &buf);
16409 if (result == ISC_R_SUCCESS) {
16410 notify_log(notify->zone, ISC_LOG_DEBUG(3),
16411 "notify response from %s: %.*s", addrbuf,
16412 (int)buf.used, rcode);
16413 }
16414
16415 fail:
16416 dns_message_detach(&message);
16417
16418 if (result == ISC_R_SUCCESS) {
16419 notify_log(notify->zone, ISC_LOG_DEBUG(1),
16420 "notify to %s successful", addrbuf);
16421 } else if (result == ISC_R_SHUTTINGDOWN || result == ISC_R_CANCELED) {
16422 /* just destroy the notify */
16423 } else if ((notify->flags & DNS_NOTIFY_TCP) == 0) {
16424 notify_log(notify->zone, ISC_LOG_NOTICE,
16425 "notify to %s failed: %s: retrying over TCP",
16426 addrbuf, isc_result_totext(result));
16427 notify->flags |= DNS_NOTIFY_TCP;
16428 dns_request_destroy(¬ify->request);
16429 notify_send_queue(notify, notify->flags & DNS_NOTIFY_STARTUP);
16430 return;
16431 } else if (result == ISC_R_TIMEDOUT) {
16432 notify_log(notify->zone, ISC_LOG_WARNING,
16433 "notify to %s failed: %s: retries exceeded", addrbuf,
16434 isc_result_totext(result));
16435 } else {
16436 notify_log(notify->zone, ISC_LOG_WARNING,
16437 "notify to %s failed: %s", addrbuf,
16438 isc_result_totext(result));
16439 }
16440 notify_destroy(notify, false);
16441 }
16442
16443 struct rss {
16444 dns_zone_t *zone;
16445 dns_db_t *db;
16446 uint32_t serial;
16447 ISC_LINK(struct rss) link;
16448 };
16449
16450 static void
16451 update_log_cb(void *arg, dns_zone_t *zone, int level, const char *message) {
16452 UNUSED(arg);
16453 dns_zone_log(zone, level, "%s", message);
16454 }
16455
16456 static isc_result_t
16457 dnskey_inuse(dns_zone_t *zone, dns_rdata_t *rdata, isc_mem_t *mctx,
16458 dns_dnsseckeylist_t *keylist, bool *inuse) {
16459 isc_result_t result;
16460 dst_key_t *dstkey = NULL;
16461
16462 result = dns_dnssec_keyfromrdata(dns_zone_getorigin(zone), rdata, mctx,
16463 &dstkey);
16464 if (result != ISC_R_SUCCESS) {
16465 dns_zone_log(zone, ISC_LOG_ERROR,
16466 "dns_dnssec_keyfromrdata() failed: %s",
16467 isc_result_totext(result));
16468 return result;
16469 }
16470
16471 for (dns_dnsseckey_t *k = ISC_LIST_HEAD(*keylist); k != NULL;
16472 k = ISC_LIST_NEXT(k, link))
16473 {
16474 if (dst_key_pubcompare(k->key, dstkey, false)) {
16475 *inuse = true;
16476 break;
16477 }
16478 }
16479
16480 dst_key_free(&dstkey);
16481 return ISC_R_SUCCESS;
16482 }
16483
16484 static isc_result_t
16485 cdnskey_inuse(dns_zone_t *zone, dns_rdata_t *rdata,
16486 dns_dnsseckeylist_t *keylist, bool *inuse) {
16487 isc_result_t result;
16488 dns_rdata_cdnskey_t cdnskey;
16489
16490 result = dns_rdata_tostruct(rdata, &cdnskey, NULL);
16491 if (result != ISC_R_SUCCESS) {
16492 dns_zone_log(zone, ISC_LOG_ERROR,
16493 "dns_rdata_tostruct(cdnskey) failed: %s",
16494 isc_result_totext(result));
16495 return result;
16496 }
16497
16498 for (dns_dnsseckey_t *k = ISC_LIST_HEAD(*keylist); k != NULL;
16499 k = ISC_LIST_NEXT(k, link))
16500 {
16501 dns_rdata_t cdnskeyrdata = DNS_RDATA_INIT;
16502 unsigned char keybuf[DST_KEY_MAXSIZE];
16503
16504 result = dns_dnssec_make_dnskey(k->key, keybuf, sizeof(keybuf),
16505 &cdnskeyrdata);
16506 if (result != ISC_R_SUCCESS) {
16507 dns_zone_log(zone, ISC_LOG_ERROR,
16508 "dns_dnssec_make_dnskey() failed: %s",
16509 isc_result_totext(result));
16510 return result;
16511 }
16512
16513 cdnskeyrdata.type = dns_rdatatype_cdnskey;
16514 if (dns_rdata_compare(rdata, &cdnskeyrdata) == 0) {
16515 *inuse = true;
16516 break;
16517 }
16518 }
16519
16520 return ISC_R_SUCCESS;
16521 }
16522
16523 static isc_result_t
16524 cds_inuse(dns_zone_t *zone, dns_rdata_t *rdata, dns_dnsseckeylist_t *keylist,
16525 bool *inuse) {
16526 isc_result_t result;
16527 dns_rdata_ds_t cds;
16528
16529 result = dns_rdata_tostruct(rdata, &cds, NULL);
16530 if (result != ISC_R_SUCCESS) {
16531 dns_zone_log(zone, ISC_LOG_ERROR,
16532 "dns_rdata_tostruct(cds) failed: %s",
16533 isc_result_totext(result));
16534 return result;
16535 }
16536
16537 for (dns_dnsseckey_t *k = ISC_LIST_HEAD(*keylist); k != NULL;
16538 k = ISC_LIST_NEXT(k, link))
16539 {
16540 dns_rdata_t dnskey = DNS_RDATA_INIT;
16541 dns_rdata_t cdsrdata = DNS_RDATA_INIT;
16542 unsigned char keybuf[DST_KEY_MAXSIZE];
16543 unsigned char cdsbuf[DNS_DS_BUFFERSIZE];
16544
16545 if (dst_key_id(k->key) != cds.key_tag ||
16546 dst_key_alg(k->key) != cds.algorithm)
16547 {
16548 continue;
16549 }
16550 result = dns_dnssec_make_dnskey(k->key, keybuf, sizeof(keybuf),
16551 &dnskey);
16552 if (result != ISC_R_SUCCESS) {
16553 dns_zone_log(zone, ISC_LOG_ERROR,
16554 "dns_dnssec_make_dnskey() failed: %s",
16555 isc_result_totext(result));
16556 return result;
16557 }
16558 result = dns_ds_buildrdata(dns_zone_getorigin(zone), &dnskey,
16559 cds.digest_type, cdsbuf, &cdsrdata);
16560 if (result != ISC_R_SUCCESS) {
16561 dns_zone_log(zone, ISC_LOG_ERROR,
16562 "dns_ds_buildrdata(keytag=%d, algo=%d, "
16563 "digest=%d) failed: %s",
16564 cds.key_tag, cds.algorithm,
16565 cds.digest_type,
16566 isc_result_totext(result));
16567 return result;
16568 }
16569
16570 cdsrdata.type = dns_rdatatype_cds;
16571 if (dns_rdata_compare(rdata, &cdsrdata) == 0) {
16572 *inuse = true;
16573 break;
16574 }
16575 }
16576
16577 return ISC_R_SUCCESS;
16578 }
16579
16580 isc_result_t
16581 dns_zone_dnskey_inuse(dns_zone_t *zone, dns_rdata_t *rdata, bool *inuse) {
16582 dns_dnsseckeylist_t keylist;
16583 dns_dnsseckey_t *key = NULL;
16584 isc_result_t result = ISC_R_SUCCESS;
16585 isc_stdtime_t now = isc_stdtime_now();
16586 isc_mem_t *mctx;
16587 dns_kasp_t *kasp;
16588 dns_keystorelist_t *keystores;
16589 const char *keydir;
16590
16591 REQUIRE(DNS_ZONE_VALID(zone));
16592 REQUIRE(dns_rdatatype_iskeymaterial(rdata->type));
16593
16594 mctx = zone->mctx;
16595
16596 ISC_LIST_INIT(keylist);
16597
16598 *inuse = false;
16599
16600 kasp = dns_zone_getkasp(zone);
16601 keydir = dns_zone_getkeydirectory(zone);
16602 keystores = dns_zone_getkeystores(zone);
16603
16604 dns_zone_lock_keyfiles(zone);
16605 result = dns_dnssec_findmatchingkeys(dns_zone_getorigin(zone), kasp,
16606 keydir, keystores, now, false,
16607 mctx, &keylist);
16608 dns_zone_unlock_keyfiles(zone);
16609 if (result == ISC_R_NOTFOUND) {
16610 return ISC_R_SUCCESS;
16611 } else if (result != ISC_R_SUCCESS) {
16612 dns_zone_log(zone, ISC_LOG_ERROR,
16613 "dns_dnssec_findmatchingkeys() failed: %s",
16614 isc_result_totext(result));
16615 return result;
16616 }
16617
16618 switch (rdata->type) {
16619 case dns_rdatatype_dnskey:
16620 result = dnskey_inuse(zone, rdata, mctx, &keylist, inuse);
16621 break;
16622 case dns_rdatatype_cdnskey:
16623 result = cdnskey_inuse(zone, rdata, &keylist, inuse);
16624 break;
16625 case dns_rdatatype_cds:
16626 result = cds_inuse(zone, rdata, &keylist, inuse);
16627 break;
16628 default:
16629 UNREACHABLE();
16630 break;
16631 }
16632
16633 while (!ISC_LIST_EMPTY(keylist)) {
16634 key = ISC_LIST_HEAD(keylist);
16635 ISC_LIST_UNLINK(keylist, key, link);
16636 dns_dnsseckey_destroy(mctx, &key);
16637 }
16638 return result;
16639 }
16640
16641 static isc_result_t
16642 sync_secure_journal(dns_zone_t *zone, dns_zone_t *raw, dns_journal_t *journal,
16643 uint32_t start, uint32_t end, dns_difftuple_t **soatuplep,
16644 dns_diff_t *diff) {
16645 isc_result_t result;
16646 dns_difftuple_t *tuple = NULL;
16647 dns_diffop_t op = DNS_DIFFOP_ADD;
16648 int n_soa = 0;
16649
16650 REQUIRE(soatuplep != NULL);
16651
16652 if (start == end) {
16653 return DNS_R_UNCHANGED;
16654 }
16655
16656 CHECK(dns_journal_iter_init(journal, start, end, NULL));
16657 for (result = dns_journal_first_rr(journal); result == ISC_R_SUCCESS;
16658 result = dns_journal_next_rr(journal))
16659 {
16660 dns_name_t *name = NULL;
16661 uint32_t ttl;
16662 dns_rdata_t *rdata = NULL;
16663 dns_journal_current_rr(journal, &name, &ttl, &rdata);
16664
16665 if (rdata->type == dns_rdatatype_soa) {
16666 n_soa++;
16667 if (n_soa == 2) {
16668 /*
16669 * Save the latest raw SOA record.
16670 */
16671 if (*soatuplep != NULL) {
16672 dns_difftuple_free(soatuplep);
16673 }
16674 CHECK(dns_difftuple_create(
16675 diff->mctx, DNS_DIFFOP_ADD, name, ttl,
16676 rdata, soatuplep));
16677 }
16678 if (n_soa == 3) {
16679 n_soa = 1;
16680 }
16681 continue;
16682 }
16683
16684 /* Sanity. */
16685 if (n_soa == 0) {
16686 dns_zone_log(raw, ISC_LOG_ERROR,
16687 "corrupt journal file: '%s'\n",
16688 raw->journal);
16689 return ISC_R_FAILURE;
16690 }
16691
16692 if (zone->privatetype != 0 && rdata->type == zone->privatetype)
16693 {
16694 continue;
16695 }
16696
16697 /*
16698 * Skip DNSSEC records that BIND maintains with inline-signing.
16699 */
16700 if (rdata->type == dns_rdatatype_nsec ||
16701 rdata->type == dns_rdatatype_rrsig ||
16702 rdata->type == dns_rdatatype_nsec3 ||
16703 rdata->type == dns_rdatatype_nsec3param)
16704 {
16705 continue;
16706 }
16707 /*
16708 * Allow DNSKEY, CDNSKEY, CDS because users should be able to
16709 * update the zone with these records from a different provider,
16710 * but skip records that are under our control.
16711 */
16712 if (dns_rdatatype_iskeymaterial(rdata->type)) {
16713 bool inuse = false;
16714 isc_result_t r = dns_zone_dnskey_inuse(zone, rdata,
16715 &inuse);
16716 if (r == ISC_R_SUCCESS && inuse) {
16717 continue;
16718 }
16719 }
16720
16721 op = (n_soa == 1) ? DNS_DIFFOP_DEL : DNS_DIFFOP_ADD;
16722
16723 CHECK(dns_difftuple_create(diff->mctx, op, name, ttl, rdata,
16724 &tuple));
16725 dns_diff_appendminimal(diff, &tuple);
16726 }
16727 if (result == ISC_R_NOMORE) {
16728 result = ISC_R_SUCCESS;
16729 }
16730
16731 cleanup:
16732 return result;
16733 }
16734
16735 /*
16736 * Filter the key material preserving TTL changes. If kasp in effect honour the
16737 * existing ttl. The lists returned by sync_secure_db/dns_db_diffx should be
16738 * DNSSEC RRset order so we can process 'del' and 'add' in parallel rather than
16739 * searching for TTL only changes first and processing them, then checking the
16740 * 'in use' status on a subsequent pass.
16741 */
16742
16743 static void
16744 filter_keymaterial(dns_zone_t *zone, dns_difftuplelist_t *del,
16745 dns_difftuplelist_t *add, bool kasp, dns_ttl_t ttl) {
16746 dns_difftuple_t *deltuple = ISC_LIST_HEAD(*del);
16747 dns_difftuple_t *addtuple = ISC_LIST_HEAD(*add);
16748 isc_result_t result;
16749
16750 while (deltuple != NULL || addtuple != NULL) {
16751 dns_difftuple_t *delnext = NULL, *addnext = NULL;
16752 bool inuse = false;
16753 if (deltuple != NULL) {
16754 delnext = ISC_LIST_NEXT(deltuple, link);
16755 }
16756 if (addtuple != NULL) {
16757 addnext = ISC_LIST_NEXT(addtuple, link);
16758 }
16759 if (deltuple != NULL && addtuple != NULL) {
16760 int n = dns_rdata_compare(&deltuple->rdata,
16761 &addtuple->rdata);
16762 if (n == 0) {
16763 /*
16764 * If the rdata is equal then the only
16765 * difference will be a TTL change.
16766 */
16767 if (kasp) {
16768 /* TTL is managed by dnssec-policy */
16769 ISC_LIST_UNLINK(*del, deltuple, link);
16770 dns_difftuple_free(&deltuple);
16771 ISC_LIST_UNLINK(*add, addtuple, link);
16772 dns_difftuple_free(&addtuple);
16773 }
16774 deltuple = delnext;
16775 addtuple = addnext;
16776 continue;
16777 }
16778 if (n < 0) {
16779 goto checkdel;
16780 }
16781 goto checkadd;
16782 } else if (deltuple != NULL) {
16783 checkdel:
16784 result = dns_zone_dnskey_inuse(zone, &deltuple->rdata,
16785 &inuse);
16786 if (result == ISC_R_SUCCESS && inuse) {
16787 ISC_LIST_UNLINK(*del, deltuple, link);
16788 dns_difftuple_free(&deltuple);
16789 }
16790 deltuple = delnext;
16791 } else {
16792 checkadd:
16793 result = dns_zone_dnskey_inuse(zone, &addtuple->rdata,
16794 &inuse);
16795 if (result == ISC_R_SUCCESS && inuse) {
16796 ISC_LIST_UNLINK(*add, addtuple, link);
16797 dns_difftuple_free(&addtuple);
16798 } else if (kasp) {
16799 addtuple->ttl = ttl;
16800 }
16801 addtuple = addnext;
16802 }
16803 }
16804 }
16805
16806 static isc_result_t
16807 sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb,
16808 dns_dbversion_t *secver, dns_difftuple_t **soatuple,
16809 dns_diff_t *diff) {
16810 isc_result_t result;
16811 dns_db_t *rawdb = NULL;
16812 dns_dbversion_t *rawver = NULL;
16813 dns_difftuple_t *tuple = NULL, *next;
16814 dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
16815 dns_rdata_soa_t oldsoa, newsoa;
16816 dns_difftuplelist_t add = ISC_LIST_INITIALIZER;
16817 dns_difftuplelist_t del = ISC_LIST_INITIALIZER;
16818 dns_difftuplelist_t keyadd = ISC_LIST_INITIALIZER;
16819 dns_difftuplelist_t keydel = ISC_LIST_INITIALIZER;
16820 dns_difftuplelist_t ckeyadd = ISC_LIST_INITIALIZER;
16821 dns_difftuplelist_t ckeydel = ISC_LIST_INITIALIZER;
16822 dns_difftuplelist_t cdsadd = ISC_LIST_INITIALIZER;
16823 dns_difftuplelist_t cdsdel = ISC_LIST_INITIALIZER;
16824 dns_kasp_t *kasp = NULL;
16825 dns_ttl_t keyttl = 0, ckeyttl = 0, cdsttl = 0;
16826
16827 REQUIRE(DNS_ZONE_VALID(seczone));
16828 REQUIRE(soatuple != NULL && *soatuple == NULL);
16829
16830 if (!seczone->sourceserialset) {
16831 return DNS_R_UNCHANGED;
16832 }
16833
16834 dns_db_attach(raw->db, &rawdb);
16835 dns_db_currentversion(rawdb, &rawver);
16836 result = dns_db_diffx(diff, rawdb, rawver, secdb, secver, NULL);
16837 dns_db_closeversion(rawdb, &rawver, false);
16838 dns_db_detach(&rawdb);
16839
16840 if (result != ISC_R_SUCCESS) {
16841 return result;
16842 }
16843
16844 /*
16845 * If kasp is in effect honour the existing DNSKEY, CDNSKEY and CDS
16846 * TTLs.
16847 */
16848 kasp = seczone->kasp;
16849 if (kasp != NULL) {
16850 dns_rdataset_t rdataset;
16851 dns_dbnode_t *node = NULL;
16852 dns_ttl_t ttl = dns_kasp_dnskeyttl(kasp);
16853
16854 dns_rdataset_init(&rdataset);
16855
16856 result = dns_db_getoriginnode(secdb, &node);
16857 RUNTIME_CHECK(result == ISC_R_SUCCESS);
16858
16859 result = dns_db_findrdataset(
16860 secdb, node, secver, dns_rdatatype_dnskey,
16861 dns_rdatatype_none, 0, &rdataset, NULL);
16862 keyttl = (result == ISC_R_SUCCESS) ? rdataset.ttl : ttl;
16863 if (dns_rdataset_isassociated(&rdataset)) {
16864 dns_rdataset_disassociate(&rdataset);
16865 }
16866
16867 result = dns_db_findrdataset(
16868 secdb, node, secver, dns_rdatatype_cdnskey,
16869 dns_rdatatype_none, 0, &rdataset, NULL);
16870 ckeyttl = (result == ISC_R_SUCCESS) ? rdataset.ttl : ttl;
16871 if (dns_rdataset_isassociated(&rdataset)) {
16872 dns_rdataset_disassociate(&rdataset);
16873 }
16874
16875 result = dns_db_findrdataset(
16876 secdb, node, secver, dns_rdatatype_cds,
16877 dns_rdatatype_none, 0, &rdataset, NULL);
16878 cdsttl = (result == ISC_R_SUCCESS) ? rdataset.ttl : ttl;
16879 if (dns_rdataset_isassociated(&rdataset)) {
16880 dns_rdataset_disassociate(&rdataset);
16881 }
16882 dns_db_detachnode(secdb, &node);
16883 }
16884
16885 for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL; tuple = next) {
16886 dns_difftuplelist_t *al = &add, *dl = &del;
16887
16888 next = ISC_LIST_NEXT(tuple, link);
16889
16890 /*
16891 * Skip private records that BIND maintains with inline-signing.
16892 */
16893 if (seczone->privatetype != 0 &&
16894 tuple->rdata.type == seczone->privatetype)
16895 {
16896 ISC_LIST_UNLINK(diff->tuples, tuple, link);
16897 dns_difftuple_free(&tuple);
16898 continue;
16899 }
16900
16901 /*
16902 * Skip DNSSEC records that BIND maintains with inline-signing.
16903 */
16904 if (tuple->rdata.type == dns_rdatatype_nsec ||
16905 tuple->rdata.type == dns_rdatatype_rrsig ||
16906 tuple->rdata.type == dns_rdatatype_nsec3 ||
16907 tuple->rdata.type == dns_rdatatype_nsec3param)
16908 {
16909 ISC_LIST_UNLINK(diff->tuples, tuple, link);
16910 dns_difftuple_free(&tuple);
16911 continue;
16912 }
16913
16914 /*
16915 * Apex DNSKEY, CDNSKEY and CDS need special processing so
16916 * split them out.
16917 */
16918 if (dns_rdatatype_iskeymaterial(tuple->rdata.type) &&
16919 dns_name_equal(&tuple->name, &seczone->origin))
16920 {
16921 switch (tuple->rdata.type) {
16922 case dns_rdatatype_dnskey:
16923 al = &keyadd;
16924 dl = &keydel;
16925 break;
16926 case dns_rdatatype_cdnskey:
16927 al = &ckeyadd;
16928 dl = &ckeydel;
16929 break;
16930 case dns_rdatatype_cds:
16931 al = &cdsadd;
16932 dl = &cdsdel;
16933 break;
16934 default:
16935 UNREACHABLE();
16936 }
16937 }
16938
16939 if (tuple->rdata.type == dns_rdatatype_soa) {
16940 if (tuple->op == DNS_DIFFOP_DEL) {
16941 INSIST(oldtuple == NULL);
16942 oldtuple = tuple;
16943 }
16944 if (tuple->op == DNS_DIFFOP_ADD) {
16945 INSIST(newtuple == NULL);
16946 newtuple = tuple;
16947 }
16948 }
16949
16950 /*
16951 * Split into deletions and additions.
16952 */
16953 ISC_LIST_UNLINK(diff->tuples, tuple, link);
16954 switch (tuple->op) {
16955 case DNS_DIFFOP_DEL:
16956 case DNS_DIFFOP_DELRESIGN:
16957 ISC_LIST_APPEND(*dl, tuple, link);
16958 break;
16959 case DNS_DIFFOP_ADD:
16960 case DNS_DIFFOP_ADDRESIGN:
16961 ISC_LIST_APPEND(*al, tuple, link);
16962 break;
16963 default:
16964 UNREACHABLE();
16965 }
16966 }
16967
16968 if (oldtuple != NULL && newtuple != NULL) {
16969 result = dns_rdata_tostruct(&oldtuple->rdata, &oldsoa, NULL);
16970 RUNTIME_CHECK(result == ISC_R_SUCCESS);
16971
16972 result = dns_rdata_tostruct(&newtuple->rdata, &newsoa, NULL);
16973 RUNTIME_CHECK(result == ISC_R_SUCCESS);
16974
16975 /*
16976 * If the SOA records are the same except for the serial
16977 * remove them from the diff.
16978 */
16979 if (oldtuple->ttl == newtuple->ttl &&
16980 oldsoa.refresh == newsoa.refresh &&
16981 oldsoa.retry == newsoa.retry &&
16982 oldsoa.minimum == newsoa.minimum &&
16983 oldsoa.expire == newsoa.expire &&
16984 dns_name_equal(&oldsoa.origin, &newsoa.origin) &&
16985 dns_name_equal(&oldsoa.contact, &newsoa.contact))
16986 {
16987 ISC_LIST_UNLINK(del, oldtuple, link);
16988 dns_difftuple_free(&oldtuple);
16989 ISC_LIST_UNLINK(add, newtuple, link);
16990 dns_difftuple_free(&newtuple);
16991 }
16992 }
16993
16994 /*
16995 * Filter out keys we manage but still allow TTL changes.
16996 */
16997 filter_keymaterial(seczone, &keydel, &keyadd, kasp != NULL, keyttl);
16998 filter_keymaterial(seczone, &ckeydel, &ckeyadd, kasp != NULL, ckeyttl);
16999 filter_keymaterial(seczone, &cdsdel, &cdsadd, kasp != NULL, cdsttl);
17000
17001 /*
17002 * Rebuild the diff now that we have filtered it
17003 */
17004 ISC_LIST_APPENDLIST(diff->tuples, del, link);
17005 ISC_LIST_APPENDLIST(diff->tuples, keydel, link);
17006 ISC_LIST_APPENDLIST(diff->tuples, ckeydel, link);
17007 ISC_LIST_APPENDLIST(diff->tuples, cdsdel, link);
17008 ISC_LIST_APPENDLIST(diff->tuples, add, link);
17009 ISC_LIST_APPENDLIST(diff->tuples, keyadd, link);
17010 ISC_LIST_APPENDLIST(diff->tuples, ckeyadd, link);
17011 ISC_LIST_APPENDLIST(diff->tuples, cdsadd, link);
17012
17013 if (ISC_LIST_EMPTY(diff->tuples)) {
17014 return DNS_R_UNCHANGED;
17015 }
17016
17017 /*
17018 * If there are still SOA records in the diff they can now be removed
17019 * saving the new SOA record.
17020 */
17021 if (oldtuple != NULL) {
17022 ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
17023 dns_difftuple_free(&oldtuple);
17024 }
17025
17026 if (newtuple != NULL) {
17027 ISC_LIST_UNLINK(diff->tuples, newtuple, link);
17028 *soatuple = newtuple;
17029 }
17030
17031 return ISC_R_SUCCESS;
17032 }
17033
17034 static void
17035 receive_secure_serial(void *arg) {
17036 struct rss *rss = (struct rss *)arg;
17037 dns_zone_t *zone = rss->zone;
17038 isc_result_t result = ISC_R_SUCCESS;
17039 dns_journal_t *rjournal = NULL;
17040 dns_journal_t *sjournal = NULL;
17041 uint32_t start, end = rss->serial;
17042 dns_difftuple_t *tuple = NULL, *soatuple = NULL;
17043 dns_update_log_t log = { update_log_cb, NULL };
17044 uint32_t newserial = 0, desired = 0;
17045 isc_time_t timenow;
17046 int level = ISC_LOG_ERROR;
17047
17048 ENTER;
17049
17050 LOCK_ZONE(zone);
17051
17052 /*
17053 * The receive_secure_serial() is loop-serialized for the zone. Make
17054 * sure there's no processing currently running.
17055 */
17056
17057 INSIST(zone->rss == NULL || zone->rss == rss);
17058
17059 if (zone->rss != NULL) {
17060 INSIST(zone->rss == rss);
17061 UNLOCK_ZONE(zone);
17062 } else {
17063 zone->rss = rss;
17064 dns_diff_init(zone->mctx, &zone->rss_diff);
17065
17066 /*
17067 * zone->db may be NULL, if the load from disk failed.
17068 */
17069 result = ISC_R_SUCCESS;
17070 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
17071 if (zone->db != NULL) {
17072 dns_db_attach(zone->db, &zone->rss_db);
17073 } else {
17074 result = ISC_R_FAILURE;
17075 }
17076 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17077
17078 if (result == ISC_R_SUCCESS && zone->raw != NULL) {
17079 dns_zone_attach(zone->raw, &zone->rss_raw);
17080 } else {
17081 result = ISC_R_FAILURE;
17082 }
17083
17084 UNLOCK_ZONE(zone);
17085
17086 CHECK(result);
17087
17088 /*
17089 * We first attempt to sync the raw zone to the secure zone
17090 * by using the raw zone's journal, applying all the deltas
17091 * from the latest source-serial of the secure zone up to
17092 * the current serial number of the raw zone.
17093 *
17094 * If that fails, then we'll fall back to a direct comparison
17095 * between raw and secure zones.
17096 */
17097 CHECK(dns_journal_open(zone->rss_raw->mctx,
17098 zone->rss_raw->journal,
17099 DNS_JOURNAL_WRITE, &rjournal));
17100
17101 result = dns_journal_open(zone->mctx, zone->journal,
17102 DNS_JOURNAL_READ, &sjournal);
17103 if (result != ISC_R_NOTFOUND) {
17104 CHECK(result);
17105 }
17106
17107 if (!dns_journal_get_sourceserial(rjournal, &start)) {
17108 start = dns_journal_first_serial(rjournal);
17109 dns_journal_set_sourceserial(rjournal, start);
17110 }
17111 if (sjournal != NULL) {
17112 uint32_t serial;
17113 /*
17114 * We read the secure journal first, if that
17115 * exists use its value provided it is greater
17116 * that from the raw journal.
17117 */
17118 if (dns_journal_get_sourceserial(sjournal, &serial)) {
17119 if (isc_serial_gt(serial, start)) {
17120 start = serial;
17121 }
17122 }
17123 dns_journal_destroy(&sjournal);
17124 }
17125
17126 dns_db_currentversion(zone->rss_db, &zone->rss_oldver);
17127 CHECK(dns_db_newversion(zone->rss_db, &zone->rss_newver));
17128
17129 /*
17130 * Try to apply diffs from the raw zone's journal to the secure
17131 * zone. If that fails, we recover by syncing up the databases
17132 * directly.
17133 */
17134 result = sync_secure_journal(zone, zone->rss_raw, rjournal,
17135 start, end, &soatuple,
17136 &zone->rss_diff);
17137 if (result == DNS_R_UNCHANGED) {
17138 goto cleanup;
17139 } else if (result != ISC_R_SUCCESS) {
17140 CHECK(sync_secure_db(zone, zone->rss_raw, zone->rss_db,
17141 zone->rss_oldver, &soatuple,
17142 &zone->rss_diff));
17143 }
17144
17145 CHECK(dns_diff_apply(&zone->rss_diff, zone->rss_db,
17146 zone->rss_newver));
17147
17148 if (soatuple != NULL) {
17149 uint32_t oldserial;
17150
17151 CHECK(dns_db_createsoatuple(
17152 zone->rss_db, zone->rss_oldver,
17153 zone->rss_diff.mctx, DNS_DIFFOP_DEL, &tuple));
17154 oldserial = dns_soa_getserial(&tuple->rdata);
17155 newserial = desired =
17156 dns_soa_getserial(&soatuple->rdata);
17157 if (!isc_serial_gt(newserial, oldserial)) {
17158 newserial = oldserial + 1;
17159 if (newserial == 0) {
17160 newserial++;
17161 }
17162 dns_soa_setserial(newserial, &soatuple->rdata);
17163 }
17164 CHECK(do_one_tuple(&tuple, zone->rss_db,
17165 zone->rss_newver, &zone->rss_diff));
17166 CHECK(do_one_tuple(&soatuple, zone->rss_db,
17167 zone->rss_newver, &zone->rss_diff));
17168 } else {
17169 CHECK(update_soa_serial(zone, zone->rss_db,
17170 zone->rss_newver,
17171 &zone->rss_diff, zone->mctx,
17172 zone->updatemethod));
17173 }
17174 }
17175 result = dns_update_signaturesinc(
17176 &log, zone, zone->rss_db, zone->rss_oldver, zone->rss_newver,
17177 &zone->rss_diff, zone->sigvalidityinterval, &zone->rss_state);
17178 if (result == DNS_R_CONTINUE) {
17179 if (rjournal != NULL) {
17180 dns_journal_destroy(&rjournal);
17181 }
17182 isc_async_run(zone->loop, receive_secure_serial, rss);
17183 return;
17184 }
17185
17186 /*
17187 * If something went wrong while trying to update the secure zone and
17188 * the latter was already signed before, do not apply raw zone deltas
17189 * to it as that would break existing DNSSEC signatures. However, if
17190 * the secure zone was not yet signed (e.g. because no signing keys
17191 * were created for it), commence applying raw zone deltas to it so
17192 * that contents of the raw zone and the secure zone are kept in sync.
17193 */
17194 if (result != ISC_R_SUCCESS && dns_db_issecure(zone->rss_db)) {
17195 goto cleanup;
17196 }
17197
17198 if (rjournal == NULL) {
17199 CHECK(dns_journal_open(zone->rss_raw->mctx,
17200 zone->rss_raw->journal,
17201 DNS_JOURNAL_WRITE, &rjournal));
17202 }
17203 CHECK(zone_journal(zone, &zone->rss_diff, &end,
17204 "receive_secure_serial"));
17205
17206 dns_journal_set_sourceserial(rjournal, end);
17207 dns_journal_commit(rjournal);
17208
17209 LOCK_ZONE(zone);
17210 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
17211
17212 zone->sourceserial = end;
17213 zone->sourceserialset = true;
17214 zone_needdump(zone, DNS_DUMP_DELAY);
17215
17216 /*
17217 * Set resign time to make sure it is set to the earliest
17218 * signature expiration.
17219 */
17220 set_resigntime(zone);
17221 timenow = isc_time_now();
17222 zone_settimer(zone, &timenow);
17223 UNLOCK_ZONE(zone);
17224
17225 dns_db_closeversion(zone->rss_db, &zone->rss_oldver, false);
17226 dns_db_closeversion(zone->rss_db, &zone->rss_newver, true);
17227
17228 if (newserial != 0) {
17229 dns_zone_log(zone, ISC_LOG_INFO, "serial %u (unsigned %u)",
17230 newserial, desired);
17231 }
17232
17233 cleanup:
17234 isc_mem_put(zone->mctx, rss, sizeof(*rss));
17235 zone->rss = NULL;
17236
17237 if (zone->rss_raw != NULL) {
17238 dns_zone_detach(&zone->rss_raw);
17239 }
17240 if (result != ISC_R_SUCCESS) {
17241 LOCK_ZONE(zone);
17242 set_resigntime(zone);
17243 timenow = isc_time_now();
17244 zone_settimer(zone, &timenow);
17245 UNLOCK_ZONE(zone);
17246 if (result == DNS_R_UNCHANGED) {
17247 level = ISC_LOG_INFO;
17248 }
17249 dns_zone_log(zone, level, "receive_secure_serial: %s",
17250 isc_result_totext(result));
17251 }
17252 if (tuple != NULL) {
17253 dns_difftuple_free(&tuple);
17254 }
17255 if (soatuple != NULL) {
17256 dns_difftuple_free(&soatuple);
17257 }
17258 if (zone->rss_db != NULL) {
17259 if (zone->rss_oldver != NULL) {
17260 dns_db_closeversion(zone->rss_db, &zone->rss_oldver,
17261 false);
17262 }
17263 if (zone->rss_newver != NULL) {
17264 dns_db_closeversion(zone->rss_db, &zone->rss_newver,
17265 false);
17266 }
17267 dns_db_detach(&zone->rss_db);
17268 }
17269 INSIST(zone->rss_oldver == NULL);
17270 INSIST(zone->rss_newver == NULL);
17271 if (rjournal != NULL) {
17272 dns_journal_destroy(&rjournal);
17273 }
17274 dns_diff_clear(&zone->rss_diff);
17275
17276 dns_zone_idetach(&zone);
17277 }
17278
17279 static isc_result_t
17280 zone_send_secureserial(dns_zone_t *zone, uint32_t serial) {
17281 struct rss *rss = NULL;
17282
17283 rss = isc_mem_get(zone->secure->mctx, sizeof(*rss));
17284 *rss = (struct rss){
17285 .serial = serial,
17286 .link = ISC_LINK_INITIALIZER,
17287 };
17288
17289 INSIST(LOCKED_ZONE(zone->secure));
17290 zone_iattach(zone->secure, &rss->zone);
17291 isc_async_run(zone->secure->loop, receive_secure_serial, rss);
17292
17293 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
17294 return ISC_R_SUCCESS;
17295 }
17296
17297 static isc_result_t
17298 checkandaddsoa(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
17299 dns_name_t *name, dns_rdataset_t *rdataset, uint32_t oldserial) {
17300 dns_rdata_soa_t soa;
17301 dns_rdata_t rdata = DNS_RDATA_INIT;
17302 dns_rdatalist_t temprdatalist;
17303 dns_rdataset_t temprdataset;
17304 isc_buffer_t b;
17305 isc_result_t result;
17306 unsigned char buf[DNS_SOA_BUFFERSIZE];
17307
17308 result = dns_rdataset_first(rdataset);
17309 RUNTIME_CHECK(result == ISC_R_SUCCESS);
17310 dns_rdataset_current(rdataset, &rdata);
17311 result = dns_rdata_tostruct(&rdata, &soa, NULL);
17312 RUNTIME_CHECK(result == ISC_R_SUCCESS);
17313
17314 if (isc_serial_gt(soa.serial, oldserial)) {
17315 return dns_db_addrdataset(db, node, version, 0, rdataset, 0,
17316 NULL);
17317 }
17318 /*
17319 * Always bump the serial.
17320 */
17321 oldserial++;
17322 if (oldserial == 0) {
17323 oldserial++;
17324 }
17325 soa.serial = oldserial;
17326
17327 /*
17328 * Construct a replacement rdataset.
17329 */
17330 dns_rdata_reset(&rdata);
17331 isc_buffer_init(&b, buf, sizeof(buf));
17332 result = dns_rdata_fromstruct(&rdata, rdataset->rdclass,
17333 dns_rdatatype_soa, &soa, &b);
17334 RUNTIME_CHECK(result == ISC_R_SUCCESS);
17335 dns_rdatalist_init(&temprdatalist);
17336 temprdatalist.rdclass = rdata.rdclass;
17337 temprdatalist.type = rdata.type;
17338 temprdatalist.ttl = rdataset->ttl;
17339 ISC_LIST_APPEND(temprdatalist.rdata, &rdata, link);
17340
17341 dns_rdataset_init(&temprdataset);
17342 dns_rdatalist_tordataset(&temprdatalist, &temprdataset);
17343
17344 dns_rdataset_getownercase(rdataset, name);
17345 dns_rdataset_setownercase(&temprdataset, name);
17346 return dns_db_addrdataset(db, node, version, 0, &temprdataset, 0, NULL);
17347 }
17348
17349 /*
17350 * This function should populate an nsec3paramlist_t with the
17351 * nsecparam_t data from a zone.
17352 */
17353 static isc_result_t
17354 save_nsec3param(dns_zone_t *zone, nsec3paramlist_t *nsec3list) {
17355 isc_result_t result;
17356 dns_dbnode_t *node = NULL;
17357 dns_rdataset_t rdataset, prdataset;
17358 dns_dbversion_t *version = NULL;
17359 nsec3param_t *nsec3param = NULL;
17360 nsec3param_t *nsec3p = NULL;
17361 nsec3param_t *next;
17362 dns_db_t *db = NULL;
17363 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
17364
17365 REQUIRE(DNS_ZONE_VALID(zone));
17366 REQUIRE(nsec3list != NULL);
17367 REQUIRE(ISC_LIST_EMPTY(*nsec3list));
17368
17369 dns_rdataset_init(&rdataset);
17370 dns_rdataset_init(&prdataset);
17371
17372 dns_db_attach(zone->db, &db);
17373 CHECK(dns_db_getoriginnode(db, &node));
17374
17375 dns_db_currentversion(db, &version);
17376 result = dns_db_findrdataset(db, node, version,
17377 dns_rdatatype_nsec3param,
17378 dns_rdatatype_none, 0, &rdataset, NULL);
17379
17380 if (result != ISC_R_SUCCESS) {
17381 goto getprivate;
17382 }
17383
17384 /*
17385 * Walk nsec3param rdataset making a list of parameters (note that
17386 * multiple simultaneous nsec3 chains are annoyingly legal -- this
17387 * is why we use an nsec3list, even though we will usually only
17388 * have one).
17389 */
17390 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
17391 result = dns_rdataset_next(&rdataset))
17392 {
17393 dns_rdata_t rdata = DNS_RDATA_INIT;
17394 dns_rdata_t private = DNS_RDATA_INIT;
17395
17396 dns_rdataset_current(&rdataset, &rdata);
17397 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
17398 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
17399 "looping through nsec3param data");
17400 nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
17401 ISC_LINK_INIT(nsec3param, link);
17402
17403 /*
17404 * now transfer the data from the rdata to
17405 * the nsec3param
17406 */
17407 dns_nsec3param_toprivate(&rdata, &private, zone->privatetype,
17408 nsec3param->data,
17409 sizeof(nsec3param->data));
17410 nsec3param->length = private.length;
17411 ISC_LIST_APPEND(*nsec3list, nsec3param, link);
17412 }
17413
17414 getprivate:
17415 result = dns_db_findrdataset(db, node, version, zone->privatetype,
17416 dns_rdatatype_none, 0, &prdataset, NULL);
17417 if (result != ISC_R_SUCCESS) {
17418 goto done;
17419 }
17420
17421 /*
17422 * walk private type records, converting them to nsec3 parameters
17423 * using dns_nsec3param_fromprivate(), do the right thing based on
17424 * CREATE and REMOVE flags
17425 */
17426 for (result = dns_rdataset_first(&prdataset); result == ISC_R_SUCCESS;
17427 result = dns_rdataset_next(&prdataset))
17428 {
17429 dns_rdata_t rdata = DNS_RDATA_INIT;
17430 dns_rdata_t private = DNS_RDATA_INIT;
17431
17432 dns_rdataset_current(&prdataset, &private);
17433 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
17434 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
17435 "looping through nsec3param private data");
17436
17437 /*
17438 * Do we have a valid private record?
17439 */
17440 if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
17441 sizeof(buf)))
17442 {
17443 continue;
17444 }
17445
17446 /*
17447 * Remove any NSEC3PARAM records scheduled to be removed.
17448 */
17449 if (NSEC3REMOVE(rdata.data[1])) {
17450 /*
17451 * Zero out the flags.
17452 */
17453 rdata.data[1] = 0;
17454
17455 for (nsec3p = ISC_LIST_HEAD(*nsec3list); nsec3p != NULL;
17456 nsec3p = next)
17457 {
17458 next = ISC_LIST_NEXT(nsec3p, link);
17459
17460 if (nsec3p->length ==
17461 (unsigned int)rdata.length + 1 &&
17462 memcmp(rdata.data, nsec3p->data + 1,
17463 nsec3p->length - 1) == 0)
17464 {
17465 ISC_LIST_UNLINK(*nsec3list, nsec3p,
17466 link);
17467 isc_mem_put(zone->mctx, nsec3p,
17468 sizeof(nsec3param_t));
17469 }
17470 }
17471 continue;
17472 }
17473
17474 nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
17475 ISC_LINK_INIT(nsec3param, link);
17476
17477 /*
17478 * Copy the remaining private records so the nsec/nsec3
17479 * chain gets created.
17480 */
17481 INSIST(private.length <= sizeof(nsec3param->data));
17482 memmove(nsec3param->data, private.data, private.length);
17483 nsec3param->length = private.length;
17484 ISC_LIST_APPEND(*nsec3list, nsec3param, link);
17485 }
17486
17487 done:
17488 if (result == ISC_R_NOMORE || result == ISC_R_NOTFOUND) {
17489 result = ISC_R_SUCCESS;
17490 }
17491
17492 cleanup:
17493 if (node != NULL) {
17494 dns_db_detachnode(db, &node);
17495 }
17496 if (version != NULL) {
17497 dns_db_closeversion(db, &version, false);
17498 }
17499 if (db != NULL) {
17500 dns_db_detach(&db);
17501 }
17502 if (dns_rdataset_isassociated(&rdataset)) {
17503 dns_rdataset_disassociate(&rdataset);
17504 }
17505 if (dns_rdataset_isassociated(&prdataset)) {
17506 dns_rdataset_disassociate(&prdataset);
17507 }
17508 return result;
17509 }
17510
17511 /*
17512 * Populate new zone db with private type records found by save_nsec3param().
17513 */
17514 static isc_result_t
17515 restore_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
17516 nsec3paramlist_t *nsec3list) {
17517 isc_result_t result = ISC_R_SUCCESS;
17518 dns_diff_t diff;
17519 dns_rdata_t rdata;
17520 nsec3param_t *nsec3p = NULL;
17521 nsec3param_t *next;
17522
17523 REQUIRE(DNS_ZONE_VALID(zone));
17524 REQUIRE(!ISC_LIST_EMPTY(*nsec3list));
17525
17526 dns_diff_init(zone->mctx, &diff);
17527
17528 /*
17529 * Loop through the list of private-type records, set the INITIAL
17530 * and CREATE flags, and the add the record to the apex of the tree
17531 * in db.
17532 */
17533 for (nsec3p = ISC_LIST_HEAD(*nsec3list); nsec3p != NULL; nsec3p = next)
17534 {
17535 next = ISC_LIST_NEXT(nsec3p, link);
17536 dns_rdata_init(&rdata);
17537 nsec3p->data[2] = DNS_NSEC3FLAG_CREATE | DNS_NSEC3FLAG_INITIAL;
17538 rdata.length = nsec3p->length;
17539 rdata.data = nsec3p->data;
17540 rdata.type = zone->privatetype;
17541 rdata.rdclass = zone->rdclass;
17542 result = update_one_rr(db, version, &diff, DNS_DIFFOP_ADD,
17543 &zone->origin, 0, &rdata);
17544 if (result != ISC_R_SUCCESS) {
17545 break;
17546 }
17547 }
17548
17549 dns_diff_clear(&diff);
17550 return result;
17551 }
17552
17553 static isc_result_t
17554 copy_non_dnssec_records(dns_db_t *db, dns_db_t *version, dns_db_t *rawdb,
17555 dns_dbiterator_t *dbiterator, unsigned int *oldserial) {
17556 dns_dbnode_t *rawnode = NULL, *node = NULL;
17557 dns_fixedname_t fixed;
17558 dns_name_t *name = dns_fixedname_initname(&fixed);
17559 dns_rdataset_t rdataset;
17560 dns_rdatasetiter_t *rdsit = NULL;
17561 isc_result_t result;
17562
17563 result = dns_dbiterator_current(dbiterator, &rawnode, name);
17564 if (result != ISC_R_SUCCESS) {
17565 return ISC_R_SUCCESS;
17566 }
17567
17568 dns_dbiterator_pause(dbiterator);
17569
17570 result = dns_db_findnode(db, name, true, &node);
17571 if (result != ISC_R_SUCCESS) {
17572 goto cleanup;
17573 }
17574
17575 result = dns_db_allrdatasets(rawdb, rawnode, NULL, 0, 0, &rdsit);
17576 if (result != ISC_R_SUCCESS) {
17577 goto cleanup;
17578 }
17579
17580 dns_rdataset_init(&rdataset);
17581
17582 for (result = dns_rdatasetiter_first(rdsit); result == ISC_R_SUCCESS;
17583 result = dns_rdatasetiter_next(rdsit))
17584 {
17585 dns_rdatasetiter_current(rdsit, &rdataset);
17586 if (rdataset.type == dns_rdatatype_nsec ||
17587 rdataset.type == dns_rdatatype_rrsig ||
17588 rdataset.type == dns_rdatatype_nsec3 ||
17589 rdataset.type == dns_rdatatype_nsec3param)
17590 {
17591 dns_rdataset_disassociate(&rdataset);
17592 continue;
17593 }
17594 /*
17595 * Allow DNSKEY, CDNSKEY, CDS because users should be able to
17596 * update the zone with these records from a different provider,
17597 * and thus they may exist in the raw version of the zone.
17598 */
17599
17600 if (rdataset.type == dns_rdatatype_soa && oldserial != NULL) {
17601 result = checkandaddsoa(db, node, version, name,
17602 &rdataset, *oldserial);
17603 } else {
17604 result = dns_db_addrdataset(db, node, version, 0,
17605 &rdataset, 0, NULL);
17606 }
17607 dns_rdataset_disassociate(&rdataset);
17608 if (result != ISC_R_SUCCESS) {
17609 goto cleanup;
17610 }
17611 }
17612 if (result == ISC_R_NOMORE) {
17613 result = ISC_R_SUCCESS;
17614 }
17615
17616 cleanup:
17617 if (rdsit != NULL) {
17618 dns_rdatasetiter_destroy(&rdsit);
17619 }
17620 if (rawnode) {
17621 dns_db_detachnode(rawdb, &rawnode);
17622 }
17623 if (node) {
17624 dns_db_detachnode(db, &node);
17625 }
17626 return result;
17627 }
17628
17629 static void
17630 receive_secure_db(void *arg) {
17631 isc_result_t result;
17632 struct rss *rss = (struct rss *)arg;
17633 dns_zone_t *zone = rss->zone;
17634 dns_db_t *rawdb = rss->db, *db = NULL;
17635 dns_dbiterator_t *dbiterator = NULL;
17636 dns_dbversion_t *version = NULL;
17637 isc_time_t loadtime;
17638 unsigned int oldserial = 0, *oldserialp = NULL;
17639 nsec3paramlist_t nsec3list;
17640
17641 ISC_LIST_INIT(nsec3list);
17642
17643 LOCK_ZONE(zone);
17644 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || !inline_secure(zone)) {
17645 CHECK(ISC_R_SHUTTINGDOWN);
17646 }
17647
17648 loadtime = isc_time_now();
17649 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
17650 if (zone->db != NULL) {
17651 result = dns_db_getsoaserial(zone->db, NULL, &oldserial);
17652 if (result == ISC_R_SUCCESS) {
17653 oldserialp = &oldserial;
17654 }
17655
17656 /*
17657 * assemble nsec3parameters from the old zone, and set a flag
17658 * if any are found
17659 */
17660 result = save_nsec3param(zone, &nsec3list);
17661 if (result != ISC_R_SUCCESS) {
17662 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17663 goto cleanup;
17664 }
17665 }
17666 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17667
17668 CHECK(dns_db_create(zone->mctx, zone->db_argv[0], &zone->origin,
17669 dns_dbtype_zone, zone->rdclass, zone->db_argc - 1,
17670 zone->db_argv + 1, &db));
17671
17672 result = dns_db_setgluecachestats(db, zone->gluecachestats);
17673 if (result != ISC_R_NOTIMPLEMENTED) {
17674 CHECK(result);
17675 }
17676
17677 CHECK(dns_db_newversion(db, &version));
17678 CHECK(dns_db_createiterator(rawdb, DNS_DB_NONSEC3, &dbiterator));
17679
17680 for (result = dns_dbiterator_first(dbiterator); result == ISC_R_SUCCESS;
17681 result = dns_dbiterator_next(dbiterator))
17682 {
17683 CHECK(copy_non_dnssec_records(db, version, rawdb, dbiterator,
17684 oldserialp));
17685 }
17686 dns_dbiterator_destroy(&dbiterator);
17687 if (result != ISC_R_NOMORE) {
17688 goto cleanup;
17689 }
17690
17691 /*
17692 * Call restore_nsec3param() to create private-type records from
17693 * the old nsec3 parameters and insert them into db
17694 */
17695 if (!ISC_LIST_EMPTY(nsec3list)) {
17696 CHECK(restore_nsec3param(zone, db, version, &nsec3list));
17697 }
17698
17699 dns_db_closeversion(db, &version, true);
17700
17701 /*
17702 * Lock hierarchy: zmgr, zone, raw.
17703 */
17704 INSIST(zone != zone->raw);
17705 LOCK_ZONE(zone->raw);
17706 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
17707 result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
17708 zone_needdump(zone, 0); /* XXXMPA */
17709 UNLOCK_ZONE(zone->raw);
17710
17711 /*
17712 * Process any queued NSEC3PARAM change requests.
17713 */
17714 process_zone_setnsec3param(zone);
17715
17716 cleanup:
17717 UNLOCK_ZONE(zone);
17718 if (dbiterator != NULL) {
17719 dns_dbiterator_destroy(&dbiterator);
17720 }
17721 if (result != ISC_R_SUCCESS) {
17722 dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_db: %s",
17723 isc_result_totext(result));
17724 }
17725
17726 while (!ISC_LIST_EMPTY(nsec3list)) {
17727 nsec3param_t *nsec3p;
17728 nsec3p = ISC_LIST_HEAD(nsec3list);
17729 ISC_LIST_UNLINK(nsec3list, nsec3p, link);
17730 isc_mem_put(zone->mctx, nsec3p, sizeof(nsec3param_t));
17731 }
17732 if (db != NULL) {
17733 if (version != NULL) {
17734 dns_db_closeversion(db, &version, false);
17735 }
17736 dns_db_detach(&db);
17737 }
17738
17739 dns_db_detach(&rawdb);
17740 isc_mem_put(zone->mctx, rss, sizeof(*rss));
17741 dns_zone_idetach(&zone);
17742
17743 INSIST(version == NULL);
17744 }
17745
17746 static isc_result_t
17747 zone_send_securedb(dns_zone_t *zone, dns_db_t *db) {
17748 struct rss *rss = NULL;
17749
17750 rss = isc_mem_get(zone->secure->mctx, sizeof(*rss));
17751 *rss = (struct rss){ .link = ISC_LINK_INITIALIZER };
17752
17753 INSIST(LOCKED_ZONE(zone->secure));
17754 zone_iattach(zone->secure, &rss->zone);
17755 dns_db_attach(db, &rss->db);
17756 isc_async_run(zone->secure->loop, receive_secure_db, rss);
17757
17758 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
17759 return ISC_R_SUCCESS;
17760 }
17761
17762 isc_result_t
17763 dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump) {
17764 isc_result_t result;
17765 dns_zone_t *secure = NULL;
17766
17767 REQUIRE(DNS_ZONE_VALID(zone));
17768 again:
17769 LOCK_ZONE(zone);
17770 if (inline_raw(zone)) {
17771 secure = zone->secure;
17772 INSIST(secure != zone);
17773 TRYLOCK_ZONE(result, secure);
17774 if (result != ISC_R_SUCCESS) {
17775 UNLOCK_ZONE(zone);
17776 secure = NULL;
17777 isc_thread_yield();
17778 goto again;
17779 }
17780 }
17781 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
17782 result = zone_replacedb(zone, db, dump);
17783 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
17784 if (secure != NULL) {
17785 UNLOCK_ZONE(secure);
17786 }
17787 UNLOCK_ZONE(zone);
17788 return result;
17789 }
17790
17791 static isc_result_t
17792 zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump) {
17793 dns_dbversion_t *ver;
17794 isc_result_t result;
17795 unsigned int soacount = 0;
17796 unsigned int nscount = 0;
17797
17798 /*
17799 * 'zone' and 'zone->db' locked by caller.
17800 */
17801 REQUIRE(DNS_ZONE_VALID(zone));
17802 REQUIRE(LOCKED_ZONE(zone));
17803 if (inline_raw(zone)) {
17804 REQUIRE(LOCKED_ZONE(zone->secure));
17805 }
17806
17807 result = zone_get_from_db(zone, db, &nscount, &soacount, NULL, NULL,
17808 NULL, NULL, NULL, NULL, NULL);
17809 if (result == ISC_R_SUCCESS) {
17810 if (soacount != 1) {
17811 dns_zone_log(zone, ISC_LOG_ERROR, "has %d SOA records",
17812 soacount);
17813 result = DNS_R_BADZONE;
17814 }
17815 if (nscount == 0 && zone->type != dns_zone_key) {
17816 dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records");
17817 result = DNS_R_BADZONE;
17818 }
17819 if (result != ISC_R_SUCCESS) {
17820 return result;
17821 }
17822 } else {
17823 dns_zone_log(zone, ISC_LOG_ERROR,
17824 "retrieving SOA and NS records failed: %s",
17825 isc_result_totext(result));
17826 return result;
17827 }
17828
17829 result = check_nsec3param(zone, db);
17830 if (result != ISC_R_SUCCESS) {
17831 return result;
17832 }
17833
17834 ver = NULL;
17835 dns_db_currentversion(db, &ver);
17836
17837 /*
17838 * The initial version of a secondary zone is always dumped;
17839 * subsequent versions may be journaled instead if this
17840 * is enabled in the configuration.
17841 */
17842 if (zone->db != NULL && zone->journal != NULL &&
17843 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
17844 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER))
17845 {
17846 uint32_t serial, oldserial;
17847
17848 dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
17849
17850 result = dns_db_getsoaserial(db, ver, &serial);
17851 if (result != ISC_R_SUCCESS) {
17852 dns_zone_log(zone, ISC_LOG_ERROR,
17853 "ixfr-from-differences: unable to get "
17854 "new serial");
17855 goto fail;
17856 }
17857
17858 /*
17859 * This is checked in zone_postload() for primary zones.
17860 */
17861 result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL,
17862 &oldserial, NULL, NULL, NULL, NULL,
17863 NULL);
17864 RUNTIME_CHECK(result == ISC_R_SUCCESS);
17865 RUNTIME_CHECK(soacount > 0U);
17866 if ((zone->type == dns_zone_secondary ||
17867 (zone->type == dns_zone_redirect &&
17868 dns_remote_addresses(&zone->primaries) != NULL)) &&
17869 !isc_serial_gt(serial, oldserial))
17870 {
17871 uint32_t serialmin, serialmax;
17872 serialmin = (oldserial + 1) & 0xffffffffU;
17873 serialmax = (oldserial + 0x7fffffffU) & 0xffffffffU;
17874 dns_zone_log(zone, ISC_LOG_ERROR,
17875 "ixfr-from-differences: failed: "
17876 "new serial (%u) out of range [%u - %u]",
17877 serial, serialmin, serialmax);
17878 result = ISC_R_RANGE;
17879 goto fail;
17880 }
17881
17882 result = dns_db_diff(zone->mctx, db, ver, zone->db, NULL,
17883 zone->journal);
17884 if (result != ISC_R_SUCCESS) {
17885 char strbuf[ISC_STRERRORSIZE];
17886 strerror_r(errno, strbuf, sizeof(strbuf));
17887 dns_zone_log(zone, ISC_LOG_ERROR,
17888 "ixfr-from-differences: failed: "
17889 "%s",
17890 strbuf);
17891 goto fallback;
17892 }
17893 if (dump) {
17894 zone_needdump(zone, DNS_DUMP_DELAY);
17895 } else {
17896 zone_journal_compact(zone, zone->db, serial);
17897 }
17898 if (zone->type == dns_zone_primary && inline_raw(zone)) {
17899 zone_send_secureserial(zone, serial);
17900 }
17901 } else {
17902 fallback:
17903 if (dump && zone->masterfile != NULL) {
17904 /*
17905 * If DNS_ZONEFLG_FORCEXFER was set we don't want
17906 * to keep the old masterfile.
17907 */
17908 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) &&
17909 remove(zone->masterfile) < 0 && errno != ENOENT)
17910 {
17911 char strbuf[ISC_STRERRORSIZE];
17912 strerror_r(errno, strbuf, sizeof(strbuf));
17913 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
17914 DNS_LOGMODULE_ZONE,
17915 ISC_LOG_WARNING,
17916 "unable to remove masterfile "
17917 "'%s': '%s'",
17918 zone->masterfile, strbuf);
17919 }
17920 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0) {
17921 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NODELAY);
17922 } else {
17923 zone_needdump(zone, 0);
17924 }
17925 }
17926 if (dump && zone->journal != NULL) {
17927 /*
17928 * The in-memory database just changed, and
17929 * because 'dump' is set, it didn't change by
17930 * being loaded from disk. Also, we have not
17931 * journaled diffs for this change.
17932 * Therefore, the on-disk journal is missing
17933 * the deltas for this change. Since it can
17934 * no longer be used to bring the zone
17935 * up-to-date, it is useless and should be
17936 * removed.
17937 */
17938 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
17939 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
17940 "removing journal file");
17941 if (remove(zone->journal) < 0 && errno != ENOENT) {
17942 char strbuf[ISC_STRERRORSIZE];
17943 strerror_r(errno, strbuf, sizeof(strbuf));
17944 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
17945 DNS_LOGMODULE_ZONE,
17946 ISC_LOG_WARNING,
17947 "unable to remove journal "
17948 "'%s': '%s'",
17949 zone->journal, strbuf);
17950 }
17951 }
17952
17953 if (inline_raw(zone)) {
17954 zone_send_securedb(zone, db);
17955 }
17956 }
17957
17958 dns_db_closeversion(db, &ver, false);
17959
17960 dns_zone_log(zone, ISC_LOG_DEBUG(3), "replacing zone database");
17961
17962 if (zone->db != NULL) {
17963 zone_detachdb(zone);
17964 }
17965 zone_attachdb(zone, db);
17966 dns_db_setloop(zone->db, zone->loop);
17967 dns_db_setmaxrrperset(zone->db, zone->maxrrperset);
17968 dns_db_setmaxtypepername(zone->db, zone->maxtypepername);
17969 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED | DNS_ZONEFLG_NEEDNOTIFY);
17970 return ISC_R_SUCCESS;
17971
17972 fail:
17973 dns_db_closeversion(db, &ver, false);
17974 return result;
17975 }
17976
17977 /* The caller must hold the dblock as a writer. */
17978 static void
17979 zone_attachdb(dns_zone_t *zone, dns_db_t *db) {
17980 REQUIRE(zone->db == NULL && db != NULL);
17981
17982 dns_db_attach(db, &zone->db);
17983 }
17984
17985 /* The caller must hold the dblock as a writer. */
17986 static void
17987 zone_detachdb(dns_zone_t *zone) {
17988 REQUIRE(zone->db != NULL);
17989
17990 dns_zone_rpz_disable_db(zone, zone->db);
17991 dns_zone_catz_disable_db(zone, zone->db);
17992 dns_db_detach(&zone->db);
17993 }
17994
17995 static void
17996 zone_xfrdone(dns_zone_t *zone, uint32_t *expireopt, isc_result_t result) {
17997 isc_time_t now, expiretime;
17998 bool again = false;
17999 unsigned int soacount;
18000 unsigned int nscount;
18001 uint32_t serial, refresh, retry, expire, minimum, soattl, oldexpire;
18002 isc_result_t xfrresult = result;
18003 bool free_needed;
18004 dns_zone_t *secure = NULL;
18005
18006 REQUIRE(DNS_ZONE_VALID(zone));
18007
18008 dns_zone_logc(
18009 zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(1),
18010 expireopt == NULL ? "zone transfer finished: %s"
18011 : "zone transfer finished: %s, expire=%u",
18012 isc_result_totext(result), expireopt != NULL ? *expireopt : 0);
18013
18014 /*
18015 * Obtaining a lock on the zone->secure (see zone_send_secureserial)
18016 * could result in a deadlock due to a LOR so we will spin if we
18017 * can't obtain both locks.
18018 */
18019 again:
18020 LOCK_ZONE(zone);
18021 if (inline_raw(zone)) {
18022 secure = zone->secure;
18023 INSIST(secure != zone);
18024 TRYLOCK_ZONE(result, secure);
18025 if (result != ISC_R_SUCCESS) {
18026 UNLOCK_ZONE(zone);
18027 secure = NULL;
18028 isc_thread_yield();
18029 goto again;
18030 }
18031 }
18032
18033 INSIST(DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH));
18034 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
18035 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
18036
18037 now = isc_time_now();
18038 switch (xfrresult) {
18039 case ISC_R_SUCCESS:
18040 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
18041 FALLTHROUGH;
18042 case DNS_R_UPTODATE:
18043 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FORCEXFER |
18044 DNS_ZONEFLG_FIRSTREFRESH);
18045 /*
18046 * Has the zone expired underneath us?
18047 */
18048 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
18049 if (zone->db == NULL) {
18050 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
18051 goto same_primary;
18052 }
18053
18054 oldexpire = zone->expire;
18055
18056 /*
18057 * Update the zone structure's data from the actual
18058 * SOA received.
18059 */
18060 nscount = 0;
18061 soacount = 0;
18062 INSIST(zone->db != NULL);
18063 result = zone_get_from_db(zone, zone->db, &nscount, &soacount,
18064 &soattl, &serial, &refresh, &retry,
18065 &expire, &minimum, NULL);
18066 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
18067 if (result == ISC_R_SUCCESS) {
18068 if (soacount != 1) {
18069 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
18070 ISC_LOG_ERROR,
18071 "transferred zone "
18072 "has %d SOA records",
18073 soacount);
18074 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
18075 {
18076 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
18077 zone->retry = DNS_ZONE_DEFAULTRETRY;
18078 }
18079 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
18080 zone_unload(zone);
18081 goto next_primary;
18082 }
18083 if (nscount == 0) {
18084 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
18085 ISC_LOG_ERROR,
18086 "transferred zone "
18087 "has no NS records");
18088 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
18089 {
18090 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
18091 zone->retry = DNS_ZONE_DEFAULTRETRY;
18092 }
18093 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
18094 zone_unload(zone);
18095 goto next_primary;
18096 }
18097 zone->refresh = RANGE(refresh, zone->minrefresh,
18098 zone->maxrefresh);
18099 zone->retry = RANGE(retry, zone->minretry,
18100 zone->maxretry);
18101 zone->expire = RANGE(expire,
18102 zone->refresh + zone->retry,
18103 DNS_MAX_EXPIRE);
18104 zone->soattl = soattl;
18105 zone->minimum = minimum;
18106 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
18107 }
18108
18109 /*
18110 * Set our next refresh time.
18111 */
18112 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
18113 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
18114 zone->refreshtime = now;
18115 } else {
18116 DNS_ZONE_JITTER_ADD(&now, zone->refresh,
18117 &zone->refreshtime);
18118 }
18119
18120 /*
18121 * Set our next expire time. If the parent returned
18122 * an EXPIRE option use that to update zone->expiretime.
18123 */
18124 expire = zone->expire;
18125 if (expireopt != NULL && *expireopt < expire) {
18126 expire = *expireopt;
18127 }
18128 DNS_ZONE_TIME_ADD(&now, expire, &expiretime);
18129 if (oldexpire != zone->expire ||
18130 isc_time_compare(&expiretime, &zone->expiretime) > 0)
18131 {
18132 zone->expiretime = expiretime;
18133 }
18134
18135 /*
18136 * Set loadtime.
18137 */
18138 zone->loadtime = now;
18139
18140 if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS) {
18141 char buf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
18142 if (zone->tsigkey != NULL) {
18143 char namebuf[DNS_NAME_FORMATSIZE];
18144 dns_name_format(zone->tsigkey->name, namebuf,
18145 sizeof(namebuf));
18146 snprintf(buf, sizeof(buf), ": TSIG '%s'",
18147 namebuf);
18148 } else {
18149 buf[0] = '\0';
18150 }
18151 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
18152 ISC_LOG_INFO, "transferred serial %u%s",
18153 serial, buf);
18154 if (inline_raw(zone)) {
18155 zone_send_secureserial(zone, serial);
18156 }
18157 }
18158
18159 /*
18160 * This is not necessary if we just performed a AXFR
18161 * however it is necessary for an IXFR / UPTODATE and
18162 * won't hurt with an AXFR.
18163 */
18164 if (zone->masterfile != NULL || zone->journal != NULL) {
18165 unsigned int delay = DNS_DUMP_DELAY;
18166 isc_interval_t i;
18167 isc_time_t when;
18168
18169 /*
18170 * Compute effective modification time.
18171 */
18172 isc_interval_set(&i, zone->expire, 0);
18173 result = isc_time_subtract(&zone->expiretime, &i,
18174 &when);
18175 if (result != ISC_R_SUCCESS) {
18176 when = now;
18177 }
18178
18179 result = ISC_R_FAILURE;
18180 if (zone->journal != NULL) {
18181 result = isc_file_settime(zone->journal, &when);
18182 }
18183 if (result != ISC_R_SUCCESS && zone->masterfile != NULL)
18184 {
18185 result = isc_file_settime(zone->masterfile,
18186 &when);
18187 }
18188
18189 if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NODELAY) != 0) ||
18190 result == ISC_R_FILENOTFOUND)
18191 {
18192 delay = 0;
18193 }
18194
18195 if ((result == ISC_R_SUCCESS ||
18196 result == ISC_R_FILENOTFOUND) &&
18197 zone->masterfile != NULL)
18198 {
18199 zone_needdump(zone, delay);
18200 } else if (result != ISC_R_SUCCESS) {
18201 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
18202 ISC_LOG_ERROR,
18203 "transfer: could not set file "
18204 "modification time of '%s': %s",
18205 zone->masterfile,
18206 isc_result_totext(result));
18207 }
18208 }
18209 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NODELAY);
18210 inc_stats(zone, dns_zonestatscounter_xfrsuccess);
18211 break;
18212
18213 case DNS_R_BADIXFR:
18214 /* Force retry with AXFR. */
18215 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOIXFR);
18216 goto same_primary;
18217
18218 case DNS_R_TOOMANYRECORDS:
18219 case DNS_R_VERIFYFAILURE:
18220 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
18221 inc_stats(zone, dns_zonestatscounter_xfrfail);
18222 break;
18223
18224 case ISC_R_SHUTTINGDOWN:
18225 dns_remote_reset(&zone->primaries, true);
18226 break;
18227
18228 default:
18229 next_primary:
18230 /*
18231 * Skip to next failed / untried primary.
18232 */
18233 dns_remote_next(&zone->primaries, true);
18234 same_primary:
18235 if (dns_remote_done(&zone->primaries)) {
18236 dns_remote_reset(&zone->primaries, false);
18237 } else {
18238 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
18239 again = true;
18240 }
18241 inc_stats(zone, dns_zonestatscounter_xfrfail);
18242 break;
18243 }
18244 zone_settimer(zone, &now);
18245
18246 /*
18247 * We are called as the done callback of a zone
18248 * transfer object that just entered its shutting-down state or
18249 * failed to start. Since we are no longer responsible for shutting
18250 * it down, we can detach our reference.
18251 */
18252 if (zone->xfr != NULL) {
18253 dns_xfrin_detach(&zone->xfr);
18254 }
18255
18256 if (zone->tsigkey != NULL) {
18257 dns_tsigkey_detach(&zone->tsigkey);
18258 }
18259
18260 if (zone->transport != NULL) {
18261 dns_transport_detach(&zone->transport);
18262 }
18263
18264 /*
18265 * Handle any deferred journal compaction.
18266 */
18267 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDCOMPACT)) {
18268 dns_db_t *db = NULL;
18269 if (dns_zone_getdb(zone, &db) == ISC_R_SUCCESS) {
18270 zone_journal_compact(zone, db, zone->compact_serial);
18271 dns_db_detach(&db);
18272 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
18273 }
18274 }
18275
18276 if (secure != NULL) {
18277 UNLOCK_ZONE(secure);
18278 }
18279 /*
18280 * This transfer finishing freed up a transfer quota slot.
18281 * Let any other zones waiting for quota have it.
18282 */
18283 if (zone->zmgr != NULL &&
18284 zone->statelist == &zone->zmgr->xfrin_in_progress)
18285 {
18286 UNLOCK_ZONE(zone);
18287 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
18288 ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
18289 zone->statelist = NULL;
18290 zmgr_resume_xfrs(zone->zmgr, false);
18291 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
18292 LOCK_ZONE(zone);
18293 }
18294
18295 /*
18296 * Retry with a different server if necessary.
18297 */
18298 if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
18299 queue_soa_query(zone);
18300 }
18301
18302 isc_refcount_decrement(&zone->irefs);
18303 free_needed = exit_check(zone);
18304 UNLOCK_ZONE(zone);
18305 if (free_needed) {
18306 zone_free(zone);
18307 }
18308 }
18309
18310 static void
18311 zone_loaddone(void *arg, isc_result_t result) {
18312 dns_load_t *load = arg;
18313 dns_zone_t *zone;
18314 isc_result_t tresult;
18315 dns_zone_t *secure = NULL;
18316
18317 zone = load->zone;
18318
18319 ENTER;
18320
18321 /*
18322 * If zone loading failed, remove the update db callbacks prior
18323 * to calling the list of callbacks in the zone load structure.
18324 */
18325 if (result != ISC_R_SUCCESS) {
18326 dns_zone_rpz_disable_db(zone, load->db);
18327 dns_zone_catz_disable_db(zone, load->db);
18328 }
18329
18330 tresult = dns_db_endload(load->db, &load->callbacks);
18331 if (tresult != ISC_R_SUCCESS &&
18332 (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
18333 {
18334 result = tresult;
18335 }
18336
18337 /*
18338 * Lock hierarchy: zmgr, zone, raw.
18339 */
18340 again:
18341 LOCK_ZONE(zone);
18342 INSIST(zone != zone->raw);
18343 if (inline_secure(zone)) {
18344 LOCK_ZONE(zone->raw);
18345 } else if (inline_raw(zone)) {
18346 secure = zone->secure;
18347 TRYLOCK_ZONE(tresult, secure);
18348 if (tresult != ISC_R_SUCCESS) {
18349 UNLOCK_ZONE(zone);
18350 secure = NULL;
18351 isc_thread_yield();
18352 goto again;
18353 }
18354 }
18355 (void)zone_postload(zone, load->db, load->loadtime, result);
18356 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADING);
18357 zone_idetach(&load->callbacks.zone);
18358 /*
18359 * Leave the zone frozen if the reload fails.
18360 */
18361 if ((result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) &&
18362 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_THAW))
18363 {
18364 zone->update_disabled = false;
18365 }
18366 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_THAW);
18367 if (inline_secure(zone)) {
18368 UNLOCK_ZONE(zone->raw);
18369 } else if (secure != NULL) {
18370 UNLOCK_ZONE(secure);
18371 }
18372 UNLOCK_ZONE(zone);
18373
18374 dns_db_detach(&load->db);
18375 if (zone->loadctx != NULL) {
18376 dns_loadctx_detach(&zone->loadctx);
18377 }
18378 isc_mem_put(zone->mctx, load, sizeof(*load));
18379
18380 dns_zone_idetach(&zone);
18381 }
18382
18383 void
18384 dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) {
18385 REQUIRE(DNS_ZONE_VALID(zone));
18386 REQUIRE(table != NULL);
18387 REQUIRE(*table == NULL);
18388
18389 LOCK_ZONE(zone);
18390 if (zone->ssutable != NULL) {
18391 dns_ssutable_attach(zone->ssutable, table);
18392 }
18393 UNLOCK_ZONE(zone);
18394 }
18395
18396 void
18397 dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
18398 REQUIRE(DNS_ZONE_VALID(zone));
18399
18400 LOCK_ZONE(zone);
18401 if (zone->ssutable != NULL) {
18402 dns_ssutable_detach(&zone->ssutable);
18403 }
18404 if (table != NULL) {
18405 dns_ssutable_attach(table, &zone->ssutable);
18406 }
18407 UNLOCK_ZONE(zone);
18408 }
18409
18410 void
18411 dns_zone_setsigvalidityinterval(dns_zone_t *zone, uint32_t interval) {
18412 REQUIRE(DNS_ZONE_VALID(zone));
18413
18414 zone->sigvalidityinterval = interval;
18415 }
18416
18417 uint32_t
18418 dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
18419 REQUIRE(DNS_ZONE_VALID(zone));
18420
18421 return zone->sigvalidityinterval;
18422 }
18423
18424 void
18425 dns_zone_setkeyvalidityinterval(dns_zone_t *zone, uint32_t interval) {
18426 REQUIRE(DNS_ZONE_VALID(zone));
18427
18428 zone->keyvalidityinterval = interval;
18429 }
18430
18431 uint32_t
18432 dns_zone_getkeyvalidityinterval(dns_zone_t *zone) {
18433 REQUIRE(DNS_ZONE_VALID(zone));
18434
18435 return zone->keyvalidityinterval;
18436 }
18437
18438 void
18439 dns_zone_setsigresigninginterval(dns_zone_t *zone, uint32_t interval) {
18440 isc_time_t now;
18441
18442 REQUIRE(DNS_ZONE_VALID(zone));
18443
18444 LOCK_ZONE(zone);
18445 zone->sigresigninginterval = interval;
18446 set_resigntime(zone);
18447 if (zone->loop != NULL) {
18448 now = isc_time_now();
18449 zone_settimer(zone, &now);
18450 }
18451 UNLOCK_ZONE(zone);
18452 }
18453
18454 uint32_t
18455 dns_zone_getsigresigninginterval(dns_zone_t *zone) {
18456 REQUIRE(DNS_ZONE_VALID(zone));
18457
18458 return zone->sigresigninginterval;
18459 }
18460
18461 void
18462 dns_zone_getsourceaddr(dns_zone_t *zone, isc_sockaddr_t *sourceaddr) {
18463 REQUIRE(DNS_ZONE_VALID(zone));
18464 REQUIRE(sourceaddr != NULL);
18465
18466 LOCK_ZONE(zone);
18467 INSIST(dns_remote_count(&zone->primaries) > 0);
18468 *sourceaddr = zone->sourceaddr;
18469 UNLOCK_ZONE(zone);
18470 }
18471
18472 isc_result_t
18473 dns_zone_getprimaryaddr(dns_zone_t *zone, isc_sockaddr_t *primaryaddr) {
18474 isc_result_t result = ISC_R_NOMORE;
18475
18476 REQUIRE(DNS_ZONE_VALID(zone));
18477 REQUIRE(primaryaddr != NULL);
18478
18479 LOCK_ZONE(zone);
18480 INSIST(dns_remote_count(&zone->primaries) > 0);
18481 if (!dns_remote_done(&zone->primaries)) {
18482 *primaryaddr = dns_remote_curraddr(&zone->primaries);
18483 result = ISC_R_SUCCESS;
18484 }
18485 UNLOCK_ZONE(zone);
18486
18487 return result;
18488 }
18489
18490 isc_time_t
18491 dns_zone_getxfrintime(dns_zone_t *zone) {
18492 isc_time_t xfrintime;
18493
18494 REQUIRE(DNS_ZONE_VALID(zone));
18495
18496 LOCK_ZONE(zone);
18497 xfrintime = zone->xfrintime;
18498 UNLOCK_ZONE(zone);
18499
18500 return xfrintime;
18501 }
18502
18503 static void
18504 queue_xfrin(dns_zone_t *zone) {
18505 isc_result_t result;
18506 dns_zonemgr_t *zmgr = zone->zmgr;
18507
18508 ENTER;
18509
18510 INSIST(zone->statelist == NULL);
18511
18512 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18513 ISC_LIST_APPEND(zmgr->waiting_for_xfrin, zone, statelink);
18514 isc_refcount_increment0(&zone->irefs);
18515 zone->statelist = &zmgr->waiting_for_xfrin;
18516 result = zmgr_start_xfrin_ifquota(zmgr, zone);
18517 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18518
18519 if (result == ISC_R_QUOTA) {
18520 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
18521 "zone transfer deferred due to quota");
18522 } else if (result != ISC_R_SUCCESS) {
18523 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
18524 "starting zone transfer: %s",
18525 isc_result_totext(result));
18526 }
18527 }
18528
18529 /*
18530 * Get the transport type used for the SOA query to the current primary server
18531 * before an ongoing incoming zone transfer.
18532 *
18533 * Requires:
18534 * The zone is locked by the caller.
18535 */
18536 static dns_transport_type_t
18537 get_request_transport_type(dns_zone_t *zone) {
18538 dns_transport_type_t transport_type = DNS_TRANSPORT_NONE;
18539
18540 if (zone->transport != NULL) {
18541 transport_type = dns_transport_get_type(zone->transport);
18542 } else {
18543 transport_type = (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC))
18544 ? DNS_TRANSPORT_TCP
18545 : DNS_TRANSPORT_UDP;
18546
18547 /* Check if the peer is forced to always use TCP. */
18548 if (transport_type != DNS_TRANSPORT_TCP &&
18549 !dns_remote_done(&zone->primaries))
18550 {
18551 isc_result_t result;
18552 isc_sockaddr_t primaryaddr;
18553 isc_netaddr_t primaryip;
18554 dns_peer_t *peer = NULL;
18555
18556 primaryaddr = dns_remote_curraddr(&zone->primaries);
18557 isc_netaddr_fromsockaddr(&primaryip, &primaryaddr);
18558 result = dns_peerlist_peerbyaddr(zone->view->peers,
18559 &primaryip, &peer);
18560 if (result == ISC_R_SUCCESS && peer != NULL) {
18561 bool usetcp;
18562 result = dns_peer_getforcetcp(peer, &usetcp);
18563 if (result == ISC_R_SUCCESS && usetcp) {
18564 transport_type = DNS_TRANSPORT_TCP;
18565 }
18566 }
18567 }
18568 }
18569
18570 return transport_type;
18571 }
18572
18573 dns_transport_type_t
18574 dns_zone_getrequesttransporttype(dns_zone_t *zone) {
18575 dns_transport_type_t transport_type;
18576
18577 REQUIRE(DNS_ZONE_VALID(zone));
18578
18579 LOCK_ZONE(zone);
18580 transport_type = get_request_transport_type(zone);
18581 UNLOCK_ZONE(zone);
18582
18583 return transport_type;
18584 }
18585
18586 /*
18587 * This event callback is called when a zone has received
18588 * any necessary zone transfer quota. This is the time
18589 * to go ahead and start the transfer.
18590 */
18591 static void
18592 got_transfer_quota(void *arg) {
18593 dns_zone_t *zone = (dns_zone_t *)arg;
18594 isc_result_t result = ISC_R_SUCCESS;
18595 dns_peer_t *peer = NULL;
18596 char primary[ISC_SOCKADDR_FORMATSIZE];
18597 char source[ISC_SOCKADDR_FORMATSIZE];
18598 dns_rdatatype_t xfrtype;
18599 isc_netaddr_t primaryip;
18600 isc_sockaddr_t primaryaddr;
18601 isc_sockaddr_t sourceaddr;
18602 isc_time_t now;
18603 dns_transport_type_t soa_transport_type = DNS_TRANSPORT_NONE;
18604 const char *soa_before = "";
18605 bool loaded;
18606 isc_tlsctx_cache_t *zmgr_tlsctx_cache = NULL;
18607 dns_xfrin_t *xfr = NULL;
18608
18609 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
18610 zone_xfrdone(zone, NULL, ISC_R_CANCELED);
18611 return;
18612 }
18613
18614 now = isc_time_now();
18615
18616 primaryaddr = dns_remote_curraddr(&zone->primaries);
18617 isc_sockaddr_format(&primaryaddr, primary, sizeof(primary));
18618 if (dns_zonemgr_unreachable(zone->zmgr, &primaryaddr, &zone->sourceaddr,
18619 &now))
18620 {
18621 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
18622 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
18623 "got_transfer_quota: skipping zone transfer as "
18624 "primary %s (source %s) is unreachable (cached)",
18625 primary, source);
18626 zone_xfrdone(zone, NULL, ISC_R_CANCELED);
18627 return;
18628 }
18629
18630 isc_netaddr_fromsockaddr(&primaryip, &primaryaddr);
18631 (void)dns_peerlist_peerbyaddr(zone->view->peers, &primaryip, &peer);
18632
18633 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR)) {
18634 soa_before = "SOA before ";
18635 }
18636 /*
18637 * Decide whether we should request IXFR or AXFR.
18638 */
18639 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
18640 loaded = (zone->db != NULL);
18641 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
18642
18643 if (!loaded) {
18644 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(1),
18645 "no database exists yet, requesting AXFR of "
18646 "initial version from %s",
18647 primary);
18648 xfrtype = dns_rdatatype_axfr;
18649 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
18650 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(1),
18651 "forced reload, requesting AXFR of "
18652 "initial version from %s",
18653 primary);
18654 xfrtype = dns_rdatatype_axfr;
18655 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOIXFR)) {
18656 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(1),
18657 "retrying with AXFR from %s due to "
18658 "previous IXFR failure",
18659 primary);
18660 xfrtype = dns_rdatatype_axfr;
18661 LOCK_ZONE(zone);
18662 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOIXFR);
18663 UNLOCK_ZONE(zone);
18664 } else {
18665 bool use_ixfr = true;
18666 if (peer != NULL) {
18667 result = dns_peer_getrequestixfr(peer, &use_ixfr);
18668 }
18669 if (peer == NULL || result != ISC_R_SUCCESS) {
18670 use_ixfr = zone->requestixfr;
18671 }
18672 if (!use_ixfr) {
18673 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
18674 ISC_LOG_DEBUG(1),
18675 "IXFR disabled, "
18676 "requesting %sAXFR from %s",
18677 soa_before, primary);
18678 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR)) {
18679 xfrtype = dns_rdatatype_soa;
18680 } else {
18681 xfrtype = dns_rdatatype_axfr;
18682 }
18683 } else {
18684 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
18685 ISC_LOG_DEBUG(1),
18686 "requesting IXFR from %s", primary);
18687 xfrtype = dns_rdatatype_ixfr;
18688 }
18689 }
18690
18691 /*
18692 * Determine if we should attempt to sign the request with TSIG.
18693 */
18694 result = ISC_R_NOTFOUND;
18695
18696 /*
18697 * First, look for a tsig key in the primaries statement, then
18698 * try for a server key.
18699 */
18700 if (dns_remote_keyname(&zone->primaries) != NULL) {
18701 dns_view_t *view = dns_zone_getview(zone);
18702 dns_name_t *keyname = dns_remote_keyname(&zone->primaries);
18703 result = dns_view_gettsig(view, keyname, &zone->tsigkey);
18704 }
18705 if (result != ISC_R_SUCCESS) {
18706 INSIST(zone->tsigkey == NULL);
18707 result = dns_view_getpeertsig(zone->view, &primaryip,
18708 &zone->tsigkey);
18709 }
18710 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
18711 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
18712 "could not get TSIG key for zone transfer: %s",
18713 isc_result_totext(result));
18714 }
18715
18716 /*
18717 * Get the TLS transport for the primary, if configured.
18718 */
18719 if (dns_remote_tlsname(&zone->primaries) != NULL) {
18720 dns_view_t *view = dns_zone_getview(zone);
18721 dns_name_t *tlsname = dns_remote_tlsname(&zone->primaries);
18722 result = dns_view_gettransport(view, DNS_TRANSPORT_TLS, tlsname,
18723 &zone->transport);
18724 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
18725 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
18726 ISC_LOG_ERROR,
18727 "could not get TLS configuration for "
18728 "zone transfer: %s",
18729 isc_result_totext(result));
18730 }
18731 }
18732
18733 LOCK_ZONE(zone);
18734 if (xfrtype != dns_rdatatype_soa) {
18735 /*
18736 * If 'xfrtype' is dns_rdatatype_soa, then the SOA query will be
18737 * performed by xfrin, otherwise, the SOA request performed by
18738 * soa_query() was successful and we should inform the xfrin
18739 * about the transport type used for that query, so that the
18740 * information can be presented in the statistics channel.
18741 */
18742 soa_transport_type = get_request_transport_type(zone);
18743 }
18744 sourceaddr = zone->sourceaddr;
18745 UNLOCK_ZONE(zone);
18746
18747 INSIST(isc_sockaddr_pf(&primaryaddr) == isc_sockaddr_pf(&sourceaddr));
18748
18749 zmgr_tlsctx_attach(zone->zmgr, &zmgr_tlsctx_cache);
18750
18751 dns_xfrin_create(zone, xfrtype, &primaryaddr, &sourceaddr,
18752 zone->tsigkey, soa_transport_type, zone->transport,
18753 zmgr_tlsctx_cache, zone->mctx, &xfr);
18754 INSIST(xfr != NULL);
18755
18756 isc_tlsctx_cache_detach(&zmgr_tlsctx_cache);
18757
18758 LOCK_ZONE(zone);
18759 if (zone->xfr != NULL) {
18760 dns_xfrin_detach(&zone->xfr);
18761 }
18762 dns_xfrin_attach(xfr, &zone->xfr);
18763 UNLOCK_ZONE(zone);
18764
18765 dns_xfrin_detach(&xfr);
18766
18767 /*
18768 * Any failure in this function is handled like a failed
18769 * zone transfer. This ensures that we get removed from
18770 * zmgr->xfrin_in_progress.
18771 */
18772 result = dns_xfrin_start(zone->xfr, zone_xfrdone);
18773 if (result != ISC_R_SUCCESS) {
18774 zone_xfrdone(zone, NULL, result);
18775 return;
18776 }
18777
18778 LOCK_ZONE(zone);
18779 if (xfrtype == dns_rdatatype_axfr) {
18780 if (isc_sockaddr_pf(&primaryaddr) == PF_INET) {
18781 inc_stats(zone, dns_zonestatscounter_axfrreqv4);
18782 } else {
18783 inc_stats(zone, dns_zonestatscounter_axfrreqv6);
18784 }
18785 } else if (xfrtype == dns_rdatatype_ixfr) {
18786 if (isc_sockaddr_pf(&primaryaddr) == PF_INET) {
18787 inc_stats(zone, dns_zonestatscounter_ixfrreqv4);
18788 } else {
18789 inc_stats(zone, dns_zonestatscounter_ixfrreqv6);
18790 }
18791 }
18792 UNLOCK_ZONE(zone);
18793 }
18794
18795 /*
18796 * Update forwarding support.
18797 */
18798
18799 static void
18800 forward_destroy(dns_forward_t *forward) {
18801 forward->magic = 0;
18802 if (forward->request != NULL) {
18803 dns_request_destroy(&forward->request);
18804 }
18805 if (forward->msgbuf != NULL) {
18806 isc_buffer_free(&forward->msgbuf);
18807 }
18808 if (forward->transport != NULL) {
18809 dns_transport_detach(&forward->transport);
18810 }
18811 if (forward->zone != NULL) {
18812 LOCK(&forward->zone->lock);
18813 if (ISC_LINK_LINKED(forward, link)) {
18814 ISC_LIST_UNLINK(forward->zone->forwards, forward, link);
18815 }
18816 UNLOCK(&forward->zone->lock);
18817 dns_zone_idetach(&forward->zone);
18818 }
18819 isc_mem_putanddetach(&forward->mctx, forward, sizeof(*forward));
18820 }
18821
18822 static isc_result_t
18823 sendtoprimary(dns_forward_t *forward) {
18824 isc_result_t result;
18825 isc_sockaddr_t src, any;
18826 dns_zone_t *zone = forward->zone;
18827 bool tls_transport_invalid = false;
18828 isc_tlsctx_cache_t *zmgr_tlsctx_cache = NULL;
18829
18830 LOCK_ZONE(zone);
18831
18832 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
18833 UNLOCK_ZONE(zone);
18834 return ISC_R_CANCELED;
18835 }
18836
18837 next:
18838 if (forward->which >= dns_remote_count(&forward->zone->primaries)) {
18839 UNLOCK_ZONE(zone);
18840 return ISC_R_NOMORE;
18841 }
18842
18843 forward->addr = dns_remote_addr(&zone->primaries, forward->which);
18844
18845 if (isc_sockaddr_disabled(&forward->addr)) {
18846 forward->which++;
18847 goto next;
18848 }
18849
18850 /*
18851 * Always use TCP regardless of whether the original update
18852 * used TCP.
18853 * XXX The timeout may but a bit small if we are far down a
18854 * transfer graph and have to try several primaries.
18855 */
18856 switch (isc_sockaddr_pf(&forward->addr)) {
18857 case PF_INET:
18858 isc_sockaddr_any(&any);
18859 src = zone->primaries.sources[forward->which];
18860 if (isc_sockaddr_equal(&src, &any)) {
18861 src = zone->xfrsource4;
18862 }
18863 break;
18864 case PF_INET6:
18865 isc_sockaddr_any6(&any);
18866 src = zone->primaries.sources[forward->which];
18867 if (isc_sockaddr_equal(&src, &any)) {
18868 src = zone->xfrsource6;
18869 }
18870 break;
18871 default:
18872 result = ISC_R_NOTIMPLEMENTED;
18873 goto unlock;
18874 }
18875
18876 if (forward->transport != NULL) {
18877 dns_transport_detach(&forward->transport);
18878 }
18879
18880 if (dns_remote_tlsname(&zone->primaries) != NULL &&
18881 zone->primaries.tlsnames[forward->which] != NULL)
18882 {
18883 dns_view_t *view = dns_zone_getview(zone);
18884 dns_name_t *tlsname = zone->primaries.tlsnames[forward->which];
18885
18886 result = dns_view_gettransport(view, DNS_TRANSPORT_TLS, tlsname,
18887 &forward->transport);
18888
18889 if (result != ISC_R_SUCCESS) {
18890 /* Log the error message when unlocked. */
18891 tls_transport_invalid = true;
18892 goto unlock;
18893 }
18894 }
18895
18896 zmgr_tlsctx_attach(zone->zmgr, &zmgr_tlsctx_cache);
18897
18898 result = dns_request_createraw(
18899 forward->zone->view->requestmgr, forward->msgbuf, &src,
18900 &forward->addr, forward->transport, zmgr_tlsctx_cache,
18901 forward->options, 15 /* XXX */, 0, 0, forward->zone->loop,
18902 forward_callback, forward, &forward->request);
18903
18904 isc_tlsctx_cache_detach(&zmgr_tlsctx_cache);
18905
18906 if (result == ISC_R_SUCCESS) {
18907 if (!ISC_LINK_LINKED(forward, link)) {
18908 ISC_LIST_APPEND(zone->forwards, forward, link);
18909 }
18910 }
18911
18912 unlock:
18913 UNLOCK_ZONE(zone);
18914
18915 if (tls_transport_invalid) {
18916 dns_zone_log(zone, ISC_LOG_ERROR,
18917 "could not get TLS configuration "
18918 "for dynamic update: %s",
18919 isc_result_totext(result));
18920 }
18921
18922 return result;
18923 }
18924
18925 static void
18926 forward_callback(void *arg) {
18927 dns_request_t *request = (dns_request_t *)arg;
18928 dns_forward_t *forward = dns_request_getarg(request);
18929 dns_message_t *msg = NULL;
18930 char primary[ISC_SOCKADDR_FORMATSIZE];
18931 isc_result_t result;
18932 dns_zone_t *zone;
18933
18934 INSIST(DNS_FORWARD_VALID(forward));
18935 zone = forward->zone;
18936 INSIST(DNS_ZONE_VALID(zone));
18937
18938 ENTER;
18939
18940 isc_sockaddr_format(&forward->addr, primary, sizeof(primary));
18941
18942 result = dns_request_getresult(request);
18943 if (result != ISC_R_SUCCESS) {
18944 dns_zone_log(zone, ISC_LOG_INFO,
18945 "could not forward dynamic update to %s: %s",
18946 primary, isc_result_totext(result));
18947 goto next_primary;
18948 }
18949
18950 dns_message_create(zone->mctx, NULL, NULL, DNS_MESSAGE_INTENTPARSE,
18951 &msg);
18952
18953 result = dns_request_getresponse(request, msg,
18954 DNS_MESSAGEPARSE_PRESERVEORDER |
18955 DNS_MESSAGEPARSE_CLONEBUFFER);
18956 if (result != ISC_R_SUCCESS) {
18957 goto next_primary;
18958 }
18959
18960 /*
18961 * Unexpected opcode.
18962 */
18963 if (msg->opcode != dns_opcode_update) {
18964 char opcode[128];
18965 isc_buffer_t rb;
18966
18967 isc_buffer_init(&rb, opcode, sizeof(opcode));
18968 (void)dns_opcode_totext(msg->opcode, &rb);
18969
18970 dns_zone_log(zone, ISC_LOG_INFO,
18971 "forwarding dynamic update: "
18972 "unexpected opcode (%.*s) from %s",
18973 (int)rb.used, opcode, primary);
18974 goto next_primary;
18975 }
18976
18977 switch (msg->rcode) {
18978 /*
18979 * Pass these rcodes back to client.
18980 */
18981 case dns_rcode_noerror:
18982 case dns_rcode_yxdomain:
18983 case dns_rcode_yxrrset:
18984 case dns_rcode_nxrrset:
18985 case dns_rcode_refused:
18986 case dns_rcode_nxdomain: {
18987 char rcode[128];
18988 isc_buffer_t rb;
18989
18990 isc_buffer_init(&rb, rcode, sizeof(rcode));
18991 (void)dns_rcode_totext(msg->rcode, &rb);
18992 dns_zone_log(zone, ISC_LOG_INFO,
18993 "forwarded dynamic update: "
18994 "primary %s returned: %.*s",
18995 primary, (int)rb.used, rcode);
18996 break;
18997 }
18998
18999 /* These should not occur if the primaries/zone are valid. */
19000 case dns_rcode_notzone:
19001 case dns_rcode_notauth: {
19002 char rcode[128];
19003 isc_buffer_t rb;
19004
19005 isc_buffer_init(&rb, rcode, sizeof(rcode));
19006 (void)dns_rcode_totext(msg->rcode, &rb);
19007 dns_zone_log(zone, ISC_LOG_WARNING,
19008 "forwarding dynamic update: "
19009 "unexpected response: primary %s returned: %.*s",
19010 primary, (int)rb.used, rcode);
19011 goto next_primary;
19012 }
19013
19014 /* Try another server for these rcodes. */
19015 case dns_rcode_formerr:
19016 case dns_rcode_servfail:
19017 case dns_rcode_notimp:
19018 case dns_rcode_badvers:
19019 default:
19020 goto next_primary;
19021 }
19022
19023 /* call callback */
19024 (forward->callback)(forward->callback_arg, ISC_R_SUCCESS, msg);
19025 msg = NULL;
19026 dns_request_destroy(&forward->request);
19027 forward_destroy(forward);
19028 return;
19029
19030 next_primary:
19031 if (msg != NULL) {
19032 dns_message_detach(&msg);
19033 }
19034 forward->which++;
19035 dns_request_destroy(&forward->request);
19036 result = sendtoprimary(forward);
19037 if (result != ISC_R_SUCCESS) {
19038 /* call callback */
19039 dns_zone_log(zone, ISC_LOG_DEBUG(3),
19040 "exhausted dynamic update forwarder list");
19041 (forward->callback)(forward->callback_arg, result, NULL);
19042 forward_destroy(forward);
19043 }
19044 }
19045
19046 isc_result_t
19047 dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
19048 dns_updatecallback_t callback, void *callback_arg) {
19049 dns_forward_t *forward;
19050 isc_result_t result;
19051 isc_region_t *mr;
19052
19053 REQUIRE(DNS_ZONE_VALID(zone));
19054 REQUIRE(msg != NULL);
19055 REQUIRE(callback != NULL);
19056
19057 forward = isc_mem_get(zone->mctx, sizeof(*forward));
19058 *forward = (dns_forward_t){ .callback = callback,
19059 .callback_arg = callback_arg,
19060 .options = DNS_REQUESTOPT_TCP };
19061 ISC_LINK_INIT(forward, link);
19062 forward->magic = FORWARD_MAGIC;
19063
19064 /*
19065 * If we have a SIG(0) signed message we need to preserve the
19066 * query id as that is included in the SIG(0) computation.
19067 */
19068 if (msg->sig0 != NULL) {
19069 forward->options |= DNS_REQUESTOPT_FIXEDID;
19070 }
19071
19072 mr = dns_message_getrawmessage(msg);
19073 if (mr == NULL) {
19074 result = ISC_R_UNEXPECTEDEND;
19075 goto cleanup;
19076 }
19077
19078 isc_buffer_allocate(zone->mctx, &forward->msgbuf, mr->length);
19079 result = isc_buffer_copyregion(forward->msgbuf, mr);
19080 if (result != ISC_R_SUCCESS) {
19081 goto cleanup;
19082 }
19083
19084 isc_mem_attach(zone->mctx, &forward->mctx);
19085 dns_zone_iattach(zone, &forward->zone);
19086 result = sendtoprimary(forward);
19087
19088 cleanup:
19089 if (result != ISC_R_SUCCESS) {
19090 forward_destroy(forward);
19091 }
19092 return result;
19093 }
19094
19095 isc_result_t
19096 dns_zone_next(dns_zone_t *zone, dns_zone_t **next) {
19097 REQUIRE(DNS_ZONE_VALID(zone));
19098 REQUIRE(next != NULL && *next == NULL);
19099
19100 *next = ISC_LIST_NEXT(zone, link);
19101 if (*next == NULL) {
19102 return ISC_R_NOMORE;
19103 } else {
19104 return ISC_R_SUCCESS;
19105 }
19106 }
19107
19108 isc_result_t
19109 dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) {
19110 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19111 REQUIRE(first != NULL && *first == NULL);
19112
19113 *first = ISC_LIST_HEAD(zmgr->zones);
19114 if (*first == NULL) {
19115 return ISC_R_NOMORE;
19116 } else {
19117 return ISC_R_SUCCESS;
19118 }
19119 }
19120
19121 /***
19122 *** Zone manager.
19123 ***/
19124
19125 static void
19126 zonemgr_keymgmt_init(dns_zonemgr_t *zmgr) {
19127 dns_keymgmt_t *mgmt = isc_mem_get(zmgr->mctx, sizeof(*mgmt));
19128
19129 *mgmt = (dns_keymgmt_t){
19130 .magic = KEYMGMT_MAGIC,
19131 };
19132
19133 isc_mem_attach(zmgr->mctx, &mgmt->mctx);
19134 isc_rwlock_init(&mgmt->lock);
19135 isc_hashmap_create(mgmt->mctx, DNS_KEYMGMT_HASH_BITS, &mgmt->table);
19136
19137 zmgr->keymgmt = mgmt;
19138 }
19139
19140 static void
19141 zonemgr_keymgmt_destroy(dns_zonemgr_t *zmgr) {
19142 dns_keymgmt_t *mgmt = zmgr->keymgmt;
19143
19144 REQUIRE(DNS_KEYMGMT_VALID(mgmt));
19145
19146 mgmt->magic = 0;
19147
19148 RWLOCK(&mgmt->lock, isc_rwlocktype_write);
19149 INSIST(isc_hashmap_count(mgmt->table) == 0);
19150 RWUNLOCK(&mgmt->lock, isc_rwlocktype_write);
19151 isc_hashmap_destroy(&mgmt->table);
19152
19153 isc_rwlock_destroy(&mgmt->lock);
19154 isc_mem_putanddetach(&mgmt->mctx, mgmt, sizeof(dns_keymgmt_t));
19155 }
19156
19157 static bool
19158 kfio_match(void *node, const void *key) {
19159 const dns_keyfileio_t *kfio = node;
19160
19161 return dns_name_equal(kfio->name, key);
19162 }
19163
19164 static void
19165 zonemgr_keymgmt_add(dns_zonemgr_t *zmgr, dns_zone_t *zone,
19166 dns_keyfileio_t **added) {
19167 dns_keymgmt_t *mgmt = zmgr->keymgmt;
19168 dns_keyfileio_t *kfio = NULL;
19169 isc_result_t result;
19170 dns_fixedname_t fname;
19171 dns_name_t *name;
19172
19173 REQUIRE(DNS_KEYMGMT_VALID(mgmt));
19174 REQUIRE(added != NULL && *added == NULL);
19175
19176 name = dns_fixedname_initname(&fname);
19177 dns_name_downcase(&zone->origin, name, NULL);
19178
19179 RWLOCK(&mgmt->lock, isc_rwlocktype_write);
19180
19181 result = isc_hashmap_find(mgmt->table, dns_name_hash(name), kfio_match,
19182 name, (void **)&kfio);
19183 switch (result) {
19184 case ISC_R_SUCCESS:
19185 isc_refcount_increment(&kfio->references);
19186 break;
19187 case ISC_R_NOTFOUND:
19188 kfio = isc_mem_get(mgmt->mctx, sizeof(*kfio));
19189 *kfio = (dns_keyfileio_t){
19190 .magic = KEYFILEIO_MAGIC,
19191 };
19192 isc_refcount_init(&kfio->references, 1);
19193 kfio->name = dns_fixedname_initname(&kfio->fname);
19194 dns_name_copy(name, kfio->name);
19195
19196 isc_mutex_init(&kfio->lock);
19197 result = isc_hashmap_add(mgmt->table, dns_name_hash(kfio->name),
19198 kfio_match, kfio->name, kfio, NULL);
19199 INSIST(result == ISC_R_SUCCESS);
19200 break;
19201 default:
19202 UNREACHABLE();
19203 }
19204 *added = kfio;
19205 RWUNLOCK(&mgmt->lock, isc_rwlocktype_write);
19206 }
19207
19208 static bool
19209 match_ptr(void *node, const void *key) {
19210 return node == key;
19211 }
19212
19213 static void
19214 zonemgr_keymgmt_delete(dns_zonemgr_t *zmgr, dns_keyfileio_t **deleted) {
19215 REQUIRE(DNS_KEYMGMT_VALID(zmgr->keymgmt));
19216 REQUIRE(deleted != NULL && DNS_KEYFILEIO_VALID(*deleted));
19217
19218 dns_keymgmt_t *mgmt = zmgr->keymgmt;
19219 dns_keyfileio_t *kfio = *deleted;
19220 isc_result_t result;
19221
19222 *deleted = NULL;
19223
19224 RWLOCK(&mgmt->lock, isc_rwlocktype_write);
19225
19226 if (isc_refcount_decrement(&kfio->references) == 1) {
19227 isc_refcount_destroy(&kfio->references);
19228 kfio->magic = 0;
19229 isc_mutex_destroy(&kfio->lock);
19230
19231 result = isc_hashmap_delete(mgmt->table,
19232 dns_name_hash(kfio->name),
19233 match_ptr, kfio);
19234 INSIST(result == ISC_R_SUCCESS);
19235
19236 isc_mem_put(mgmt->mctx, kfio, sizeof(*kfio));
19237 }
19238
19239 RWUNLOCK(&mgmt->lock, isc_rwlocktype_write);
19240 }
19241
19242 void
19243 dns_zonemgr_create(isc_mem_t *mctx, isc_nm_t *netmgr, dns_zonemgr_t **zmgrp) {
19244 dns_zonemgr_t *zmgr = NULL;
19245 isc_loop_t *loop = isc_loop();
19246 isc_loopmgr_t *loopmgr = isc_loop_getloopmgr(loop);
19247
19248 REQUIRE(mctx != NULL);
19249 REQUIRE(netmgr != NULL);
19250 REQUIRE(zmgrp != NULL && *zmgrp == NULL);
19251
19252 zmgr = isc_mem_get(mctx, sizeof(*zmgr));
19253
19254 *zmgr = (dns_zonemgr_t){
19255 .loopmgr = loopmgr,
19256 .netmgr = netmgr,
19257 .workers = isc_loopmgr_nloops(loopmgr),
19258 .transfersin = 10,
19259 .transfersperns = 2,
19260 };
19261
19262 isc_refcount_init(&zmgr->refs, 1);
19263 isc_mem_attach(mctx, &zmgr->mctx);
19264
19265 ISC_LIST_INIT(zmgr->zones);
19266 ISC_LIST_INIT(zmgr->waiting_for_xfrin);
19267 ISC_LIST_INIT(zmgr->xfrin_in_progress);
19268 memset(zmgr->unreachable, 0, sizeof(zmgr->unreachable));
19269 for (size_t i = 0; i < UNREACH_CACHE_SIZE; i++) {
19270 atomic_init(&zmgr->unreachable[i].expire, 0);
19271 }
19272 isc_rwlock_init(&zmgr->rwlock);
19273
19274 /* Unreachable lock. */
19275 isc_rwlock_init(&zmgr->urlock);
19276
19277 isc_ratelimiter_create(loop, &zmgr->checkdsrl);
19278 isc_ratelimiter_create(loop, &zmgr->notifyrl);
19279 isc_ratelimiter_create(loop, &zmgr->refreshrl);
19280 isc_ratelimiter_create(loop, &zmgr->startupnotifyrl);
19281 isc_ratelimiter_create(loop, &zmgr->startuprefreshrl);
19282
19283 zmgr->mctxpool = isc_mem_cget(zmgr->mctx, zmgr->workers,
19284 sizeof(zmgr->mctxpool[0]));
19285 for (size_t i = 0; i < zmgr->workers; i++) {
19286 isc_mem_create(&zmgr->mctxpool[i]);
19287 isc_mem_setname(zmgr->mctxpool[i], "zonemgr-mctxpool");
19288 }
19289
19290 /* Key file I/O locks. */
19291 zonemgr_keymgmt_init(zmgr);
19292
19293 /* Default to 20 refresh queries / notifies / checkds per second. */
19294 setrl(zmgr->checkdsrl, &zmgr->checkdsrate, 20);
19295 setrl(zmgr->notifyrl, &zmgr->notifyrate, 20);
19296 setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, 20);
19297 setrl(zmgr->refreshrl, &zmgr->serialqueryrate, 20);
19298 setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, 20);
19299 isc_ratelimiter_setpushpop(zmgr->startupnotifyrl, true);
19300 isc_ratelimiter_setpushpop(zmgr->startuprefreshrl, true);
19301
19302 zmgr->tlsctx_cache = NULL;
19303 isc_rwlock_init(&zmgr->tlsctx_cache_rwlock);
19304
19305 zmgr->magic = ZONEMGR_MAGIC;
19306
19307 *zmgrp = zmgr;
19308 }
19309
19310 isc_result_t
19311 dns_zonemgr_createzone(dns_zonemgr_t *zmgr, dns_zone_t **zonep) {
19312 isc_mem_t *mctx = NULL;
19313 dns_zone_t *zone = NULL;
19314 unsigned int tid;
19315
19316 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19317 REQUIRE(zonep != NULL && *zonep == NULL);
19318
19319 if (zmgr->mctxpool == NULL) {
19320 return ISC_R_FAILURE;
19321 }
19322
19323 tid = isc_random_uniform(zmgr->workers);
19324
19325 mctx = zmgr->mctxpool[tid];
19326 if (mctx == NULL) {
19327 return ISC_R_FAILURE;
19328 }
19329
19330 dns_zone_create(&zone, mctx, tid);
19331
19332 *zonep = zone;
19333
19334 return ISC_R_SUCCESS;
19335 }
19336
19337 isc_result_t
19338 dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
19339 REQUIRE(DNS_ZONE_VALID(zone));
19340 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19341
19342 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
19343 LOCK_ZONE(zone);
19344 REQUIRE(zone->timer == NULL);
19345 REQUIRE(zone->zmgr == NULL);
19346
19347 isc_loop_t *loop = isc_loop_get(zmgr->loopmgr, zone->tid);
19348 isc_loop_attach(loop, &zone->loop);
19349
19350 zonemgr_keymgmt_add(zmgr, zone, &zone->kfio);
19351 INSIST(zone->kfio != NULL);
19352
19353 ISC_LIST_APPEND(zmgr->zones, zone, link);
19354 zone->zmgr = zmgr;
19355
19356 isc_refcount_increment(&zmgr->refs);
19357
19358 UNLOCK_ZONE(zone);
19359 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
19360 return ISC_R_SUCCESS;
19361 }
19362
19363 void
19364 dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
19365 REQUIRE(DNS_ZONE_VALID(zone));
19366 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19367 REQUIRE(zone->zmgr == zmgr);
19368
19369 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
19370 LOCK_ZONE(zone);
19371
19372 ISC_LIST_UNLINK(zmgr->zones, zone, link);
19373
19374 if (zone->kfio != NULL) {
19375 zonemgr_keymgmt_delete(zmgr, &zone->kfio);
19376 ENSURE(zone->kfio == NULL);
19377 }
19378
19379 if (zone->timer != NULL) {
19380 isc_refcount_decrement(&zone->irefs);
19381 isc_timer_destroy(&zone->timer);
19382 }
19383
19384 isc_loop_detach(&zone->loop);
19385
19386 /* Detach below, outside of the write lock. */
19387 zone->zmgr = NULL;
19388
19389 UNLOCK_ZONE(zone);
19390 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
19391
19392 dns_zonemgr_detach(&zmgr);
19393 }
19394
19395 void
19396 dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) {
19397 REQUIRE(DNS_ZONEMGR_VALID(source));
19398 REQUIRE(target != NULL && *target == NULL);
19399
19400 isc_refcount_increment(&source->refs);
19401
19402 *target = source;
19403 }
19404
19405 void
19406 dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
19407 dns_zonemgr_t *zmgr;
19408
19409 REQUIRE(zmgrp != NULL);
19410 zmgr = *zmgrp;
19411 *zmgrp = NULL;
19412 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19413
19414 if (isc_refcount_decrement(&zmgr->refs) == 1) {
19415 zonemgr_free(zmgr);
19416 }
19417 }
19418
19419 isc_result_t
19420 dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
19421 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19422
19423 RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
19424 for (dns_zone_t *zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
19425 zone = ISC_LIST_NEXT(zone, link))
19426 {
19427 isc_time_t now;
19428
19429 LOCK_ZONE(zone);
19430 now = isc_time_now();
19431 zone_settimer(zone, &now);
19432 UNLOCK_ZONE(zone);
19433 }
19434 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
19435
19436 /*
19437 * Recent configuration changes may have increased the
19438 * amount of available transfers quota. Make sure any
19439 * transfers currently blocked on quota get started if
19440 * possible.
19441 */
19442 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
19443 zmgr_resume_xfrs(zmgr, true);
19444 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
19445 return ISC_R_SUCCESS;
19446 }
19447
19448 void
19449 dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) {
19450 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19451
19452 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
19453 zmgr_resume_xfrs(zmgr, true);
19454 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
19455 }
19456
19457 void
19458 dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
19459 dns_zone_t *zone;
19460
19461 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19462
19463 isc_ratelimiter_shutdown(zmgr->checkdsrl);
19464 isc_ratelimiter_shutdown(zmgr->notifyrl);
19465 isc_ratelimiter_shutdown(zmgr->refreshrl);
19466 isc_ratelimiter_shutdown(zmgr->startupnotifyrl);
19467 isc_ratelimiter_shutdown(zmgr->startuprefreshrl);
19468
19469 for (size_t i = 0; i < zmgr->workers; i++) {
19470 isc_mem_detach(&zmgr->mctxpool[i]);
19471 }
19472
19473 RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
19474 for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
19475 zone = ISC_LIST_NEXT(zone, link))
19476 {
19477 LOCK_ZONE(zone);
19478 forward_cancel(zone);
19479 UNLOCK_ZONE(zone);
19480 }
19481 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
19482 }
19483
19484 static void
19485 zonemgr_free(dns_zonemgr_t *zmgr) {
19486 REQUIRE(ISC_LIST_EMPTY(zmgr->zones));
19487
19488 zmgr->magic = 0;
19489
19490 isc_refcount_destroy(&zmgr->refs);
19491 isc_ratelimiter_detach(&zmgr->checkdsrl);
19492 isc_ratelimiter_detach(&zmgr->notifyrl);
19493 isc_ratelimiter_detach(&zmgr->refreshrl);
19494 isc_ratelimiter_detach(&zmgr->startupnotifyrl);
19495 isc_ratelimiter_detach(&zmgr->startuprefreshrl);
19496
19497 isc_mem_cput(zmgr->mctx, zmgr->mctxpool, zmgr->workers,
19498 sizeof(zmgr->mctxpool[0]));
19499
19500 isc_rwlock_destroy(&zmgr->urlock);
19501 isc_rwlock_destroy(&zmgr->rwlock);
19502 isc_rwlock_destroy(&zmgr->tlsctx_cache_rwlock);
19503
19504 zonemgr_keymgmt_destroy(zmgr);
19505
19506 if (zmgr->tlsctx_cache != NULL) {
19507 isc_tlsctx_cache_detach(&zmgr->tlsctx_cache);
19508 }
19509 isc_mem_putanddetach(&zmgr->mctx, zmgr, sizeof(*zmgr));
19510 }
19511
19512 void
19513 dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, uint32_t value) {
19514 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19515
19516 zmgr->transfersin = value;
19517 }
19518
19519 uint32_t
19520 dns_zonemgr_gettransfersin(dns_zonemgr_t *zmgr) {
19521 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19522
19523 return zmgr->transfersin;
19524 }
19525
19526 void
19527 dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, uint32_t value) {
19528 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19529
19530 zmgr->transfersperns = value;
19531 }
19532
19533 uint32_t
19534 dns_zonemgr_gettransfersperns(dns_zonemgr_t *zmgr) {
19535 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19536
19537 return zmgr->transfersperns;
19538 }
19539
19540 /*
19541 * Try to start a new incoming zone transfer to fill a quota
19542 * slot that was just vacated.
19543 *
19544 * Requires:
19545 * The zone manager is locked by the caller.
19546 */
19547 static void
19548 zmgr_resume_xfrs(dns_zonemgr_t *zmgr, bool multi) {
19549 dns_zone_t *zone;
19550 dns_zone_t *next;
19551
19552 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin); zone != NULL;
19553 zone = next)
19554 {
19555 isc_result_t result;
19556 next = ISC_LIST_NEXT(zone, statelink);
19557 result = zmgr_start_xfrin_ifquota(zmgr, zone);
19558 if (result == ISC_R_SUCCESS) {
19559 if (multi) {
19560 continue;
19561 }
19562 /*
19563 * We successfully filled the slot. We're done.
19564 */
19565 break;
19566 } else if (result == ISC_R_QUOTA) {
19567 /*
19568 * Not enough quota. This is probably the per-server
19569 * quota, because we usually get called when a unit of
19570 * global quota has just been freed. Try the next
19571 * zone, it may succeed if it uses another primary.
19572 */
19573 continue;
19574 } else {
19575 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
19576 ISC_LOG_DEBUG(1),
19577 "starting zone transfer: %s",
19578 isc_result_totext(result));
19579 break;
19580 }
19581 }
19582 }
19583
19584 /*
19585 * Try to start an incoming zone transfer for 'zone', quota permitting.
19586 *
19587 * Requires:
19588 * The zone manager is locked by the caller.
19589 *
19590 * Returns:
19591 * ISC_R_SUCCESS There was enough quota and we attempted to
19592 * start a transfer. zone_xfrdone() has been or will
19593 * be called.
19594 * ISC_R_QUOTA Not enough quota.
19595 * Others Failure.
19596 */
19597 static isc_result_t
19598 zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
19599 dns_peer_t *peer = NULL;
19600 isc_netaddr_t primaryip;
19601 isc_sockaddr_t curraddr;
19602 uint32_t nxfrsin, nxfrsperns;
19603 dns_zone_t *x = NULL;
19604 uint32_t maxtransfersin, maxtransfersperns;
19605
19606 /*
19607 * If we are exiting just pretend we got quota so the zone will
19608 * be cleaned up in the zone's loop context.
19609 */
19610 LOCK_ZONE(zone);
19611 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
19612 UNLOCK_ZONE(zone);
19613 goto gotquota;
19614 }
19615
19616 /*
19617 * Find any configured information about the server we'd
19618 * like to transfer this zone from.
19619 */
19620 curraddr = dns_remote_curraddr(&zone->primaries);
19621 isc_netaddr_fromsockaddr(&primaryip, &curraddr);
19622 (void)dns_peerlist_peerbyaddr(zone->view->peers, &primaryip, &peer);
19623 UNLOCK_ZONE(zone);
19624
19625 /*
19626 * Determine the total maximum number of simultaneous
19627 * transfers allowed, and the maximum for this specific
19628 * primary.
19629 */
19630 maxtransfersin = zmgr->transfersin;
19631 maxtransfersperns = zmgr->transfersperns;
19632 if (peer != NULL) {
19633 (void)dns_peer_gettransfers(peer, &maxtransfersperns);
19634 }
19635
19636 /*
19637 * Count the total number of transfers that are in progress,
19638 * and the number of transfers in progress from this primary.
19639 * We linearly scan a list of all transfers; if this turns
19640 * out to be too slow, we could hash on the primary address.
19641 */
19642 nxfrsin = nxfrsperns = 0;
19643 for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress); x != NULL;
19644 x = ISC_LIST_NEXT(x, statelink))
19645 {
19646 isc_netaddr_t xip;
19647 isc_sockaddr_t xaddr;
19648
19649 LOCK_ZONE(x);
19650 xaddr = dns_remote_curraddr(&x->primaries);
19651 isc_netaddr_fromsockaddr(&xip, &xaddr);
19652 UNLOCK_ZONE(x);
19653
19654 nxfrsin++;
19655 if (isc_netaddr_equal(&xip, &primaryip)) {
19656 nxfrsperns++;
19657 }
19658 }
19659
19660 /* Enforce quota. */
19661 if (nxfrsin >= maxtransfersin) {
19662 return ISC_R_QUOTA;
19663 }
19664
19665 if (nxfrsperns >= maxtransfersperns) {
19666 return ISC_R_QUOTA;
19667 }
19668
19669 gotquota:
19670 /*
19671 * We have sufficient quota. Move the zone to the "xfrin_in_progress"
19672 * list and start the actual transfer asynchronously.
19673 */
19674 LOCK_ZONE(zone);
19675 INSIST(zone->statelist == &zmgr->waiting_for_xfrin);
19676 ISC_LIST_UNLINK(zmgr->waiting_for_xfrin, zone, statelink);
19677 ISC_LIST_APPEND(zmgr->xfrin_in_progress, zone, statelink);
19678 zone->statelist = &zmgr->xfrin_in_progress;
19679 isc_async_run(zone->loop, got_transfer_quota, zone);
19680 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
19681 "Transfer started.");
19682 UNLOCK_ZONE(zone);
19683
19684 return ISC_R_SUCCESS;
19685 }
19686
19687 static void
19688 zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
19689 char *buf;
19690 int buflen;
19691 isc_result_t result;
19692
19693 buflen = strlen(path) + strlen(templat) + 2;
19694
19695 buf = isc_mem_get(zone->mctx, buflen);
19696
19697 result = isc_file_template(path, templat, buf, buflen);
19698 if (result != ISC_R_SUCCESS) {
19699 goto cleanup;
19700 }
19701
19702 result = isc_file_renameunique(path, buf);
19703 if (result != ISC_R_SUCCESS) {
19704 goto cleanup;
19705 }
19706
19707 dns_zone_log(zone, ISC_LOG_WARNING,
19708 "unable to load from '%s'; "
19709 "renaming file to '%s' for failure analysis and "
19710 "retransferring.",
19711 path, buf);
19712
19713 cleanup:
19714 isc_mem_put(zone->mctx, buf, buflen);
19715 }
19716
19717 static void
19718 setrl(isc_ratelimiter_t *rl, unsigned int *rate, unsigned int value) {
19719 isc_interval_t interval;
19720 uint32_t s, ns;
19721 uint32_t pertic;
19722
19723 if (value == 0) {
19724 value = 1;
19725 }
19726
19727 if (value == 1) {
19728 s = 1;
19729 ns = 0;
19730 pertic = 1;
19731 } else if (value <= 10) {
19732 s = 0;
19733 ns = 1000000000 / value;
19734 pertic = 1;
19735 } else {
19736 s = 0;
19737 ns = (1000000000 / value) * 10;
19738 pertic = 10;
19739 }
19740
19741 isc_interval_set(&interval, s, ns);
19742
19743 isc_ratelimiter_setinterval(rl, &interval);
19744 isc_ratelimiter_setpertic(rl, pertic);
19745
19746 *rate = value;
19747 }
19748
19749 void
19750 dns_zonemgr_setcheckdsrate(dns_zonemgr_t *zmgr, unsigned int value) {
19751 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19752
19753 setrl(zmgr->checkdsrl, &zmgr->checkdsrate, value);
19754 }
19755
19756 void
19757 dns_zonemgr_setnotifyrate(dns_zonemgr_t *zmgr, unsigned int value) {
19758 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19759
19760 setrl(zmgr->notifyrl, &zmgr->notifyrate, value);
19761 }
19762
19763 void
19764 dns_zonemgr_setstartupnotifyrate(dns_zonemgr_t *zmgr, unsigned int value) {
19765 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19766
19767 setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, value);
19768 }
19769
19770 void
19771 dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) {
19772 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19773
19774 setrl(zmgr->refreshrl, &zmgr->serialqueryrate, value);
19775 /* XXXMPA separate out once we have the code to support this. */
19776 setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, value);
19777 }
19778
19779 unsigned int
19780 dns_zonemgr_getnotifyrate(dns_zonemgr_t *zmgr) {
19781 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19782
19783 return zmgr->notifyrate;
19784 }
19785
19786 unsigned int
19787 dns_zonemgr_getstartupnotifyrate(dns_zonemgr_t *zmgr) {
19788 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19789
19790 return zmgr->startupnotifyrate;
19791 }
19792
19793 unsigned int
19794 dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
19795 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19796
19797 return zmgr->serialqueryrate;
19798 }
19799
19800 bool
19801 dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
19802 isc_sockaddr_t *local, isc_time_t *now) {
19803 unsigned int i;
19804 uint32_t seconds = isc_time_seconds(now);
19805 uint32_t count = 0;
19806
19807 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19808
19809 RWLOCK(&zmgr->urlock, isc_rwlocktype_read);
19810 for (i = 0; i < UNREACH_CACHE_SIZE; i++) {
19811 if (atomic_load(&zmgr->unreachable[i].expire) >= seconds &&
19812 isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
19813 isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
19814 {
19815 atomic_store_relaxed(&zmgr->unreachable[i].last,
19816 seconds);
19817 count = zmgr->unreachable[i].count;
19818 break;
19819 }
19820 }
19821 RWUNLOCK(&zmgr->urlock, isc_rwlocktype_read);
19822 return i < UNREACH_CACHE_SIZE && count > 1U;
19823 }
19824
19825 void
19826 dns_zonemgr_unreachabledel(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
19827 isc_sockaddr_t *local) {
19828 unsigned int i;
19829
19830 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19831
19832 RWLOCK(&zmgr->urlock, isc_rwlocktype_read);
19833 for (i = 0; i < UNREACH_CACHE_SIZE; i++) {
19834 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
19835 isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
19836 {
19837 atomic_store_relaxed(&zmgr->unreachable[i].expire, 0);
19838 break;
19839 }
19840 }
19841 RWUNLOCK(&zmgr->urlock, isc_rwlocktype_read);
19842 }
19843
19844 void
19845 dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
19846 isc_sockaddr_t *local, isc_time_t *now) {
19847 uint32_t seconds = isc_time_seconds(now);
19848 uint32_t expire = 0, last = seconds;
19849 unsigned int slot = UNREACH_CACHE_SIZE, oldest = 0;
19850 bool update_entry = true;
19851 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19852
19853 RWLOCK(&zmgr->urlock, isc_rwlocktype_write);
19854 for (unsigned int i = 0; i < UNREACH_CACHE_SIZE; i++) {
19855 /* Existing entry? */
19856 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
19857 isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
19858 {
19859 update_entry = false;
19860 slot = i;
19861 expire = atomic_load_relaxed(
19862 &zmgr->unreachable[i].expire);
19863 break;
19864 }
19865 /* Pick first empty slot? */
19866 if (atomic_load_relaxed(&zmgr->unreachable[i].expire) < seconds)
19867 {
19868 slot = i;
19869 break;
19870 }
19871 /* The worst case, least recently used slot? */
19872 if (atomic_load_relaxed(&zmgr->unreachable[i].last) < last) {
19873 last = atomic_load_relaxed(&zmgr->unreachable[i].last);
19874 oldest = i;
19875 }
19876 }
19877
19878 /* We haven't found any existing or free slots, use the oldest */
19879 if (slot == UNREACH_CACHE_SIZE) {
19880 slot = oldest;
19881 }
19882
19883 if (expire < seconds) {
19884 /* Expired or new entry, reset count to 1 */
19885 zmgr->unreachable[slot].count = 1;
19886 } else {
19887 zmgr->unreachable[slot].count++;
19888 }
19889 atomic_store_relaxed(&zmgr->unreachable[slot].expire,
19890 seconds + UNREACH_HOLD_TIME);
19891 atomic_store_relaxed(&zmgr->unreachable[slot].last, seconds);
19892 if (update_entry) {
19893 zmgr->unreachable[slot].remote = *remote;
19894 zmgr->unreachable[slot].local = *local;
19895 }
19896
19897 RWUNLOCK(&zmgr->urlock, isc_rwlocktype_write);
19898 }
19899
19900 void
19901 dns_zone_stopxfr(dns_zone_t *zone) {
19902 dns_xfrin_t *xfr = NULL;
19903
19904 REQUIRE(DNS_ZONE_VALID(zone));
19905
19906 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_read);
19907 LOCK_ZONE(zone);
19908 if (zone->statelist == &zone->zmgr->xfrin_in_progress &&
19909 zone->xfr != NULL)
19910 {
19911 dns_xfrin_attach(zone->xfr, &xfr);
19912 }
19913 UNLOCK_ZONE(zone);
19914 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_read);
19915
19916 if (xfr != NULL) {
19917 dns_xfrin_shutdown(xfr);
19918 dns_xfrin_detach(&xfr);
19919 }
19920 }
19921
19922 void
19923 dns_zone_forcexfr(dns_zone_t *zone) {
19924 REQUIRE(DNS_ZONE_VALID(zone));
19925
19926 if (zone->type == dns_zone_primary ||
19927 (zone->type == dns_zone_redirect &&
19928 dns_remote_addresses(&zone->primaries) == NULL))
19929 {
19930 return;
19931 }
19932
19933 LOCK_ZONE(zone);
19934 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
19935 UNLOCK_ZONE(zone);
19936 dns_zone_refresh(zone);
19937 }
19938
19939 bool
19940 dns_zone_isforced(dns_zone_t *zone) {
19941 REQUIRE(DNS_ZONE_VALID(zone));
19942
19943 return DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER);
19944 }
19945
19946 isc_result_t
19947 dns_zone_setstatistics(dns_zone_t *zone, bool on) {
19948 /*
19949 * This function is obsoleted.
19950 */
19951 UNUSED(zone);
19952 UNUSED(on);
19953 return ISC_R_NOTIMPLEMENTED;
19954 }
19955
19956 uint64_t *
19957 dns_zone_getstatscounters(dns_zone_t *zone) {
19958 /*
19959 * This function is obsoleted.
19960 */
19961 UNUSED(zone);
19962 return NULL;
19963 }
19964
19965 void
19966 dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats) {
19967 REQUIRE(DNS_ZONE_VALID(zone));
19968 REQUIRE(zone->stats == NULL);
19969
19970 LOCK_ZONE(zone);
19971 zone->stats = NULL;
19972 isc_stats_attach(stats, &zone->stats);
19973 UNLOCK_ZONE(zone);
19974 }
19975
19976 void
19977 dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats) {
19978 REQUIRE(DNS_ZONE_VALID(zone));
19979
19980 LOCK_ZONE(zone);
19981 if (zone->requeststats_on && stats == NULL) {
19982 zone->requeststats_on = false;
19983 } else if (!zone->requeststats_on && stats != NULL) {
19984 if (zone->requeststats == NULL) {
19985 isc_stats_attach(stats, &zone->requeststats);
19986 }
19987 zone->requeststats_on = true;
19988 }
19989 UNLOCK_ZONE(zone);
19990 }
19991
19992 void
19993 dns_zone_setrcvquerystats(dns_zone_t *zone, dns_stats_t *stats) {
19994 REQUIRE(DNS_ZONE_VALID(zone));
19995
19996 LOCK_ZONE(zone);
19997 if (zone->requeststats_on && stats != NULL) {
19998 if (zone->rcvquerystats == NULL) {
19999 dns_stats_attach(stats, &zone->rcvquerystats);
20000 zone->requeststats_on = true;
20001 }
20002 }
20003 UNLOCK_ZONE(zone);
20004 }
20005
20006 void
20007 dns_zone_setdnssecsignstats(dns_zone_t *zone, dns_stats_t *stats) {
20008 REQUIRE(DNS_ZONE_VALID(zone));
20009
20010 LOCK_ZONE(zone);
20011 if (stats != NULL && zone->dnssecsignstats == NULL) {
20012 dns_stats_attach(stats, &zone->dnssecsignstats);
20013 }
20014 UNLOCK_ZONE(zone);
20015 }
20016
20017 dns_stats_t *
20018 dns_zone_getdnssecsignstats(dns_zone_t *zone) {
20019 REQUIRE(DNS_ZONE_VALID(zone));
20020
20021 return zone->dnssecsignstats;
20022 }
20023
20024 isc_stats_t *
20025 dns_zone_getrequeststats(dns_zone_t *zone) {
20026 /*
20027 * We don't lock zone for efficiency reason. This is not catastrophic
20028 * because requeststats must always be valid when requeststats_on is
20029 * true.
20030 * Some counters may be incremented while requeststats_on is becoming
20031 * false, or some cannot be incremented just after the statistics are
20032 * installed, but it shouldn't matter much in practice.
20033 */
20034 if (zone->requeststats_on) {
20035 return zone->requeststats;
20036 } else {
20037 return NULL;
20038 }
20039 }
20040
20041 /*
20042 * Return the received query stats bucket
20043 * see note from dns_zone_getrequeststats()
20044 */
20045 dns_stats_t *
20046 dns_zone_getrcvquerystats(dns_zone_t *zone) {
20047 if (zone->requeststats_on) {
20048 return zone->rcvquerystats;
20049 } else {
20050 return NULL;
20051 }
20052 }
20053
20054 void
20055 dns_zone_dialup(dns_zone_t *zone) {
20056 REQUIRE(DNS_ZONE_VALID(zone));
20057
20058 zone_debuglog(zone, __func__, 3, "notify = %d, refresh = %d",
20059 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY),
20060 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH));
20061
20062 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY)) {
20063 dns_zone_notify(zone, true);
20064 }
20065 if (zone->type != dns_zone_primary &&
20066 dns_remote_addresses(&zone->primaries) != NULL &&
20067 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
20068 {
20069 dns_zone_refresh(zone);
20070 }
20071 }
20072
20073 void
20074 dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
20075 REQUIRE(DNS_ZONE_VALID(zone));
20076
20077 LOCK_ZONE(zone);
20078 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
20079 DNS_ZONEFLG_DIALREFRESH |
20080 DNS_ZONEFLG_NOREFRESH);
20081 switch (dialup) {
20082 case dns_dialuptype_no:
20083 break;
20084 case dns_dialuptype_yes:
20085 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
20086 DNS_ZONEFLG_DIALREFRESH |
20087 DNS_ZONEFLG_NOREFRESH);
20088 break;
20089 case dns_dialuptype_notify:
20090 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
20091 break;
20092 case dns_dialuptype_notifypassive:
20093 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
20094 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
20095 break;
20096 case dns_dialuptype_refresh:
20097 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALREFRESH);
20098 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
20099 break;
20100 case dns_dialuptype_passive:
20101 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
20102 break;
20103 default:
20104 UNREACHABLE();
20105 }
20106 UNLOCK_ZONE(zone);
20107 }
20108
20109 isc_result_t
20110 dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory) {
20111 isc_result_t result = ISC_R_SUCCESS;
20112
20113 REQUIRE(DNS_ZONE_VALID(zone));
20114
20115 LOCK_ZONE(zone);
20116 result = dns_zone_setstring(zone, &zone->keydirectory, directory);
20117 UNLOCK_ZONE(zone);
20118
20119 return result;
20120 }
20121
20122 const char *
20123 dns_zone_getkeydirectory(dns_zone_t *zone) {
20124 REQUIRE(DNS_ZONE_VALID(zone));
20125
20126 return zone->keydirectory;
20127 }
20128
20129 void
20130 dns_zone_setkeystores(dns_zone_t *zone, dns_keystorelist_t *keystores) {
20131 REQUIRE(DNS_ZONE_VALID(zone));
20132
20133 LOCK_ZONE(zone);
20134 zone->keystores = keystores;
20135 UNLOCK_ZONE(zone);
20136 }
20137
20138 dns_keystorelist_t *
20139 dns_zone_getkeystores(dns_zone_t *zone) {
20140 dns_keystorelist_t *ks = NULL;
20141
20142 REQUIRE(DNS_ZONE_VALID(zone));
20143
20144 LOCK_ZONE(zone);
20145 if (inline_raw(zone) && zone->secure != NULL) {
20146 ks = zone->secure->keystores;
20147 } else {
20148 ks = zone->keystores;
20149 }
20150 UNLOCK_ZONE(zone);
20151
20152 return ks;
20153 }
20154
20155 unsigned int
20156 dns_zonemgr_getcount(dns_zonemgr_t *zmgr, dns_zonestate_t state) {
20157 dns_zone_t *zone;
20158 unsigned int count = 0;
20159
20160 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
20161
20162 RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
20163 switch (state) {
20164 case DNS_ZONESTATE_XFERRUNNING:
20165 for (zone = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
20166 zone != NULL; zone = ISC_LIST_NEXT(zone, statelink))
20167 {
20168 count++;
20169 }
20170 break;
20171 case DNS_ZONESTATE_XFERDEFERRED:
20172 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
20173 zone != NULL; zone = ISC_LIST_NEXT(zone, statelink))
20174 {
20175 count++;
20176 }
20177 break;
20178 case DNS_ZONESTATE_XFERFIRSTREFRESH:
20179 for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
20180 zone = ISC_LIST_NEXT(zone, link))
20181 {
20182 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FIRSTREFRESH)) {
20183 count++;
20184 }
20185 }
20186 break;
20187 case DNS_ZONESTATE_SOAQUERY:
20188 for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
20189 zone = ISC_LIST_NEXT(zone, link))
20190 {
20191 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
20192 count++;
20193 }
20194 }
20195 break;
20196 case DNS_ZONESTATE_ANY:
20197 for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
20198 zone = ISC_LIST_NEXT(zone, link))
20199 {
20200 dns_view_t *view = zone->view;
20201 if (view != NULL && strcmp(view->name, "_bind") == 0) {
20202 continue;
20203 }
20204 count++;
20205 }
20206 break;
20207 case DNS_ZONESTATE_AUTOMATIC:
20208 for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
20209 zone = ISC_LIST_NEXT(zone, link))
20210 {
20211 dns_view_t *view = zone->view;
20212 if (view != NULL && strcmp(view->name, "_bind") == 0) {
20213 continue;
20214 }
20215 if (zone->automatic) {
20216 count++;
20217 }
20218 }
20219 break;
20220 default:
20221 UNREACHABLE();
20222 }
20223
20224 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
20225
20226 return count;
20227 }
20228
20229 isc_result_t
20230 dns_zone_getxfr(dns_zone_t *zone, dns_xfrin_t **xfrp, bool *is_firstrefresh,
20231 bool *is_running, bool *is_deferred, bool *is_presoa,
20232 bool *is_pending, bool *needs_refresh) {
20233 REQUIRE(DNS_ZONE_VALID(zone));
20234 REQUIRE(xfrp != NULL && *xfrp == NULL);
20235
20236 if (zone->zmgr == NULL) {
20237 return ISC_R_FAILURE;
20238 }
20239
20240 /* Reset. */
20241 *is_firstrefresh = false;
20242 *is_running = false;
20243 *is_deferred = false;
20244 *is_presoa = false;
20245 *is_pending = false;
20246 *needs_refresh = false;
20247
20248 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_read);
20249 LOCK_ZONE(zone);
20250 *is_firstrefresh = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FIRSTREFRESH);
20251 if (zone->xfr != NULL) {
20252 dns_xfrin_attach(zone->xfr, xfrp);
20253 }
20254 if (zone->statelist == &zone->zmgr->xfrin_in_progress) {
20255 *is_running = true;
20256 /*
20257 * The NEEDREFRESH flag is set only when a notify was received
20258 * while the current zone transfer is running.
20259 */
20260 *needs_refresh = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
20261 } else if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
20262 *is_deferred = true;
20263 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
20264 if (zone->request != NULL) {
20265 *is_presoa = true;
20266 } else {
20267 *is_pending = true;
20268 }
20269 } else {
20270 /*
20271 * No operation is ongoing or pending, just check if the zone
20272 * needs a refresh by looking at the refresh and expire times.
20273 */
20274 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
20275 (zone->type == dns_zone_secondary ||
20276 zone->type == dns_zone_mirror ||
20277 zone->type == dns_zone_stub))
20278 {
20279 isc_time_t now = isc_time_now();
20280 if (isc_time_compare(&now, &zone->refreshtime) >= 0 ||
20281 isc_time_compare(&now, &zone->expiretime) >= 0)
20282 {
20283 *needs_refresh = true;
20284 }
20285 }
20286 }
20287 UNLOCK_ZONE(zone);
20288 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_read);
20289
20290 return ISC_R_SUCCESS;
20291 }
20292
20293 void
20294 dns_zone_lock_keyfiles(dns_zone_t *zone) {
20295 REQUIRE(DNS_ZONE_VALID(zone));
20296
20297 if (zone->kasp == NULL) {
20298 /* No need to lock, nothing is writing key files. */
20299 return;
20300 }
20301
20302 REQUIRE(DNS_KEYFILEIO_VALID(zone->kfio));
20303 isc_mutex_lock(&zone->kfio->lock);
20304 }
20305
20306 void
20307 dns_zone_unlock_keyfiles(dns_zone_t *zone) {
20308 REQUIRE(DNS_ZONE_VALID(zone));
20309
20310 if (zone->kasp == NULL) {
20311 /* No need to lock, nothing is writing key files. */
20312 return;
20313 }
20314
20315 REQUIRE(DNS_KEYFILEIO_VALID(zone->kfio));
20316 isc_mutex_unlock(&zone->kfio->lock);
20317 }
20318
20319 isc_result_t
20320 dns_zone_checknames(dns_zone_t *zone, const dns_name_t *name,
20321 dns_rdata_t *rdata) {
20322 bool ok = true;
20323 bool fail = false;
20324 char namebuf[DNS_NAME_FORMATSIZE];
20325 char namebuf2[DNS_NAME_FORMATSIZE];
20326 char typebuf[DNS_RDATATYPE_FORMATSIZE];
20327 int level = ISC_LOG_WARNING;
20328 dns_name_t bad;
20329
20330 REQUIRE(DNS_ZONE_VALID(zone));
20331
20332 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES) &&
20333 rdata->type != dns_rdatatype_nsec3)
20334 {
20335 return ISC_R_SUCCESS;
20336 }
20337
20338 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL) ||
20339 rdata->type == dns_rdatatype_nsec3)
20340 {
20341 level = ISC_LOG_ERROR;
20342 fail = true;
20343 }
20344
20345 ok = dns_rdata_checkowner(name, rdata->rdclass, rdata->type, true);
20346 if (!ok) {
20347 dns_name_format(name, namebuf, sizeof(namebuf));
20348 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
20349 dns_zone_log(zone, level, "%s/%s: %s", namebuf, typebuf,
20350 isc_result_totext(DNS_R_BADOWNERNAME));
20351 if (fail) {
20352 return DNS_R_BADOWNERNAME;
20353 }
20354 }
20355
20356 dns_name_init(&bad, NULL);
20357 ok = dns_rdata_checknames(rdata, name, &bad);
20358 if (!ok) {
20359 dns_name_format(name, namebuf, sizeof(namebuf));
20360 dns_name_format(&bad, namebuf2, sizeof(namebuf2));
20361 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
20362 dns_zone_log(zone, level, "%s/%s: %s: %s ", namebuf, typebuf,
20363 namebuf2, isc_result_totext(DNS_R_BADNAME));
20364 if (fail) {
20365 return DNS_R_BADNAME;
20366 }
20367 }
20368
20369 return ISC_R_SUCCESS;
20370 }
20371
20372 void
20373 dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx) {
20374 REQUIRE(DNS_ZONE_VALID(zone));
20375 zone->checkmx = checkmx;
20376 }
20377
20378 void
20379 dns_zone_setchecksrv(dns_zone_t *zone, dns_checksrvfunc_t checksrv) {
20380 REQUIRE(DNS_ZONE_VALID(zone));
20381 zone->checksrv = checksrv;
20382 }
20383
20384 void
20385 dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns) {
20386 REQUIRE(DNS_ZONE_VALID(zone));
20387 zone->checkns = checkns;
20388 }
20389
20390 void
20391 dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg) {
20392 REQUIRE(DNS_ZONE_VALID(zone));
20393
20394 LOCK_ZONE(zone);
20395 zone->isself = isself;
20396 zone->isselfarg = arg;
20397 UNLOCK_ZONE(zone);
20398 }
20399
20400 void
20401 dns_zone_setnotifydefer(dns_zone_t *zone, uint32_t defer) {
20402 REQUIRE(DNS_ZONE_VALID(zone));
20403
20404 LOCK_ZONE(zone);
20405 zone->notifydefer = defer;
20406 UNLOCK_ZONE(zone);
20407 }
20408
20409 void
20410 dns_zone_setnotifydelay(dns_zone_t *zone, uint32_t delay) {
20411 REQUIRE(DNS_ZONE_VALID(zone));
20412
20413 LOCK_ZONE(zone);
20414 zone->notifydelay = delay;
20415 UNLOCK_ZONE(zone);
20416 }
20417
20418 /*
20419 * Called when a dynamic update for an NSEC3PARAM record is received.
20420 *
20421 * If set, transform the NSEC3 salt into human-readable form so that it can be
20422 * logged. Then call zone_addnsec3chain(), passing NSEC3PARAM RDATA to it.
20423 */
20424 isc_result_t
20425 dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
20426 isc_result_t result;
20427 char salt[255 * 2 + 1];
20428
20429 REQUIRE(DNS_ZONE_VALID(zone));
20430
20431 result = dns_nsec3param_salttotext(nsec3param, salt, sizeof(salt));
20432 RUNTIME_CHECK(result == ISC_R_SUCCESS);
20433 dnssec_log(zone, ISC_LOG_NOTICE,
20434 "dns_zone_addnsec3chain(hash=%u, iterations=%u, salt=%s)",
20435 nsec3param->hash, nsec3param->iterations, salt);
20436 LOCK_ZONE(zone);
20437 result = zone_addnsec3chain(zone, nsec3param);
20438 UNLOCK_ZONE(zone);
20439
20440 return result;
20441 }
20442
20443 void
20444 dns_zone_setnodes(dns_zone_t *zone, uint32_t nodes) {
20445 REQUIRE(DNS_ZONE_VALID(zone));
20446
20447 if (nodes == 0) {
20448 nodes = 1;
20449 }
20450 zone->nodes = nodes;
20451 }
20452
20453 void
20454 dns_zone_setsignatures(dns_zone_t *zone, uint32_t signatures) {
20455 REQUIRE(DNS_ZONE_VALID(zone));
20456
20457 /*
20458 * We treat signatures as a signed value so explicitly
20459 * limit its range here.
20460 */
20461 if (signatures > INT32_MAX) {
20462 signatures = INT32_MAX;
20463 } else if (signatures == 0) {
20464 signatures = 1;
20465 }
20466 zone->signatures = signatures;
20467 }
20468
20469 uint32_t
20470 dns_zone_getsignatures(dns_zone_t *zone) {
20471 REQUIRE(DNS_ZONE_VALID(zone));
20472 return zone->signatures;
20473 }
20474
20475 void
20476 dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type) {
20477 REQUIRE(DNS_ZONE_VALID(zone));
20478 zone->privatetype = type;
20479 }
20480
20481 dns_rdatatype_t
20482 dns_zone_getprivatetype(dns_zone_t *zone) {
20483 REQUIRE(DNS_ZONE_VALID(zone));
20484 return zone->privatetype;
20485 }
20486
20487 static isc_result_t
20488 zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid,
20489 bool deleteit, bool fullsign) {
20490 dns_signing_t *signing;
20491 dns_signing_t *current;
20492 isc_result_t result = ISC_R_SUCCESS;
20493 isc_time_t now;
20494 dns_db_t *db = NULL;
20495
20496 signing = isc_mem_get(zone->mctx, sizeof *signing);
20497
20498 signing->magic = 0;
20499 signing->db = NULL;
20500 signing->dbiterator = NULL;
20501 signing->algorithm = algorithm;
20502 signing->keyid = keyid;
20503 signing->deleteit = deleteit;
20504 signing->fullsign = fullsign;
20505 signing->done = false;
20506
20507 now = isc_time_now();
20508
20509 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
20510 if (zone->db != NULL) {
20511 dns_db_attach(zone->db, &db);
20512 }
20513 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
20514
20515 if (db == NULL) {
20516 result = ISC_R_NOTFOUND;
20517 goto cleanup;
20518 }
20519
20520 dns_db_attach(db, &signing->db);
20521
20522 for (current = ISC_LIST_HEAD(zone->signing); current != NULL;
20523 current = ISC_LIST_NEXT(current, link))
20524 {
20525 if (current->db == signing->db &&
20526 current->algorithm == signing->algorithm &&
20527 current->keyid == signing->keyid)
20528 {
20529 if (current->deleteit != signing->deleteit) {
20530 current->done = true;
20531 } else {
20532 goto cleanup;
20533 }
20534 }
20535 }
20536
20537 result = dns_db_createiterator(signing->db, 0, &signing->dbiterator);
20538
20539 if (result == ISC_R_SUCCESS) {
20540 result = dns_dbiterator_first(signing->dbiterator);
20541 }
20542 if (result == ISC_R_SUCCESS) {
20543 dns_dbiterator_pause(signing->dbiterator);
20544 ISC_LIST_INITANDAPPEND(zone->signing, signing, link);
20545 signing = NULL;
20546 if (isc_time_isepoch(&zone->signingtime)) {
20547 zone->signingtime = now;
20548 if (zone->loop != NULL) {
20549 zone_settimer(zone, &now);
20550 }
20551 }
20552 }
20553
20554 cleanup:
20555 if (signing != NULL) {
20556 if (signing->db != NULL) {
20557 dns_db_detach(&signing->db);
20558 }
20559 if (signing->dbiterator != NULL) {
20560 dns_dbiterator_destroy(&signing->dbiterator);
20561 }
20562 isc_mem_put(zone->mctx, signing, sizeof *signing);
20563 }
20564 if (db != NULL) {
20565 dns_db_detach(&db);
20566 }
20567 return result;
20568 }
20569
20570 /* Called once; *timep should be set to the current time. */
20571 static isc_result_t
20572 next_keyevent(dst_key_t *key, isc_stdtime_t *timep) {
20573 isc_result_t result;
20574 isc_stdtime_t now, then = 0, event;
20575 int i;
20576
20577 now = *timep;
20578
20579 for (i = 0; i < DST_MAX_TIMES; i++) {
20580 result = dst_key_gettime(key, i, &event);
20581 if (result == ISC_R_SUCCESS && event > now &&
20582 (then == 0 || event < then))
20583 {
20584 then = event;
20585 }
20586 }
20587
20588 if (then != 0) {
20589 *timep = then;
20590 return ISC_R_SUCCESS;
20591 }
20592
20593 return ISC_R_NOTFOUND;
20594 }
20595
20596 static isc_result_t
20597 rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
20598 const dns_rdata_t *rdata, bool *flag) {
20599 dns_rdataset_t rdataset;
20600 dns_dbnode_t *node = NULL;
20601 isc_result_t result;
20602
20603 dns_rdataset_init(&rdataset);
20604 if (rdata->type == dns_rdatatype_nsec3) {
20605 CHECK(dns_db_findnsec3node(db, name, false, &node));
20606 } else {
20607 CHECK(dns_db_findnode(db, name, false, &node));
20608 }
20609 result = dns_db_findrdataset(db, node, ver, rdata->type, 0,
20610 (isc_stdtime_t)0, &rdataset, NULL);
20611 if (result == ISC_R_NOTFOUND) {
20612 *flag = false;
20613 result = ISC_R_SUCCESS;
20614 goto cleanup;
20615 }
20616
20617 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
20618 result = dns_rdataset_next(&rdataset))
20619 {
20620 dns_rdata_t myrdata = DNS_RDATA_INIT;
20621 dns_rdataset_current(&rdataset, &myrdata);
20622 if (!dns_rdata_compare(&myrdata, rdata)) {
20623 break;
20624 }
20625 }
20626 dns_rdataset_disassociate(&rdataset);
20627 if (result == ISC_R_SUCCESS) {
20628 *flag = true;
20629 } else if (result == ISC_R_NOMORE) {
20630 *flag = false;
20631 result = ISC_R_SUCCESS;
20632 }
20633
20634 cleanup:
20635 if (node != NULL) {
20636 dns_db_detachnode(db, &node);
20637 }
20638 return result;
20639 }
20640
20641 /*
20642 * Add records to signal the state of signing or of key removal.
20643 */
20644 static isc_result_t
20645 add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
20646 dns_dbversion_t *ver, dns_diff_t *diff, bool sign_all) {
20647 dns_difftuple_t *tuple = NULL, *newtuple = NULL, *next = NULL;
20648 dns_difftuple_t *addtuple = NULL, *deltuple = NULL;
20649 dns_rdata_dnskey_t dnskey;
20650 dns_rdata_t rdata = DNS_RDATA_INIT;
20651 bool flag;
20652 isc_region_t r;
20653 isc_result_t result = ISC_R_SUCCESS;
20654 uint16_t keyid;
20655 unsigned char buf[5];
20656 dns_name_t *name = dns_db_origin(db);
20657 dns_difftuplelist_t add = ISC_LIST_INITIALIZER;
20658 dns_difftuplelist_t del = ISC_LIST_INITIALIZER;
20659 dns_difftuplelist_t tuples = ISC_LIST_INITIALIZER;
20660
20661 /*
20662 * Move non DNSKEY and not DNSSEC DNSKEY records to tuples
20663 * and sort the remaining DNSKEY records to add and del.
20664 */
20665 for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL;
20666 tuple = ISC_LIST_HEAD(diff->tuples))
20667 {
20668 if (tuple->rdata.type != dns_rdatatype_dnskey) {
20669 ISC_LIST_UNLINK(diff->tuples, tuple, link);
20670 ISC_LIST_APPEND(tuples, tuple, link);
20671 continue;
20672 }
20673
20674 result = dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
20675 RUNTIME_CHECK(result == ISC_R_SUCCESS);
20676 if ((dnskey.flags & DNS_KEYFLAG_OWNERMASK) != DNS_KEYOWNER_ZONE)
20677 {
20678 ISC_LIST_UNLINK(diff->tuples, tuple, link);
20679 ISC_LIST_APPEND(tuples, tuple, link);
20680 continue;
20681 }
20682
20683 ISC_LIST_UNLINK(diff->tuples, tuple, link);
20684 switch (tuple->op) {
20685 case DNS_DIFFOP_DEL:
20686 case DNS_DIFFOP_DELRESIGN:
20687 ISC_LIST_APPEND(del, tuple, link);
20688 break;
20689 case DNS_DIFFOP_ADD:
20690 case DNS_DIFFOP_ADDRESIGN:
20691 ISC_LIST_APPEND(add, tuple, link);
20692 break;
20693 default:
20694 UNREACHABLE();
20695 }
20696 }
20697
20698 /*
20699 * Put the tuples that don't need more processing back onto
20700 * diff->tuples.
20701 */
20702 ISC_LIST_APPENDLIST(diff->tuples, tuples, link);
20703
20704 /*
20705 * Filter out DNSKEY TTL changes and put them back onto diff->tuples.
20706 */
20707 for (deltuple = ISC_LIST_HEAD(del); deltuple != NULL; deltuple = next) {
20708 next = ISC_LIST_NEXT(deltuple, link);
20709 for (addtuple = ISC_LIST_HEAD(add); addtuple != NULL;
20710 addtuple = ISC_LIST_NEXT(addtuple, link))
20711 {
20712 int n = dns_rdata_compare(&deltuple->rdata,
20713 &addtuple->rdata);
20714 if (n == 0) {
20715 ISC_LIST_UNLINK(del, deltuple, link);
20716 ISC_LIST_APPEND(diff->tuples, deltuple, link);
20717 ISC_LIST_UNLINK(add, addtuple, link);
20718 ISC_LIST_APPEND(diff->tuples, addtuple, link);
20719 break;
20720 }
20721 }
20722 }
20723
20724 /*
20725 * Combine any remaining DNSKEY changes together.
20726 */
20727 ISC_LIST_APPENDLIST(tuples, add, link);
20728 ISC_LIST_APPENDLIST(tuples, del, link);
20729
20730 /*
20731 * Add private records for keys that have been removed
20732 * or added.
20733 */
20734 for (tuple = ISC_LIST_HEAD(tuples); tuple != NULL;
20735 tuple = ISC_LIST_NEXT(tuple, link))
20736 {
20737 dns_rdata_toregion(&tuple->rdata, &r);
20738
20739 keyid = dst_region_computeid(&r);
20740
20741 buf[0] = dnskey.algorithm;
20742 buf[1] = (keyid & 0xff00) >> 8;
20743 buf[2] = (keyid & 0xff);
20744 buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1;
20745 buf[4] = 0;
20746 rdata.data = buf;
20747 rdata.length = sizeof(buf);
20748 rdata.type = privatetype;
20749 rdata.rdclass = tuple->rdata.rdclass;
20750
20751 if (sign_all || tuple->op == DNS_DIFFOP_DEL) {
20752 CHECK(rr_exists(db, ver, name, &rdata, &flag));
20753 if (flag) {
20754 continue;
20755 }
20756
20757 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
20758 name, 0, &rdata, &newtuple));
20759 CHECK(do_one_tuple(&newtuple, db, ver, diff));
20760 INSIST(newtuple == NULL);
20761 }
20762
20763 /*
20764 * Remove any record which says this operation has already
20765 * completed.
20766 */
20767 buf[4] = 1;
20768 CHECK(rr_exists(db, ver, name, &rdata, &flag));
20769 if (flag) {
20770 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL,
20771 name, 0, &rdata, &newtuple));
20772 CHECK(do_one_tuple(&newtuple, db, ver, diff));
20773 INSIST(newtuple == NULL);
20774 }
20775 }
20776
20777 cleanup:
20778 /*
20779 * Put the DNSKEY changes we cared about back on diff->tuples.
20780 */
20781 ISC_LIST_APPENDLIST(diff->tuples, tuples, link);
20782 INSIST(ISC_LIST_EMPTY(add));
20783 INSIST(ISC_LIST_EMPTY(del));
20784 INSIST(ISC_LIST_EMPTY(tuples));
20785 return result;
20786 }
20787
20788 /*
20789 * See if dns__zone_updatesigs() will update signature for RRset 'rrtype' at
20790 * the apex, and if not tickle them and cause to sign so that newly activated
20791 * keys are used.
20792 */
20793 static isc_result_t
20794 tickle_apex_rrset(dns_rdatatype_t rrtype, dns_zone_t *zone, dns_db_t *db,
20795 dns_dbversion_t *ver, isc_stdtime_t now, dns_diff_t *diff,
20796 dns__zonediff_t *zonediff, dst_key_t **keys,
20797 unsigned int nkeys, isc_stdtime_t inception,
20798 isc_stdtime_t keyexpire) {
20799 dns_difftuple_t *tuple;
20800 isc_result_t result;
20801
20802 for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL;
20803 tuple = ISC_LIST_NEXT(tuple, link))
20804 {
20805 if (tuple->rdata.type == rrtype &&
20806 dns_name_equal(&tuple->name, &zone->origin))
20807 {
20808 break;
20809 }
20810 }
20811
20812 if (tuple == NULL) {
20813 result = del_sigs(zone, db, ver, &zone->origin, rrtype,
20814 zonediff, keys, nkeys, now, false);
20815 if (result != ISC_R_SUCCESS) {
20816 dnssec_log(zone, ISC_LOG_ERROR,
20817 "sign_apex:del_sigs -> %s",
20818 isc_result_totext(result));
20819 return result;
20820 }
20821 result = add_sigs(db, ver, &zone->origin, zone, rrtype,
20822 zonediff->diff, keys, nkeys, zone->mctx, now,
20823 inception, keyexpire);
20824 if (result != ISC_R_SUCCESS) {
20825 dnssec_log(zone, ISC_LOG_ERROR,
20826 "sign_apex:add_sigs -> %s",
20827 isc_result_totext(result));
20828 return result;
20829 }
20830 }
20831
20832 return ISC_R_SUCCESS;
20833 }
20834
20835 static isc_result_t
20836 sign_apex(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
20837 isc_stdtime_t now, dns_diff_t *diff, dns__zonediff_t *zonediff) {
20838 isc_result_t result;
20839 isc_stdtime_t inception, soaexpire, keyexpire;
20840 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
20841 unsigned int nkeys = 0, i;
20842
20843 result = dns_zone_findkeys(zone, db, ver, now, zone->mctx,
20844 DNS_MAXZONEKEYS, zone_keys, &nkeys);
20845 if (result != ISC_R_SUCCESS) {
20846 dnssec_log(zone, ISC_LOG_ERROR,
20847 "sign_apex:dns_zone_findkeys -> %s",
20848 isc_result_totext(result));
20849 return result;
20850 }
20851
20852 inception = now - 3600; /* Allow for clock skew. */
20853 soaexpire = now + dns_zone_getsigvalidityinterval(zone);
20854
20855 keyexpire = dns_zone_getkeyvalidityinterval(zone);
20856 if (keyexpire == 0) {
20857 keyexpire = soaexpire - 1;
20858 } else {
20859 keyexpire += now;
20860 }
20861
20862 /*
20863 * See if dns__zone_updatesigs() will update DNSKEY/CDS/CDNSKEY
20864 * signature and if not cause them to sign so that newly activated
20865 * keys are used.
20866 */
20867 CHECK(tickle_apex_rrset(dns_rdatatype_dnskey, zone, db, ver, now, diff,
20868 zonediff, zone_keys, nkeys, inception,
20869 keyexpire));
20870 CHECK(tickle_apex_rrset(dns_rdatatype_cds, zone, db, ver, now, diff,
20871 zonediff, zone_keys, nkeys, inception,
20872 keyexpire));
20873 CHECK(tickle_apex_rrset(dns_rdatatype_cdnskey, zone, db, ver, now, diff,
20874 zonediff, zone_keys, nkeys, inception,
20875 keyexpire));
20876
20877 result = dns__zone_updatesigs(diff, db, ver, zone_keys, nkeys, zone,
20878 inception, soaexpire, keyexpire, now,
20879 zonediff);
20880 if (result != ISC_R_SUCCESS) {
20881 dnssec_log(zone, ISC_LOG_ERROR,
20882 "sign_apex:dns__zone_updatesigs -> %s",
20883 isc_result_totext(result));
20884 }
20885
20886 cleanup:
20887 for (i = 0; i < nkeys; i++) {
20888 dst_key_free(&zone_keys[i]);
20889 }
20890 return result;
20891 }
20892
20893 static isc_result_t
20894 clean_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
20895 dns_diff_t *diff) {
20896 isc_result_t result;
20897 dns_dbnode_t *node = NULL;
20898 dns_rdataset_t rdataset;
20899
20900 dns_rdataset_init(&rdataset);
20901 CHECK(dns_db_getoriginnode(db, &node));
20902
20903 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
20904 dns_rdatatype_none, 0, &rdataset, NULL);
20905 if (dns_rdataset_isassociated(&rdataset)) {
20906 dns_rdataset_disassociate(&rdataset);
20907 }
20908 if (result != ISC_R_NOTFOUND) {
20909 goto cleanup;
20910 }
20911
20912 result = dns_nsec3param_deletechains(db, ver, zone, true, diff);
20913
20914 cleanup:
20915 if (node != NULL) {
20916 dns_db_detachnode(db, &node);
20917 }
20918 return result;
20919 }
20920
20921 /*
20922 * Given an RRSIG rdataset and an algorithm, determine whether there
20923 * are any signatures using that algorithm.
20924 */
20925 static bool
20926 signed_with_alg(dns_rdataset_t *rdataset, dns_secalg_t alg) {
20927 dns_rdata_t rdata = DNS_RDATA_INIT;
20928 dns_rdata_rrsig_t rrsig;
20929 isc_result_t result;
20930
20931 REQUIRE(rdataset == NULL || rdataset->type == dns_rdatatype_rrsig);
20932 if (rdataset == NULL || !dns_rdataset_isassociated(rdataset)) {
20933 return false;
20934 }
20935
20936 for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
20937 result = dns_rdataset_next(rdataset))
20938 {
20939 dns_rdataset_current(rdataset, &rdata);
20940 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
20941 RUNTIME_CHECK(result == ISC_R_SUCCESS);
20942 dns_rdata_reset(&rdata);
20943 if (rrsig.algorithm == alg) {
20944 return true;
20945 }
20946 }
20947
20948 return false;
20949 }
20950
20951 static isc_result_t
20952 add_chains(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
20953 dns_diff_t *diff) {
20954 dns_name_t *origin;
20955 bool build_nsec3;
20956 isc_result_t result;
20957
20958 origin = dns_db_origin(db);
20959 CHECK(dns_private_chains(db, ver, zone->privatetype, NULL,
20960 &build_nsec3));
20961 if (build_nsec3) {
20962 CHECK(dns_nsec3_addnsec3sx(db, ver, origin, zone_nsecttl(zone),
20963 false, zone->privatetype, diff));
20964 }
20965 CHECK(updatesecure(db, ver, origin, zone_nsecttl(zone), true, diff));
20966
20967 cleanup:
20968 return result;
20969 }
20970
20971 static void
20972 dnssec_report(const char *format, ...) {
20973 va_list args;
20974 va_start(args, format);
20975 isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_ZONE,
20976 ISC_LOG_INFO, format, args);
20977 va_end(args);
20978 }
20979
20980 static void
20981 checkds_destroy(dns_checkds_t *checkds, bool locked) {
20982 REQUIRE(DNS_CHECKDS_VALID(checkds));
20983
20984 dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
20985 "checkds: destroy DS query");
20986
20987 if (checkds->zone != NULL) {
20988 if (!locked) {
20989 LOCK_ZONE(checkds->zone);
20990 }
20991 REQUIRE(LOCKED_ZONE(checkds->zone));
20992 if (ISC_LINK_LINKED(checkds, link)) {
20993 ISC_LIST_UNLINK(checkds->zone->checkds_requests,
20994 checkds, link);
20995 }
20996 if (!locked) {
20997 UNLOCK_ZONE(checkds->zone);
20998 }
20999 if (locked) {
21000 zone_idetach(&checkds->zone);
21001 } else {
21002 dns_zone_idetach(&checkds->zone);
21003 }
21004 }
21005 if (checkds->find != NULL) {
21006 dns_adb_destroyfind(&checkds->find);
21007 }
21008 if (checkds->request != NULL) {
21009 dns_request_destroy(&checkds->request);
21010 }
21011 if (dns_name_dynamic(&checkds->ns)) {
21012 dns_name_free(&checkds->ns, checkds->mctx);
21013 }
21014 if (checkds->key != NULL) {
21015 dns_tsigkey_detach(&checkds->key);
21016 }
21017 if (checkds->transport != NULL) {
21018 dns_transport_detach(&checkds->transport);
21019 }
21020 INSIST(checkds->rlevent == NULL);
21021 isc_mem_putanddetach(&checkds->mctx, checkds, sizeof(*checkds));
21022 }
21023
21024 static isc_result_t
21025 make_dnskey(dst_key_t *key, unsigned char *buf, int bufsize,
21026 dns_rdata_t *target) {
21027 isc_result_t result;
21028 isc_buffer_t b;
21029 isc_region_t r;
21030
21031 isc_buffer_init(&b, buf, bufsize);
21032 result = dst_key_todns(key, &b);
21033 if (result != ISC_R_SUCCESS) {
21034 return result;
21035 }
21036
21037 dns_rdata_reset(target);
21038 isc_buffer_usedregion(&b, &r);
21039 dns_rdata_fromregion(target, dst_key_class(key), dns_rdatatype_dnskey,
21040 &r);
21041 return ISC_R_SUCCESS;
21042 }
21043
21044 static bool
21045 do_checkds(dns_zone_t *zone, dst_key_t *key, isc_stdtime_t now,
21046 bool dspublish) {
21047 dns_kasp_t *kasp = zone->kasp;
21048 isc_result_t result;
21049 uint32_t count = 0;
21050 uint32_t num;
21051
21052 switch (zone->checkdstype) {
21053 case dns_checkdstype_yes:
21054 num = zone->parent_nscount;
21055 break;
21056 case dns_checkdstype_explicit:
21057 num = dns_remote_count(&zone->parentals);
21058 break;
21059 case dns_checkdstype_no:
21060 default:
21061 dns_zone_log(zone, ISC_LOG_WARNING,
21062 "checkds: option is disabled");
21063 return false;
21064 }
21065
21066 if (dspublish) {
21067 (void)dst_key_getnum(key, DST_NUM_DSPUBCOUNT, &count);
21068 count += 1;
21069 dst_key_setnum(key, DST_NUM_DSPUBCOUNT, count);
21070 dns_zone_log(zone, ISC_LOG_DEBUG(3),
21071 "checkds: %u DS published "
21072 "for key %u",
21073 count, dst_key_id(key));
21074
21075 if (count != num) {
21076 return false;
21077 }
21078 } else {
21079 (void)dst_key_getnum(key, DST_NUM_DSDELCOUNT, &count);
21080 count += 1;
21081 dst_key_setnum(key, DST_NUM_DSDELCOUNT, count);
21082 dns_zone_log(zone, ISC_LOG_DEBUG(3),
21083 "checkds: %u DS withdrawn "
21084 "for key %u",
21085 count, dst_key_id(key));
21086
21087 if (count != num) {
21088 return false;
21089 }
21090 }
21091
21092 dns_zone_log(zone, ISC_LOG_DEBUG(3),
21093 "checkds: checkds %s for key "
21094 "%u",
21095 dspublish ? "published" : "withdrawn", dst_key_id(key));
21096
21097 dns_zone_lock_keyfiles(zone);
21098 result = dns_keymgr_checkds_id(kasp, &zone->checkds_ok, now, now,
21099 dspublish, dst_key_id(key),
21100 dst_key_alg(key));
21101 dns_zone_unlock_keyfiles(zone);
21102
21103 if (result != ISC_R_SUCCESS) {
21104 dns_zone_log(zone, ISC_LOG_WARNING,
21105 "checkds: checkds for key %u failed: %s",
21106 dst_key_id(key), isc_result_totext(result));
21107 return false;
21108 }
21109
21110 return true;
21111 }
21112
21113 static isc_result_t
21114 validate_ds(dns_zone_t *zone, dns_message_t *message) {
21115 UNUSED(zone);
21116 UNUSED(message);
21117
21118 /* Get closest trust anchor */
21119
21120 /* Check that trust anchor is (grand)parent of zone. */
21121
21122 /* Find the DNSKEY signing the message. */
21123
21124 /* Check that DNSKEY is in chain of trust. */
21125
21126 /* Validate DS RRset. */
21127
21128 return ISC_R_SUCCESS;
21129 }
21130
21131 static void
21132 checkds_done(void *arg) {
21133 dns_request_t *request = (dns_request_t *)arg;
21134 dns_checkds_t *checkds = dns_request_getarg(request);
21135 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
21136 char rcode[128];
21137 dns_zone_t *zone = NULL;
21138 dns_db_t *db = NULL;
21139 dns_dbversion_t *version = NULL;
21140 dns_dnsseckey_t *key = NULL;
21141 dns_dnsseckeylist_t keys;
21142 dns_kasp_t *kasp = NULL;
21143 dns_message_t *message = NULL;
21144 dns_rdataset_t *ds_rrset = NULL;
21145 isc_buffer_t buf;
21146 isc_result_t result;
21147 isc_stdtime_t now;
21148 isc_time_t timenow;
21149 bool rekey = false;
21150 bool empty = false;
21151
21152 REQUIRE(DNS_CHECKDS_VALID(checkds));
21153
21154 zone = checkds->zone;
21155
21156 ISC_LIST_INIT(keys);
21157
21158 kasp = zone->kasp;
21159 INSIST(kasp != NULL);
21160
21161 isc_buffer_init(&buf, rcode, sizeof(rcode));
21162 isc_sockaddr_format(&checkds->dst, addrbuf, sizeof(addrbuf));
21163
21164 dns_zone_log(zone, ISC_LOG_DEBUG(1), "checkds: DS query to %s: done",
21165 addrbuf);
21166
21167 dns_message_create(zone->mctx, NULL, NULL, DNS_MESSAGE_INTENTPARSE,
21168 &message);
21169 INSIST(message != NULL);
21170
21171 CHECK(dns_request_getresult(request));
21172 CHECK(dns_request_getresponse(request, message,
21173 DNS_MESSAGEPARSE_PRESERVEORDER));
21174 CHECK(dns_rcode_totext(message->rcode, &buf));
21175
21176 dns_zone_log(zone, ISC_LOG_DEBUG(3),
21177 "checkds: DS response from %s: %.*s", addrbuf,
21178 (int)buf.used, rcode);
21179
21180 /* Validate response. */
21181 CHECK(validate_ds(zone, message));
21182
21183 /* Check RCODE. */
21184 if (message->rcode != dns_rcode_noerror) {
21185 dns_zone_log(zone, ISC_LOG_NOTICE,
21186 "checkds: bad DS response from %s: %.*s", addrbuf,
21187 (int)buf.used, rcode);
21188 goto cleanup;
21189 }
21190
21191 /* Make sure that either AA or RA bit is set. */
21192 if ((message->flags & DNS_MESSAGEFLAG_AA) == 0 &&
21193 (message->flags & DNS_MESSAGEFLAG_RA) == 0)
21194 {
21195 dns_zone_log(zone, ISC_LOG_NOTICE,
21196 "checkds: bad DS response from %s: expected AA or "
21197 "RA bit set",
21198 addrbuf);
21199 goto cleanup;
21200 }
21201
21202 /* Lookup DS RRset. */
21203 result = dns_message_firstname(message, DNS_SECTION_ANSWER);
21204 while (result == ISC_R_SUCCESS) {
21205 dns_name_t *name = NULL;
21206 dns_rdataset_t *rdataset;
21207
21208 dns_message_currentname(message, DNS_SECTION_ANSWER, &name);
21209 if (dns_name_compare(&zone->origin, name) != 0) {
21210 goto next;
21211 }
21212
21213 for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL;
21214 rdataset = ISC_LIST_NEXT(rdataset, link))
21215 {
21216 if (rdataset->type != dns_rdatatype_ds) {
21217 goto next;
21218 }
21219
21220 ds_rrset = rdataset;
21221 break;
21222 }
21223
21224 if (ds_rrset != NULL) {
21225 break;
21226 }
21227
21228 next:
21229 result = dns_message_nextname(message, DNS_SECTION_ANSWER);
21230 }
21231
21232 if (ds_rrset == NULL) {
21233 empty = true;
21234 dns_zone_log(zone, ISC_LOG_NOTICE,
21235 "checkds: empty DS response from %s", addrbuf);
21236 }
21237
21238 timenow = isc_time_now();
21239 now = isc_time_seconds(&timenow);
21240
21241 CHECK(dns_zone_getdb(zone, &db));
21242 dns_db_currentversion(db, &version);
21243
21244 KASP_LOCK(kasp);
21245 LOCK_ZONE(zone);
21246 for (key = ISC_LIST_HEAD(zone->checkds_ok); key != NULL;
21247 key = ISC_LIST_NEXT(key, link))
21248 {
21249 bool alldone = false, found = false;
21250 bool checkdspub = false, checkdsdel = false, ksk = false;
21251 dst_key_state_t ds_state = DST_KEY_STATE_NA;
21252 isc_stdtime_t published = 0, withdrawn = 0;
21253 isc_result_t ret = ISC_R_SUCCESS;
21254
21255 /* Is this key have the KSK role? */
21256 (void)dst_key_role(key->key, &ksk, NULL);
21257 if (!ksk) {
21258 continue;
21259 }
21260
21261 /* Do we need to check the DS RRset for this key? */
21262 (void)dst_key_getstate(key->key, DST_KEY_DS, &ds_state);
21263 (void)dst_key_gettime(key->key, DST_TIME_DSPUBLISH, &published);
21264 (void)dst_key_gettime(key->key, DST_TIME_DSDELETE, &withdrawn);
21265
21266 if (ds_state == DST_KEY_STATE_RUMOURED && published == 0) {
21267 checkdspub = true;
21268 } else if (ds_state == DST_KEY_STATE_UNRETENTIVE &&
21269 withdrawn == 0)
21270 {
21271 checkdsdel = true;
21272 }
21273 if (!checkdspub && !checkdsdel) {
21274 continue;
21275 }
21276
21277 if (empty) {
21278 goto dswithdrawn;
21279 }
21280
21281 /* Find the appropriate DS record. */
21282 ret = dns_rdataset_first(ds_rrset);
21283 while (ret == ISC_R_SUCCESS) {
21284 dns_rdata_ds_t ds;
21285 dns_rdata_t dnskey = DNS_RDATA_INIT;
21286 dns_rdata_t dsrdata = DNS_RDATA_INIT;
21287 dns_rdata_t rdata = DNS_RDATA_INIT;
21288 isc_result_t r;
21289 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
21290 unsigned char keybuf[DST_KEY_MAXSIZE];
21291
21292 dns_rdataset_current(ds_rrset, &rdata);
21293 r = dns_rdata_tostruct(&rdata, &ds, NULL);
21294 if (r != ISC_R_SUCCESS) {
21295 goto nextds;
21296 }
21297 /* Check key tag and algorithm. */
21298 if (dst_key_id(key->key) != ds.key_tag) {
21299 goto nextds;
21300 }
21301 if (dst_key_alg(key->key) != ds.algorithm) {
21302 goto nextds;
21303 }
21304 /* Derive DS from DNSKEY, see if the rdata is equal. */
21305 make_dnskey(key->key, keybuf, sizeof(keybuf), &dnskey);
21306 r = dns_ds_buildrdata(&zone->origin, &dnskey,
21307 ds.digest_type, dsbuf, &dsrdata);
21308 if (r != ISC_R_SUCCESS) {
21309 goto nextds;
21310 }
21311 if (dns_rdata_compare(&rdata, &dsrdata) == 0) {
21312 found = true;
21313 if (checkdspub) {
21314 /* DS Published. */
21315 alldone = do_checkds(zone, key->key,
21316 now, true);
21317 if (alldone) {
21318 rekey = true;
21319 }
21320 }
21321 }
21322
21323 nextds:
21324 ret = dns_rdataset_next(ds_rrset);
21325 }
21326
21327 dswithdrawn:
21328 /* DS withdrawn. */
21329 if (checkdsdel && !found) {
21330 alldone = do_checkds(zone, key->key, now, false);
21331 if (alldone) {
21332 rekey = true;
21333 }
21334 }
21335 }
21336 UNLOCK_ZONE(zone);
21337 KASP_UNLOCK(kasp);
21338
21339 /* Rekey after checkds. */
21340 if (rekey) {
21341 dns_zone_rekey(zone, false, false);
21342 }
21343
21344 cleanup:
21345 if (result != ISC_R_SUCCESS) {
21346 dns_zone_log(zone, ISC_LOG_DEBUG(3),
21347 "checkds: DS request failed: %s",
21348 isc_result_totext(result));
21349 }
21350
21351 if (version != NULL) {
21352 dns_db_closeversion(db, &version, false);
21353 }
21354 if (db != NULL) {
21355 dns_db_detach(&db);
21356 }
21357
21358 while (!ISC_LIST_EMPTY(keys)) {
21359 key = ISC_LIST_HEAD(keys);
21360 ISC_LIST_UNLINK(keys, key, link);
21361 dns_dnsseckey_destroy(dns_zone_getmctx(zone), &key);
21362 }
21363
21364 checkds_destroy(checkds, false);
21365 dns_message_detach(&message);
21366 }
21367
21368 static bool
21369 checkds_isqueued(dns_zone_t *zone, dns_name_t *name, isc_sockaddr_t *addr,
21370 dns_tsigkey_t *key, dns_transport_t *transport) {
21371 dns_checkds_t *checkds;
21372
21373 for (checkds = ISC_LIST_HEAD(zone->checkds_requests); checkds != NULL;
21374 checkds = ISC_LIST_NEXT(checkds, link))
21375 {
21376 if (checkds->request != NULL) {
21377 continue;
21378 }
21379 if (name != NULL && dns_name_equal(name, &checkds->ns)) {
21380 return true;
21381 }
21382 if (addr != NULL && isc_sockaddr_equal(addr, &checkds->dst) &&
21383 checkds->key == key && checkds->transport == transport)
21384 {
21385 return true;
21386 }
21387 }
21388 return false;
21389 }
21390
21391 static isc_result_t
21392 checkds_create(isc_mem_t *mctx, unsigned int flags, dns_checkds_t **checkdsp) {
21393 dns_checkds_t *checkds;
21394
21395 REQUIRE(checkdsp != NULL && *checkdsp == NULL);
21396
21397 checkds = isc_mem_get(mctx, sizeof(*checkds));
21398 *checkds = (dns_checkds_t){
21399 .flags = flags,
21400 };
21401
21402 isc_mem_attach(mctx, &checkds->mctx);
21403 isc_sockaddr_any(&checkds->dst);
21404 dns_name_init(&checkds->ns, NULL);
21405 ISC_LINK_INIT(checkds, link);
21406 checkds->magic = CHECKDS_MAGIC;
21407 *checkdsp = checkds;
21408 return ISC_R_SUCCESS;
21409 }
21410
21411 static void
21412 checkds_createmessage(dns_zone_t *zone, dns_message_t **messagep) {
21413 dns_message_t *message = NULL;
21414
21415 dns_name_t *tempname = NULL;
21416 dns_rdataset_t *temprdataset = NULL;
21417
21418 REQUIRE(DNS_ZONE_VALID(zone));
21419 REQUIRE(messagep != NULL && *messagep == NULL);
21420
21421 dns_message_create(zone->mctx, NULL, NULL, DNS_MESSAGE_INTENTRENDER,
21422 &message);
21423
21424 message->opcode = dns_opcode_query;
21425 message->rdclass = zone->rdclass;
21426 message->flags |= DNS_MESSAGEFLAG_RD;
21427
21428 dns_message_gettempname(message, &tempname);
21429
21430 dns_message_gettemprdataset(message, &temprdataset);
21431
21432 /*
21433 * Make question.
21434 */
21435 dns_name_init(tempname, NULL);
21436 dns_name_clone(&zone->origin, tempname);
21437 dns_rdataset_makequestion(temprdataset, zone->rdclass,
21438 dns_rdatatype_ds);
21439 ISC_LIST_APPEND(tempname->list, temprdataset, link);
21440 dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
21441 tempname = NULL;
21442 temprdataset = NULL;
21443
21444 *messagep = message;
21445 }
21446
21447 /*
21448 * XXXAG should check for DNS_ZONEFLG_EXITING
21449 */
21450 static void
21451 process_checkds_adb_event(void *arg) {
21452 dns_adbfind_t *find = (dns_adbfind_t *)arg;
21453 dns_checkds_t *checkds = (dns_checkds_t *)find->cbarg;
21454 dns_adbstatus_t astat = find->status;
21455
21456 REQUIRE(DNS_CHECKDS_VALID(checkds));
21457 REQUIRE(find == checkds->find);
21458
21459 switch (astat) {
21460 case DNS_ADB_MOREADDRESSES:
21461 dns_adb_destroyfind(&checkds->find);
21462 checkds_find_address(checkds);
21463 return;
21464
21465 case DNS_ADB_NOMOREADDRESSES:
21466 LOCK_ZONE(checkds->zone);
21467 checkds_send_tons(checkds);
21468 UNLOCK_ZONE(checkds->zone);
21469 break;
21470
21471 default:
21472 break;
21473 }
21474
21475 checkds_destroy(checkds, false);
21476 }
21477
21478 static void
21479 checkds_find_address(dns_checkds_t *checkds) {
21480 isc_result_t result;
21481 unsigned int options;
21482 dns_adb_t *adb = NULL;
21483
21484 REQUIRE(DNS_CHECKDS_VALID(checkds));
21485
21486 options = DNS_ADBFIND_WANTEVENT;
21487 if (isc_net_probeipv4() != ISC_R_DISABLED) {
21488 options |= DNS_ADBFIND_INET;
21489 }
21490 if (isc_net_probeipv6() != ISC_R_DISABLED) {
21491 options |= DNS_ADBFIND_INET6;
21492 }
21493
21494 dns_view_getadb(checkds->zone->view, &adb);
21495 if (adb == NULL) {
21496 goto destroy;
21497 }
21498
21499 result = dns_adb_createfind(adb, checkds->zone->loop,
21500 process_checkds_adb_event, checkds,
21501 &checkds->ns, dns_rootname, 0, options, 0,
21502 NULL, checkds->zone->view->dstport, 0, NULL,
21503 NULL, NULL, &checkds->find);
21504 dns_adb_detach(&adb);
21505
21506 /* Something failed? */
21507 if (result != ISC_R_SUCCESS) {
21508 goto destroy;
21509 }
21510
21511 /* More addresses pending? */
21512 if ((checkds->find->options & DNS_ADBFIND_WANTEVENT) != 0) {
21513 return;
21514 }
21515
21516 /* We have as many addresses as we can get. */
21517 LOCK_ZONE(checkds->zone);
21518 checkds_send_tons(checkds);
21519 UNLOCK_ZONE(checkds->zone);
21520
21521 destroy:
21522 checkds_destroy(checkds, false);
21523 }
21524
21525 static void
21526 checkds_send_toaddr(void *arg) {
21527 dns_checkds_t *checkds = (dns_checkds_t *)arg;
21528 isc_result_t result;
21529 dns_message_t *message = NULL;
21530 isc_netaddr_t dstip;
21531 dns_tsigkey_t *key = NULL;
21532 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
21533 isc_sockaddr_t src;
21534 unsigned int options, timeout;
21535 bool have_checkdssource = false;
21536 bool canceled = checkds->rlevent->canceled;
21537
21538 REQUIRE(DNS_CHECKDS_VALID(checkds));
21539
21540 isc_rlevent_free(&checkds->rlevent);
21541
21542 LOCK_ZONE(checkds->zone);
21543
21544 if (DNS_ZONE_FLAG(checkds->zone, DNS_ZONEFLG_LOADED) == 0 || canceled ||
21545 DNS_ZONE_FLAG(checkds->zone, DNS_ZONEFLG_EXITING) ||
21546 checkds->zone->view->requestmgr == NULL ||
21547 checkds->zone->db == NULL)
21548 {
21549 result = ISC_R_CANCELED;
21550 goto cleanup;
21551 }
21552
21553 /*
21554 * The raw IPv4 address should also exist. Don't send to the
21555 * mapped form.
21556 */
21557 if (isc_sockaddr_pf(&checkds->dst) == PF_INET6 &&
21558 IN6_IS_ADDR_V4MAPPED(&checkds->dst.type.sin6.sin6_addr))
21559 {
21560 isc_sockaddr_format(&checkds->dst, addrbuf, sizeof(addrbuf));
21561 dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
21562 "checkds: ignoring IPv6 mapped IPV4 address: %s",
21563 addrbuf);
21564 result = ISC_R_CANCELED;
21565 goto cleanup;
21566 }
21567
21568 checkds_createmessage(checkds->zone, &message);
21569
21570 isc_sockaddr_format(&checkds->dst, addrbuf, sizeof(addrbuf));
21571 if (checkds->key != NULL) {
21572 /* Transfer ownership of key */
21573 key = checkds->key;
21574 checkds->key = NULL;
21575 } else {
21576 isc_netaddr_fromsockaddr(&dstip, &checkds->dst);
21577 result = dns_view_getpeertsig(checkds->zone->view, &dstip,
21578 &key);
21579 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
21580 dns_zone_log(checkds->zone, ISC_LOG_ERROR,
21581 "checkds: DS query to %s not sent. "
21582 "Peer TSIG key lookup failure.",
21583 addrbuf);
21584 goto cleanup_message;
21585 }
21586 }
21587
21588 if (key != NULL) {
21589 char namebuf[DNS_NAME_FORMATSIZE];
21590
21591 dns_name_format(key->name, namebuf, sizeof(namebuf));
21592 dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
21593 "checkds: sending DS query to %s : TSIG (%s)",
21594 addrbuf, namebuf);
21595 } else {
21596 dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
21597 "checkds: sending DS query to %s", addrbuf);
21598 }
21599 options = 0;
21600 if (checkds->zone->view->peers != NULL) {
21601 dns_peer_t *peer = NULL;
21602 bool usetcp = false;
21603 result = dns_peerlist_peerbyaddr(checkds->zone->view->peers,
21604 &dstip, &peer);
21605 if (result == ISC_R_SUCCESS) {
21606 result = dns_peer_getquerysource(peer, &src);
21607 if (result == ISC_R_SUCCESS) {
21608 have_checkdssource = true;
21609 }
21610 result = dns_peer_getforcetcp(peer, &usetcp);
21611 if (result == ISC_R_SUCCESS && usetcp) {
21612 options |= DNS_FETCHOPT_TCP;
21613 }
21614 }
21615 }
21616 switch (isc_sockaddr_pf(&checkds->dst)) {
21617 case PF_INET:
21618 if (!have_checkdssource) {
21619 isc_sockaddr_t any;
21620 isc_sockaddr_any(&any);
21621
21622 src = checkds->src;
21623 if (isc_sockaddr_equal(&src, &any)) {
21624 src = checkds->zone->parentalsrc4;
21625 }
21626 }
21627 break;
21628 case PF_INET6:
21629 if (!have_checkdssource) {
21630 isc_sockaddr_t any;
21631 isc_sockaddr_any6(&any);
21632
21633 src = checkds->src;
21634 if (isc_sockaddr_equal(&src, &any)) {
21635 src = checkds->zone->parentalsrc6;
21636 }
21637 }
21638 break;
21639 default:
21640 result = ISC_R_NOTIMPLEMENTED;
21641 goto cleanup_key;
21642 }
21643
21644 dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
21645 "checkds: create request for DS query to %s", addrbuf);
21646
21647 timeout = 5;
21648 options |= DNS_REQUESTOPT_TCP;
21649 result = dns_request_create(
21650 checkds->zone->view->requestmgr, message, &src, &checkds->dst,
21651 NULL, NULL, options, key, timeout * 3 + 1, timeout, 2,
21652 checkds->zone->loop, checkds_done, checkds, &checkds->request);
21653 if (result != ISC_R_SUCCESS) {
21654 dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
21655 "checkds: dns_request_create() to %s failed: %s",
21656 addrbuf, isc_result_totext(result));
21657 }
21658
21659 cleanup_key:
21660 if (key != NULL) {
21661 dns_tsigkey_detach(&key);
21662 }
21663 cleanup_message:
21664 dns_message_detach(&message);
21665 cleanup:
21666 UNLOCK_ZONE(checkds->zone);
21667 if (result != ISC_R_SUCCESS) {
21668 checkds_destroy(checkds, false);
21669 }
21670 }
21671
21672 static void
21673 checkds_send_tons(dns_checkds_t *checkds) {
21674 dns_adbaddrinfo_t *ai;
21675 isc_sockaddr_t dst;
21676 isc_result_t result;
21677 dns_checkds_t *newcheckds = NULL;
21678 dns_zone_t *zone = NULL;
21679
21680 /*
21681 * Zone lock held by caller.
21682 */
21683 REQUIRE(DNS_CHECKDS_VALID(checkds));
21684 REQUIRE(LOCKED_ZONE(checkds->zone));
21685
21686 zone = checkds->zone;
21687
21688 if (DNS_ZONE_FLAG(checkds->zone, DNS_ZONEFLG_EXITING)) {
21689 return;
21690 }
21691
21692 for (ai = ISC_LIST_HEAD(checkds->find->list); ai != NULL;
21693 ai = ISC_LIST_NEXT(ai, publink))
21694 {
21695 dst = ai->sockaddr;
21696 if (checkds_isqueued(zone, NULL, &dst, NULL, NULL)) {
21697 continue;
21698 }
21699
21700 newcheckds = NULL;
21701 result = checkds_create(checkds->mctx, 0, &newcheckds);
21702 if (result != ISC_R_SUCCESS) {
21703 goto cleanup;
21704 }
21705 zone_iattach(zone, &newcheckds->zone);
21706 ISC_LIST_APPEND(newcheckds->zone->checkds_requests, newcheckds,
21707 link);
21708 newcheckds->dst = dst;
21709 dns_name_dup(&checkds->ns, checkds->mctx, &newcheckds->ns);
21710 switch (isc_sockaddr_pf(&newcheckds->dst)) {
21711 case PF_INET:
21712 isc_sockaddr_any(&newcheckds->src);
21713 break;
21714 case PF_INET6:
21715 isc_sockaddr_any6(&newcheckds->src);
21716 break;
21717 default:
21718 UNREACHABLE();
21719 }
21720 /*
21721 * XXXWMM: Should we attach key and transport here?
21722 * Probably not, because we expect the name servers to be
21723 * publicly available on the default transport protocol.
21724 */
21725
21726 result = isc_ratelimiter_enqueue(
21727 newcheckds->zone->zmgr->checkdsrl,
21728 newcheckds->zone->loop, checkds_send_toaddr, newcheckds,
21729 &newcheckds->rlevent);
21730 if (result != ISC_R_SUCCESS) {
21731 goto cleanup;
21732 }
21733 newcheckds = NULL;
21734 }
21735
21736 cleanup:
21737 if (newcheckds != NULL) {
21738 checkds_destroy(newcheckds, true);
21739 }
21740 }
21741
21742 static void
21743 checkds_send(dns_zone_t *zone) {
21744 dns_view_t *view = dns_zone_getview(zone);
21745 isc_result_t result;
21746 unsigned int flags = 0;
21747 unsigned int i = 0;
21748
21749 /*
21750 * Zone lock held by caller.
21751 */
21752 REQUIRE(LOCKED_ZONE(zone));
21753
21754 dns_zone_log(zone, ISC_LOG_DEBUG(3),
21755 "checkds: start sending DS queries to %u parentals",
21756 dns_remote_count(&zone->parentals));
21757
21758 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
21759 dns_zone_log(zone, ISC_LOG_DEBUG(3),
21760 "checkds: abort, named exiting");
21761 return;
21762 }
21763
21764 dns_remote_reset(&zone->parentals, false);
21765 while (!dns_remote_done(&zone->parentals)) {
21766 dns_tsigkey_t *key = NULL;
21767 dns_transport_t *transport = NULL;
21768 isc_sockaddr_t src, dst;
21769 dns_checkds_t *checkds = NULL;
21770
21771 i++;
21772
21773 if (dns_remote_keyname(&zone->parentals) != NULL) {
21774 dns_name_t *keyname =
21775 dns_remote_keyname(&zone->parentals);
21776 (void)dns_view_gettsig(view, keyname, &key);
21777 }
21778
21779 if (dns_remote_tlsname(&zone->parentals) != NULL) {
21780 dns_name_t *tlsname =
21781 dns_remote_tlsname(&zone->parentals);
21782 (void)dns_view_gettransport(view, DNS_TRANSPORT_TLS,
21783 tlsname, &transport);
21784 dns_zone_logc(
21785 zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
21786 "got TLS configuration for zone transfer");
21787 }
21788
21789 dst = dns_remote_curraddr(&zone->parentals);
21790 src = dns_remote_sourceaddr(&zone->parentals);
21791 INSIST(isc_sockaddr_pf(&src) == isc_sockaddr_pf(&dst));
21792
21793 if (isc_sockaddr_disabled(&dst)) {
21794 goto next;
21795 }
21796
21797 /* TODO: glue the transport to the checkds request */
21798
21799 if (checkds_isqueued(zone, NULL, &dst, key, transport)) {
21800 dns_zone_log(zone, ISC_LOG_DEBUG(3),
21801 "checkds: DS query to parent "
21802 "%d is queued",
21803 i);
21804 if (key != NULL) {
21805 dns_tsigkey_detach(&key);
21806 }
21807 if (transport != NULL) {
21808 dns_transport_detach(&transport);
21809 }
21810 goto next;
21811 }
21812
21813 dns_zone_log(zone, ISC_LOG_DEBUG(3),
21814 "checkds: create DS query for "
21815 "parent %d",
21816 i);
21817
21818 result = checkds_create(zone->mctx, flags, &checkds);
21819 if (result != ISC_R_SUCCESS) {
21820 dns_zone_log(zone, ISC_LOG_DEBUG(3),
21821 "checkds: create DS query for "
21822 "parent %d failed",
21823 i);
21824 goto next;
21825 }
21826 zone_iattach(zone, &checkds->zone);
21827 dns_name_dup(dns_rootname, checkds->mctx, &checkds->ns);
21828 checkds->src = src;
21829 checkds->dst = dst;
21830
21831 INSIST(checkds->key == NULL);
21832 if (key != NULL) {
21833 checkds->key = key;
21834 key = NULL;
21835 }
21836
21837 INSIST(checkds->transport == NULL);
21838 if (transport != NULL) {
21839 checkds->transport = transport;
21840 transport = NULL;
21841 }
21842
21843 ISC_LIST_APPEND(zone->checkds_requests, checkds, link);
21844 result = isc_ratelimiter_enqueue(
21845 checkds->zone->zmgr->checkdsrl, checkds->zone->loop,
21846 checkds_send_toaddr, checkds, &checkds->rlevent);
21847 if (result != ISC_R_SUCCESS) {
21848 dns_zone_log(zone, ISC_LOG_DEBUG(3),
21849 "checkds: send DS query to "
21850 "parent %d failed",
21851 i);
21852 checkds_destroy(checkds, true);
21853 }
21854
21855 next:
21856 dns_remote_next(&zone->parentals, false);
21857 }
21858 }
21859
21860 /*
21861 * An NS RRset has been fetched from the parent of a zone whose DS RRset needs
21862 * to be checked; scan the RRset and start sending queries to the parental
21863 * agents.
21864 */
21865 static void
21866 nsfetch_done(void *arg) {
21867 dns_fetchresponse_t *resp = (dns_fetchresponse_t *)arg;
21868 isc_result_t result, eresult;
21869 dns_nsfetch_t *nsfetch = NULL;
21870 dns_zone_t *zone = NULL;
21871 isc_mem_t *mctx = NULL;
21872 dns_name_t *zname = NULL;
21873 dns_name_t *pname = NULL;
21874 char pnamebuf[DNS_NAME_FORMATSIZE];
21875 bool free_needed, levelup = false;
21876 dns_rdataset_t *nsrrset = NULL;
21877 dns_rdataset_t *nssigset = NULL;
21878
21879 INSIST(resp != NULL);
21880
21881 nsfetch = resp->arg;
21882
21883 INSIST(nsfetch != NULL);
21884
21885 zone = nsfetch->zone;
21886 mctx = nsfetch->mctx;
21887 zname = dns_fixedname_name(&nsfetch->name);
21888 pname = &nsfetch->pname;
21889 nsrrset = &nsfetch->nsrrset;
21890 nssigset = &nsfetch->nssigset;
21891 eresult = resp->result;
21892
21893 /* Free resources which are not of interest */
21894 if (resp->node != NULL) {
21895 dns_db_detachnode(resp->db, &resp->node);
21896 }
21897 if (resp->db != NULL) {
21898 dns_db_detach(&resp->db);
21899 }
21900 dns_resolver_destroyfetch(&nsfetch->fetch);
21901
21902 LOCK_ZONE(zone);
21903 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || zone->view == NULL) {
21904 goto cleanup;
21905 }
21906
21907 zone->nsfetchcount--;
21908
21909 dns_name_format(pname, pnamebuf, sizeof(pnamebuf));
21910 dnssec_log(zone, ISC_LOG_DEBUG(3),
21911 "Returned from '%s' NS fetch in nsfetch_done(): %s",
21912 pnamebuf, isc_result_totext(eresult));
21913
21914 if (eresult == DNS_R_NCACHENXRRSET || eresult == DNS_R_NXRRSET) {
21915 dnssec_log(zone, ISC_LOG_DEBUG(3),
21916 "NODATA response for NS '%s', level up", pnamebuf);
21917 levelup = true;
21918 goto cleanup;
21919
21920 } else if (eresult != ISC_R_SUCCESS) {
21921 dnssec_log(zone, ISC_LOG_WARNING,
21922 "Unable to fetch NS set '%s': %s", pnamebuf,
21923 isc_result_totext(eresult));
21924 result = eresult;
21925 goto done;
21926 }
21927
21928 /* No NS records found */
21929 if (!dns_rdataset_isassociated(nsrrset)) {
21930 dnssec_log(zone, ISC_LOG_WARNING,
21931 "No NS records found for '%s'", pnamebuf);
21932 result = ISC_R_NOTFOUND;
21933 goto done;
21934 }
21935
21936 /* No RRSIGs found */
21937 if (!dns_rdataset_isassociated(nssigset)) {
21938 dnssec_log(zone, ISC_LOG_WARNING, "No NS RRSIGs found for '%s'",
21939 pnamebuf);
21940 result = DNS_R_MUSTBESECURE;
21941 goto done;
21942 }
21943
21944 /* Check trust level */
21945 if (nsrrset->trust < dns_trust_secure) {
21946 dnssec_log(zone, ISC_LOG_WARNING,
21947 "Invalid NS RRset for '%s' trust level %u", pnamebuf,
21948 nsrrset->trust);
21949 result = DNS_R_MUSTBESECURE;
21950 goto done;
21951 }
21952
21953 /* Record the number of NS records we found. */
21954 zone->parent_nscount = dns_rdataset_count(nsrrset);
21955
21956 UNLOCK_ZONE(zone);
21957
21958 /* Look up the addresses for the found parental name servers. */
21959 for (result = dns_rdataset_first(nsrrset); result == ISC_R_SUCCESS;
21960 result = dns_rdataset_next(nsrrset))
21961 {
21962 dns_checkds_t *checkds = NULL;
21963 dns_rdata_t rdata = DNS_RDATA_INIT;
21964 dns_rdata_ns_t ns;
21965 bool isqueued;
21966
21967 dns_rdataset_current(nsrrset, &rdata);
21968 result = dns_rdata_tostruct(&rdata, &ns, NULL);
21969 RUNTIME_CHECK(result == ISC_R_SUCCESS);
21970
21971 dns_rdata_reset(&rdata);
21972
21973 LOCK_ZONE(zone);
21974 isqueued = checkds_isqueued(zone, &ns.name, NULL, NULL, NULL);
21975 UNLOCK_ZONE(zone);
21976 if (isqueued) {
21977 continue;
21978 }
21979 result = checkds_create(zone->mctx, 0, &checkds);
21980 if (result != ISC_R_SUCCESS) {
21981 dns_zone_log(zone, ISC_LOG_DEBUG(3),
21982 "checkds: checkds_create() failed: %s",
21983 isc_result_totext(result));
21984 break;
21985 }
21986
21987 if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
21988 char nsnamebuf[DNS_NAME_FORMATSIZE];
21989 dns_name_format(&ns.name, nsnamebuf, sizeof(nsnamebuf));
21990 dns_zone_log(zone, ISC_LOG_DEBUG(3),
21991 "checkds: send DS query to NS %s",
21992 nsnamebuf);
21993 }
21994
21995 LOCK_ZONE(zone);
21996 zone_iattach(zone, &checkds->zone);
21997 dns_name_dup(&ns.name, zone->mctx, &checkds->ns);
21998 ISC_LIST_APPEND(zone->checkds_requests, checkds, link);
21999 UNLOCK_ZONE(zone);
22000
22001 checkds_find_address(checkds);
22002 }
22003 if (result == ISC_R_NOMORE) {
22004 result = ISC_R_SUCCESS;
22005 }
22006
22007 LOCK_ZONE(zone);
22008
22009 done:
22010 if (result != ISC_R_SUCCESS) {
22011 dnssec_log(
22012 zone, ISC_LOG_ERROR,
22013 "checkds: error during parental-agents processing: %s",
22014 isc_result_totext(result));
22015 }
22016
22017 cleanup:
22018 isc_refcount_decrement(&zone->irefs);
22019
22020 if (dns_rdataset_isassociated(nsrrset)) {
22021 dns_rdataset_disassociate(nsrrset);
22022 }
22023 if (dns_rdataset_isassociated(nssigset)) {
22024 dns_rdataset_disassociate(nssigset);
22025 }
22026
22027 dns_resolver_freefresp(&resp);
22028
22029 if (levelup) {
22030 UNLOCK_ZONE(zone);
22031 nsfetch_levelup(nsfetch);
22032 return;
22033 }
22034
22035 dns_name_free(zname, mctx);
22036 isc_mem_putanddetach(&nsfetch->mctx, nsfetch, sizeof(dns_nsfetch_t));
22037
22038 free_needed = exit_check(zone);
22039 UNLOCK_ZONE(zone);
22040
22041 if (free_needed) {
22042 zone_free(zone);
22043 }
22044 }
22045
22046 static void
22047 do_nsfetch(void *arg) {
22048 dns_nsfetch_t *nsfetch = (dns_nsfetch_t *)arg;
22049 isc_result_t result;
22050 unsigned int nlabels = 1;
22051 dns_resolver_t *resolver = NULL;
22052 dns_zone_t *zone = nsfetch->zone;
22053 unsigned int options = DNS_FETCHOPT_UNSHARED | DNS_FETCHOPT_NOCACHED;
22054
22055 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
22056 result = ISC_R_SHUTTINGDOWN;
22057 goto cleanup;
22058 }
22059
22060 result = dns_view_getresolver(zone->view, &resolver);
22061 if (result != ISC_R_SUCCESS) {
22062 goto cleanup;
22063 }
22064
22065 if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
22066 char namebuf[DNS_NAME_FORMATSIZE];
22067 dns_name_format(&nsfetch->pname, namebuf, sizeof(namebuf));
22068 dnssec_log(zone, ISC_LOG_DEBUG(3),
22069 "Create fetch for '%s' NS request", namebuf);
22070 }
22071
22072 /* Derive parent domain. XXXWMM: Check for root domain */
22073 dns_name_split(&nsfetch->pname,
22074 dns_name_countlabels(&nsfetch->pname) - nlabels, NULL,
22075 &nsfetch->pname);
22076
22077 /*
22078 * Use of DNS_FETCHOPT_NOCACHED is essential here. If it is not
22079 * set and the cache still holds a non-expired, validated version
22080 * of the RRset being queried for by the time the response is
22081 * received, the cached RRset will be passed to nsfetch_done()
22082 * instead of the one received in the response as the latter will
22083 * have a lower trust level due to not being validated until
22084 * nsfetch_done() is called.
22085 */
22086 result = dns_resolver_createfetch(
22087 resolver, &nsfetch->pname, dns_rdatatype_ns, NULL, NULL, NULL,
22088 NULL, 0, options, 0, NULL, NULL, NULL, zone->loop, nsfetch_done,
22089 nsfetch, NULL, &nsfetch->nsrrset, &nsfetch->nssigset,
22090 &nsfetch->fetch);
22091
22092 dns_resolver_detach(&resolver);
22093
22094 cleanup:
22095 if (result != ISC_R_SUCCESS) {
22096 dns_name_t *zname = dns_fixedname_name(&nsfetch->name);
22097 bool free_needed;
22098 char namebuf[DNS_NAME_FORMATSIZE];
22099 dns_name_format(&nsfetch->pname, namebuf, sizeof(namebuf));
22100 dnssec_log(zone, ISC_LOG_WARNING,
22101 "Failed to create fetch for '%s' NS request",
22102 namebuf);
22103 LOCK_ZONE(zone);
22104 zone->nsfetchcount--;
22105 isc_refcount_decrement(&zone->irefs);
22106
22107 dns_name_free(zname, zone->mctx);
22108 isc_mem_putanddetach(&nsfetch->mctx, nsfetch, sizeof(*nsfetch));
22109
22110 free_needed = exit_check(zone);
22111 UNLOCK_ZONE(zone);
22112 if (free_needed) {
22113 zone_free(zone);
22114 }
22115 }
22116 }
22117
22118 /*
22119 * Retry an NS RRset lookup, one level up. In other words, this function should
22120 * be called on an dns_nsfetch structure where the response yielded in a NODATA
22121 * response. This must be because there is an empty non-terminal inbetween the
22122 * child and parent zone.
22123 */
22124 static void
22125 nsfetch_levelup(dns_nsfetch_t *nsfetch) {
22126 dns_zone_t *zone = nsfetch->zone;
22127
22128 #ifdef ENABLE_AFL
22129 if (!dns_fuzzing_resolver) {
22130 #endif /* ifdef ENABLE_AFL */
22131 LOCK_ZONE(zone);
22132 zone->nsfetchcount++;
22133 isc_refcount_increment0(&zone->irefs);
22134
22135 dns_rdataset_init(&nsfetch->nsrrset);
22136 dns_rdataset_init(&nsfetch->nssigset);
22137 if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
22138 dnssec_log(zone, ISC_LOG_DEBUG(3),
22139 "Creating parent NS fetch in "
22140 "nsfetch_levelup()");
22141 }
22142 isc_async_run(zone->loop, do_nsfetch, nsfetch);
22143 UNLOCK_ZONE(zone);
22144 #ifdef ENABLE_AFL
22145 }
22146 #endif /* ifdef ENABLE_AFL */
22147 }
22148
22149 static void
22150 zone_checkds(dns_zone_t *zone) {
22151 bool cdscheck = false;
22152 dns_checkdstype_t checkdstype = zone->checkdstype;
22153
22154 if (checkdstype == dns_checkdstype_no) {
22155 return;
22156 }
22157
22158 for (dns_dnsseckey_t *key = ISC_LIST_HEAD(zone->checkds_ok);
22159 key != NULL; key = ISC_LIST_NEXT(key, link))
22160 {
22161 dst_key_state_t ds_state = DST_KEY_STATE_NA;
22162 bool ksk = false;
22163 isc_stdtime_t published = 0, withdrawn = 0;
22164
22165 /* Is this key have the KSK role? */
22166 (void)dst_key_role(key->key, &ksk, NULL);
22167 if (!ksk) {
22168 continue;
22169 }
22170
22171 /* Do we need to check the DS RRset? */
22172 (void)dst_key_getstate(key->key, DST_KEY_DS, &ds_state);
22173 (void)dst_key_gettime(key->key, DST_TIME_DSPUBLISH, &published);
22174 (void)dst_key_gettime(key->key, DST_TIME_DSDELETE, &withdrawn);
22175
22176 if (ds_state == DST_KEY_STATE_RUMOURED && published == 0) {
22177 dst_key_setnum(key->key, DST_NUM_DSPUBCOUNT, 0);
22178 cdscheck = true;
22179 } else if (ds_state == DST_KEY_STATE_UNRETENTIVE &&
22180 withdrawn == 0)
22181 {
22182 dst_key_setnum(key->key, DST_NUM_DSDELCOUNT, 0);
22183 cdscheck = true;
22184 }
22185 }
22186
22187 if (!cdscheck) {
22188 return;
22189 }
22190
22191 if (checkdstype == dns_checkdstype_explicit) {
22192 /* Request the DS RRset. */
22193 LOCK_ZONE(zone);
22194 checkds_send(zone);
22195 UNLOCK_ZONE(zone);
22196 return;
22197 }
22198
22199 INSIST(checkdstype == dns_checkdstype_yes);
22200
22201 #ifdef ENABLE_AFL
22202 if (!dns_fuzzing_resolver) {
22203 #endif /* ifdef ENABLE_AFL */
22204 dns_nsfetch_t *nsfetch;
22205 dns_name_t *name = NULL;
22206
22207 nsfetch = isc_mem_get(zone->mctx, sizeof(dns_nsfetch_t));
22208 *nsfetch = (dns_nsfetch_t){ .zone = zone };
22209 isc_mem_attach(zone->mctx, &nsfetch->mctx);
22210 LOCK_ZONE(zone);
22211 zone->nsfetchcount++;
22212 isc_refcount_increment0(&zone->irefs);
22213 name = dns_fixedname_initname(&nsfetch->name);
22214 dns_name_init(&nsfetch->pname, NULL);
22215 dns_name_clone(&zone->origin, &nsfetch->pname);
22216 dns_name_dup(&zone->origin, zone->mctx, name);
22217 dns_rdataset_init(&nsfetch->nsrrset);
22218 dns_rdataset_init(&nsfetch->nssigset);
22219 if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
22220 dnssec_log(
22221 zone, ISC_LOG_DEBUG(3),
22222 "Creating parent NS fetch in zone_checkds()");
22223 }
22224 isc_async_run(zone->loop, do_nsfetch, nsfetch);
22225 UNLOCK_ZONE(zone);
22226 #ifdef ENABLE_AFL
22227 }
22228 #endif /* ifdef ENABLE_AFL */
22229 }
22230
22231 static isc_result_t
22232 update_ttl(dns_rdataset_t *rdataset, dns_name_t *name, dns_ttl_t ttl,
22233 dns_diff_t *diff) {
22234 isc_result_t result;
22235
22236 /*
22237 * Delete everything using the existing TTL.
22238 */
22239 for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
22240 result = dns_rdataset_next(rdataset))
22241 {
22242 dns_difftuple_t *tuple = NULL;
22243 dns_rdata_t rdata = DNS_RDATA_INIT;
22244
22245 dns_rdataset_current(rdataset, &rdata);
22246 result = dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, name,
22247 rdataset->ttl, &rdata, &tuple);
22248 if (result != ISC_R_SUCCESS) {
22249 return result;
22250 }
22251 dns_diff_appendminimal(diff, &tuple);
22252 }
22253 if (result != ISC_R_NOMORE) {
22254 return result;
22255 }
22256
22257 /*
22258 * Add everything using the new TTL.
22259 */
22260 for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
22261 result = dns_rdataset_next(rdataset))
22262 {
22263 dns_difftuple_t *tuple = NULL;
22264 dns_rdata_t rdata = DNS_RDATA_INIT;
22265
22266 dns_rdataset_current(rdataset, &rdata);
22267 result = dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, name,
22268 ttl, &rdata, &tuple);
22269 if (result != ISC_R_SUCCESS) {
22270 return result;
22271 }
22272 dns_diff_appendminimal(diff, &tuple);
22273 }
22274 if (result != ISC_R_NOMORE) {
22275 return result;
22276 }
22277 return ISC_R_SUCCESS;
22278 }
22279
22280 static isc_result_t
22281 zone_verifykeys(dns_zone_t *zone, dns_dnsseckeylist_t *newkeys,
22282 uint32_t purgeval, isc_stdtime_t now) {
22283 dns_dnsseckey_t *key1, *key2, *next;
22284
22285 /*
22286 * Make sure that the existing keys are also present in the new keylist.
22287 */
22288 for (key1 = ISC_LIST_HEAD(zone->keyring); key1 != NULL; key1 = next) {
22289 bool found = false;
22290 next = ISC_LIST_NEXT(key1, link);
22291
22292 if (dst_key_is_unused(key1->key)) {
22293 continue;
22294 }
22295 if (dns_keymgr_key_may_be_purged(key1->key, purgeval, now)) {
22296 continue;
22297 }
22298 if (key1->purge) {
22299 continue;
22300 }
22301
22302 for (key2 = ISC_LIST_HEAD(*newkeys); key2 != NULL;
22303 key2 = ISC_LIST_NEXT(key2, link))
22304 {
22305 if (dst_key_compare(key1->key, key2->key)) {
22306 found = true;
22307 break;
22308 }
22309 }
22310
22311 if (!found) {
22312 char keystr[DST_KEY_FORMATSIZE];
22313 dst_key_format(key1->key, keystr, sizeof(keystr));
22314 dnssec_log(zone, ISC_LOG_DEBUG(1),
22315 "verifykeys: key %s - not available",
22316 keystr);
22317 return ISC_R_NOTFOUND;
22318 }
22319 }
22320
22321 /* All good. */
22322 return ISC_R_SUCCESS;
22323 }
22324
22325 static void
22326 remove_rdataset(dns_zone_t *zone, dns_diff_t *diff, dns_rdataset_t *rdataset) {
22327 if (!dns_rdataset_isassociated(rdataset)) {
22328 return;
22329 }
22330
22331 for (isc_result_t result = dns_rdataset_first(rdataset);
22332 result == ISC_R_SUCCESS; result = dns_rdataset_next(rdataset))
22333 {
22334 dns_rdata_t rdata = DNS_RDATA_INIT;
22335 dns_difftuple_t *tuple = NULL;
22336
22337 dns_rdataset_current(rdataset, &rdata);
22338 dns_difftuple_create(zone->mctx, DNS_DIFFOP_DEL, &zone->origin,
22339 rdataset->ttl, &rdata, &tuple);
22340 dns_diff_append(diff, &tuple);
22341 }
22342 return;
22343 }
22344
22345 static void
22346 add_tuple(dns_diff_t *diff, dns_difftuple_t *tuple) {
22347 dns_difftuple_t *copy = NULL;
22348
22349 dns_difftuple_copy(tuple, ©);
22350 dns_diff_appendminimal(diff, ©);
22351 }
22352
22353 static void
22354 zone_apply_skrbundle(dns_zone_t *zone, dns_skrbundle_t *bundle,
22355 dns_rdataset_t *dnskeyset, dns_rdataset_t *cdsset,
22356 dns_rdataset_t *cdnskeyset, dns_diff_t *diff) {
22357 dns_kasp_t *kasp = zone->kasp;
22358
22359 REQUIRE(DNS_ZONE_VALID(zone));
22360 REQUIRE(DNS_KASP_VALID(kasp));
22361 REQUIRE(DNS_SKRBUNDLE_VALID(bundle));
22362
22363 /* Remove existing DNSKEY, CDS, and CDNSKEY records. */
22364 remove_rdataset(zone, diff, dnskeyset);
22365 remove_rdataset(zone, diff, cdsset);
22366 remove_rdataset(zone, diff, cdnskeyset);
22367
22368 /* Add the records from the bundle. */
22369 dns_difftuple_t *tuple = ISC_LIST_HEAD(bundle->diff.tuples);
22370 while (tuple != NULL) {
22371 switch (tuple->rdata.type) {
22372 case dns_rdatatype_dnskey:
22373 add_tuple(diff, tuple);
22374 break;
22375 case dns_rdatatype_cdnskey:
22376 case dns_rdatatype_cds:
22377 add_tuple(diff, tuple);
22378 break;
22379 case dns_rdatatype_rrsig:
22380 /* Not interested in right now */
22381 break;
22382 default:
22383 INSIST(0);
22384 }
22385
22386 tuple = ISC_LIST_NEXT(tuple, link);
22387 }
22388 }
22389
22390 static void
22391 zone_rekey(dns_zone_t *zone) {
22392 isc_result_t result;
22393 dns_db_t *db = NULL;
22394 dns_dbnode_t *node = NULL;
22395 dns_dbversion_t *ver = NULL;
22396 dns_rdataset_t cdsset, soaset, soasigs, keyset, keysigs, cdnskeyset;
22397 dns_dnsseckeylist_t dnskeys, keys, rmkeys;
22398 dns_dnsseckey_t *key = NULL;
22399 dns_diff_t diff, _sig_diff;
22400 dns_kasp_t *kasp;
22401 dns_skrbundle_t *bundle = NULL;
22402 dns__zonediff_t zonediff;
22403 bool commit = false, newactive = false;
22404 bool newalg = false;
22405 bool fullsign;
22406 bool offlineksk = false;
22407 bool kasp_change = false;
22408 uint8_t options = 0;
22409 uint32_t sigval = 0;
22410 dns_ttl_t ttl = 3600;
22411 const char *dir = NULL;
22412 isc_mem_t *mctx = NULL;
22413 isc_stdtime_t now, nexttime = 0;
22414 isc_time_t timenow;
22415 isc_interval_t ival;
22416 char timebuf[80];
22417
22418 REQUIRE(DNS_ZONE_VALID(zone));
22419
22420 ISC_LIST_INIT(dnskeys);
22421 ISC_LIST_INIT(keys);
22422 ISC_LIST_INIT(rmkeys);
22423 dns_rdataset_init(&soaset);
22424 dns_rdataset_init(&soasigs);
22425 dns_rdataset_init(&keyset);
22426 dns_rdataset_init(&keysigs);
22427 dns_rdataset_init(&cdsset);
22428 dns_rdataset_init(&cdnskeyset);
22429 mctx = zone->mctx;
22430 dns_diff_init(mctx, &diff);
22431 dns_diff_init(mctx, &_sig_diff);
22432 zonediff_init(&zonediff, &_sig_diff);
22433
22434 CHECK(dns_zone_getdb(zone, &db));
22435 CHECK(dns_db_newversion(db, &ver));
22436 CHECK(dns_db_getoriginnode(db, &node));
22437
22438 timenow = isc_time_now();
22439 now = isc_time_seconds(&timenow);
22440
22441 kasp = zone->kasp;
22442 dir = dns_zone_getkeydirectory(zone);
22443
22444 dnssec_log(zone, ISC_LOG_INFO, "reconfiguring zone keys");
22445
22446 /* Get the SOA record's TTL */
22447 CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_soa,
22448 dns_rdatatype_none, 0, &soaset, &soasigs));
22449 ttl = soaset.ttl;
22450 dns_rdataset_disassociate(&soaset);
22451
22452 if (kasp != NULL) {
22453 ttl = dns_kasp_dnskeyttl(kasp);
22454 offlineksk = dns_kasp_offlineksk(kasp);
22455 sigval = dns_kasp_sigvalidity_dnskey(kasp);
22456 }
22457
22458 /* Get the current DNSKEY rdataset */
22459 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
22460 dns_rdatatype_none, 0, &keyset, &keysigs);
22461 if (result == ISC_R_SUCCESS) {
22462 /*
22463 * If we don't have a policy then use the DNSKEY ttl
22464 * if it exists. Otherwise update the DNSKEY ttl if
22465 * needed.
22466 */
22467 if (kasp == NULL) {
22468 ttl = keyset.ttl;
22469 } else if (ttl != keyset.ttl && !offlineksk) {
22470 result = update_ttl(&keyset, &zone->origin, ttl, &diff);
22471 if (result != ISC_R_SUCCESS) {
22472 dnssec_log(zone, ISC_LOG_ERROR,
22473 "Updating DNSKEY TTL from %u to %u "
22474 "failed: %s",
22475 keyset.ttl, ttl,
22476 isc_result_totext(result));
22477 goto cleanup;
22478 }
22479 dnssec_log(zone, ISC_LOG_INFO,
22480 "Updating DNSKEY TTL from %u to %u",
22481 keyset.ttl, ttl);
22482 keyset.ttl = ttl;
22483 }
22484
22485 dns_zone_lock_keyfiles(zone);
22486
22487 result = dns_dnssec_keylistfromrdataset(
22488 &zone->origin, kasp, dir, mctx, &keyset, &keysigs,
22489 &soasigs, false, false, &dnskeys);
22490
22491 dns_zone_unlock_keyfiles(zone);
22492
22493 CHECK(result);
22494 } else if (result != ISC_R_NOTFOUND) {
22495 goto cleanup;
22496 }
22497
22498 /* Get the current CDS rdataset */
22499 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_cds,
22500 dns_rdatatype_none, 0, &cdsset, NULL);
22501 if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdsset)) {
22502 dns_rdataset_disassociate(&cdsset);
22503 } else if (result == ISC_R_SUCCESS && kasp != NULL &&
22504 ttl != cdsset.ttl && !offlineksk)
22505 {
22506 result = update_ttl(&cdsset, &zone->origin, ttl, &diff);
22507 if (result != ISC_R_SUCCESS) {
22508 dnssec_log(zone, ISC_LOG_ERROR,
22509 "Updating CDS TTL from %u to %u failed: %s",
22510 cdsset.ttl, ttl, isc_result_totext(result));
22511 goto cleanup;
22512 }
22513 dnssec_log(zone, ISC_LOG_INFO, "Updating CDS TTL from %u to %u",
22514 cdsset.ttl, ttl);
22515 cdsset.ttl = ttl;
22516 }
22517
22518 /* Get the current CDNSKEY rdataset */
22519 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_cdnskey,
22520 dns_rdatatype_none, 0, &cdnskeyset, NULL);
22521 if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdnskeyset)) {
22522 dns_rdataset_disassociate(&cdnskeyset);
22523 } else if (result == ISC_R_SUCCESS && kasp != NULL &&
22524 ttl != cdnskeyset.ttl && !offlineksk)
22525 {
22526 result = update_ttl(&cdnskeyset, &zone->origin, ttl, &diff);
22527 if (result != ISC_R_SUCCESS) {
22528 dnssec_log(
22529 zone, ISC_LOG_ERROR,
22530 "Updating CDNSKEY TTL from %u to %u failed: %s",
22531 cdnskeyset.ttl, ttl, isc_result_totext(result));
22532 goto cleanup;
22533 }
22534 dnssec_log(zone, ISC_LOG_INFO,
22535 "Updating CDNSKEY TTL from %u to %u", cdnskeyset.ttl,
22536 ttl);
22537 cdnskeyset.ttl = ttl;
22538 }
22539
22540 /*
22541 * True when called from "rndc sign". Indicates the zone should be
22542 * fully signed now.
22543 */
22544 fullsign = DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_FULLSIGN);
22545 if (fullsign) {
22546 options |= DNS_KEYMGRATTR_FULLSIGN;
22547 }
22548
22549 /*
22550 * True when called from "rndc dnssec -step". Indicates the zone
22551 * is allowed to do the next step(s) in the keymgr process.
22552 */
22553 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FORCEKEYMGR)) {
22554 options |= DNS_KEYMGRATTR_FORCESTEP;
22555 }
22556
22557 if (offlineksk) {
22558 /* Lookup the correct bundle in the SKR. */
22559 LOCK_ZONE(zone);
22560 if (zone->skr == NULL) {
22561 UNLOCK_ZONE(zone);
22562 dnssec_log(zone, ISC_LOG_DEBUG(1),
22563 "zone_rekey:dns_skr_lookup failed: "
22564 "no SKR available");
22565 CHECK(DNS_R_NOSKRFILE);
22566 }
22567 bundle = dns_skr_lookup(zone->skr, now, sigval);
22568 zone->skrbundle = bundle;
22569 UNLOCK_ZONE(zone);
22570
22571 if (bundle == NULL) {
22572 char nowstr[26]; /* Minimal buf per ctime_r() spec. */
22573 char utc[sizeof("YYYYMMDDHHSSMM")];
22574 isc_buffer_t b;
22575 isc_region_t r;
22576 isc_buffer_init(&b, utc, sizeof(utc));
22577
22578 isc_stdtime_tostring(now, nowstr, sizeof(nowstr));
22579 (void)dns_time32_totext(now, &b);
22580 isc_buffer_usedregion(&b, &r);
22581 dnssec_log(zone, ISC_LOG_DEBUG(1),
22582 "zone_rekey:dns_skr_lookup failed: "
22583 "no available SKR bundle for time "
22584 "%.*s (%s)",
22585 (int)r.length, r.base, nowstr);
22586 CHECK(DNS_R_NOSKRBUNDLE);
22587 }
22588
22589 zone_apply_skrbundle(zone, bundle, &keyset, &cdsset,
22590 &cdnskeyset, &diff);
22591
22592 dns_skrbundle_t *next = ISC_LIST_NEXT(bundle, link);
22593 if (next != NULL) {
22594 if (nexttime == 0) {
22595 nexttime = next->inception;
22596 }
22597 } else {
22598 dnssec_log(zone, ISC_LOG_WARNING,
22599 "zone_rekey: last bundle in skr, please "
22600 "import new skr file");
22601 }
22602 }
22603
22604 /*
22605 * DNSSEC Key and Signing Policy
22606 */
22607
22608 KASP_LOCK(kasp);
22609
22610 dns_zone_lock_keyfiles(zone);
22611 result = dns_dnssec_findmatchingkeys(&zone->origin, kasp, dir,
22612 zone->keystores, now, false, mctx,
22613 &keys);
22614 dns_zone_unlock_keyfiles(zone);
22615
22616 if (result != ISC_R_SUCCESS) {
22617 dnssec_log(zone, ISC_LOG_DEBUG(1),
22618 "zone_rekey:dns_dnssec_findmatchingkeys failed: %s",
22619 isc_result_totext(result));
22620 }
22621
22622 if (kasp != NULL && !offlineksk) {
22623 /* Verify new keys. */
22624 isc_result_t ret = zone_verifykeys(
22625 zone, &keys, dns_kasp_purgekeys(kasp), now);
22626 if (ret != ISC_R_SUCCESS) {
22627 dnssec_log(zone, ISC_LOG_ERROR,
22628 "zone_rekey:zone_verifykeys failed: "
22629 "some key files are missing");
22630 KASP_UNLOCK(kasp);
22631 goto cleanup;
22632 }
22633
22634 /*
22635 * Check DS at parental agents. Clear ongoing checks.
22636 */
22637 LOCK_ZONE(zone);
22638 checkds_cancel(zone);
22639 clear_keylist(&zone->checkds_ok, zone->mctx);
22640 ISC_LIST_INIT(zone->checkds_ok);
22641 UNLOCK_ZONE(zone);
22642
22643 ret = dns_zone_getdnsseckeys(zone, db, ver, now,
22644 &zone->checkds_ok);
22645 if (ret == ISC_R_SUCCESS) {
22646 zone_checkds(zone);
22647 } else {
22648 dnssec_log(zone,
22649 (ret == ISC_R_NOTFOUND) ? ISC_LOG_DEBUG(1)
22650 : ISC_LOG_ERROR,
22651 "zone_rekey:dns_zone_getdnsseckeys failed: "
22652 "%s",
22653 isc_result_totext(ret));
22654 }
22655
22656 /* Run keymgr. */
22657 if (result == ISC_R_SUCCESS || result == ISC_R_NOTFOUND) {
22658 dns_zone_lock_keyfiles(zone);
22659 result = dns_keymgr_run(&zone->origin, zone->rdclass,
22660 mctx, &keys, &dnskeys, dir,
22661 kasp, options, now, &nexttime);
22662 dns_zone_unlock_keyfiles(zone);
22663
22664 if (result == ISC_R_SUCCESS) {
22665 kasp_change = true;
22666 } else if (result == DNS_R_UNCHANGED) {
22667 result = ISC_R_SUCCESS;
22668 } else {
22669 dnssec_log(zone, ISC_LOG_ERROR,
22670 "zone_rekey:dns_keymgr_run "
22671 "failed: %s",
22672 isc_result_totext(result));
22673 KASP_UNLOCK(kasp);
22674 goto cleanup;
22675 }
22676 }
22677 } else if (offlineksk) {
22678 /*
22679 * With offline-ksk enabled we don't run the keymgr.
22680 * Instead we derive the states from the timing metadata.
22681 */
22682 dns_zone_lock_keyfiles(zone);
22683 result = dns_keymgr_offline(&zone->origin, &keys, kasp, now,
22684 &nexttime);
22685 dns_zone_unlock_keyfiles(zone);
22686
22687 if (result != ISC_R_SUCCESS) {
22688 dnssec_log(zone, ISC_LOG_ERROR,
22689 "zone_rekey:dns_keymgr_offline "
22690 "failed: %s",
22691 isc_result_totext(result));
22692 }
22693 }
22694
22695 KASP_UNLOCK(kasp);
22696
22697 /*
22698 * Update CDS, CDNSKEY and DNSKEY record sets if the keymgr ran
22699 * successfully (dns_keymgr_run returned ISC_R_SUCCESS), or in
22700 * case of DNSSEC management without dnssec-policy if we have keys
22701 * (dns_dnssec_findmatchingkeys returned ISC_R_SUCCESS).
22702 */
22703 if (result == ISC_R_SUCCESS) {
22704 dns_kasp_digestlist_t digests;
22705 bool cdsdel = false;
22706 bool cdnskeydel = false;
22707 bool cdnskeypub = true;
22708 bool sane_diff, sane_dnskey;
22709 isc_stdtime_t when;
22710
22711 result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys,
22712 &zone->origin, ttl, &diff, mctx,
22713 dnssec_report);
22714 /*
22715 * Keys couldn't be updated for some reason;
22716 * try again later.
22717 */
22718 if (result != ISC_R_SUCCESS) {
22719 dnssec_log(zone, ISC_LOG_ERROR,
22720 "zone_rekey:couldn't update zone keys: %s",
22721 isc_result_totext(result));
22722 goto cleanup;
22723 }
22724
22725 if (offlineksk) {
22726 /* We can skip a lot of things */
22727 goto post_sync;
22728 }
22729
22730 /*
22731 * Publish CDS/CDNSKEY DELETE records if the zone is
22732 * transitioning from secure to insecure.
22733 */
22734 if (kasp != NULL) {
22735 if (strcmp(dns_kasp_getname(kasp), "insecure") == 0) {
22736 cdsdel = true;
22737 cdnskeydel = true;
22738 }
22739 digests = dns_kasp_digests(kasp);
22740 cdnskeypub = dns_kasp_cdnskey(kasp);
22741 } else {
22742 /* Check if there is a CDS DELETE record. */
22743 if (dns_rdataset_isassociated(&cdsset)) {
22744 for (result = dns_rdataset_first(&cdsset);
22745 result == ISC_R_SUCCESS;
22746 result = dns_rdataset_next(&cdsset))
22747 {
22748 dns_rdata_t crdata = DNS_RDATA_INIT;
22749 dns_rdataset_current(&cdsset, &crdata);
22750 /*
22751 * CDS deletion record has this form
22752 * "0 0 0 00" which is 5 zero octets.
22753 */
22754 if (crdata.length == 5U &&
22755 memcmp(crdata.data,
22756 (unsigned char[5]){ 0, 0, 0,
22757 0, 0 },
22758 5) == 0)
22759 {
22760 cdsdel = true;
22761 break;
22762 }
22763 }
22764 }
22765
22766 /* Check if there is a CDNSKEY DELETE record. */
22767 if (dns_rdataset_isassociated(&cdnskeyset)) {
22768 for (result = dns_rdataset_first(&cdnskeyset);
22769 result == ISC_R_SUCCESS;
22770 result = dns_rdataset_next(&cdnskeyset))
22771 {
22772 dns_rdata_t crdata = DNS_RDATA_INIT;
22773 dns_rdataset_current(&cdnskeyset,
22774 &crdata);
22775 /*
22776 * CDNSKEY deletion record has this form
22777 * "0 3 0 AA==" which is 2 zero octets,
22778 * a 3, and 2 zero octets.
22779 */
22780 if (crdata.length == 5U &&
22781 memcmp(crdata.data,
22782 (unsigned char[5]){ 0, 0, 3,
22783 0, 0 },
22784 5) == 0)
22785 {
22786 cdnskeydel = true;
22787 break;
22788 }
22789 }
22790 }
22791
22792 digests = dns_kasp_digests(zone->defaultkasp);
22793 }
22794
22795 /*
22796 * Update CDS / CDNSKEY records.
22797 */
22798 result = dns_dnssec_syncupdate(&dnskeys, &rmkeys, &cdsset,
22799 &cdnskeyset, now, &digests,
22800 cdnskeypub, ttl, &diff, mctx);
22801 if (result != ISC_R_SUCCESS) {
22802 dnssec_log(zone, ISC_LOG_ERROR,
22803 "zone_rekey:couldn't update CDS/CDNSKEY: %s",
22804 isc_result_totext(result));
22805 goto cleanup;
22806 }
22807
22808 if (cdsdel || cdnskeydel) {
22809 /*
22810 * Only publish CDS/CDNSKEY DELETE records if there is
22811 * a KSK that can be used to verify the RRset. This
22812 * means there must be a key with the KSK role that is
22813 * published and is used for signing.
22814 */
22815 bool allow = false;
22816 for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
22817 key = ISC_LIST_NEXT(key, link))
22818 {
22819 dst_key_t *dstk = key->key;
22820
22821 if (dst_key_is_published(dstk, now, &when) &&
22822 dst_key_is_signing(dstk, DST_BOOL_KSK, now,
22823 &when))
22824 {
22825 allow = true;
22826 break;
22827 }
22828 }
22829 if (cdsdel) {
22830 cdsdel = allow;
22831 }
22832 if (cdnskeydel) {
22833 cdnskeydel = allow;
22834 }
22835 }
22836 result = dns_dnssec_syncdelete(
22837 &cdsset, &cdnskeyset, &zone->origin, zone->rdclass, ttl,
22838 &diff, mctx, cdsdel, cdnskeydel);
22839 if (result != ISC_R_SUCCESS) {
22840 dnssec_log(zone, ISC_LOG_ERROR,
22841 "zone_rekey:couldn't update CDS/CDNSKEY "
22842 "DELETE records: %s",
22843 isc_result_totext(result));
22844 goto cleanup;
22845 }
22846
22847 post_sync:
22848 /*
22849 * See if any pre-existing keys have newly become active;
22850 * also, see if any new key is for a new algorithm, as in that
22851 * event, we need to sign the zone fully. (If there's a new
22852 * key, but it's for an already-existing algorithm, then
22853 * the zone signing can be handled incrementally.)
22854 */
22855 for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
22856 key = ISC_LIST_NEXT(key, link))
22857 {
22858 if (!key->first_sign) {
22859 continue;
22860 }
22861
22862 newactive = true;
22863
22864 if (!dns_rdataset_isassociated(&keysigs)) {
22865 newalg = true;
22866 break;
22867 }
22868
22869 if (signed_with_alg(&keysigs, dst_key_alg(key->key))) {
22870 /*
22871 * This isn't a new algorithm; clear
22872 * first_sign so we won't sign the
22873 * whole zone with this key later.
22874 */
22875 key->first_sign = false;
22876 } else {
22877 newalg = true;
22878 break;
22879 }
22880 }
22881
22882 /*
22883 * A sane diff is one that is not empty, and that does not
22884 * introduce a zone with NSEC only DNSKEYs along with NSEC3
22885 * chains.
22886 */
22887 sane_dnskey = dns_zone_check_dnskey_nsec3(zone, db, ver, &diff,
22888 NULL, 0);
22889 sane_diff = !ISC_LIST_EMPTY(diff.tuples) && sane_dnskey;
22890 if (!sane_dnskey) {
22891 dnssec_log(zone, ISC_LOG_ERROR,
22892 "NSEC only DNSKEYs and NSEC3 chains not "
22893 "allowed");
22894 }
22895
22896 if (newactive || fullsign || sane_diff || kasp_change) {
22897 CHECK(dns_diff_apply(&diff, db, ver));
22898 CHECK(clean_nsec3param(zone, db, ver, &diff));
22899 CHECK(add_signing_records(db, zone->privatetype, ver,
22900 &diff, newalg || fullsign));
22901 CHECK(update_soa_serial(zone, db, ver, &diff, mctx,
22902 zone->updatemethod));
22903 CHECK(add_chains(zone, db, ver, &diff));
22904 CHECK(sign_apex(zone, db, ver, now, &diff, &zonediff));
22905 CHECK(zone_journal(zone, zonediff.diff, NULL,
22906 "zone_rekey"));
22907 commit = true;
22908 }
22909 }
22910
22911 dns_db_closeversion(db, &ver, true);
22912
22913 LOCK_ZONE(zone);
22914
22915 if (commit) {
22916 dns_difftuple_t *tuple;
22917 dns_stats_t *dnssecsignstats =
22918 dns_zone_getdnssecsignstats(zone);
22919
22920 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
22921
22922 zone_needdump(zone, DNS_DUMP_DELAY);
22923
22924 zone_settimer(zone, &timenow);
22925
22926 /* Remove any signatures from removed keys. */
22927 if (!ISC_LIST_EMPTY(rmkeys)) {
22928 for (key = ISC_LIST_HEAD(rmkeys); key != NULL;
22929 key = ISC_LIST_NEXT(key, link))
22930 {
22931 result = zone_signwithkey(
22932 zone, dst_key_alg(key->key),
22933 dst_key_id(key->key), true, false);
22934 if (result != ISC_R_SUCCESS) {
22935 dnssec_log(zone, ISC_LOG_ERROR,
22936 "zone_signwithkey failed: "
22937 "%s",
22938 isc_result_totext(result));
22939 }
22940
22941 /* Clear DNSSEC sign statistics. */
22942 if (dnssecsignstats != NULL) {
22943 dns_dnssecsignstats_clear(
22944 dnssecsignstats,
22945 dst_key_id(key->key),
22946 dst_key_alg(key->key));
22947 /*
22948 * Also clear the dnssec-sign
22949 * statistics of the revoked key id.
22950 */
22951 dns_dnssecsignstats_clear(
22952 dnssecsignstats,
22953 dst_key_rid(key->key),
22954 dst_key_alg(key->key));
22955 }
22956 }
22957 }
22958
22959 if (fullsign) {
22960 /*
22961 * "rndc sign" was called, so we now sign the zone
22962 * with all active keys, whether they're new or not.
22963 */
22964 for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
22965 key = ISC_LIST_NEXT(key, link))
22966 {
22967 if (!key->force_sign && !key->hint_sign) {
22968 continue;
22969 }
22970
22971 result = zone_signwithkey(
22972 zone, dst_key_alg(key->key),
22973 dst_key_id(key->key), false, true);
22974 if (result != ISC_R_SUCCESS) {
22975 dnssec_log(zone, ISC_LOG_ERROR,
22976 "zone_signwithkey failed: "
22977 "%s",
22978 isc_result_totext(result));
22979 }
22980 }
22981 /*
22982 * ...and remove signatures for all inactive keys.
22983 */
22984 ISC_LIST_FOREACH(dnskeys, key, link) {
22985 if (!key->force_sign && !key->hint_sign) {
22986 result = zone_signwithkey(
22987 zone, dst_key_alg(key->key),
22988 dst_key_id(key->key), true,
22989 false);
22990 if (result != ISC_R_SUCCESS) {
22991 dnssec_log(zone, ISC_LOG_ERROR,
22992 "zone_signwithkey "
22993 "failed: "
22994 "%s",
22995 isc_result_totext(
22996 result));
22997 }
22998 }
22999 }
23000
23001 } else if (newalg) {
23002 /*
23003 * We haven't been told to sign fully, but a new
23004 * algorithm was added to the DNSKEY. We sign
23005 * the full zone, but only with newly active
23006 * keys.
23007 */
23008 for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
23009 key = ISC_LIST_NEXT(key, link))
23010 {
23011 if (!key->first_sign) {
23012 continue;
23013 }
23014
23015 result = zone_signwithkey(
23016 zone, dst_key_alg(key->key),
23017 dst_key_id(key->key), false, false);
23018 if (result != ISC_R_SUCCESS) {
23019 dnssec_log(zone, ISC_LOG_ERROR,
23020 "zone_signwithkey failed: "
23021 "%s",
23022 isc_result_totext(result));
23023 }
23024 }
23025 }
23026
23027 /*
23028 * Clear fullsign flag, if it was set, so we don't do
23029 * another full signing next time.
23030 */
23031 DNS_ZONEKEY_CLROPTION(zone, DNS_ZONEKEY_FULLSIGN);
23032
23033 /*
23034 * Cause the zone to add/delete NSEC3 chains for the
23035 * deferred NSEC3PARAM changes.
23036 */
23037 for (tuple = ISC_LIST_HEAD(zonediff.diff->tuples);
23038 tuple != NULL; tuple = ISC_LIST_NEXT(tuple, link))
23039 {
23040 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
23041 dns_rdata_t rdata = DNS_RDATA_INIT;
23042 dns_rdata_nsec3param_t nsec3param;
23043
23044 if (tuple->rdata.type != zone->privatetype ||
23045 tuple->op != DNS_DIFFOP_ADD)
23046 {
23047 continue;
23048 }
23049
23050 if (!dns_nsec3param_fromprivate(&tuple->rdata, &rdata,
23051 buf, sizeof(buf)))
23052 {
23053 continue;
23054 }
23055
23056 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
23057 RUNTIME_CHECK(result == ISC_R_SUCCESS);
23058 if (nsec3param.flags == 0) {
23059 continue;
23060 }
23061
23062 result = zone_addnsec3chain(zone, &nsec3param);
23063 if (result != ISC_R_SUCCESS) {
23064 dnssec_log(zone, ISC_LOG_ERROR,
23065 "zone_addnsec3chain failed: %s",
23066 isc_result_totext(result));
23067 }
23068 }
23069
23070 /*
23071 * Activate any NSEC3 chain updates that may have
23072 * been scheduled before this rekey.
23073 */
23074 if (fullsign || newalg) {
23075 resume_addnsec3chain(zone);
23076 }
23077
23078 /*
23079 * Schedule the next resigning event
23080 */
23081 set_resigntime(zone);
23082 }
23083
23084 isc_time_settoepoch(&zone->refreshkeytime);
23085
23086 /*
23087 * If keymgr provided a next time, use the calculated next rekey time.
23088 */
23089 if (kasp != NULL) {
23090 isc_time_t timenext;
23091 uint32_t nexttime_seconds;
23092
23093 /*
23094 * Set the key refresh timer to the next scheduled key event
23095 * or to 'dnssec-loadkeys-interval' seconds in the future
23096 * if no next key event is scheduled (nexttime == 0).
23097 */
23098 if (nexttime > 0) {
23099 nexttime_seconds = nexttime - now;
23100 } else {
23101 nexttime_seconds = zone->refreshkeyinterval;
23102 }
23103
23104 DNS_ZONE_TIME_ADD(&timenow, nexttime_seconds, &timenext);
23105 zone->refreshkeytime = timenext;
23106 zone_settimer(zone, &timenow);
23107 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
23108
23109 dnssec_log(zone, ISC_LOG_DEBUG(3),
23110 "next key event in %u seconds", nexttime_seconds);
23111 dnssec_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
23112 }
23113 /*
23114 * If we're doing key maintenance, set the key refresh timer to
23115 * the next scheduled key event or to 'dnssec-loadkeys-interval'
23116 * seconds in the future, whichever is sooner.
23117 */
23118 else if (DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
23119 {
23120 isc_time_t timethen;
23121 isc_stdtime_t then;
23122
23123 DNS_ZONE_TIME_ADD(&timenow, zone->refreshkeyinterval,
23124 &timethen);
23125 zone->refreshkeytime = timethen;
23126
23127 for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
23128 key = ISC_LIST_NEXT(key, link))
23129 {
23130 then = now;
23131 result = next_keyevent(key->key, &then);
23132 if (result != ISC_R_SUCCESS) {
23133 continue;
23134 }
23135
23136 DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
23137 if (isc_time_compare(&timethen, &zone->refreshkeytime) <
23138 0)
23139 {
23140 zone->refreshkeytime = timethen;
23141 }
23142 }
23143
23144 zone_settimer(zone, &timenow);
23145
23146 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
23147 dnssec_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
23148 }
23149 UNLOCK_ZONE(zone);
23150
23151 /*
23152 * Remember which keys have been used.
23153 */
23154 if (!ISC_LIST_EMPTY(zone->keyring)) {
23155 clear_keylist(&zone->keyring, zone->mctx);
23156 }
23157 while ((key = ISC_LIST_HEAD(dnskeys)) != NULL) {
23158 if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
23159 /* This debug log is used in the kasp system test */
23160 char algbuf[DNS_SECALG_FORMATSIZE];
23161 dns_secalg_format(dst_key_alg(key->key), algbuf,
23162 sizeof(algbuf));
23163 dnssec_log(zone, ISC_LOG_DEBUG(3),
23164 "zone_rekey done: key %d/%s",
23165 dst_key_id(key->key), algbuf);
23166 }
23167 ISC_LIST_UNLINK(dnskeys, key, link);
23168 ISC_LIST_APPEND(zone->keyring, key, link);
23169 }
23170
23171 result = ISC_R_SUCCESS;
23172
23173 cleanup:
23174 LOCK_ZONE(zone);
23175 if (result != ISC_R_SUCCESS) {
23176 /*
23177 * Something went wrong; try again in ten minutes or
23178 * after a key refresh interval, whichever is shorter.
23179 */
23180 int loglevel = ISC_LOG_DEBUG(3);
23181 if (result != DNS_R_NOTLOADED) {
23182 loglevel = ISC_LOG_ERROR;
23183 }
23184 dnssec_log(zone, loglevel,
23185 "zone_rekey failure: %s (retry in %u seconds)",
23186 isc_result_totext(result),
23187 ISC_MIN(zone->refreshkeyinterval, 600));
23188 isc_interval_set(&ival, ISC_MIN(zone->refreshkeyinterval, 600),
23189 0);
23190 isc_time_nowplusinterval(&zone->refreshkeytime, &ival);
23191 }
23192
23193 /*
23194 * Clear forcekeymgr flag, if it was set, so we don't do
23195 * another force next time.
23196 */
23197 DNS_ZONE_CLROPTION(zone, DNS_ZONEOPT_FORCEKEYMGR);
23198
23199 UNLOCK_ZONE(zone);
23200
23201 dns_diff_clear(&diff);
23202 dns_diff_clear(&_sig_diff);
23203
23204 clear_keylist(&dnskeys, mctx);
23205 clear_keylist(&keys, mctx);
23206 clear_keylist(&rmkeys, mctx);
23207
23208 if (ver != NULL) {
23209 dns_db_closeversion(db, &ver, false);
23210 }
23211 if (dns_rdataset_isassociated(&cdsset)) {
23212 dns_rdataset_disassociate(&cdsset);
23213 }
23214 if (dns_rdataset_isassociated(&keyset)) {
23215 dns_rdataset_disassociate(&keyset);
23216 }
23217 if (dns_rdataset_isassociated(&keysigs)) {
23218 dns_rdataset_disassociate(&keysigs);
23219 }
23220 if (dns_rdataset_isassociated(&soasigs)) {
23221 dns_rdataset_disassociate(&soasigs);
23222 }
23223 if (dns_rdataset_isassociated(&cdnskeyset)) {
23224 dns_rdataset_disassociate(&cdnskeyset);
23225 }
23226 if (node != NULL) {
23227 dns_db_detachnode(db, &node);
23228 }
23229 if (db != NULL) {
23230 dns_db_detach(&db);
23231 }
23232
23233 INSIST(ver == NULL);
23234 }
23235
23236 void
23237 dns_zone_rekey(dns_zone_t *zone, bool fullsign, bool forcekeymgr) {
23238 isc_time_t now;
23239
23240 if (zone->type == dns_zone_primary && zone->loop != NULL) {
23241 LOCK_ZONE(zone);
23242
23243 if (fullsign) {
23244 DNS_ZONEKEY_SETOPTION(zone, DNS_ZONEKEY_FULLSIGN);
23245 }
23246 if (forcekeymgr) {
23247 DNS_ZONE_SETOPTION(zone, DNS_ZONEOPT_FORCEKEYMGR);
23248 }
23249
23250 now = isc_time_now();
23251 zone->refreshkeytime = now;
23252 zone_settimer(zone, &now);
23253
23254 UNLOCK_ZONE(zone);
23255 }
23256 }
23257
23258 isc_result_t
23259 dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
23260 unsigned int *errors) {
23261 isc_result_t result;
23262 dns_dbnode_t *node = NULL;
23263
23264 REQUIRE(DNS_ZONE_VALID(zone));
23265 REQUIRE(errors != NULL);
23266
23267 result = dns_db_getoriginnode(db, &node);
23268 if (result != ISC_R_SUCCESS) {
23269 return result;
23270 }
23271 result = zone_count_ns_rr(zone, db, node, version, NULL, errors, false);
23272 dns_db_detachnode(db, &node);
23273 return result;
23274 }
23275
23276 isc_result_t
23277 dns_zone_cdscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version) {
23278 isc_result_t result;
23279 dns_dbnode_t *node = NULL;
23280 dns_rdataset_t dnskey, cds, cdnskey;
23281 unsigned char algorithms[256];
23282 unsigned int i;
23283 bool empty = false;
23284
23285 enum { notexpected = 0, expected = 1, found = 2 };
23286
23287 REQUIRE(DNS_ZONE_VALID(zone));
23288
23289 result = dns_db_getoriginnode(db, &node);
23290 if (result != ISC_R_SUCCESS) {
23291 return result;
23292 }
23293
23294 dns_rdataset_init(&cds);
23295 dns_rdataset_init(&dnskey);
23296 dns_rdataset_init(&cdnskey);
23297
23298 result = dns_db_findrdataset(db, node, version, dns_rdatatype_cds,
23299 dns_rdatatype_none, 0, &cds, NULL);
23300 if (result != ISC_R_NOTFOUND) {
23301 CHECK(result);
23302 }
23303
23304 result = dns_db_findrdataset(db, node, version, dns_rdatatype_cdnskey,
23305 dns_rdatatype_none, 0, &cdnskey, NULL);
23306 if (result != ISC_R_NOTFOUND) {
23307 CHECK(result);
23308 }
23309
23310 if (!dns_rdataset_isassociated(&cds) &&
23311 !dns_rdataset_isassociated(&cdnskey))
23312 {
23313 result = ISC_R_SUCCESS;
23314 goto cleanup;
23315 }
23316
23317 result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
23318 dns_rdatatype_none, 0, &dnskey, NULL);
23319 if (result == ISC_R_NOTFOUND) {
23320 empty = true;
23321 } else {
23322 CHECK(result);
23323 }
23324
23325 /*
23326 * For each DNSSEC algorithm in the CDS RRset there must be
23327 * a matching DNSKEY record with the exception of a CDS deletion
23328 * record which must be by itself.
23329 */
23330 if (dns_rdataset_isassociated(&cds)) {
23331 bool logged_digest_type[DNS_DSDIGEST_MAX + 1] = { 0 };
23332 bool delete = false;
23333 memset(algorithms, notexpected, sizeof(algorithms));
23334 for (result = dns_rdataset_first(&cds); result == ISC_R_SUCCESS;
23335 result = dns_rdataset_next(&cds))
23336 {
23337 dns_rdata_t crdata = DNS_RDATA_INIT;
23338 dns_rdata_cds_t structcds;
23339
23340 dns_rdataset_current(&cds, &crdata);
23341 /*
23342 * CDS deletion record has this form "0 0 0 00" which
23343 * is 5 zero octets.
23344 */
23345 if (crdata.length == 5U &&
23346 memcmp(crdata.data,
23347 (unsigned char[5]){ 0, 0, 0, 0, 0 }, 5) == 0)
23348 {
23349 delete = true;
23350 continue;
23351 }
23352
23353 if (empty) {
23354 CHECK(DNS_R_BADCDS);
23355 }
23356
23357 CHECK(dns_rdata_tostruct(&crdata, &structcds, NULL));
23358
23359 /*
23360 * Log deprecated CDS digest types.
23361 */
23362 switch (structcds.digest_type) {
23363 case DNS_DSDIGEST_SHA1:
23364 case DNS_DSDIGEST_GOST:
23365 if (!logged_digest_type[structcds.digest_type])
23366 {
23367 char algbuf[DNS_DSDIGEST_FORMATSIZE];
23368 dns_dsdigest_format(
23369 structcds.digest_type, algbuf,
23370 sizeof(algbuf));
23371 dnssec_log(zone, ISC_LOG_WARNING,
23372 "deprecated CDS digest type "
23373 "%u (%s)",
23374 structcds.digest_type,
23375 algbuf);
23376 logged_digest_type[structcds.digest_type] =
23377 true;
23378 }
23379 break;
23380 }
23381
23382 if (algorithms[structcds.algorithm] == 0) {
23383 algorithms[structcds.algorithm] = expected;
23384 }
23385 for (result = dns_rdataset_first(&dnskey);
23386 result == ISC_R_SUCCESS;
23387 result = dns_rdataset_next(&dnskey))
23388 {
23389 dns_rdata_t rdata = DNS_RDATA_INIT;
23390 dns_rdata_dnskey_t structdnskey;
23391
23392 dns_rdataset_current(&dnskey, &rdata);
23393 CHECK(dns_rdata_tostruct(&rdata, &structdnskey,
23394 NULL));
23395
23396 if (structdnskey.algorithm ==
23397 structcds.algorithm)
23398 {
23399 algorithms[structcds.algorithm] = found;
23400 }
23401 }
23402 if (result != ISC_R_NOMORE) {
23403 goto cleanup;
23404 }
23405 }
23406 for (i = 0; i < sizeof(algorithms); i++) {
23407 if (delete) {
23408 if (algorithms[i] != notexpected) {
23409 CHECK(DNS_R_BADCDS);
23410 }
23411 } else if (algorithms[i] == expected) {
23412 CHECK(DNS_R_BADCDS);
23413 }
23414 }
23415 }
23416
23417 /*
23418 * For each DNSSEC algorithm in the CDNSKEY RRset there must be
23419 * a matching DNSKEY record with the exception of a CDNSKEY deletion
23420 * record which must be by itself.
23421 */
23422 if (dns_rdataset_isassociated(&cdnskey)) {
23423 bool delete = false;
23424 memset(algorithms, notexpected, sizeof(algorithms));
23425 for (result = dns_rdataset_first(&cdnskey);
23426 result == ISC_R_SUCCESS;
23427 result = dns_rdataset_next(&cdnskey))
23428 {
23429 dns_rdata_t crdata = DNS_RDATA_INIT;
23430 dns_rdata_cdnskey_t structcdnskey;
23431
23432 dns_rdataset_current(&cdnskey, &crdata);
23433 /*
23434 * CDNSKEY deletion record has this form
23435 * "0 3 0 AA==" which is 2 zero octets, a 3,
23436 * and 2 zero octets.
23437 */
23438 if (crdata.length == 5U &&
23439 memcmp(crdata.data,
23440 (unsigned char[5]){ 0, 0, 3, 0, 0 }, 5) == 0)
23441 {
23442 delete = true;
23443 continue;
23444 }
23445
23446 if (empty) {
23447 CHECK(DNS_R_BADCDNSKEY);
23448 }
23449
23450 CHECK(dns_rdata_tostruct(&crdata, &structcdnskey,
23451 NULL));
23452 if (algorithms[structcdnskey.algorithm] == 0) {
23453 algorithms[structcdnskey.algorithm] = expected;
23454 }
23455 for (result = dns_rdataset_first(&dnskey);
23456 result == ISC_R_SUCCESS;
23457 result = dns_rdataset_next(&dnskey))
23458 {
23459 dns_rdata_t rdata = DNS_RDATA_INIT;
23460 dns_rdata_dnskey_t structdnskey;
23461
23462 dns_rdataset_current(&dnskey, &rdata);
23463 CHECK(dns_rdata_tostruct(&rdata, &structdnskey,
23464 NULL));
23465
23466 if (structdnskey.algorithm ==
23467 structcdnskey.algorithm)
23468 {
23469 algorithms[structcdnskey.algorithm] =
23470 found;
23471 }
23472 }
23473 if (result != ISC_R_NOMORE) {
23474 goto cleanup;
23475 }
23476 }
23477 for (i = 0; i < sizeof(algorithms); i++) {
23478 if (delete) {
23479 if (algorithms[i] != notexpected) {
23480 CHECK(DNS_R_BADCDNSKEY);
23481 }
23482 } else if (algorithms[i] == expected) {
23483 CHECK(DNS_R_BADCDNSKEY);
23484 }
23485 }
23486 }
23487 result = ISC_R_SUCCESS;
23488
23489 cleanup:
23490 if (dns_rdataset_isassociated(&cds)) {
23491 dns_rdataset_disassociate(&cds);
23492 }
23493 if (dns_rdataset_isassociated(&dnskey)) {
23494 dns_rdataset_disassociate(&dnskey);
23495 }
23496 if (dns_rdataset_isassociated(&cdnskey)) {
23497 dns_rdataset_disassociate(&cdnskey);
23498 }
23499 dns_db_detachnode(db, &node);
23500 return result;
23501 }
23502
23503 void
23504 dns_zone_setautomatic(dns_zone_t *zone, bool automatic) {
23505 REQUIRE(DNS_ZONE_VALID(zone));
23506
23507 LOCK_ZONE(zone);
23508 zone->automatic = automatic;
23509 UNLOCK_ZONE(zone);
23510 }
23511
23512 bool
23513 dns_zone_getautomatic(dns_zone_t *zone) {
23514 REQUIRE(DNS_ZONE_VALID(zone));
23515 return zone->automatic;
23516 }
23517
23518 void
23519 dns_zone_setadded(dns_zone_t *zone, bool added) {
23520 REQUIRE(DNS_ZONE_VALID(zone));
23521
23522 LOCK_ZONE(zone);
23523 zone->added = added;
23524 UNLOCK_ZONE(zone);
23525 }
23526
23527 bool
23528 dns_zone_getadded(dns_zone_t *zone) {
23529 REQUIRE(DNS_ZONE_VALID(zone));
23530 return zone->added;
23531 }
23532
23533 isc_result_t
23534 dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db) {
23535 isc_time_t loadtime;
23536 isc_result_t result;
23537 dns_zone_t *secure = NULL;
23538
23539 loadtime = isc_time_now();
23540
23541 /*
23542 * Lock hierarchy: zmgr, zone, raw.
23543 */
23544 again:
23545 LOCK_ZONE(zone);
23546 INSIST(zone != zone->raw);
23547 if (inline_secure(zone)) {
23548 LOCK_ZONE(zone->raw);
23549 } else if (inline_raw(zone)) {
23550 secure = zone->secure;
23551 TRYLOCK_ZONE(result, secure);
23552 if (result != ISC_R_SUCCESS) {
23553 UNLOCK_ZONE(zone);
23554 secure = NULL;
23555 isc_thread_yield();
23556 goto again;
23557 }
23558 }
23559 result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
23560 if (inline_secure(zone)) {
23561 UNLOCK_ZONE(zone->raw);
23562 } else if (secure != NULL) {
23563 UNLOCK_ZONE(secure);
23564 }
23565 UNLOCK_ZONE(zone);
23566 return result;
23567 }
23568
23569 isc_result_t
23570 dns_zone_setrefreshkeyinterval(dns_zone_t *zone, uint32_t interval) {
23571 REQUIRE(DNS_ZONE_VALID(zone));
23572 if (interval == 0) {
23573 return ISC_R_RANGE;
23574 }
23575 /* Maximum value: 24 hours (3600 minutes) */
23576 if (interval > (24 * 60)) {
23577 interval = (24 * 60);
23578 }
23579 /* Multiply by 60 for seconds */
23580 zone->refreshkeyinterval = interval * 60;
23581 return ISC_R_SUCCESS;
23582 }
23583
23584 void
23585 dns_zone_setrequestixfr(dns_zone_t *zone, bool flag) {
23586 REQUIRE(DNS_ZONE_VALID(zone));
23587 zone->requestixfr = flag;
23588 }
23589
23590 bool
23591 dns_zone_getrequestixfr(dns_zone_t *zone) {
23592 REQUIRE(DNS_ZONE_VALID(zone));
23593 return zone->requestixfr;
23594 }
23595
23596 void
23597 dns_zone_setixfrratio(dns_zone_t *zone, uint32_t ratio) {
23598 REQUIRE(DNS_ZONE_VALID(zone));
23599 zone->ixfr_ratio = ratio;
23600 }
23601
23602 uint32_t
23603 dns_zone_getixfrratio(dns_zone_t *zone) {
23604 REQUIRE(DNS_ZONE_VALID(zone));
23605 return zone->ixfr_ratio;
23606 }
23607
23608 void
23609 dns_zone_setrequestexpire(dns_zone_t *zone, bool flag) {
23610 REQUIRE(DNS_ZONE_VALID(zone));
23611 zone->requestexpire = flag;
23612 }
23613
23614 bool
23615 dns_zone_getrequestexpire(dns_zone_t *zone) {
23616 REQUIRE(DNS_ZONE_VALID(zone));
23617 return zone->requestexpire;
23618 }
23619
23620 void
23621 dns_zone_setserialupdatemethod(dns_zone_t *zone, dns_updatemethod_t method) {
23622 REQUIRE(DNS_ZONE_VALID(zone));
23623 zone->updatemethod = method;
23624 }
23625
23626 dns_updatemethod_t
23627 dns_zone_getserialupdatemethod(dns_zone_t *zone) {
23628 REQUIRE(DNS_ZONE_VALID(zone));
23629 return zone->updatemethod;
23630 }
23631
23632 /*
23633 * Lock hierarchy: zmgr, zone, raw.
23634 */
23635 isc_result_t
23636 dns_zone_link(dns_zone_t *zone, dns_zone_t *raw) {
23637 dns_zonemgr_t *zmgr;
23638
23639 REQUIRE(DNS_ZONE_VALID(zone));
23640 REQUIRE(zone->zmgr != NULL);
23641 REQUIRE(zone->loop != NULL);
23642 REQUIRE(zone->raw == NULL);
23643
23644 REQUIRE(DNS_ZONE_VALID(raw));
23645 REQUIRE(raw->zmgr == NULL);
23646 REQUIRE(raw->loop == NULL);
23647 REQUIRE(raw->secure == NULL);
23648
23649 REQUIRE(zone != raw);
23650
23651 /*
23652 * Lock hierarchy: zmgr, zone, raw.
23653 */
23654 zmgr = zone->zmgr;
23655 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
23656 LOCK_ZONE(zone);
23657 LOCK_ZONE(raw);
23658
23659 isc_loop_attach(zone->loop, &raw->loop);
23660
23661 /* dns_zone_attach(raw, &zone->raw); */
23662 isc_refcount_increment(&raw->references);
23663 zone->raw = raw;
23664
23665 /* dns_zone_iattach(zone, &raw->secure); */
23666 zone_iattach(zone, &raw->secure);
23667
23668 ISC_LIST_APPEND(zmgr->zones, raw, link);
23669 raw->zmgr = zmgr;
23670 isc_refcount_increment(&zmgr->refs);
23671
23672 UNLOCK_ZONE(raw);
23673 UNLOCK_ZONE(zone);
23674 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
23675 return ISC_R_SUCCESS;
23676 }
23677
23678 void
23679 dns_zone_getraw(dns_zone_t *zone, dns_zone_t **raw) {
23680 REQUIRE(DNS_ZONE_VALID(zone));
23681 REQUIRE(raw != NULL && *raw == NULL);
23682
23683 LOCK(&zone->lock);
23684 INSIST(zone != zone->raw);
23685 if (zone->raw != NULL) {
23686 dns_zone_attach(zone->raw, raw);
23687 }
23688 UNLOCK(&zone->lock);
23689 }
23690
23691 bool
23692 dns_zone_israw(dns_zone_t *zone) {
23693 bool israw;
23694 REQUIRE(DNS_ZONE_VALID(zone));
23695 LOCK(&zone->lock);
23696 israw = zone->secure != NULL;
23697 UNLOCK(&zone->lock);
23698 return israw;
23699 }
23700
23701 bool
23702 dns_zone_issecure(dns_zone_t *zone) {
23703 bool issecure;
23704 REQUIRE(DNS_ZONE_VALID(zone));
23705 LOCK(&zone->lock);
23706 issecure = zone->raw != NULL;
23707 UNLOCK(&zone->lock);
23708 return issecure;
23709 }
23710
23711 struct keydone {
23712 bool all;
23713 unsigned char data[5];
23714 dns_zone_t *zone;
23715 };
23716
23717 #define PENDINGFLAGS (DNS_NSEC3FLAG_CREATE | DNS_NSEC3FLAG_INITIAL)
23718
23719 static void
23720 keydone(void *arg) {
23721 bool commit = false;
23722 isc_result_t result;
23723 dns_rdata_t rdata = DNS_RDATA_INIT;
23724 dns_dbversion_t *oldver = NULL, *newver = NULL;
23725 dns_db_t *db = NULL;
23726 dns_dbnode_t *node = NULL;
23727 dns_rdataset_t rdataset;
23728 dns_diff_t diff;
23729 struct keydone *kd = (struct keydone *)arg;
23730 dns_zone_t *zone = kd->zone;
23731 dns_update_log_t log = { update_log_cb, NULL };
23732 bool clear_pending = false;
23733
23734 INSIST(DNS_ZONE_VALID(zone));
23735
23736 ENTER;
23737
23738 dns_rdataset_init(&rdataset);
23739 dns_diff_init(zone->mctx, &diff);
23740
23741 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
23742 if (zone->db != NULL) {
23743 dns_db_attach(zone->db, &db);
23744 }
23745 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
23746 if (db == NULL) {
23747 goto cleanup;
23748 }
23749
23750 dns_db_currentversion(db, &oldver);
23751 result = dns_db_newversion(db, &newver);
23752 if (result != ISC_R_SUCCESS) {
23753 dnssec_log(zone, ISC_LOG_ERROR,
23754 "keydone:dns_db_newversion -> %s",
23755 isc_result_totext(result));
23756 goto cleanup;
23757 }
23758
23759 CHECK(dns_db_getoriginnode(db, &node));
23760
23761 result = dns_db_findrdataset(db, node, newver, zone->privatetype,
23762 dns_rdatatype_none, 0, &rdataset, NULL);
23763 if (result != ISC_R_SUCCESS) {
23764 INSIST(!dns_rdataset_isassociated(&rdataset));
23765 goto cleanup;
23766 }
23767
23768 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
23769 result = dns_rdataset_next(&rdataset))
23770 {
23771 bool found = false;
23772
23773 dns_rdataset_current(&rdataset, &rdata);
23774
23775 if (kd->all) {
23776 if (rdata.length == 5 && rdata.data[0] != 0 &&
23777 rdata.data[3] == 0 && rdata.data[4] == 1)
23778 {
23779 found = true;
23780 } else if (rdata.data[0] == 0 &&
23781 (rdata.data[2] & PENDINGFLAGS) != 0)
23782 {
23783 found = true;
23784 clear_pending = true;
23785 }
23786 } else if (rdata.length == 5 &&
23787 memcmp(rdata.data, kd->data, 5) == 0)
23788 {
23789 found = true;
23790 }
23791
23792 if (found) {
23793 CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_DEL,
23794 &zone->origin, rdataset.ttl,
23795 &rdata));
23796 }
23797 dns_rdata_reset(&rdata);
23798 }
23799
23800 if (!ISC_LIST_EMPTY(diff.tuples)) {
23801 /* Write changes to journal file. */
23802 CHECK(update_soa_serial(zone, db, newver, &diff, zone->mctx,
23803 zone->updatemethod));
23804
23805 result = dns_update_signatures(&log, zone, db, oldver, newver,
23806 &diff,
23807 zone->sigvalidityinterval);
23808 if (!clear_pending) {
23809 CHECK(result);
23810 }
23811
23812 CHECK(zone_journal(zone, &diff, NULL, "keydone"));
23813 commit = true;
23814
23815 LOCK_ZONE(zone);
23816 DNS_ZONE_SETFLAG(zone,
23817 DNS_ZONEFLG_LOADED | DNS_ZONEFLG_NEEDNOTIFY);
23818 zone_needdump(zone, 30);
23819 UNLOCK_ZONE(zone);
23820 }
23821
23822 cleanup:
23823 if (dns_rdataset_isassociated(&rdataset)) {
23824 dns_rdataset_disassociate(&rdataset);
23825 }
23826 if (db != NULL) {
23827 if (node != NULL) {
23828 dns_db_detachnode(db, &node);
23829 }
23830 if (oldver != NULL) {
23831 dns_db_closeversion(db, &oldver, false);
23832 }
23833 if (newver != NULL) {
23834 dns_db_closeversion(db, &newver, commit);
23835 }
23836 dns_db_detach(&db);
23837 }
23838 dns_diff_clear(&diff);
23839 isc_mem_put(zone->mctx, kd, sizeof(*kd));
23840 dns_zone_idetach(&zone);
23841
23842 INSIST(oldver == NULL);
23843 INSIST(newver == NULL);
23844 }
23845
23846 isc_result_t
23847 dns_zone_keydone(dns_zone_t *zone, const char *keystr) {
23848 isc_result_t result = ISC_R_SUCCESS;
23849 struct keydone *kd = NULL;
23850 isc_buffer_t b;
23851
23852 REQUIRE(DNS_ZONE_VALID(zone));
23853
23854 LOCK_ZONE(zone);
23855
23856 kd = isc_mem_get(zone->mctx, sizeof(*kd));
23857 *kd = (struct keydone){ .all = false };
23858
23859 if (strcasecmp(keystr, "all") == 0) {
23860 kd->all = true;
23861 } else {
23862 isc_textregion_t r;
23863 const char *algstr = NULL;
23864 dns_keytag_t keyid;
23865 dns_secalg_t alg;
23866 size_t n;
23867
23868 n = sscanf(keystr, "%hu/", &keyid);
23869 if (n == 0U) {
23870 CHECK(ISC_R_FAILURE);
23871 }
23872
23873 algstr = strchr(keystr, '/');
23874 if (algstr != NULL) {
23875 algstr++;
23876 } else {
23877 CHECK(ISC_R_FAILURE);
23878 }
23879
23880 n = sscanf(algstr, "%hhu", &alg);
23881 if (n == 0U) {
23882 r.base = UNCONST(algstr);
23883 r.length = strlen(algstr);
23884 CHECK(dns_secalg_fromtext(&alg, &r));
23885 }
23886
23887 /* construct a private-type rdata */
23888 isc_buffer_init(&b, kd->data, sizeof(kd->data));
23889 isc_buffer_putuint8(&b, alg);
23890 isc_buffer_putuint8(&b, (keyid & 0xff00) >> 8);
23891 isc_buffer_putuint8(&b, keyid & 0xff);
23892 isc_buffer_putuint8(&b, 0);
23893 isc_buffer_putuint8(&b, 1);
23894 }
23895
23896 zone_iattach(zone, &kd->zone);
23897 isc_async_run(zone->loop, keydone, kd);
23898 kd = NULL;
23899
23900 cleanup:
23901 if (kd != NULL) {
23902 isc_mem_put(zone->mctx, kd, sizeof(*kd));
23903 }
23904 UNLOCK_ZONE(zone);
23905 return result;
23906 }
23907
23908 /*
23909 * Called from the zone loop's queue after the relevant event is posted by
23910 * dns_zone_setnsec3param().
23911 */
23912 static void
23913 setnsec3param(void *arg) {
23914 struct np3 *npe = (struct np3 *)arg;
23915 dns_zone_t *zone = npe->zone;
23916 bool loadpending;
23917
23918 INSIST(DNS_ZONE_VALID(zone));
23919
23920 ENTER;
23921
23922 LOCK_ZONE(zone);
23923 loadpending = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING);
23924 UNLOCK_ZONE(zone);
23925
23926 /*
23927 * The receive_secure_serial() and setnsec3param() calls are
23928 * loop-serialized for the zone. Make sure there's no processing
23929 * currently running.
23930 */
23931 INSIST(zone->rss_newver == NULL);
23932
23933 bool rescheduled = false;
23934 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
23935 /*
23936 * The zone is not yet fully loaded. Reschedule the event to
23937 * be picked up later. This turns this function into a busy
23938 * wait, but it only happens at startup.
23939 */
23940 if (zone->db == NULL && loadpending) {
23941 rescheduled = true;
23942 isc_async_run(zone->loop, setnsec3param, npe);
23943 }
23944 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
23945 if (rescheduled) {
23946 return;
23947 }
23948
23949 rss_post(npe);
23950
23951 dns_zone_idetach(&zone);
23952 }
23953
23954 static void
23955 salt2text(unsigned char *salt, uint8_t saltlen, unsigned char *text,
23956 unsigned int textlen) {
23957 isc_region_t r;
23958 isc_buffer_t buf;
23959 isc_result_t result;
23960
23961 r.base = salt;
23962 r.length = (unsigned int)saltlen;
23963
23964 isc_buffer_init(&buf, text, textlen);
23965 result = isc_hex_totext(&r, 2, "", &buf);
23966 if (result == ISC_R_SUCCESS) {
23967 text[saltlen * 2] = 0;
23968 } else {
23969 text[0] = 0;
23970 }
23971 }
23972
23973 /*
23974 * Check whether NSEC3 chain addition or removal specified by the private-type
23975 * record passed with the event was already queued (or even fully performed).
23976 * If not, modify the relevant private-type records at the zone apex and call
23977 * resume_addnsec3chain().
23978 */
23979 static void
23980 rss_post(void *arg) {
23981 struct np3 *npe = (struct np3 *)arg;
23982 dns_zone_t *zone = npe->zone;
23983 nsec3param_t *np = &npe->params;
23984 bool commit = false;
23985 isc_result_t result;
23986 dns_dbversion_t *oldver = NULL, *newver = NULL;
23987 dns_db_t *db = NULL;
23988 dns_dbnode_t *node = NULL;
23989 dns_rdataset_t prdataset, nrdataset;
23990 dns_diff_t diff;
23991 dns_update_log_t log = { update_log_cb, NULL };
23992 dns_rdata_t rdata;
23993 bool nseconly;
23994 bool exists = false;
23995
23996 ENTER;
23997
23998 dns_rdataset_init(&prdataset);
23999 dns_rdataset_init(&nrdataset);
24000 dns_diff_init(zone->mctx, &diff);
24001
24002 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
24003 if (zone->db != NULL) {
24004 dns_db_attach(zone->db, &db);
24005 }
24006 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
24007 if (db == NULL) {
24008 goto cleanup;
24009 }
24010
24011 dns_db_currentversion(db, &oldver);
24012 result = dns_db_newversion(db, &newver);
24013 if (result != ISC_R_SUCCESS) {
24014 dnssec_log(zone, ISC_LOG_ERROR,
24015 "setnsec3param:dns_db_newversion -> %s",
24016 isc_result_totext(result));
24017 goto cleanup;
24018 }
24019
24020 CHECK(dns_db_getoriginnode(db, &node));
24021
24022 /*
24023 * Do we need to look up the NSEC3 parameters?
24024 */
24025 if (np->lookup) {
24026 dns_rdata_nsec3param_t param;
24027 dns_rdata_t nrdata = DNS_RDATA_INIT;
24028 dns_rdata_t prdata = DNS_RDATA_INIT;
24029 unsigned char nbuf[DNS_NSEC3PARAM_BUFFERSIZE];
24030 unsigned char saltbuf[255];
24031 isc_buffer_t b;
24032
24033 param.salt = NULL;
24034 result = dns__zone_lookup_nsec3param(zone, &np->rdata, ¶m,
24035 saltbuf, np->resalt);
24036 if (result == ISC_R_SUCCESS) {
24037 /*
24038 * Success because the NSEC3PARAM already exists, but
24039 * function returns void, so goto cleanup.
24040 */
24041 goto cleanup;
24042 }
24043 if (result != DNS_R_NSEC3RESALT && result != ISC_R_NOTFOUND) {
24044 dnssec_log(zone, ISC_LOG_DEBUG(3),
24045 "setnsec3param:lookup nsec3param -> %s",
24046 isc_result_totext(result));
24047 goto cleanup;
24048 }
24049
24050 INSIST(param.salt != NULL);
24051
24052 /* Update NSEC3 parameters. */
24053 np->rdata.hash = param.hash;
24054 np->rdata.flags = param.flags;
24055 np->rdata.iterations = param.iterations;
24056 np->rdata.salt_length = param.salt_length;
24057 np->rdata.salt = param.salt;
24058
24059 isc_buffer_init(&b, nbuf, sizeof(nbuf));
24060 CHECK(dns_rdata_fromstruct(&nrdata, zone->rdclass,
24061 dns_rdatatype_nsec3param, &np->rdata,
24062 &b));
24063 dns_nsec3param_toprivate(&nrdata, &prdata, zone->privatetype,
24064 np->data, sizeof(np->data));
24065 np->length = prdata.length;
24066 np->nsec = false;
24067 }
24068
24069 /*
24070 * Does a private-type record already exist for this chain?
24071 */
24072 result = dns_db_findrdataset(db, node, newver, zone->privatetype,
24073 dns_rdatatype_none, 0, &prdataset, NULL);
24074 if (result == ISC_R_SUCCESS) {
24075 for (result = dns_rdataset_first(&prdataset);
24076 result == ISC_R_SUCCESS;
24077 result = dns_rdataset_next(&prdataset))
24078 {
24079 dns_rdata_init(&rdata);
24080 dns_rdataset_current(&prdataset, &rdata);
24081
24082 if (np->length == rdata.length &&
24083 memcmp(rdata.data, np->data, np->length) == 0)
24084 {
24085 exists = true;
24086 break;
24087 }
24088 }
24089 } else if (result != ISC_R_NOTFOUND) {
24090 INSIST(!dns_rdataset_isassociated(&prdataset));
24091 goto cleanup;
24092 }
24093
24094 /*
24095 * Does the chain already exist?
24096 */
24097 result = dns_db_findrdataset(db, node, newver, dns_rdatatype_nsec3param,
24098 dns_rdatatype_none, 0, &nrdataset, NULL);
24099 if (result == ISC_R_SUCCESS) {
24100 for (result = dns_rdataset_first(&nrdataset);
24101 result == ISC_R_SUCCESS;
24102 result = dns_rdataset_next(&nrdataset))
24103 {
24104 dns_rdata_init(&rdata);
24105 dns_rdataset_current(&nrdataset, &rdata);
24106
24107 if (np->length == ((unsigned int)rdata.length + 1) &&
24108 memcmp(rdata.data, np->data + 1, np->length - 1) ==
24109 0)
24110 {
24111 exists = true;
24112 break;
24113 }
24114 }
24115 } else if (result != ISC_R_NOTFOUND) {
24116 INSIST(!dns_rdataset_isassociated(&nrdataset));
24117 goto cleanup;
24118 }
24119
24120 /*
24121 * We need to remove any existing NSEC3 chains if the supplied NSEC3
24122 * parameters are supposed to replace the current ones or if we are
24123 * switching to NSEC.
24124 */
24125 if (!exists && np->replace && (np->length != 0 || np->nsec)) {
24126 CHECK(dns_nsec3param_deletechains(db, newver, zone, !np->nsec,
24127 &diff));
24128 }
24129
24130 if (!exists && np->length != 0) {
24131 /*
24132 * We're creating an NSEC3 chain. Add the private-type record
24133 * passed in the event handler's argument to the zone apex.
24134 *
24135 * If the zone is not currently capable of supporting an NSEC3
24136 * chain (due to the DNSKEY RRset at the zone apex not existing
24137 * or containing at least one key using an NSEC-only
24138 * algorithm), add the INITIAL flag, so these parameters can be
24139 * used later when NSEC3 becomes available.
24140 */
24141 dns_rdata_init(&rdata);
24142
24143 np->data[2] |= DNS_NSEC3FLAG_CREATE;
24144 result = dns_nsec_nseconly(db, newver, NULL, &nseconly);
24145 if (result == ISC_R_NOTFOUND || nseconly) {
24146 np->data[2] |= DNS_NSEC3FLAG_INITIAL;
24147 }
24148
24149 rdata.length = np->length;
24150 rdata.data = np->data;
24151 rdata.type = zone->privatetype;
24152 rdata.rdclass = zone->rdclass;
24153 CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_ADD,
24154 &zone->origin, 0, &rdata));
24155 }
24156
24157 /*
24158 * If we changed anything in the zone, write changes to journal file
24159 * and set commit to true so that resume_addnsec3chain() will be
24160 * called below in order to kick off adding/removing relevant NSEC3
24161 * records.
24162 */
24163 if (!ISC_LIST_EMPTY(diff.tuples)) {
24164 CHECK(update_soa_serial(zone, db, newver, &diff, zone->mctx,
24165 zone->updatemethod));
24166 result = dns_update_signatures(&log, zone, db, oldver, newver,
24167 &diff,
24168 zone->sigvalidityinterval);
24169 if (result != ISC_R_NOTFOUND) {
24170 CHECK(result);
24171 }
24172 CHECK(zone_journal(zone, &diff, NULL, "setnsec3param"));
24173 commit = true;
24174
24175 LOCK_ZONE(zone);
24176 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
24177 zone_needdump(zone, 30);
24178 UNLOCK_ZONE(zone);
24179 }
24180
24181 cleanup:
24182 if (dns_rdataset_isassociated(&prdataset)) {
24183 dns_rdataset_disassociate(&prdataset);
24184 }
24185 if (dns_rdataset_isassociated(&nrdataset)) {
24186 dns_rdataset_disassociate(&nrdataset);
24187 }
24188 if (node != NULL) {
24189 dns_db_detachnode(db, &node);
24190 }
24191 if (oldver != NULL) {
24192 dns_db_closeversion(db, &oldver, false);
24193 }
24194 if (newver != NULL) {
24195 dns_db_closeversion(db, &newver, commit);
24196 }
24197 if (db != NULL) {
24198 dns_db_detach(&db);
24199 }
24200 if (commit) {
24201 LOCK_ZONE(zone);
24202 resume_addnsec3chain(zone);
24203 UNLOCK_ZONE(zone);
24204 }
24205 dns_diff_clear(&diff);
24206 isc_mem_put(zone->mctx, npe, sizeof(*npe));
24207
24208 INSIST(oldver == NULL);
24209 INSIST(newver == NULL);
24210 }
24211
24212 /*
24213 * Check if zone has NSEC3PARAM (and thus a chain) with the right parameters.
24214 *
24215 * If 'salt' is NULL, a match is found if the salt has the requested length,
24216 * otherwise the NSEC3 salt must match the requested salt value too.
24217 *
24218 * Returns ISC_R_SUCCESS, if a match is found, or an error if no match is
24219 * found, or if the db lookup failed.
24220 */
24221 isc_result_t
24222 dns__zone_lookup_nsec3param(dns_zone_t *zone, dns_rdata_nsec3param_t *lookup,
24223 dns_rdata_nsec3param_t *param,
24224 unsigned char saltbuf[255], bool resalt) {
24225 isc_result_t result = ISC_R_UNEXPECTED;
24226 dns_dbnode_t *node = NULL;
24227 dns_db_t *db = NULL;
24228 dns_dbversion_t *version = NULL;
24229 dns_rdataset_t rdataset;
24230 dns_rdata_nsec3param_t nsec3param;
24231 dns_rdata_t rdata = DNS_RDATA_INIT;
24232
24233 REQUIRE(DNS_ZONE_VALID(zone));
24234
24235 dns_rdataset_init(&rdataset);
24236
24237 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
24238 if (zone->db != NULL) {
24239 dns_db_attach(zone->db, &db);
24240 }
24241 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
24242 if (db == NULL) {
24243 result = ISC_R_FAILURE;
24244 goto setparam;
24245 }
24246
24247 result = dns_db_findnode(db, &zone->origin, false, &node);
24248 if (result != ISC_R_SUCCESS) {
24249 dns_zone_log(zone, ISC_LOG_ERROR,
24250 "dns__zone_lookup_nsec3param:"
24251 "dns_db_findnode -> %s",
24252 isc_result_totext(result));
24253 result = ISC_R_FAILURE;
24254 goto setparam;
24255 }
24256 dns_db_currentversion(db, &version);
24257
24258 result = dns_db_findrdataset(db, node, version,
24259 dns_rdatatype_nsec3param,
24260 dns_rdatatype_none, 0, &rdataset, NULL);
24261 if (result != ISC_R_SUCCESS) {
24262 INSIST(!dns_rdataset_isassociated(&rdataset));
24263 if (result != ISC_R_NOTFOUND) {
24264 dns_zone_log(zone, ISC_LOG_ERROR,
24265 "dns__zone_lookup_nsec3param:"
24266 "dns_db_findrdataset -> %s",
24267 isc_result_totext(result));
24268 }
24269 goto setparam;
24270 }
24271
24272 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
24273 result = dns_rdataset_next(&rdataset))
24274 {
24275 dns_rdataset_current(&rdataset, &rdata);
24276 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
24277 INSIST(result == ISC_R_SUCCESS);
24278 dns_rdata_reset(&rdata);
24279
24280 /* Check parameters. */
24281 if (nsec3param.hash != lookup->hash) {
24282 continue;
24283 }
24284 if (nsec3param.iterations != lookup->iterations) {
24285 continue;
24286 }
24287 if (nsec3param.salt_length != lookup->salt_length) {
24288 continue;
24289 }
24290 if (lookup->salt != NULL) {
24291 if (memcmp(nsec3param.salt, lookup->salt,
24292 lookup->salt_length) != 0)
24293 {
24294 continue;
24295 }
24296 }
24297 /* Found a match. */
24298 result = ISC_R_SUCCESS;
24299 param->hash = nsec3param.hash;
24300 param->flags = nsec3param.flags;
24301 param->iterations = nsec3param.iterations;
24302 param->salt_length = nsec3param.salt_length;
24303 param->salt = nsec3param.salt;
24304 break;
24305 }
24306
24307 if (result == ISC_R_NOMORE) {
24308 result = ISC_R_NOTFOUND;
24309 }
24310
24311 setparam:
24312 if (result != ISC_R_SUCCESS) {
24313 /* Found no match. */
24314 param->hash = lookup->hash;
24315 param->flags = lookup->flags;
24316 param->iterations = lookup->iterations;
24317 param->salt_length = lookup->salt_length;
24318 param->salt = lookup->salt;
24319 }
24320
24321 if (result != ISC_R_NOTFOUND) {
24322 CHECK(result);
24323 }
24324
24325 if (param->salt_length == 0) {
24326 param->salt = (unsigned char *)"-";
24327 } else if (resalt || param->salt == NULL) {
24328 unsigned char *newsalt;
24329 unsigned char salttext[255 * 2 + 1];
24330 do {
24331 /* Generate a new salt. */
24332 result = dns_nsec3_generate_salt(saltbuf,
24333 param->salt_length);
24334 if (result != ISC_R_SUCCESS) {
24335 break;
24336 }
24337 newsalt = saltbuf;
24338 salt2text(newsalt, param->salt_length, salttext,
24339 sizeof(salttext));
24340 dnssec_log(zone, ISC_LOG_INFO, "generated salt: %s",
24341 salttext);
24342 /* Check for salt conflict. */
24343 if (param->salt != NULL &&
24344 memcmp(newsalt, param->salt, param->salt_length) ==
24345 0)
24346 {
24347 result = ISC_R_SUCCESS;
24348 } else {
24349 param->salt = newsalt;
24350 result = DNS_R_NSEC3RESALT;
24351 }
24352 } while (result == ISC_R_SUCCESS);
24353
24354 INSIST(result != ISC_R_SUCCESS);
24355 }
24356
24357 cleanup:
24358 if (dns_rdataset_isassociated(&rdataset)) {
24359 dns_rdataset_disassociate(&rdataset);
24360 }
24361 if (node != NULL) {
24362 dns_db_detachnode(db, &node);
24363 }
24364 if (version != NULL) {
24365 dns_db_closeversion(db, &version, false);
24366 }
24367 if (db != NULL) {
24368 dns_db_detach(&db);
24369 }
24370
24371 return result;
24372 }
24373
24374 /*
24375 * Called when an "rndc signing -nsec3param ..." command is received, or the
24376 * 'dnssec-policy' has changed.
24377 *
24378 * Allocate and prepare an nsec3param_t structure which holds information about
24379 * the NSEC3 changes requested for the zone:
24380 *
24381 * - if NSEC3 is to be disabled ("-nsec3param none"), only set the "nsec"
24382 * field of the structure to true and the "replace" field to the value
24383 * of the "replace" argument, leaving other fields initialized to zeros, to
24384 * signal that the zone should be signed using NSEC instead of NSEC3,
24385 *
24386 * - otherwise, prepare NSEC3PARAM RDATA that will eventually be inserted at
24387 * the zone apex, convert it to a private-type record and store the latter
24388 * in the "data" field of the nsec3param_t structure.
24389 *
24390 * Once the nsec3param_t structure is prepared, post an event to the zone's
24391 * loop which will cause setnsec3param() to be called with the prepared
24392 * structure passed as an argument.
24393 */
24394 isc_result_t
24395 dns_zone_setnsec3param(dns_zone_t *zone, uint8_t hash, uint8_t flags,
24396 uint16_t iter, uint8_t saltlen, unsigned char *salt,
24397 bool replace, bool resalt) {
24398 isc_result_t result = ISC_R_SUCCESS;
24399 dns_rdata_nsec3param_t param, lookup;
24400 dns_rdata_t nrdata = DNS_RDATA_INIT;
24401 dns_rdata_t prdata = DNS_RDATA_INIT;
24402 unsigned char nbuf[DNS_NSEC3PARAM_BUFFERSIZE];
24403 unsigned char saltbuf[255];
24404 struct np3 *npe = NULL;
24405 nsec3param_t *np = NULL;
24406 isc_buffer_t b;
24407 bool do_lookup = false;
24408
24409 REQUIRE(DNS_ZONE_VALID(zone));
24410
24411 LOCK_ZONE(zone);
24412
24413 /*
24414 * First check if the requested NSEC3 parameters are already
24415 * set, if so, no need to set again.
24416 */
24417 if (hash != 0) {
24418 lookup.hash = hash;
24419 lookup.flags = flags;
24420 lookup.iterations = iter;
24421 lookup.salt_length = saltlen;
24422 lookup.salt = salt;
24423 param.salt = NULL;
24424 result = dns__zone_lookup_nsec3param(zone, &lookup, ¶m,
24425 saltbuf, resalt);
24426 if (result == ISC_R_SUCCESS) {
24427 UNLOCK_ZONE(zone);
24428 return ISC_R_SUCCESS;
24429 }
24430 /*
24431 * Schedule lookup if lookup above failed (may happen if
24432 * zone db is NULL for example).
24433 */
24434 do_lookup = (param.salt == NULL) ? true : false;
24435 }
24436
24437 npe = isc_mem_get(zone->mctx, sizeof(*npe));
24438 *npe = (struct np3){
24439 .link = ISC_LINK_INITIALIZER,
24440 };
24441
24442 np = &npe->params;
24443 *np = (struct nsec3param){
24444 .replace = replace,
24445 .resalt = resalt,
24446 .lookup = do_lookup,
24447 };
24448
24449 if (hash == 0) {
24450 np->nsec = true;
24451 dnssec_log(zone, ISC_LOG_DEBUG(3), "setnsec3param:nsec");
24452 } else {
24453 param.common.rdclass = zone->rdclass;
24454 param.common.rdtype = dns_rdatatype_nsec3param;
24455 ISC_LINK_INIT(¶m.common, link);
24456 param.mctx = NULL;
24457 /*
24458 * nsec3 specific param set in
24459 * dns__zone_lookup_nsec3param()
24460 */
24461 isc_buffer_init(&b, nbuf, sizeof(nbuf));
24462
24463 if (param.salt != NULL) {
24464 CHECK(dns_rdata_fromstruct(&nrdata, zone->rdclass,
24465 dns_rdatatype_nsec3param,
24466 ¶m, &b));
24467 dns_nsec3param_toprivate(&nrdata, &prdata,
24468 zone->privatetype, np->data,
24469 sizeof(np->data));
24470 np->length = prdata.length;
24471 }
24472
24473 np->rdata = param;
24474
24475 if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
24476 unsigned char salttext[255 * 2 + 1];
24477 if (param.salt != NULL) {
24478 salt2text(param.salt, param.salt_length,
24479 salttext, sizeof(salttext));
24480 }
24481 dnssec_log(zone, ISC_LOG_DEBUG(3),
24482 "setnsec3param:nsec3 %u %u %u %u:%s",
24483 param.hash, param.flags, param.iterations,
24484 param.salt_length,
24485 param.salt == NULL ? "unknown"
24486 : (char *)salttext);
24487 }
24488 }
24489
24490 /*
24491 * setnsec3param() will silently return early if the zone does
24492 * not yet have a database. Prevent that by queueing the event
24493 * up if zone->db is NULL. All events queued here are
24494 * subsequently processed by receive_secure_db() if it ever gets
24495 * called or simply freed by zone_free() otherwise.
24496 */
24497
24498 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
24499 if (zone->db != NULL) {
24500 zone_iattach(zone, &npe->zone);
24501 isc_async_run(zone->loop, setnsec3param, npe);
24502 } else {
24503 ISC_LIST_APPEND(zone->setnsec3param_queue, npe, link);
24504 }
24505 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
24506
24507 result = ISC_R_SUCCESS;
24508
24509 cleanup:
24510 UNLOCK_ZONE(zone);
24511 return result;
24512 }
24513
24514 isc_result_t
24515 dns_zone_getloadtime(dns_zone_t *zone, isc_time_t *loadtime) {
24516 REQUIRE(DNS_ZONE_VALID(zone));
24517 REQUIRE(loadtime != NULL);
24518
24519 LOCK_ZONE(zone);
24520 *loadtime = zone->loadtime;
24521 UNLOCK_ZONE(zone);
24522 return ISC_R_SUCCESS;
24523 }
24524
24525 isc_result_t
24526 dns_zone_getexpiretime(dns_zone_t *zone, isc_time_t *expiretime) {
24527 REQUIRE(DNS_ZONE_VALID(zone));
24528 REQUIRE(expiretime != NULL);
24529
24530 LOCK_ZONE(zone);
24531 *expiretime = zone->expiretime;
24532 UNLOCK_ZONE(zone);
24533 return ISC_R_SUCCESS;
24534 }
24535
24536 isc_result_t
24537 dns_zone_getrefreshtime(dns_zone_t *zone, isc_time_t *refreshtime) {
24538 REQUIRE(DNS_ZONE_VALID(zone));
24539 REQUIRE(refreshtime != NULL);
24540
24541 LOCK_ZONE(zone);
24542 *refreshtime = zone->refreshtime;
24543 UNLOCK_ZONE(zone);
24544 return ISC_R_SUCCESS;
24545 }
24546
24547 isc_result_t
24548 dns_zone_getrefreshkeytime(dns_zone_t *zone, isc_time_t *refreshkeytime) {
24549 REQUIRE(DNS_ZONE_VALID(zone));
24550 REQUIRE(refreshkeytime != NULL);
24551
24552 LOCK_ZONE(zone);
24553 *refreshkeytime = zone->refreshkeytime;
24554 UNLOCK_ZONE(zone);
24555 return ISC_R_SUCCESS;
24556 }
24557
24558 unsigned int
24559 dns_zone_getincludes(dns_zone_t *zone, char ***includesp) {
24560 dns_include_t *include;
24561 char **array = NULL;
24562 unsigned int n = 0;
24563
24564 REQUIRE(DNS_ZONE_VALID(zone));
24565 REQUIRE(includesp != NULL && *includesp == NULL);
24566
24567 LOCK_ZONE(zone);
24568 if (zone->nincludes == 0) {
24569 goto done;
24570 }
24571
24572 array = isc_mem_allocate(zone->mctx, sizeof(char *) * zone->nincludes);
24573 for (include = ISC_LIST_HEAD(zone->includes); include != NULL;
24574 include = ISC_LIST_NEXT(include, link))
24575 {
24576 INSIST(n < zone->nincludes);
24577 array[n++] = isc_mem_strdup(zone->mctx, include->name);
24578 }
24579 INSIST(n == zone->nincludes);
24580 *includesp = array;
24581
24582 done:
24583 UNLOCK_ZONE(zone);
24584 return n;
24585 }
24586
24587 void
24588 dns_zone_setstatlevel(dns_zone_t *zone, dns_zonestat_level_t level) {
24589 REQUIRE(DNS_ZONE_VALID(zone));
24590
24591 zone->statlevel = level;
24592 }
24593
24594 dns_zonestat_level_t
24595 dns_zone_getstatlevel(dns_zone_t *zone) {
24596 REQUIRE(DNS_ZONE_VALID(zone));
24597
24598 return zone->statlevel;
24599 }
24600
24601 static void
24602 setserial(void *arg) {
24603 uint32_t oldserial, desired;
24604 bool commit = false;
24605 isc_result_t result;
24606 dns_dbversion_t *oldver = NULL, *newver = NULL;
24607 dns_db_t *db = NULL;
24608 dns_diff_t diff;
24609 struct setserial *sse = (struct setserial *)arg;
24610 dns_zone_t *zone = sse->zone;
24611 dns_update_log_t log = { update_log_cb, NULL };
24612 dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
24613
24614 INSIST(DNS_ZONE_VALID(zone));
24615
24616 ENTER;
24617
24618 if (zone->update_disabled) {
24619 goto disabled;
24620 }
24621
24622 desired = sse->serial;
24623
24624 dns_diff_init(zone->mctx, &diff);
24625
24626 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
24627 if (zone->db != NULL) {
24628 dns_db_attach(zone->db, &db);
24629 }
24630 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
24631 if (db == NULL) {
24632 goto cleanup;
24633 }
24634
24635 dns_db_currentversion(db, &oldver);
24636 result = dns_db_newversion(db, &newver);
24637 if (result != ISC_R_SUCCESS) {
24638 dns_zone_log(zone, ISC_LOG_ERROR,
24639 "setserial:dns_db_newversion -> %s",
24640 isc_result_totext(result));
24641 goto cleanup;
24642 }
24643
24644 CHECK(dns_db_createsoatuple(db, oldver, diff.mctx, DNS_DIFFOP_DEL,
24645 &oldtuple));
24646 CHECK(dns_difftuple_copy(oldtuple, &newtuple));
24647 newtuple->op = DNS_DIFFOP_ADD;
24648
24649 oldserial = dns_soa_getserial(&oldtuple->rdata);
24650 if (desired == 0U) {
24651 desired = 1;
24652 }
24653 if (!isc_serial_gt(desired, oldserial)) {
24654 if (desired != oldserial) {
24655 dns_zone_log(zone, ISC_LOG_INFO,
24656 "setserial: desired serial (%u) "
24657 "out of range (%u-%u)",
24658 desired, oldserial + 1,
24659 oldserial + 0x7fffffff);
24660 }
24661 goto cleanup;
24662 }
24663
24664 dns_soa_setserial(desired, &newtuple->rdata);
24665 CHECK(do_one_tuple(&oldtuple, db, newver, &diff));
24666 CHECK(do_one_tuple(&newtuple, db, newver, &diff));
24667 result = dns_update_signatures(&log, zone, db, oldver, newver, &diff,
24668 zone->sigvalidityinterval);
24669 if (result != ISC_R_NOTFOUND) {
24670 CHECK(result);
24671 }
24672
24673 /* Write changes to journal file. */
24674 CHECK(zone_journal(zone, &diff, NULL, "setserial"));
24675 commit = true;
24676
24677 LOCK_ZONE(zone);
24678 zone_needdump(zone, 30);
24679 UNLOCK_ZONE(zone);
24680
24681 cleanup:
24682 if (oldtuple != NULL) {
24683 dns_difftuple_free(&oldtuple);
24684 }
24685 if (newtuple != NULL) {
24686 dns_difftuple_free(&newtuple);
24687 }
24688 if (oldver != NULL) {
24689 dns_db_closeversion(db, &oldver, false);
24690 }
24691 if (newver != NULL) {
24692 dns_db_closeversion(db, &newver, commit);
24693 }
24694 if (db != NULL) {
24695 dns_db_detach(&db);
24696 }
24697 dns_diff_clear(&diff);
24698
24699 disabled:
24700 isc_mem_put(zone->mctx, sse, sizeof(*sse));
24701 dns_zone_idetach(&zone);
24702
24703 INSIST(oldver == NULL);
24704 INSIST(newver == NULL);
24705 }
24706
24707 isc_result_t
24708 dns_zone_setserial(dns_zone_t *zone, uint32_t serial) {
24709 isc_result_t result = ISC_R_SUCCESS;
24710 struct setserial *sse = NULL;
24711
24712 REQUIRE(DNS_ZONE_VALID(zone));
24713
24714 LOCK_ZONE(zone);
24715
24716 if (!inline_secure(zone)) {
24717 if (!dns_zone_isdynamic(zone, true)) {
24718 CHECK(DNS_R_NOTDYNAMIC);
24719 }
24720 }
24721
24722 if (zone->update_disabled) {
24723 CHECK(DNS_R_FROZEN);
24724 }
24725
24726 sse = isc_mem_get(zone->mctx, sizeof(*sse));
24727 *sse = (struct setserial){ .serial = serial };
24728 zone_iattach(zone, &sse->zone);
24729 isc_async_run(zone->loop, setserial, sse);
24730
24731 cleanup:
24732 UNLOCK_ZONE(zone);
24733 return result;
24734 }
24735
24736 isc_stats_t *
24737 dns_zone_getgluecachestats(dns_zone_t *zone) {
24738 REQUIRE(DNS_ZONE_VALID(zone));
24739
24740 return zone->gluecachestats;
24741 }
24742
24743 bool
24744 dns_zone_isloaded(dns_zone_t *zone) {
24745 REQUIRE(DNS_ZONE_VALID(zone));
24746
24747 return DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED);
24748 }
24749
24750 isc_result_t
24751 dns_zone_verifydb(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver) {
24752 dns_dbversion_t *version = NULL;
24753 dns_keytable_t *secroots = NULL;
24754 isc_result_t result;
24755 dns_name_t *origin;
24756
24757 REQUIRE(DNS_ZONE_VALID(zone));
24758 REQUIRE(db != NULL);
24759
24760 ENTER;
24761
24762 if (dns_zone_gettype(zone) != dns_zone_mirror) {
24763 return ISC_R_SUCCESS;
24764 }
24765
24766 if (ver == NULL) {
24767 dns_db_currentversion(db, &version);
24768 } else {
24769 version = ver;
24770 }
24771
24772 if (zone->view != NULL) {
24773 result = dns_view_getsecroots(zone->view, &secroots);
24774 CHECK(result);
24775 }
24776
24777 origin = dns_db_origin(db);
24778 result = dns_zoneverify_dnssec(zone, db, version, origin, secroots,
24779 zone->mctx, true, false, dnssec_report);
24780
24781 cleanup:
24782 if (secroots != NULL) {
24783 dns_keytable_detach(&secroots);
24784 }
24785
24786 if (ver == NULL) {
24787 dns_db_closeversion(db, &version, false);
24788 }
24789
24790 if (result != ISC_R_SUCCESS) {
24791 dnssec_log(zone, ISC_LOG_ERROR, "zone verification failed: %s",
24792 isc_result_totext(result));
24793 result = DNS_R_VERIFYFAILURE;
24794 }
24795
24796 return result;
24797 }
24798
24799 static dns_ttl_t
24800 zone_nsecttl(dns_zone_t *zone) {
24801 REQUIRE(DNS_ZONE_VALID(zone));
24802
24803 return ISC_MIN(zone->minimum, zone->soattl);
24804 }
24805
24806 void
24807 dns_zonemgr_set_tlsctx_cache(dns_zonemgr_t *zmgr,
24808 isc_tlsctx_cache_t *tlsctx_cache) {
24809 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
24810 REQUIRE(tlsctx_cache != NULL);
24811
24812 RWLOCK(&zmgr->tlsctx_cache_rwlock, isc_rwlocktype_write);
24813
24814 if (zmgr->tlsctx_cache != NULL) {
24815 isc_tlsctx_cache_detach(&zmgr->tlsctx_cache);
24816 }
24817
24818 isc_tlsctx_cache_attach(tlsctx_cache, &zmgr->tlsctx_cache);
24819
24820 RWUNLOCK(&zmgr->tlsctx_cache_rwlock, isc_rwlocktype_write);
24821 }
24822
24823 static void
24824 zmgr_tlsctx_attach(dns_zonemgr_t *zmgr, isc_tlsctx_cache_t **ptlsctx_cache) {
24825 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
24826 REQUIRE(ptlsctx_cache != NULL && *ptlsctx_cache == NULL);
24827
24828 RWLOCK(&zmgr->tlsctx_cache_rwlock, isc_rwlocktype_read);
24829
24830 INSIST(zmgr->tlsctx_cache != NULL);
24831 isc_tlsctx_cache_attach(zmgr->tlsctx_cache, ptlsctx_cache);
24832
24833 RWUNLOCK(&zmgr->tlsctx_cache_rwlock, isc_rwlocktype_read);
24834 }
24835
24836 isc_mem_t *
24837 dns_zone_getmem(dns_zone_t *zone) {
24838 return zone->mctx;
24839 }
24840
24841 unsigned int
24842 dns_zone_gettid(dns_zone_t *zone) {
24843 return zone->tid;
24844 }
24845
24846 isc_loop_t *
24847 dns_zone_getloop(dns_zone_t *zone) {
24848 return zone->loop;
24849 }
24850
24851 isc_result_t
24852 dns_zone_makedb(dns_zone_t *zone, dns_db_t **dbp) {
24853 REQUIRE(DNS_ZONE_VALID(zone));
24854 REQUIRE(dbp != NULL && *dbp == NULL);
24855
24856 dns_db_t *db = NULL;
24857
24858 isc_result_t result = dns_db_create(
24859 zone->mctx, zone->db_argv[0], &zone->origin,
24860 (zone->type == dns_zone_stub) ? dns_dbtype_stub
24861 : dns_dbtype_zone,
24862 zone->rdclass, zone->db_argc - 1, zone->db_argv + 1, &db);
24863 if (result != ISC_R_SUCCESS) {
24864 return result;
24865 }
24866
24867 switch (zone->type) {
24868 case dns_zone_primary:
24869 case dns_zone_secondary:
24870 case dns_zone_mirror:
24871 result = dns_db_setgluecachestats(db, zone->gluecachestats);
24872 if (result == ISC_R_NOTIMPLEMENTED) {
24873 result = ISC_R_SUCCESS;
24874 }
24875 if (result != ISC_R_SUCCESS) {
24876 dns_db_detach(&db);
24877 return result;
24878 }
24879 break;
24880 default:
24881 break;
24882 }
24883
24884 dns_db_setloop(db, zone->loop);
24885 dns_db_setmaxrrperset(db, zone->maxrrperset);
24886 dns_db_setmaxtypepername(db, zone->maxtypepername);
24887
24888 *dbp = db;
24889
24890 return ISC_R_SUCCESS;
24891 }
24892
24893 isc_result_t
24894 dns_zone_import_skr(dns_zone_t *zone, const char *file) {
24895 dns_skr_t *skr = NULL;
24896 isc_result_t result;
24897
24898 REQUIRE(DNS_ZONE_VALID(zone));
24899 REQUIRE(zone->kasp != NULL);
24900 REQUIRE(file != NULL);
24901
24902 dns_skr_create(zone->mctx, file, &zone->origin, zone->rdclass, &skr);
24903
24904 CHECK(dns_skr_read(zone->mctx, file, &zone->origin, zone->rdclass,
24905 dns_kasp_dnskeyttl(zone->kasp), &skr));
24906
24907 dns_zone_setskr(zone, skr);
24908 dnssec_log(zone, ISC_LOG_DEBUG(1), "imported skr file %s", file);
24909
24910 cleanup:
24911 dns_skr_detach(&skr);
24912
24913 return result;
24914 }
24915