zone.c revision 1.16.2.2 1 /* $NetBSD: zone.c,v 1.16.2.2 2024/02/25 15:46:54 martin Exp $ */
2
3 /*
4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5 *
6 * SPDX-License-Identifier: MPL-2.0
7 *
8 * This Source Code Form is subject to the terms of the Mozilla Public
9 * License, v. 2.0. If a copy of the MPL was not distributed with this
10 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11 *
12 * See the COPYRIGHT file distributed with this work for additional
13 * information regarding copyright ownership.
14 */
15
16 /*! \file */
17
18 #include <errno.h>
19 #include <inttypes.h>
20 #include <stdbool.h>
21
22 #include <isc/atomic.h>
23 #include <isc/file.h>
24 #include <isc/hex.h>
25 #include <isc/md.h>
26 #include <isc/mutex.h>
27 #include <isc/pool.h>
28 #include <isc/print.h>
29 #include <isc/random.h>
30 #include <isc/ratelimiter.h>
31 #include <isc/refcount.h>
32 #include <isc/result.h>
33 #include <isc/rwlock.h>
34 #include <isc/serial.h>
35 #include <isc/stats.h>
36 #include <isc/stdtime.h>
37 #include <isc/strerr.h>
38 #include <isc/string.h>
39 #include <isc/taskpool.h>
40 #include <isc/thread.h>
41 #include <isc/timer.h>
42 #include <isc/tls.h>
43 #include <isc/util.h>
44
45 #include <dns/acl.h>
46 #include <dns/adb.h>
47 #include <dns/callbacks.h>
48 #include <dns/catz.h>
49 #include <dns/db.h>
50 #include <dns/dbiterator.h>
51 #include <dns/dlz.h>
52 #include <dns/dnssec.h>
53 #include <dns/events.h>
54 #include <dns/journal.h>
55 #include <dns/kasp.h>
56 #include <dns/keydata.h>
57 #include <dns/keymgr.h>
58 #include <dns/keytable.h>
59 #include <dns/keyvalues.h>
60 #include <dns/log.h>
61 #include <dns/master.h>
62 #include <dns/masterdump.h>
63 #include <dns/message.h>
64 #include <dns/name.h>
65 #include <dns/nsec.h>
66 #include <dns/nsec3.h>
67 #include <dns/opcode.h>
68 #include <dns/peer.h>
69 #include <dns/private.h>
70 #include <dns/rcode.h>
71 #include <dns/rdata.h>
72 #include <dns/rdataclass.h>
73 #include <dns/rdatalist.h>
74 #include <dns/rdataset.h>
75 #include <dns/rdatasetiter.h>
76 #include <dns/rdatastruct.h>
77 #include <dns/rdatatype.h>
78 #include <dns/request.h>
79 #include <dns/resolver.h>
80 #include <dns/rriterator.h>
81 #include <dns/soa.h>
82 #include <dns/ssu.h>
83 #include <dns/stats.h>
84 #include <dns/time.h>
85 #include <dns/tsig.h>
86 #include <dns/update.h>
87 #include <dns/xfrin.h>
88 #include <dns/zone.h>
89 #include <dns/zoneverify.h>
90 #include <dns/zt.h>
91
92 #include <dst/dst.h>
93
94 #include "zone_p.h"
95
96 #define ZONE_MAGIC ISC_MAGIC('Z', 'O', 'N', 'E')
97 #define DNS_ZONE_VALID(zone) ISC_MAGIC_VALID(zone, ZONE_MAGIC)
98
99 #define NOTIFY_MAGIC ISC_MAGIC('N', 't', 'f', 'y')
100 #define DNS_NOTIFY_VALID(notify) ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)
101
102 #define CHECKDS_MAGIC ISC_MAGIC('C', 'h', 'D', 'S')
103 #define DNS_CHECKDS_VALID(checkds) ISC_MAGIC_VALID(checkds, CHECKDS_MAGIC)
104
105 #define STUB_MAGIC ISC_MAGIC('S', 't', 'u', 'b')
106 #define DNS_STUB_VALID(stub) ISC_MAGIC_VALID(stub, STUB_MAGIC)
107
108 #define ZONEMGR_MAGIC ISC_MAGIC('Z', 'm', 'g', 'r')
109 #define DNS_ZONEMGR_VALID(stub) ISC_MAGIC_VALID(stub, ZONEMGR_MAGIC)
110
111 #define LOAD_MAGIC ISC_MAGIC('L', 'o', 'a', 'd')
112 #define DNS_LOAD_VALID(load) ISC_MAGIC_VALID(load, LOAD_MAGIC)
113
114 #define FORWARD_MAGIC ISC_MAGIC('F', 'o', 'r', 'w')
115 #define DNS_FORWARD_VALID(load) ISC_MAGIC_VALID(load, FORWARD_MAGIC)
116
117 #define IO_MAGIC ISC_MAGIC('Z', 'm', 'I', 'O')
118 #define DNS_IO_VALID(load) ISC_MAGIC_VALID(load, IO_MAGIC)
119
120 #define KEYMGMT_MAGIC ISC_MAGIC('M', 'g', 'm', 't')
121 #define DNS_KEYMGMT_VALID(load) ISC_MAGIC_VALID(load, KEYMGMT_MAGIC)
122
123 #define KEYFILEIO_MAGIC ISC_MAGIC('K', 'y', 'I', 'O')
124 #define DNS_KEYFILEIO_VALID(kfio) ISC_MAGIC_VALID(kfio, KEYFILEIO_MAGIC)
125
126 /*%
127 * Ensure 'a' is at least 'min' but not more than 'max'.
128 */
129 #define RANGE(a, min, max) (((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max)))
130
131 #define NSEC3REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
132
133 /*%
134 * Key flags
135 */
136 #define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
137 #define KSK(x) ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
138 #define ID(x) dst_key_id(x)
139 #define ALG(x) dst_key_alg(x)
140
141 /*%
142 * KASP flags
143 */
144 #define KASP_LOCK(k) \
145 if ((k) != NULL) { \
146 LOCK((&((k)->lock))); \
147 }
148
149 #define KASP_UNLOCK(k) \
150 if ((k) != NULL) { \
151 UNLOCK((&((k)->lock))); \
152 }
153
154 /*
155 * Default values.
156 */
157 #define DNS_DEFAULT_IDLEIN 3600 /*%< 1 hour */
158 #define DNS_DEFAULT_IDLEOUT 3600 /*%< 1 hour */
159 #define MAX_XFER_TIME (2 * 3600) /*%< Documented default is 2 hours */
160 #define RESIGN_DELAY 3600 /*%< 1 hour */
161
162 #ifndef DNS_MAX_EXPIRE
163 #define DNS_MAX_EXPIRE 14515200 /*%< 24 weeks */
164 #endif /* ifndef DNS_MAX_EXPIRE */
165
166 #ifndef DNS_DUMP_DELAY
167 #define DNS_DUMP_DELAY 900 /*%< 15 minutes */
168 #endif /* ifndef DNS_DUMP_DELAY */
169
170 typedef struct dns_notify dns_notify_t;
171 typedef struct dns_checkds dns_checkds_t;
172 typedef struct dns_stub dns_stub_t;
173 typedef struct dns_load dns_load_t;
174 typedef struct dns_forward dns_forward_t;
175 typedef ISC_LIST(dns_forward_t) dns_forwardlist_t;
176 typedef struct dns_io dns_io_t;
177 typedef ISC_LIST(dns_io_t) dns_iolist_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_keyfetch dns_keyfetch_t;
184 typedef struct dns_asyncload dns_asyncload_t;
185 typedef struct dns_include dns_include_t;
186
187 #define DNS_ZONE_CHECKLOCK
188 #ifdef DNS_ZONE_CHECKLOCK
189 #define LOCK_ZONE(z) \
190 do { \
191 LOCK(&(z)->lock); \
192 INSIST(!(z)->locked); \
193 (z)->locked = true; \
194 } while (0)
195 #define UNLOCK_ZONE(z) \
196 do { \
197 (z)->locked = false; \
198 UNLOCK(&(z)->lock); \
199 } while (0)
200 #define LOCKED_ZONE(z) ((z)->locked)
201 #define TRYLOCK_ZONE(result, z) \
202 do { \
203 result = isc_mutex_trylock(&(z)->lock); \
204 if (result == ISC_R_SUCCESS) { \
205 INSIST(!(z)->locked); \
206 (z)->locked = true; \
207 } \
208 } while (0)
209 #else /* ifdef DNS_ZONE_CHECKLOCK */
210 #define LOCK_ZONE(z) LOCK(&(z)->lock)
211 #define UNLOCK_ZONE(z) UNLOCK(&(z)->lock)
212 #define LOCKED_ZONE(z) true
213 #define TRYLOCK_ZONE(result, z) \
214 do { \
215 result = isc_mutex_trylock(&(z)->lock); \
216 } while (0)
217 #endif /* ifdef DNS_ZONE_CHECKLOCK */
218
219 #define ZONEDB_INITLOCK(l) isc_rwlock_init((l), 0, 0)
220 #define ZONEDB_DESTROYLOCK(l) isc_rwlock_destroy(l)
221 #define ZONEDB_LOCK(l, t) RWLOCK((l), (t))
222 #define ZONEDB_UNLOCK(l, t) RWUNLOCK((l), (t))
223
224 #ifdef ENABLE_AFL
225 extern bool dns_fuzzing_resolver;
226 #endif /* ifdef ENABLE_AFL */
227
228 /*%
229 * Hold key file IO locks.
230 */
231 typedef struct dns_keyfileio {
232 unsigned int magic;
233 struct dns_keyfileio *next;
234 uint32_t hashval;
235 dns_fixedname_t fname;
236 dns_name_t *name;
237 isc_refcount_t references;
238 isc_mutex_t lock;
239 } dns_keyfileio_t;
240
241 struct dns_keymgmt {
242 unsigned int magic;
243 isc_rwlock_t lock;
244 isc_mem_t *mctx;
245
246 dns_keyfileio_t **table;
247
248 atomic_uint_fast32_t count;
249
250 uint32_t bits;
251 };
252
253 struct dns_zone {
254 /* Unlocked */
255 unsigned int magic;
256 isc_mutex_t lock;
257 #ifdef DNS_ZONE_CHECKLOCK
258 bool locked;
259 #endif /* ifdef DNS_ZONE_CHECKLOCK */
260 isc_mem_t *mctx;
261 isc_refcount_t erefs;
262
263 isc_rwlock_t dblock;
264 dns_db_t *db; /* Locked by dblock */
265
266 /* Locked */
267 dns_zonemgr_t *zmgr;
268 ISC_LINK(dns_zone_t) link; /* Used by zmgr. */
269 isc_timer_t *timer;
270 isc_refcount_t irefs;
271 dns_name_t origin;
272 char *masterfile;
273 const FILE *stream; /* loading from a stream? */
274 ISC_LIST(dns_include_t) includes; /* Include files */
275 ISC_LIST(dns_include_t) newincludes; /* Loading */
276 unsigned int nincludes;
277 dns_masterformat_t masterformat;
278 const dns_master_style_t *masterstyle;
279 char *journal;
280 int32_t journalsize;
281 dns_rdataclass_t rdclass;
282 dns_zonetype_t type;
283 #ifdef __NetBSD__
284 atomic_uint_fast32_t flags;
285 atomic_uint_fast32_t options;
286 #else
287 atomic_uint_fast64_t flags;
288 atomic_uint_fast64_t options;
289 #endif
290 unsigned int db_argc;
291 char **db_argv;
292 isc_time_t expiretime;
293 isc_time_t refreshtime;
294 isc_time_t dumptime;
295 isc_time_t loadtime;
296 isc_time_t notifytime;
297 isc_time_t resigntime;
298 isc_time_t keywarntime;
299 isc_time_t signingtime;
300 isc_time_t nsec3chaintime;
301 isc_time_t refreshkeytime;
302 uint32_t refreshkeyinterval;
303 uint32_t refreshkeycount;
304 uint32_t refresh;
305 uint32_t retry;
306 uint32_t expire;
307 uint32_t minimum;
308 isc_stdtime_t key_expiry;
309 isc_stdtime_t log_key_expired_timer;
310 char *keydirectory;
311 dns_keyfileio_t *kfio;
312
313 uint32_t maxrefresh;
314 uint32_t minrefresh;
315 uint32_t maxretry;
316 uint32_t minretry;
317
318 uint32_t maxrecords;
319
320 isc_sockaddr_t *primaries;
321 dns_name_t **primarykeynames;
322 dns_name_t **primarytlsnames;
323 bool *primariesok;
324 unsigned int primariescnt;
325 unsigned int curprimary;
326 isc_sockaddr_t primaryaddr;
327
328 isc_sockaddr_t *parentals;
329 dns_name_t **parentalkeynames;
330 dns_name_t **parentaltlsnames;
331 dns_dnsseckeylist_t checkds_ok;
332 unsigned int parentalscnt;
333 isc_sockaddr_t parentaladdr;
334
335 dns_notifytype_t notifytype;
336 isc_sockaddr_t *notify;
337 dns_name_t **notifykeynames;
338 dns_name_t **notifytlsnames;
339 unsigned int notifycnt;
340 isc_sockaddr_t notifyfrom;
341 isc_task_t *task;
342 isc_task_t *loadtask;
343 isc_sockaddr_t notifysrc4;
344 isc_sockaddr_t notifysrc6;
345 isc_sockaddr_t parentalsrc4;
346 isc_sockaddr_t parentalsrc6;
347 isc_sockaddr_t xfrsource4;
348 isc_sockaddr_t xfrsource6;
349 isc_sockaddr_t altxfrsource4;
350 isc_sockaddr_t altxfrsource6;
351 isc_sockaddr_t sourceaddr;
352 dns_xfrin_ctx_t *xfr; /* task locked */
353 dns_tsigkey_t *tsigkey; /* key used for xfr */
354 dns_transport_t *transport; /* transport used for xfr */
355 /* Access Control Lists */
356 dns_acl_t *update_acl;
357 dns_acl_t *forward_acl;
358 dns_acl_t *notify_acl;
359 dns_acl_t *query_acl;
360 dns_acl_t *queryon_acl;
361 dns_acl_t *xfr_acl;
362 bool update_disabled;
363 bool zero_no_soa_ttl;
364 dns_severity_t check_names;
365 ISC_LIST(dns_notify_t) notifies;
366 ISC_LIST(dns_checkds_t) checkds_requests;
367 dns_request_t *request;
368 dns_loadctx_t *lctx;
369 dns_io_t *readio;
370 dns_dumpctx_t *dctx;
371 dns_io_t *writeio;
372 uint32_t maxxfrin;
373 uint32_t maxxfrout;
374 uint32_t idlein;
375 uint32_t idleout;
376 isc_event_t ctlevent;
377 dns_ssutable_t *ssutable;
378 uint32_t sigvalidityinterval;
379 uint32_t keyvalidityinterval;
380 uint32_t sigresigninginterval;
381 dns_view_t *view;
382 dns_view_t *prev_view;
383 dns_kasp_t *kasp;
384 dns_checkmxfunc_t checkmx;
385 dns_checksrvfunc_t checksrv;
386 dns_checknsfunc_t checkns;
387 /*%
388 * Zones in certain states such as "waiting for zone transfer"
389 * or "zone transfer in progress" are kept on per-state linked lists
390 * in the zone manager using the 'statelink' field. The 'statelist'
391 * field points at the list the zone is currently on. It the zone
392 * is not on any such list, statelist is NULL.
393 */
394 ISC_LINK(dns_zone_t) statelink;
395 dns_zonelist_t *statelist;
396 /*%
397 * Statistics counters about zone management.
398 */
399 isc_stats_t *stats;
400 /*%
401 * Optional per-zone statistics counters. Counted outside of this
402 * module.
403 */
404 dns_zonestat_level_t statlevel;
405 bool requeststats_on;
406 isc_stats_t *requeststats;
407 dns_stats_t *rcvquerystats;
408 dns_stats_t *dnssecsignstats;
409 uint32_t notifydelay;
410 dns_isselffunc_t isself;
411 void *isselfarg;
412
413 char *strnamerd;
414 char *strname;
415 char *strrdclass;
416 char *strviewname;
417
418 /*%
419 * Serial number for deferred journal compaction.
420 */
421 uint32_t compact_serial;
422 /*%
423 * Keys that are signing the zone for the first time.
424 */
425 dns_signinglist_t signing;
426 dns_nsec3chainlist_t nsec3chain;
427 /*%
428 * List of outstanding NSEC3PARAM change requests.
429 */
430 isc_eventlist_t setnsec3param_queue;
431 /*%
432 * Signing / re-signing quantum stopping parameters.
433 */
434 uint32_t signatures;
435 uint32_t nodes;
436 dns_rdatatype_t privatetype;
437
438 /*%
439 * Autosigning/key-maintenance options
440 */
441 #ifdef __NetBSD__
442 atomic_uint_fast32_t keyopts;
443 #else
444 atomic_uint_fast64_t keyopts;
445 #endif
446
447 /*%
448 * True if added by "rndc addzone"
449 */
450 bool added;
451
452 /*%
453 * True if added by automatically by named.
454 */
455 bool automatic;
456
457 /*%
458 * response policy data to be relayed to the database
459 */
460 dns_rpz_zones_t *rpzs;
461 dns_rpz_num_t rpz_num;
462
463 /*%
464 * catalog zone data
465 */
466 dns_catz_zones_t *catzs;
467
468 /*%
469 * parent catalog zone
470 */
471 dns_catz_zone_t *parentcatz;
472
473 /*%
474 * Serial number update method.
475 */
476 dns_updatemethod_t updatemethod;
477
478 /*%
479 * whether ixfr is requested
480 */
481 bool requestixfr;
482 uint32_t ixfr_ratio;
483
484 /*%
485 * whether EDNS EXPIRE is requested
486 */
487 bool requestexpire;
488
489 /*%
490 * Outstanding forwarded UPDATE requests.
491 */
492 dns_forwardlist_t forwards;
493
494 dns_zone_t *raw;
495 dns_zone_t *secure;
496
497 bool sourceserialset;
498 uint32_t sourceserial;
499
500 /*%
501 * soa and maximum zone ttl
502 */
503 dns_ttl_t soattl;
504 dns_ttl_t maxttl;
505
506 /*
507 * Inline zone signing state.
508 */
509 dns_diff_t rss_diff;
510 isc_eventlist_t rss_events;
511 isc_eventlist_t rss_post;
512 dns_dbversion_t *rss_newver;
513 dns_dbversion_t *rss_oldver;
514 dns_db_t *rss_db;
515 dns_zone_t *rss_raw;
516 isc_event_t *rss_event;
517 dns_update_state_t *rss_state;
518
519 isc_stats_t *gluecachestats;
520 };
521
522 #define zonediff_init(z, d) \
523 do { \
524 dns__zonediff_t *_z = (z); \
525 (_z)->diff = (d); \
526 (_z)->offline = false; \
527 } while (0)
528
529 #define DNS_ZONE_FLAG(z, f) ((atomic_load_relaxed(&(z)->flags) & (f)) != 0)
530 #define DNS_ZONE_SETFLAG(z, f) atomic_fetch_or(&(z)->flags, (f))
531 #define DNS_ZONE_CLRFLAG(z, f) atomic_fetch_and(&(z)->flags, ~(f))
532 typedef enum {
533 DNS_ZONEFLG_REFRESH = 0x00000001U, /*%< refresh check in progress */
534 DNS_ZONEFLG_NEEDDUMP = 0x00000002U, /*%< zone need consolidation */
535 DNS_ZONEFLG_USEVC = 0x00000004U, /*%< use tcp for refresh query */
536 DNS_ZONEFLG_DUMPING = 0x00000008U, /*%< a dump is in progress */
537 DNS_ZONEFLG_HASINCLUDE = 0x00000010U, /*%< $INCLUDE in zone file */
538 DNS_ZONEFLG_LOADED = 0x00000020U, /*%< database has loaded */
539 DNS_ZONEFLG_EXITING = 0x00000040U, /*%< zone is being destroyed */
540 DNS_ZONEFLG_EXPIRED = 0x00000080U, /*%< zone has expired */
541 DNS_ZONEFLG_NEEDREFRESH = 0x00000100U, /*%< refresh check needed */
542 DNS_ZONEFLG_UPTODATE = 0x00000200U, /*%< zone contents are
543 * up-to-date */
544 DNS_ZONEFLG_NEEDNOTIFY = 0x00000400U, /*%< need to send out notify
545 * messages */
546 DNS_ZONEFLG_FIXJOURNAL = 0x00000800U, /*%< journal file had
547 * recoverable error,
548 * needs rewriting */
549 DNS_ZONEFLG_NOPRIMARIES = 0x00001000U, /*%< an attempt to refresh a
550 * zone with no primaries
551 * occurred */
552 DNS_ZONEFLG_LOADING = 0x00002000U, /*%< load from disk in progress*/
553 DNS_ZONEFLG_HAVETIMERS = 0x00004000U, /*%< timer values have been set
554 * from SOA (if not set, we
555 * are still using
556 * default timer values) */
557 DNS_ZONEFLG_FORCEXFER = 0x00008000U, /*%< Force a zone xfer */
558 DNS_ZONEFLG_NOREFRESH = 0x00010000U,
559 DNS_ZONEFLG_DIALNOTIFY = 0x00020000U,
560 DNS_ZONEFLG_DIALREFRESH = 0x00040000U,
561 DNS_ZONEFLG_SHUTDOWN = 0x00080000U,
562 DNS_ZONEFLG_NOIXFR = 0x00100000U, /*%< IXFR failed, force AXFR */
563 DNS_ZONEFLG_FLUSH = 0x00200000U,
564 DNS_ZONEFLG_NOEDNS = 0x00400000U,
565 DNS_ZONEFLG_USEALTXFRSRC = 0x00800000U,
566 DNS_ZONEFLG_SOABEFOREAXFR = 0x01000000U,
567 DNS_ZONEFLG_NEEDCOMPACT = 0x02000000U,
568 DNS_ZONEFLG_REFRESHING = 0x04000000U, /*%< Refreshing keydata */
569 DNS_ZONEFLG_THAW = 0x08000000U,
570 DNS_ZONEFLG_LOADPENDING = 0x10000000U, /*%< Loading scheduled */
571 DNS_ZONEFLG_NODELAY = 0x20000000U,
572 DNS_ZONEFLG_SENDSECURE = 0x40000000U,
573 DNS_ZONEFLG_NEEDSTARTUPNOTIFY = 0x80000000U, /*%< need to send out
574 * notify due to the zone
575 * just being loaded for
576 * the first time. */
577 #ifndef __NetBSD__
578 /*
579 * DO NOT add any new zone flags here until all platforms
580 * support 64-bit enum values. Currently they fail on
581 * Windows.
582 */
583 DNS_ZONEFLG___MAX = UINT64_MAX, /* trick to make the ENUM 64-bit wide */
584 #endif
585 } dns_zoneflg_t;
586
587 #define DNS_ZONE_OPTION(z, o) ((atomic_load_relaxed(&(z)->options) & (o)) != 0)
588 #define DNS_ZONE_SETOPTION(z, o) atomic_fetch_or(&(z)->options, (o))
589 #define DNS_ZONE_CLROPTION(z, o) atomic_fetch_and(&(z)->options, ~(o))
590
591 #define DNS_ZONEKEY_OPTION(z, o) \
592 ((atomic_load_relaxed(&(z)->keyopts) & (o)) != 0)
593 #define DNS_ZONEKEY_SETOPTION(z, o) atomic_fetch_or(&(z)->keyopts, (o))
594 #define DNS_ZONEKEY_CLROPTION(z, o) atomic_fetch_and(&(z)->keyopts, ~(o))
595
596 /* Flags for zone_load() */
597 typedef enum {
598 DNS_ZONELOADFLAG_NOSTAT = 0x00000001U, /* Do not stat() master files */
599 DNS_ZONELOADFLAG_THAW = 0x00000002U, /* Thaw the zone on successful
600 * load. */
601 } dns_zoneloadflag_t;
602
603 #define UNREACH_CACHE_SIZE 10U
604 #define UNREACH_HOLD_TIME 600 /* 10 minutes */
605
606 #define CHECK(op) \
607 do { \
608 result = (op); \
609 if (result != ISC_R_SUCCESS) \
610 goto failure; \
611 } while (0)
612
613 struct dns_unreachable {
614 isc_sockaddr_t remote;
615 isc_sockaddr_t local;
616 atomic_uint_fast32_t expire;
617 atomic_uint_fast32_t last;
618 uint32_t count;
619 };
620
621 struct dns_zonemgr {
622 unsigned int magic;
623 isc_mem_t *mctx;
624 isc_refcount_t refs;
625 isc_taskmgr_t *taskmgr;
626 isc_timermgr_t *timermgr;
627 isc_nm_t *netmgr;
628 isc_taskpool_t *zonetasks;
629 isc_taskpool_t *loadtasks;
630 isc_task_t *task;
631 isc_pool_t *mctxpool;
632 isc_ratelimiter_t *checkdsrl;
633 isc_ratelimiter_t *notifyrl;
634 isc_ratelimiter_t *refreshrl;
635 isc_ratelimiter_t *startupnotifyrl;
636 isc_ratelimiter_t *startuprefreshrl;
637 isc_rwlock_t rwlock;
638 isc_mutex_t iolock;
639 isc_rwlock_t urlock;
640
641 /* Locked by rwlock. */
642 dns_zonelist_t zones;
643 dns_zonelist_t waiting_for_xfrin;
644 dns_zonelist_t xfrin_in_progress;
645
646 /* Configuration data. */
647 uint32_t transfersin;
648 uint32_t transfersperns;
649 unsigned int checkdsrate;
650 unsigned int notifyrate;
651 unsigned int startupnotifyrate;
652 unsigned int serialqueryrate;
653 unsigned int startupserialqueryrate;
654
655 /* Locked by iolock */
656 uint32_t iolimit;
657 uint32_t ioactive;
658 dns_iolist_t high;
659 dns_iolist_t low;
660
661 /* Locked by urlock. */
662 /* LRU cache */
663 struct dns_unreachable unreachable[UNREACH_CACHE_SIZE];
664
665 dns_keymgmt_t *keymgmt;
666
667 isc_tlsctx_cache_t *tlsctx_cache;
668 isc_rwlock_t tlsctx_cache_rwlock;
669 };
670
671 /*%
672 * Hold notify state.
673 */
674 struct dns_notify {
675 unsigned int magic;
676 unsigned int flags;
677 isc_mem_t *mctx;
678 dns_zone_t *zone;
679 dns_adbfind_t *find;
680 dns_request_t *request;
681 dns_name_t ns;
682 isc_sockaddr_t dst;
683 dns_tsigkey_t *key;
684 dns_transport_t *transport;
685 ISC_LINK(dns_notify_t) link;
686 isc_event_t *event;
687 };
688
689 #define DNS_NOTIFY_NOSOA 0x0001U
690 #define DNS_NOTIFY_STARTUP 0x0002U
691
692 /*%
693 * Hold checkds state.
694 */
695 struct dns_checkds {
696 unsigned int magic;
697 unsigned int flags;
698 isc_mem_t *mctx;
699 dns_zone_t *zone;
700 dns_request_t *request;
701 isc_sockaddr_t dst;
702 dns_tsigkey_t *key;
703 dns_transport_t *transport;
704 ISC_LINK(dns_checkds_t) link;
705 isc_event_t *event;
706 };
707
708 /*%
709 * dns_stub holds state while performing a 'stub' transfer.
710 * 'db' is the zone's 'db' or a new one if this is the initial
711 * transfer.
712 */
713
714 struct dns_stub {
715 unsigned int magic;
716 isc_mem_t *mctx;
717 dns_zone_t *zone;
718 dns_db_t *db;
719 dns_dbversion_t *version;
720 atomic_uint_fast32_t pending_requests;
721 };
722
723 /*%
724 * Hold load state.
725 */
726 struct dns_load {
727 unsigned int magic;
728 isc_mem_t *mctx;
729 dns_zone_t *zone;
730 dns_db_t *db;
731 isc_time_t loadtime;
732 dns_rdatacallbacks_t callbacks;
733 };
734
735 /*%
736 * Hold forward state.
737 */
738 struct dns_forward {
739 unsigned int magic;
740 isc_mem_t *mctx;
741 dns_zone_t *zone;
742 isc_buffer_t *msgbuf;
743 dns_request_t *request;
744 uint32_t which;
745 isc_sockaddr_t addr;
746 dns_updatecallback_t callback;
747 void *callback_arg;
748 unsigned int options;
749 ISC_LINK(dns_forward_t) link;
750 };
751
752 /*%
753 * Hold IO request state.
754 */
755 struct dns_io {
756 unsigned int magic;
757 dns_zonemgr_t *zmgr;
758 bool high;
759 isc_task_t *task;
760 ISC_LINK(dns_io_t) link;
761 isc_event_t *event;
762 };
763
764 /*%
765 * Hold state for when we are signing a zone with a new
766 * DNSKEY as result of an update.
767 */
768 struct dns_signing {
769 unsigned int magic;
770 dns_db_t *db;
771 dns_dbiterator_t *dbiterator;
772 dns_secalg_t algorithm;
773 uint16_t keyid;
774 bool deleteit;
775 bool done;
776 ISC_LINK(dns_signing_t) link;
777 };
778
779 struct dns_nsec3chain {
780 unsigned int magic;
781 dns_db_t *db;
782 dns_dbiterator_t *dbiterator;
783 dns_rdata_nsec3param_t nsec3param;
784 unsigned char salt[255];
785 bool done;
786 bool seen_nsec;
787 bool delete_nsec;
788 bool save_delete_nsec;
789 ISC_LINK(dns_nsec3chain_t) link;
790 };
791
792 /*%<
793 * 'dbiterator' contains a iterator for the database. If we are creating
794 * a NSEC3 chain only the non-NSEC3 nodes will be iterated. If we are
795 * removing a NSEC3 chain then both NSEC3 and non-NSEC3 nodes will be
796 * iterated.
797 *
798 * 'nsec3param' contains the parameters of the NSEC3 chain being created
799 * or removed.
800 *
801 * 'salt' is buffer space and is referenced via 'nsec3param.salt'.
802 *
803 * 'seen_nsec' will be set to true if, while iterating the zone to create a
804 * NSEC3 chain, a NSEC record is seen.
805 *
806 * 'delete_nsec' will be set to true if, at the completion of the creation
807 * of a NSEC3 chain, 'seen_nsec' is true. If 'delete_nsec' is true then we
808 * are in the process of deleting the NSEC chain.
809 *
810 * 'save_delete_nsec' is used to store the initial state of 'delete_nsec'
811 * so it can be recovered in the event of a error.
812 */
813
814 struct dns_keyfetch {
815 isc_mem_t *mctx;
816 dns_fixedname_t name;
817 dns_rdataset_t keydataset;
818 dns_rdataset_t dnskeyset;
819 dns_rdataset_t dnskeysigset;
820 dns_zone_t *zone;
821 dns_db_t *db;
822 dns_fetch_t *fetch;
823 };
824
825 /*%
826 * Hold state for an asynchronous load
827 */
828 struct dns_asyncload {
829 dns_zone_t *zone;
830 unsigned int flags;
831 dns_zt_zoneloaded_t loaded;
832 void *loaded_arg;
833 };
834
835 /*%
836 * Reference to an include file encountered during loading
837 */
838 struct dns_include {
839 char *name;
840 isc_time_t filetime;
841 ISC_LINK(dns_include_t) link;
842 };
843
844 /*
845 * These can be overridden by the -T mkeytimers option on the command
846 * line, so that we can test with shorter periods than specified in
847 * RFC 5011.
848 */
849 #define HOUR 3600
850 #define DAY (24 * HOUR)
851 #define MONTH (30 * DAY)
852 unsigned int dns_zone_mkey_hour = HOUR;
853 unsigned int dns_zone_mkey_day = DAY;
854 unsigned int dns_zone_mkey_month = MONTH;
855
856 #define SEND_BUFFER_SIZE 2048
857
858 static void
859 zone_settimer(dns_zone_t *, isc_time_t *);
860 static void
861 cancel_refresh(dns_zone_t *);
862 static void
863 zone_debuglog(dns_zone_t *zone, const char *, int debuglevel, const char *msg,
864 ...) ISC_FORMAT_PRINTF(4, 5);
865 static void
866 notify_log(dns_zone_t *zone, int level, const char *fmt, ...)
867 ISC_FORMAT_PRINTF(3, 4);
868 static void
869 dnssec_log(dns_zone_t *zone, int level, const char *fmt, ...)
870 ISC_FORMAT_PRINTF(3, 4);
871 static void
872 queue_xfrin(dns_zone_t *zone);
873 static isc_result_t
874 update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
875 dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
876 dns_rdata_t *rdata);
877 static void
878 zone_unload(dns_zone_t *zone);
879 static void
880 zone_expire(dns_zone_t *zone);
881 static void
882 zone_refresh(dns_zone_t *zone);
883 static void
884 zone_iattach(dns_zone_t *source, dns_zone_t **target);
885 static void
886 zone_idetach(dns_zone_t **zonep);
887 static isc_result_t
888 zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump);
889 static void
890 zone_attachdb(dns_zone_t *zone, dns_db_t *db);
891 static void
892 zone_detachdb(dns_zone_t *zone);
893 static void
894 zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs);
895 static void
896 zone_catz_disable(dns_zone_t *zone);
897 static isc_result_t
898 default_journal(dns_zone_t *zone);
899 static void
900 zone_xfrdone(dns_zone_t *zone, isc_result_t result);
901 static isc_result_t
902 zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
903 isc_result_t result);
904 static void
905 zone_needdump(dns_zone_t *zone, unsigned int delay);
906 static void
907 zone_shutdown(isc_task_t *, isc_event_t *);
908 static void
909 zone_loaddone(void *arg, isc_result_t result);
910 static isc_result_t
911 zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime);
912 static void
913 zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length);
914 static void
915 zone_name_tostr(dns_zone_t *zone, char *buf, size_t length);
916 static void
917 zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length);
918 static void
919 zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length);
920 static isc_result_t
921 zone_send_secureserial(dns_zone_t *zone, uint32_t serial);
922 static void
923 refresh_callback(isc_task_t *, isc_event_t *);
924 static void
925 stub_callback(isc_task_t *, isc_event_t *);
926 static void
927 queue_soa_query(dns_zone_t *zone);
928 static void
929 soa_query(isc_task_t *, isc_event_t *);
930 static void
931 ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub);
932 static int
933 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type);
934 static void
935 checkds_cancel(dns_zone_t *zone);
936 static void
937 checkds_send(dns_zone_t *zone);
938 static isc_result_t
939 checkds_createmessage(dns_zone_t *zone, dns_message_t **messagep);
940 static void
941 checkds_done(isc_task_t *task, isc_event_t *event);
942 static void
943 checkds_send_toaddr(isc_task_t *task, isc_event_t *event);
944 static void
945 notify_cancel(dns_zone_t *zone);
946 static void
947 notify_find_address(dns_notify_t *notify);
948 static void
949 notify_send(dns_notify_t *notify);
950 static isc_result_t
951 notify_createmessage(dns_zone_t *zone, unsigned int flags,
952 dns_message_t **messagep);
953 static void
954 notify_done(isc_task_t *task, isc_event_t *event);
955 static void
956 notify_send_toaddr(isc_task_t *task, isc_event_t *event);
957 static isc_result_t
958 zone_dump(dns_zone_t *, bool);
959 static void
960 got_transfer_quota(isc_task_t *task, isc_event_t *event);
961 static isc_result_t
962 zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone);
963 static void
964 zmgr_resume_xfrs(dns_zonemgr_t *zmgr, bool multi);
965 static void
966 zonemgr_free(dns_zonemgr_t *zmgr);
967 static isc_result_t
968 zonemgr_getio(dns_zonemgr_t *zmgr, bool high, isc_task_t *task,
969 isc_taskaction_t action, void *arg, dns_io_t **iop);
970 static void
971 zonemgr_putio(dns_io_t **iop);
972 static void
973 zonemgr_cancelio(dns_io_t *io);
974 static void
975 rss_post(dns_zone_t *, isc_event_t *);
976
977 static isc_result_t
978 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
979 unsigned int *soacount, uint32_t *soattl, uint32_t *serial,
980 uint32_t *refresh, uint32_t *retry, uint32_t *expire,
981 uint32_t *minimum, unsigned int *errors);
982
983 static void
984 zone_freedbargs(dns_zone_t *zone);
985 static void
986 forward_callback(isc_task_t *task, isc_event_t *event);
987 static void
988 zone_saveunique(dns_zone_t *zone, const char *path, const char *templat);
989 static void
990 zone_maintenance(dns_zone_t *zone);
991 static void
992 zone_notify(dns_zone_t *zone, isc_time_t *now);
993 static void
994 dump_done(void *arg, isc_result_t result);
995 static isc_result_t
996 zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid,
997 bool deleteit);
998 static isc_result_t
999 delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
1000 dns_name_t *name, dns_diff_t *diff);
1001 static void
1002 zone_rekey(dns_zone_t *zone);
1003 static isc_result_t
1004 zone_send_securedb(dns_zone_t *zone, dns_db_t *db);
1005 static dns_ttl_t
1006 zone_nsecttl(dns_zone_t *zone);
1007 static void
1008 setrl(isc_ratelimiter_t *rl, unsigned int *rate, unsigned int value);
1009 static void
1010 zone_journal_compact(dns_zone_t *zone, dns_db_t *db, uint32_t serial);
1011 static isc_result_t
1012 zone_journal_rollforward(dns_zone_t *zone, dns_db_t *db, bool *needdump,
1013 bool *fixjournal);
1014
1015 #define ENTER zone_debuglog(zone, me, 1, "enter")
1016
1017 static void
1018 zmgr_tlsctx_attach(dns_zonemgr_t *zmgr, isc_tlsctx_cache_t **ptlsctx_cache);
1019 /*%<
1020 * Attach to TLS client context cache used for zone transfers via
1021 * encrypted transports (e.g. XoT).
1022 *
1023 * The obtained reference needs to be detached by a call to
1024 * 'isc_tlsctx_cache_detach()' when not needed anymore.
1025 *
1026 * Requires:
1027 *\li 'zmgr' is a valid zone manager.
1028 *\li 'ptlsctx_cache' is not 'NULL' and points to 'NULL'.
1029 */
1030
1031 static const unsigned int dbargc_default = 1;
1032 static const char *dbargv_default[] = { "rbt" };
1033
1034 #define DNS_ZONE_JITTER_ADD(a, b, c) \
1035 do { \
1036 isc_interval_t _i; \
1037 uint32_t _j; \
1038 _j = (b)-isc_random_uniform((b) / 4); \
1039 isc_interval_set(&_i, _j, 0); \
1040 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
1041 dns_zone_log(zone, ISC_LOG_WARNING, \
1042 "epoch approaching: upgrade required: " \
1043 "now + %s failed", \
1044 #b); \
1045 isc_interval_set(&_i, _j / 2, 0); \
1046 (void)isc_time_add((a), &_i, (c)); \
1047 } \
1048 } while (0)
1049
1050 #define DNS_ZONE_TIME_ADD(a, b, c) \
1051 do { \
1052 isc_interval_t _i; \
1053 isc_interval_set(&_i, (b), 0); \
1054 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
1055 dns_zone_log(zone, ISC_LOG_WARNING, \
1056 "epoch approaching: upgrade required: " \
1057 "now + %s failed", \
1058 #b); \
1059 isc_interval_set(&_i, (b) / 2, 0); \
1060 (void)isc_time_add((a), &_i, (c)); \
1061 } \
1062 } while (0)
1063
1064 typedef struct nsec3param nsec3param_t;
1065 struct nsec3param {
1066 dns_rdata_nsec3param_t rdata;
1067 unsigned char data[DNS_NSEC3PARAM_BUFFERSIZE + 1];
1068 unsigned int length;
1069 bool nsec;
1070 bool replace;
1071 bool resalt;
1072 bool lookup;
1073 ISC_LINK(nsec3param_t) link;
1074 };
1075 typedef ISC_LIST(nsec3param_t) nsec3paramlist_t;
1076 struct np3event {
1077 isc_event_t event;
1078 nsec3param_t params;
1079 };
1080
1081 struct ssevent {
1082 isc_event_t event;
1083 uint32_t serial;
1084 };
1085
1086 struct stub_cb_args {
1087 dns_stub_t *stub;
1088 dns_tsigkey_t *tsig_key;
1089 uint16_t udpsize;
1090 int timeout;
1091 bool reqnsid;
1092 };
1093
1094 struct stub_glue_request {
1095 dns_request_t *request;
1096 dns_name_t name;
1097 struct stub_cb_args *args;
1098 bool ipv4;
1099 };
1100
1101 /*%
1102 * Increment resolver-related statistics counters. Zone must be locked.
1103 */
1104 static void
1105 inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
1106 if (zone->stats != NULL) {
1107 isc_stats_increment(zone->stats, counter);
1108 }
1109 }
1110
1111 /***
1112 *** Public functions.
1113 ***/
1114
1115 isc_result_t
1116 dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
1117 isc_result_t result;
1118 isc_time_t now;
1119 dns_zone_t *zone = NULL;
1120 dns_zone_t z = { .masterformat = dns_masterformat_none,
1121 .journalsize = -1,
1122 .rdclass = dns_rdataclass_none,
1123 .type = dns_zone_none,
1124 .refresh = DNS_ZONE_DEFAULTREFRESH,
1125 .retry = DNS_ZONE_DEFAULTRETRY,
1126 .maxrefresh = DNS_ZONE_MAXREFRESH,
1127 .minrefresh = DNS_ZONE_MINREFRESH,
1128 .maxretry = DNS_ZONE_MAXRETRY,
1129 .minretry = DNS_ZONE_MINRETRY,
1130 .notifytype = dns_notifytype_yes,
1131 .zero_no_soa_ttl = true,
1132 .check_names = dns_severity_ignore,
1133 .idlein = DNS_DEFAULT_IDLEIN,
1134 .idleout = DNS_DEFAULT_IDLEOUT,
1135 .maxxfrin = MAX_XFER_TIME,
1136 .maxxfrout = MAX_XFER_TIME,
1137 .sigvalidityinterval = 30 * 24 * 3600,
1138 .sigresigninginterval = 7 * 24 * 3600,
1139 .statlevel = dns_zonestat_none,
1140 .notifydelay = 5,
1141 .signatures = 10,
1142 .nodes = 100,
1143 .privatetype = (dns_rdatatype_t)0xffffU,
1144 .rpz_num = DNS_RPZ_INVALID_NUM,
1145 .requestixfr = true,
1146 .ixfr_ratio = 100,
1147 .requestexpire = true,
1148 .updatemethod = dns_updatemethod_increment,
1149 .magic = ZONE_MAGIC };
1150
1151 REQUIRE(zonep != NULL && *zonep == NULL);
1152 REQUIRE(mctx != NULL);
1153
1154 TIME_NOW(&now);
1155 zone = isc_mem_get(mctx, sizeof(*zone));
1156 *zone = z;
1157
1158 zone->mctx = NULL;
1159 isc_mem_attach(mctx, &zone->mctx);
1160 isc_mutex_init(&zone->lock);
1161 ZONEDB_INITLOCK(&zone->dblock);
1162 /* XXX MPA check that all elements are initialised */
1163 #ifdef DNS_ZONE_CHECKLOCK
1164 zone->locked = false;
1165 #endif /* ifdef DNS_ZONE_CHECKLOCK */
1166
1167 zone->notifytime = now;
1168
1169 ISC_LINK_INIT(zone, link);
1170 isc_refcount_init(&zone->erefs, 1);
1171 isc_refcount_init(&zone->irefs, 0);
1172 dns_name_init(&zone->origin, NULL);
1173 ISC_LIST_INIT(zone->includes);
1174 ISC_LIST_INIT(zone->newincludes);
1175 atomic_init(&zone->flags, 0);
1176 atomic_init(&zone->options, 0);
1177 atomic_init(&zone->keyopts, 0);
1178 isc_time_settoepoch(&zone->expiretime);
1179 isc_time_settoepoch(&zone->refreshtime);
1180 isc_time_settoepoch(&zone->dumptime);
1181 isc_time_settoepoch(&zone->loadtime);
1182 isc_time_settoepoch(&zone->resigntime);
1183 isc_time_settoepoch(&zone->keywarntime);
1184 isc_time_settoepoch(&zone->signingtime);
1185 isc_time_settoepoch(&zone->nsec3chaintime);
1186 isc_time_settoepoch(&zone->refreshkeytime);
1187 ISC_LIST_INIT(zone->notifies);
1188 ISC_LIST_INIT(zone->checkds_requests);
1189 isc_sockaddr_any(&zone->notifysrc4);
1190 isc_sockaddr_any6(&zone->notifysrc6);
1191 isc_sockaddr_any(&zone->parentalsrc4);
1192 isc_sockaddr_any6(&zone->parentalsrc6);
1193 isc_sockaddr_any(&zone->xfrsource4);
1194 isc_sockaddr_any6(&zone->xfrsource6);
1195 isc_sockaddr_any(&zone->altxfrsource4);
1196 isc_sockaddr_any6(&zone->altxfrsource6);
1197 ISC_LINK_INIT(zone, statelink);
1198 ISC_LIST_INIT(zone->signing);
1199 ISC_LIST_INIT(zone->nsec3chain);
1200 ISC_LIST_INIT(zone->setnsec3param_queue);
1201 ISC_LIST_INIT(zone->forwards);
1202 ISC_LIST_INIT(zone->rss_events);
1203 ISC_LIST_INIT(zone->rss_post);
1204
1205 result = isc_stats_create(mctx, &zone->gluecachestats,
1206 dns_gluecachestatscounter_max);
1207 if (result != ISC_R_SUCCESS) {
1208 goto free_refs;
1209 }
1210
1211 /* Must be after magic is set. */
1212 dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
1213
1214 ISC_EVENT_INIT(&zone->ctlevent, sizeof(zone->ctlevent), 0, NULL,
1215 DNS_EVENT_ZONECONTROL, zone_shutdown, zone, zone, NULL,
1216 NULL);
1217 *zonep = zone;
1218 return (ISC_R_SUCCESS);
1219
1220 free_refs:
1221 isc_refcount_decrement0(&zone->erefs);
1222 isc_refcount_destroy(&zone->erefs);
1223 isc_refcount_destroy(&zone->irefs);
1224 ZONEDB_DESTROYLOCK(&zone->dblock);
1225 isc_mutex_destroy(&zone->lock);
1226 isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
1227 return (result);
1228 }
1229
1230 static void
1231 clear_keylist(dns_dnsseckeylist_t *list, isc_mem_t *mctx) {
1232 dns_dnsseckey_t *key;
1233 while (!ISC_LIST_EMPTY(*list)) {
1234 key = ISC_LIST_HEAD(*list);
1235 ISC_LIST_UNLINK(*list, key, link);
1236 dns_dnsseckey_destroy(mctx, &key);
1237 }
1238 }
1239
1240 /*
1241 * Free a zone. Because we require that there be no more
1242 * outstanding events or references, no locking is necessary.
1243 */
1244 static void
1245 zone_free(dns_zone_t *zone) {
1246 dns_signing_t *signing;
1247 dns_nsec3chain_t *nsec3chain;
1248 isc_event_t *event;
1249 dns_include_t *include;
1250
1251 REQUIRE(DNS_ZONE_VALID(zone));
1252 isc_refcount_destroy(&zone->erefs);
1253 isc_refcount_destroy(&zone->irefs);
1254 REQUIRE(!LOCKED_ZONE(zone));
1255 REQUIRE(zone->timer == NULL);
1256 REQUIRE(zone->zmgr == NULL);
1257
1258 /*
1259 * Managed objects. Order is important.
1260 */
1261 if (zone->request != NULL) {
1262 dns_request_destroy(&zone->request); /* XXXMPA */
1263 }
1264 INSIST(zone->readio == NULL);
1265 INSIST(zone->statelist == NULL);
1266 INSIST(zone->writeio == NULL);
1267 INSIST(zone->view == NULL);
1268 INSIST(zone->prev_view == NULL);
1269
1270 if (zone->task != NULL) {
1271 isc_task_detach(&zone->task);
1272 }
1273 if (zone->loadtask != NULL) {
1274 isc_task_detach(&zone->loadtask);
1275 }
1276
1277 /* Unmanaged objects */
1278 while (!ISC_LIST_EMPTY(zone->setnsec3param_queue)) {
1279 event = ISC_LIST_HEAD(zone->setnsec3param_queue);
1280 ISC_LIST_UNLINK(zone->setnsec3param_queue, event, ev_link);
1281 isc_event_free(&event);
1282 }
1283 while (!ISC_LIST_EMPTY(zone->rss_post)) {
1284 event = ISC_LIST_HEAD(zone->rss_post);
1285 ISC_LIST_UNLINK(zone->rss_post, event, ev_link);
1286 isc_event_free(&event);
1287 }
1288 for (signing = ISC_LIST_HEAD(zone->signing); signing != NULL;
1289 signing = ISC_LIST_HEAD(zone->signing))
1290 {
1291 ISC_LIST_UNLINK(zone->signing, signing, link);
1292 dns_db_detach(&signing->db);
1293 dns_dbiterator_destroy(&signing->dbiterator);
1294 isc_mem_put(zone->mctx, signing, sizeof *signing);
1295 }
1296 for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain); nsec3chain != NULL;
1297 nsec3chain = ISC_LIST_HEAD(zone->nsec3chain))
1298 {
1299 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
1300 dns_db_detach(&nsec3chain->db);
1301 dns_dbiterator_destroy(&nsec3chain->dbiterator);
1302 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
1303 }
1304 for (include = ISC_LIST_HEAD(zone->includes); include != NULL;
1305 include = ISC_LIST_HEAD(zone->includes))
1306 {
1307 ISC_LIST_UNLINK(zone->includes, include, link);
1308 isc_mem_free(zone->mctx, include->name);
1309 isc_mem_put(zone->mctx, include, sizeof *include);
1310 }
1311 for (include = ISC_LIST_HEAD(zone->newincludes); include != NULL;
1312 include = ISC_LIST_HEAD(zone->newincludes))
1313 {
1314 ISC_LIST_UNLINK(zone->newincludes, include, link);
1315 isc_mem_free(zone->mctx, include->name);
1316 isc_mem_put(zone->mctx, include, sizeof *include);
1317 }
1318 if (zone->masterfile != NULL) {
1319 isc_mem_free(zone->mctx, zone->masterfile);
1320 }
1321 zone->masterfile = NULL;
1322 if (zone->keydirectory != NULL) {
1323 isc_mem_free(zone->mctx, zone->keydirectory);
1324 }
1325 zone->keydirectory = NULL;
1326 if (zone->kasp != NULL) {
1327 dns_kasp_detach(&zone->kasp);
1328 }
1329 if (!ISC_LIST_EMPTY(zone->checkds_ok)) {
1330 clear_keylist(&zone->checkds_ok, zone->mctx);
1331 }
1332
1333 zone->journalsize = -1;
1334 if (zone->journal != NULL) {
1335 isc_mem_free(zone->mctx, zone->journal);
1336 }
1337 zone->journal = NULL;
1338 if (zone->stats != NULL) {
1339 isc_stats_detach(&zone->stats);
1340 }
1341 if (zone->requeststats != NULL) {
1342 isc_stats_detach(&zone->requeststats);
1343 }
1344 if (zone->rcvquerystats != NULL) {
1345 dns_stats_detach(&zone->rcvquerystats);
1346 }
1347 if (zone->dnssecsignstats != NULL) {
1348 dns_stats_detach(&zone->dnssecsignstats);
1349 }
1350 if (zone->db != NULL) {
1351 zone_detachdb(zone);
1352 }
1353 if (zone->rpzs != NULL) {
1354 REQUIRE(zone->rpz_num < zone->rpzs->p.num_zones);
1355 dns_rpz_detach_rpzs(&zone->rpzs);
1356 zone->rpz_num = DNS_RPZ_INVALID_NUM;
1357 }
1358 if (zone->catzs != NULL) {
1359 dns_catz_detach_catzs(&zone->catzs);
1360 }
1361 zone_freedbargs(zone);
1362 dns_zone_setparentals(zone, NULL, NULL, NULL, 0);
1363 dns_zone_setprimaries(zone, NULL, NULL, NULL, 0);
1364 dns_zone_setalsonotify(zone, NULL, NULL, NULL, 0);
1365
1366 zone->check_names = dns_severity_ignore;
1367 if (zone->update_acl != NULL) {
1368 dns_acl_detach(&zone->update_acl);
1369 }
1370 if (zone->forward_acl != NULL) {
1371 dns_acl_detach(&zone->forward_acl);
1372 }
1373 if (zone->notify_acl != NULL) {
1374 dns_acl_detach(&zone->notify_acl);
1375 }
1376 if (zone->query_acl != NULL) {
1377 dns_acl_detach(&zone->query_acl);
1378 }
1379 if (zone->queryon_acl != NULL) {
1380 dns_acl_detach(&zone->queryon_acl);
1381 }
1382 if (zone->xfr_acl != NULL) {
1383 dns_acl_detach(&zone->xfr_acl);
1384 }
1385 if (dns_name_dynamic(&zone->origin)) {
1386 dns_name_free(&zone->origin, zone->mctx);
1387 }
1388 if (zone->strnamerd != NULL) {
1389 isc_mem_free(zone->mctx, zone->strnamerd);
1390 }
1391 if (zone->strname != NULL) {
1392 isc_mem_free(zone->mctx, zone->strname);
1393 }
1394 if (zone->strrdclass != NULL) {
1395 isc_mem_free(zone->mctx, zone->strrdclass);
1396 }
1397 if (zone->strviewname != NULL) {
1398 isc_mem_free(zone->mctx, zone->strviewname);
1399 }
1400 if (zone->ssutable != NULL) {
1401 dns_ssutable_detach(&zone->ssutable);
1402 }
1403 if (zone->gluecachestats != NULL) {
1404 isc_stats_detach(&zone->gluecachestats);
1405 }
1406
1407 /* last stuff */
1408 ZONEDB_DESTROYLOCK(&zone->dblock);
1409 isc_mutex_destroy(&zone->lock);
1410 zone->magic = 0;
1411 isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
1412 }
1413
1414 /*
1415 * Returns true iff this the signed side of an inline-signing zone.
1416 * Caller should hold zone lock.
1417 */
1418 static bool
1419 inline_secure(dns_zone_t *zone) {
1420 REQUIRE(DNS_ZONE_VALID(zone));
1421 if (zone->raw != NULL) {
1422 return (true);
1423 }
1424 return (false);
1425 }
1426
1427 /*
1428 * Returns true iff this the unsigned side of an inline-signing zone
1429 * Caller should hold zone lock.
1430 */
1431 static bool
1432 inline_raw(dns_zone_t *zone) {
1433 REQUIRE(DNS_ZONE_VALID(zone));
1434 if (zone->secure != NULL) {
1435 return (true);
1436 }
1437 return (false);
1438 }
1439
1440 /*
1441 * Single shot.
1442 */
1443 void
1444 dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
1445 char namebuf[1024];
1446
1447 REQUIRE(DNS_ZONE_VALID(zone));
1448 REQUIRE(rdclass != dns_rdataclass_none);
1449
1450 /*
1451 * Test and set.
1452 */
1453 LOCK_ZONE(zone);
1454 INSIST(zone != zone->raw);
1455 REQUIRE(zone->rdclass == dns_rdataclass_none ||
1456 zone->rdclass == rdclass);
1457 zone->rdclass = rdclass;
1458
1459 if (zone->strnamerd != NULL) {
1460 isc_mem_free(zone->mctx, zone->strnamerd);
1461 }
1462 if (zone->strrdclass != NULL) {
1463 isc_mem_free(zone->mctx, zone->strrdclass);
1464 }
1465
1466 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1467 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1468 zone_rdclass_tostr(zone, namebuf, sizeof namebuf);
1469 zone->strrdclass = isc_mem_strdup(zone->mctx, namebuf);
1470
1471 if (inline_secure(zone)) {
1472 dns_zone_setclass(zone->raw, rdclass);
1473 }
1474 UNLOCK_ZONE(zone);
1475 }
1476
1477 dns_rdataclass_t
1478 dns_zone_getclass(dns_zone_t *zone) {
1479 REQUIRE(DNS_ZONE_VALID(zone));
1480
1481 return (zone->rdclass);
1482 }
1483
1484 void
1485 dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
1486 REQUIRE(DNS_ZONE_VALID(zone));
1487
1488 LOCK_ZONE(zone);
1489 zone->notifytype = notifytype;
1490 UNLOCK_ZONE(zone);
1491 }
1492
1493 isc_result_t
1494 dns_zone_getserial(dns_zone_t *zone, uint32_t *serialp) {
1495 isc_result_t result;
1496 unsigned int soacount;
1497
1498 REQUIRE(DNS_ZONE_VALID(zone));
1499 REQUIRE(serialp != NULL);
1500
1501 LOCK_ZONE(zone);
1502 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1503 if (zone->db != NULL) {
1504 result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL,
1505 serialp, NULL, NULL, NULL, NULL,
1506 NULL);
1507 if (result == ISC_R_SUCCESS && soacount == 0) {
1508 result = ISC_R_FAILURE;
1509 }
1510 } else {
1511 result = DNS_R_NOTLOADED;
1512 }
1513 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1514 UNLOCK_ZONE(zone);
1515
1516 return (result);
1517 }
1518
1519 /*
1520 * Single shot.
1521 */
1522 void
1523 dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) {
1524 char namebuf[1024];
1525
1526 REQUIRE(DNS_ZONE_VALID(zone));
1527 REQUIRE(type != dns_zone_none);
1528
1529 /*
1530 * Test and set.
1531 */
1532 LOCK_ZONE(zone);
1533 REQUIRE(zone->type == dns_zone_none || zone->type == type);
1534 zone->type = type;
1535
1536 if (zone->strnamerd != NULL) {
1537 isc_mem_free(zone->mctx, zone->strnamerd);
1538 }
1539
1540 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1541 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1542 UNLOCK_ZONE(zone);
1543 }
1544
1545 static void
1546 zone_freedbargs(dns_zone_t *zone) {
1547 unsigned int i;
1548
1549 /* Free the old database argument list. */
1550 if (zone->db_argv != NULL) {
1551 for (i = 0; i < zone->db_argc; i++) {
1552 isc_mem_free(zone->mctx, zone->db_argv[i]);
1553 }
1554 isc_mem_put(zone->mctx, zone->db_argv,
1555 zone->db_argc * sizeof(*zone->db_argv));
1556 }
1557 zone->db_argc = 0;
1558 zone->db_argv = NULL;
1559 }
1560
1561 isc_result_t
1562 dns_zone_getdbtype(dns_zone_t *zone, char ***argv, isc_mem_t *mctx) {
1563 size_t size = 0;
1564 unsigned int i;
1565 isc_result_t result = ISC_R_SUCCESS;
1566 void *mem;
1567 char **tmp, *tmp2, *base;
1568
1569 REQUIRE(DNS_ZONE_VALID(zone));
1570 REQUIRE(argv != NULL && *argv == NULL);
1571
1572 LOCK_ZONE(zone);
1573 size = (zone->db_argc + 1) * sizeof(char *);
1574 for (i = 0; i < zone->db_argc; i++) {
1575 size += strlen(zone->db_argv[i]) + 1;
1576 }
1577 mem = isc_mem_allocate(mctx, size);
1578 {
1579 tmp = mem;
1580 tmp2 = mem;
1581 base = mem;
1582 tmp2 += (zone->db_argc + 1) * sizeof(char *);
1583 for (i = 0; i < zone->db_argc; i++) {
1584 *tmp++ = tmp2;
1585 strlcpy(tmp2, zone->db_argv[i], size - (tmp2 - base));
1586 tmp2 += strlen(tmp2) + 1;
1587 }
1588 *tmp = NULL;
1589 }
1590 UNLOCK_ZONE(zone);
1591 *argv = mem;
1592 return (result);
1593 }
1594
1595 void
1596 dns_zone_setdbtype(dns_zone_t *zone, unsigned int dbargc,
1597 const char *const *dbargv) {
1598 char **argv = NULL;
1599 unsigned int i;
1600
1601 REQUIRE(DNS_ZONE_VALID(zone));
1602 REQUIRE(dbargc >= 1);
1603 REQUIRE(dbargv != NULL);
1604
1605 LOCK_ZONE(zone);
1606
1607 /* Set up a new database argument list. */
1608 argv = isc_mem_get(zone->mctx, dbargc * sizeof(*argv));
1609 for (i = 0; i < dbargc; i++) {
1610 argv[i] = NULL;
1611 }
1612 for (i = 0; i < dbargc; i++) {
1613 argv[i] = isc_mem_strdup(zone->mctx, dbargv[i]);
1614 }
1615
1616 /* Free the old list. */
1617 zone_freedbargs(zone);
1618
1619 zone->db_argc = dbargc;
1620 zone->db_argv = argv;
1621
1622 UNLOCK_ZONE(zone);
1623 }
1624
1625 static void
1626 dns_zone_setview_helper(dns_zone_t *zone, dns_view_t *view) {
1627 char namebuf[1024];
1628
1629 if (zone->prev_view == NULL && zone->view != NULL) {
1630 dns_view_weakattach(zone->view, &zone->prev_view);
1631 }
1632
1633 INSIST(zone != zone->raw);
1634 if (zone->view != NULL) {
1635 dns_view_sfd_del(zone->view, &zone->origin);
1636 dns_view_weakdetach(&zone->view);
1637 }
1638 dns_view_weakattach(view, &zone->view);
1639 dns_view_sfd_add(view, &zone->origin);
1640
1641 if (zone->strviewname != NULL) {
1642 isc_mem_free(zone->mctx, zone->strviewname);
1643 }
1644 if (zone->strnamerd != NULL) {
1645 isc_mem_free(zone->mctx, zone->strnamerd);
1646 }
1647
1648 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1649 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1650 zone_viewname_tostr(zone, namebuf, sizeof namebuf);
1651 zone->strviewname = isc_mem_strdup(zone->mctx, namebuf);
1652
1653 if (inline_secure(zone)) {
1654 dns_zone_setview(zone->raw, view);
1655 }
1656 }
1657
1658 void
1659 dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
1660 REQUIRE(DNS_ZONE_VALID(zone));
1661
1662 LOCK_ZONE(zone);
1663 dns_zone_setview_helper(zone, view);
1664 UNLOCK_ZONE(zone);
1665 }
1666
1667 dns_view_t *
1668 dns_zone_getview(dns_zone_t *zone) {
1669 REQUIRE(DNS_ZONE_VALID(zone));
1670
1671 return (zone->view);
1672 }
1673
1674 void
1675 dns_zone_setviewcommit(dns_zone_t *zone) {
1676 REQUIRE(DNS_ZONE_VALID(zone));
1677
1678 LOCK_ZONE(zone);
1679 if (zone->prev_view != NULL) {
1680 dns_view_weakdetach(&zone->prev_view);
1681 }
1682 if (inline_secure(zone)) {
1683 dns_zone_setviewcommit(zone->raw);
1684 }
1685 UNLOCK_ZONE(zone);
1686 }
1687
1688 void
1689 dns_zone_setviewrevert(dns_zone_t *zone) {
1690 REQUIRE(DNS_ZONE_VALID(zone));
1691
1692 LOCK_ZONE(zone);
1693 if (zone->prev_view != NULL) {
1694 dns_zone_setview_helper(zone, zone->prev_view);
1695 dns_view_weakdetach(&zone->prev_view);
1696 }
1697 if (zone->catzs != NULL) {
1698 zone_catz_enable(zone, zone->catzs);
1699 }
1700 if (inline_secure(zone)) {
1701 dns_zone_setviewrevert(zone->raw);
1702 }
1703 UNLOCK_ZONE(zone);
1704 }
1705
1706 isc_result_t
1707 dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
1708 isc_result_t result = ISC_R_SUCCESS;
1709 char namebuf[1024];
1710
1711 REQUIRE(DNS_ZONE_VALID(zone));
1712 REQUIRE(origin != NULL);
1713
1714 LOCK_ZONE(zone);
1715 INSIST(zone != zone->raw);
1716 if (dns_name_dynamic(&zone->origin)) {
1717 dns_name_free(&zone->origin, zone->mctx);
1718 dns_name_init(&zone->origin, NULL);
1719 }
1720 dns_name_dup(origin, zone->mctx, &zone->origin);
1721
1722 if (zone->strnamerd != NULL) {
1723 isc_mem_free(zone->mctx, zone->strnamerd);
1724 }
1725 if (zone->strname != NULL) {
1726 isc_mem_free(zone->mctx, zone->strname);
1727 }
1728
1729 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1730 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1731 zone_name_tostr(zone, namebuf, sizeof namebuf);
1732 zone->strname = isc_mem_strdup(zone->mctx, namebuf);
1733
1734 if (inline_secure(zone)) {
1735 result = dns_zone_setorigin(zone->raw, origin);
1736 }
1737 UNLOCK_ZONE(zone);
1738 return (result);
1739 }
1740
1741 static isc_result_t
1742 dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
1743 char *copy;
1744
1745 if (value != NULL) {
1746 copy = isc_mem_strdup(zone->mctx, value);
1747 } else {
1748 copy = NULL;
1749 }
1750
1751 if (*field != NULL) {
1752 isc_mem_free(zone->mctx, *field);
1753 }
1754
1755 *field = copy;
1756 return (ISC_R_SUCCESS);
1757 }
1758
1759 isc_result_t
1760 dns_zone_setfile(dns_zone_t *zone, const char *file, dns_masterformat_t format,
1761 const dns_master_style_t *style) {
1762 isc_result_t result = ISC_R_SUCCESS;
1763
1764 REQUIRE(DNS_ZONE_VALID(zone));
1765 REQUIRE(zone->stream == NULL);
1766
1767 LOCK_ZONE(zone);
1768 result = dns_zone_setstring(zone, &zone->masterfile, file);
1769 if (result == ISC_R_SUCCESS) {
1770 zone->masterformat = format;
1771 if (format == dns_masterformat_text) {
1772 zone->masterstyle = style;
1773 }
1774 result = default_journal(zone);
1775 }
1776 UNLOCK_ZONE(zone);
1777
1778 return (result);
1779 }
1780
1781 const char *
1782 dns_zone_getfile(dns_zone_t *zone) {
1783 REQUIRE(DNS_ZONE_VALID(zone));
1784
1785 return (zone->masterfile);
1786 }
1787
1788 isc_result_t
1789 dns_zone_setstream(dns_zone_t *zone, const FILE *stream,
1790 dns_masterformat_t format, const dns_master_style_t *style) {
1791 isc_result_t result = ISC_R_SUCCESS;
1792
1793 REQUIRE(DNS_ZONE_VALID(zone));
1794 REQUIRE(stream != NULL);
1795 REQUIRE(zone->masterfile == NULL);
1796
1797 LOCK_ZONE(zone);
1798 zone->stream = stream;
1799 zone->masterformat = format;
1800 if (format == dns_masterformat_text) {
1801 zone->masterstyle = style;
1802 }
1803 result = default_journal(zone);
1804 UNLOCK_ZONE(zone);
1805
1806 return (result);
1807 }
1808
1809 dns_ttl_t
1810 dns_zone_getmaxttl(dns_zone_t *zone) {
1811 REQUIRE(DNS_ZONE_VALID(zone));
1812
1813 return (zone->maxttl);
1814 }
1815
1816 void
1817 dns_zone_setmaxttl(dns_zone_t *zone, dns_ttl_t maxttl) {
1818 REQUIRE(DNS_ZONE_VALID(zone));
1819
1820 LOCK_ZONE(zone);
1821 if (maxttl != 0) {
1822 DNS_ZONE_SETOPTION(zone, DNS_ZONEOPT_CHECKTTL);
1823 } else {
1824 DNS_ZONE_CLROPTION(zone, DNS_ZONEOPT_CHECKTTL);
1825 }
1826 zone->maxttl = maxttl;
1827 UNLOCK_ZONE(zone);
1828
1829 return;
1830 }
1831
1832 static isc_result_t
1833 default_journal(dns_zone_t *zone) {
1834 isc_result_t result;
1835 char *journal;
1836
1837 REQUIRE(DNS_ZONE_VALID(zone));
1838 REQUIRE(LOCKED_ZONE(zone));
1839
1840 if (zone->masterfile != NULL) {
1841 /* Calculate string length including '\0'. */
1842 int len = strlen(zone->masterfile) + sizeof(".jnl");
1843 journal = isc_mem_allocate(zone->mctx, len);
1844 strlcpy(journal, zone->masterfile, len);
1845 strlcat(journal, ".jnl", len);
1846 } else {
1847 journal = NULL;
1848 }
1849 result = dns_zone_setstring(zone, &zone->journal, journal);
1850 if (journal != NULL) {
1851 isc_mem_free(zone->mctx, journal);
1852 }
1853 return (result);
1854 }
1855
1856 isc_result_t
1857 dns_zone_setjournal(dns_zone_t *zone, const char *myjournal) {
1858 isc_result_t result = ISC_R_SUCCESS;
1859
1860 REQUIRE(DNS_ZONE_VALID(zone));
1861
1862 LOCK_ZONE(zone);
1863 result = dns_zone_setstring(zone, &zone->journal, myjournal);
1864 UNLOCK_ZONE(zone);
1865
1866 return (result);
1867 }
1868
1869 char *
1870 dns_zone_getjournal(dns_zone_t *zone) {
1871 REQUIRE(DNS_ZONE_VALID(zone));
1872
1873 return (zone->journal);
1874 }
1875
1876 /*
1877 * Return true iff the zone is "dynamic", in the sense that the zone's
1878 * master file (if any) is written by the server, rather than being
1879 * updated manually and read by the server.
1880 *
1881 * This is true for secondary zones, mirror zones, stub zones, key zones,
1882 * and zones that allow dynamic updates either by having an update
1883 * policy ("ssutable") or an "allow-update" ACL with a value other than
1884 * exactly "{ none; }".
1885 */
1886 bool
1887 dns_zone_isdynamic(dns_zone_t *zone, bool ignore_freeze) {
1888 REQUIRE(DNS_ZONE_VALID(zone));
1889
1890 if (zone->type == dns_zone_secondary || zone->type == dns_zone_mirror ||
1891 zone->type == dns_zone_stub || zone->type == dns_zone_key ||
1892 (zone->type == dns_zone_redirect && zone->primaries != NULL))
1893 {
1894 return (true);
1895 }
1896
1897 /* Inline zones are always dynamic. */
1898 if (zone->type == dns_zone_primary && zone->raw != NULL) {
1899 return (true);
1900 }
1901
1902 /* If !ignore_freeze, we need check whether updates are disabled. */
1903 if (zone->type == dns_zone_primary &&
1904 (!zone->update_disabled || ignore_freeze) &&
1905 ((zone->ssutable != NULL) ||
1906 (zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl))))
1907 {
1908 return (true);
1909 }
1910
1911 return (false);
1912 }
1913
1914 /*
1915 * Set the response policy index and information for a zone.
1916 */
1917 isc_result_t
1918 dns_zone_rpz_enable(dns_zone_t *zone, dns_rpz_zones_t *rpzs,
1919 dns_rpz_num_t rpz_num) {
1920 /*
1921 * Only RBTDB zones can be used for response policy zones,
1922 * because only they have the code to create the summary data.
1923 * Only zones that are loaded instead of mmap()ed create the
1924 * summary data and so can be policy zones.
1925 */
1926 if (strcmp(zone->db_argv[0], "rbt") != 0 &&
1927 strcmp(zone->db_argv[0], "rbt64") != 0)
1928 {
1929 return (ISC_R_NOTIMPLEMENTED);
1930 }
1931
1932 /*
1933 * This must happen only once or be redundant.
1934 */
1935 LOCK_ZONE(zone);
1936 if (zone->rpzs != NULL) {
1937 REQUIRE(zone->rpzs == rpzs && zone->rpz_num == rpz_num);
1938 } else {
1939 REQUIRE(zone->rpz_num == DNS_RPZ_INVALID_NUM);
1940 dns_rpz_attach_rpzs(rpzs, &zone->rpzs);
1941 zone->rpz_num = rpz_num;
1942 }
1943 rpzs->defined |= DNS_RPZ_ZBIT(rpz_num);
1944 UNLOCK_ZONE(zone);
1945
1946 return (ISC_R_SUCCESS);
1947 }
1948
1949 dns_rpz_num_t
1950 dns_zone_get_rpz_num(dns_zone_t *zone) {
1951 return (zone->rpz_num);
1952 }
1953
1954 /*
1955 * If a zone is a response policy zone, mark its new database.
1956 */
1957 void
1958 dns_zone_rpz_enable_db(dns_zone_t *zone, dns_db_t *db) {
1959 isc_result_t result;
1960 if (zone->rpz_num == DNS_RPZ_INVALID_NUM) {
1961 return;
1962 }
1963 REQUIRE(zone->rpzs != NULL);
1964 result = dns_db_updatenotify_register(db, dns_rpz_dbupdate_callback,
1965 zone->rpzs->zones[zone->rpz_num]);
1966 REQUIRE(result == ISC_R_SUCCESS);
1967 }
1968
1969 static void
1970 dns_zone_rpz_disable_db(dns_zone_t *zone, dns_db_t *db) {
1971 if (zone->rpz_num == DNS_RPZ_INVALID_NUM) {
1972 return;
1973 }
1974 REQUIRE(zone->rpzs != NULL);
1975 (void)dns_db_updatenotify_unregister(db, dns_rpz_dbupdate_callback,
1976 zone->rpzs->zones[zone->rpz_num]);
1977 }
1978
1979 /*
1980 * If a zone is a catalog zone, attach it to update notification in database.
1981 */
1982 void
1983 dns_zone_catz_enable_db(dns_zone_t *zone, dns_db_t *db) {
1984 REQUIRE(DNS_ZONE_VALID(zone));
1985 REQUIRE(db != NULL);
1986
1987 if (zone->catzs != NULL) {
1988 dns_catz_dbupdate_register(db, zone->catzs);
1989 }
1990 }
1991
1992 static void
1993 dns_zone_catz_disable_db(dns_zone_t *zone, dns_db_t *db) {
1994 REQUIRE(DNS_ZONE_VALID(zone));
1995 REQUIRE(db != NULL);
1996
1997 if (zone->catzs != NULL) {
1998 dns_catz_dbupdate_unregister(db, zone->catzs);
1999 }
2000 }
2001
2002 static void
2003 zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs) {
2004 REQUIRE(DNS_ZONE_VALID(zone));
2005 REQUIRE(catzs != NULL);
2006
2007 INSIST(zone->catzs == NULL || zone->catzs == catzs);
2008 dns_catz_catzs_set_view(catzs, zone->view);
2009 if (zone->catzs == NULL) {
2010 dns_catz_attach_catzs(catzs, &zone->catzs);
2011 }
2012 }
2013
2014 void
2015 dns_zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs) {
2016 REQUIRE(DNS_ZONE_VALID(zone));
2017
2018 LOCK_ZONE(zone);
2019 zone_catz_enable(zone, catzs);
2020 UNLOCK_ZONE(zone);
2021 }
2022
2023 static void
2024 zone_catz_disable(dns_zone_t *zone) {
2025 REQUIRE(DNS_ZONE_VALID(zone));
2026
2027 if (zone->catzs != NULL) {
2028 if (zone->db != NULL) {
2029 dns_zone_catz_disable_db(zone, zone->db);
2030 }
2031 dns_catz_detach_catzs(&zone->catzs);
2032 }
2033 }
2034
2035 void
2036 dns_zone_catz_disable(dns_zone_t *zone) {
2037 REQUIRE(DNS_ZONE_VALID(zone));
2038
2039 LOCK_ZONE(zone);
2040 zone_catz_disable(zone);
2041 UNLOCK_ZONE(zone);
2042 }
2043
2044 bool
2045 dns_zone_catz_is_enabled(dns_zone_t *zone) {
2046 REQUIRE(DNS_ZONE_VALID(zone));
2047
2048 return (zone->catzs != NULL);
2049 }
2050
2051 /*
2052 * Set catalog zone ownership of the zone
2053 */
2054 void
2055 dns_zone_set_parentcatz(dns_zone_t *zone, dns_catz_zone_t *catz) {
2056 REQUIRE(DNS_ZONE_VALID(zone));
2057 REQUIRE(catz != NULL);
2058 LOCK_ZONE(zone);
2059 INSIST(zone->parentcatz == NULL || zone->parentcatz == catz);
2060 zone->parentcatz = catz;
2061 UNLOCK_ZONE(zone);
2062 }
2063
2064 dns_catz_zone_t *
2065 dns_zone_get_parentcatz(const dns_zone_t *zone) {
2066 REQUIRE(DNS_ZONE_VALID(zone));
2067 return (zone->parentcatz);
2068 }
2069
2070 static bool
2071 zone_touched(dns_zone_t *zone) {
2072 isc_result_t result;
2073 isc_time_t modtime;
2074 dns_include_t *include;
2075
2076 REQUIRE(DNS_ZONE_VALID(zone));
2077
2078 result = isc_file_getmodtime(zone->masterfile, &modtime);
2079 if (result != ISC_R_SUCCESS ||
2080 isc_time_compare(&modtime, &zone->loadtime) > 0)
2081 {
2082 return (true);
2083 }
2084
2085 for (include = ISC_LIST_HEAD(zone->includes); include != NULL;
2086 include = ISC_LIST_NEXT(include, link))
2087 {
2088 result = isc_file_getmodtime(include->name, &modtime);
2089 if (result != ISC_R_SUCCESS ||
2090 isc_time_compare(&modtime, &include->filetime) > 0)
2091 {
2092 return (true);
2093 }
2094 }
2095
2096 return (false);
2097 }
2098
2099 /*
2100 * Note: when dealing with inline-signed zones, external callers will always
2101 * call zone_load() for the secure zone; zone_load() calls itself recursively
2102 * in order to load the raw zone.
2103 */
2104 static isc_result_t
2105 zone_load(dns_zone_t *zone, unsigned int flags, bool locked) {
2106 isc_result_t result;
2107 isc_time_t now;
2108 isc_time_t loadtime;
2109 dns_db_t *db = NULL;
2110 bool rbt, hasraw, is_dynamic;
2111
2112 REQUIRE(DNS_ZONE_VALID(zone));
2113
2114 if (!locked) {
2115 LOCK_ZONE(zone);
2116 }
2117
2118 INSIST(zone != zone->raw);
2119 hasraw = inline_secure(zone);
2120 if (hasraw) {
2121 /*
2122 * We are trying to load an inline-signed zone. First call
2123 * self recursively to try loading the raw version of the zone.
2124 * Assuming the raw zone file is readable, there are two
2125 * possibilities:
2126 *
2127 * a) the raw zone was not yet loaded and thus it will be
2128 * loaded now, synchronously; if this succeeds, a
2129 * subsequent attempt to load the signed zone file will
2130 * take place and thus zone_postload() will be called
2131 * twice: first for the raw zone and then for the secure
2132 * zone; the latter call will take care of syncing the raw
2133 * version with the secure version,
2134 *
2135 * b) the raw zone was already loaded and we are trying to
2136 * reload it, which will happen asynchronously; this means
2137 * zone_postload() will only be called for the raw zone
2138 * because "result" returned by the zone_load() call below
2139 * will not be ISC_R_SUCCESS but rather DNS_R_CONTINUE;
2140 * zone_postload() called for the raw zone will take care
2141 * of syncing the raw version with the secure version.
2142 */
2143 result = zone_load(zone->raw, flags, false);
2144 if (result != ISC_R_SUCCESS) {
2145 if (!locked) {
2146 UNLOCK_ZONE(zone);
2147 }
2148 return (result);
2149 }
2150 LOCK_ZONE(zone->raw);
2151 }
2152
2153 TIME_NOW(&now);
2154
2155 INSIST(zone->type != dns_zone_none);
2156
2157 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
2158 if ((flags & DNS_ZONELOADFLAG_THAW) != 0) {
2159 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
2160 }
2161 result = DNS_R_CONTINUE;
2162 goto cleanup;
2163 }
2164
2165 INSIST(zone->db_argc >= 1);
2166
2167 rbt = strcmp(zone->db_argv[0], "rbt") == 0 ||
2168 strcmp(zone->db_argv[0], "rbt64") == 0;
2169
2170 if (zone->db != NULL && zone->masterfile == NULL && rbt) {
2171 /*
2172 * The zone has no master file configured.
2173 */
2174 result = ISC_R_SUCCESS;
2175 goto cleanup;
2176 }
2177
2178 is_dynamic = dns_zone_isdynamic(zone, false);
2179 if (zone->db != NULL && is_dynamic) {
2180 /*
2181 * This is a secondary, stub, or dynamically updated zone
2182 * being reloaded. Do nothing - the database we already
2183 * have is guaranteed to be up-to-date.
2184 */
2185 if (zone->type == dns_zone_primary && !hasraw) {
2186 result = DNS_R_DYNAMIC;
2187 } else {
2188 result = ISC_R_SUCCESS;
2189 }
2190 goto cleanup;
2191 }
2192
2193 /*
2194 * Store the current time before the zone is loaded, so that if the
2195 * file changes between the time of the load and the time that
2196 * zone->loadtime is set, then the file will still be reloaded
2197 * the next time dns_zone_load is called.
2198 */
2199 TIME_NOW(&loadtime);
2200
2201 /*
2202 * Don't do the load if the file that stores the zone is older
2203 * than the last time the zone was loaded. If the zone has not
2204 * been loaded yet, zone->loadtime will be the epoch.
2205 */
2206 if (zone->masterfile != NULL) {
2207 isc_time_t filetime;
2208
2209 /*
2210 * The file is already loaded. If we are just doing a
2211 * "rndc reconfig", we are done.
2212 */
2213 if (!isc_time_isepoch(&zone->loadtime) &&
2214 (flags & DNS_ZONELOADFLAG_NOSTAT) != 0)
2215 {
2216 result = ISC_R_SUCCESS;
2217 goto cleanup;
2218 }
2219
2220 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
2221 !zone_touched(zone))
2222 {
2223 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2224 ISC_LOG_DEBUG(1),
2225 "skipping load: master file "
2226 "older than last load");
2227 result = DNS_R_UPTODATE;
2228 goto cleanup;
2229 }
2230
2231 /*
2232 * If the file modification time is in the past
2233 * set loadtime to that value.
2234 */
2235 result = isc_file_getmodtime(zone->masterfile, &filetime);
2236 if (result == ISC_R_SUCCESS &&
2237 isc_time_compare(&loadtime, &filetime) > 0)
2238 {
2239 loadtime = filetime;
2240 }
2241 }
2242
2243 /*
2244 * Built in zones (with the exception of empty zones) don't need
2245 * to be reloaded.
2246 */
2247 if (zone->type == dns_zone_primary &&
2248 strcmp(zone->db_argv[0], "_builtin") == 0 &&
2249 (zone->db_argc < 2 || strcmp(zone->db_argv[1], "empty") != 0) &&
2250 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
2251 {
2252 result = ISC_R_SUCCESS;
2253 goto cleanup;
2254 }
2255
2256 /*
2257 * Zones associated with a DLZ don't need to be loaded either,
2258 * but we need to associate the database with the zone object.
2259 */
2260 if (strcmp(zone->db_argv[0], "dlz") == 0) {
2261 dns_dlzdb_t *dlzdb;
2262 dns_dlzfindzone_t findzone;
2263
2264 for (dlzdb = ISC_LIST_HEAD(zone->view->dlz_unsearched);
2265 dlzdb != NULL; dlzdb = ISC_LIST_NEXT(dlzdb, link))
2266 {
2267 INSIST(DNS_DLZ_VALID(dlzdb));
2268 if (strcmp(zone->db_argv[1], dlzdb->dlzname) == 0) {
2269 break;
2270 }
2271 }
2272
2273 if (dlzdb == NULL) {
2274 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2275 ISC_LOG_ERROR,
2276 "DLZ %s does not exist or is set "
2277 "to 'search yes;'",
2278 zone->db_argv[1]);
2279 result = ISC_R_NOTFOUND;
2280 goto cleanup;
2281 }
2282
2283 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
2284 /* ask SDLZ driver if the zone is supported */
2285 findzone = dlzdb->implementation->methods->findzone;
2286 result = (*findzone)(dlzdb->implementation->driverarg,
2287 dlzdb->dbdata, dlzdb->mctx,
2288 zone->view->rdclass, &zone->origin, NULL,
2289 NULL, &db);
2290 if (result != ISC_R_NOTFOUND) {
2291 if (zone->db != NULL) {
2292 zone_detachdb(zone);
2293 }
2294 zone_attachdb(zone, db);
2295 dns_db_detach(&db);
2296 result = ISC_R_SUCCESS;
2297 }
2298 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
2299
2300 if (result == ISC_R_SUCCESS) {
2301 if (dlzdb->configure_callback == NULL) {
2302 goto cleanup;
2303 }
2304
2305 result = (*dlzdb->configure_callback)(zone->view, dlzdb,
2306 zone);
2307 if (result != ISC_R_SUCCESS) {
2308 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2309 ISC_LOG_ERROR,
2310 "DLZ configuration callback: %s",
2311 isc_result_totext(result));
2312 }
2313 }
2314 goto cleanup;
2315 }
2316
2317 if ((zone->type == dns_zone_secondary ||
2318 zone->type == dns_zone_mirror || zone->type == dns_zone_stub ||
2319 (zone->type == dns_zone_redirect && zone->primaries != NULL)) &&
2320 rbt)
2321 {
2322 if (zone->stream == NULL &&
2323 (zone->masterfile == NULL ||
2324 !isc_file_exists(zone->masterfile)))
2325 {
2326 if (zone->masterfile != NULL) {
2327 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2328 ISC_LOG_DEBUG(1),
2329 "no master file");
2330 }
2331 zone->refreshtime = now;
2332 if (zone->task != NULL) {
2333 zone_settimer(zone, &now);
2334 }
2335 result = ISC_R_SUCCESS;
2336 goto cleanup;
2337 }
2338 }
2339
2340 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
2341 "starting load");
2342
2343 result = dns_db_create(zone->mctx, zone->db_argv[0], &zone->origin,
2344 (zone->type == dns_zone_stub) ? dns_dbtype_stub
2345 : dns_dbtype_zone,
2346 zone->rdclass, zone->db_argc - 1,
2347 zone->db_argv + 1, &db);
2348
2349 if (result != ISC_R_SUCCESS) {
2350 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
2351 "loading zone: creating database: %s",
2352 isc_result_totext(result));
2353 goto cleanup;
2354 }
2355 dns_db_settask(db, zone->task);
2356
2357 if (zone->type == dns_zone_primary ||
2358 zone->type == dns_zone_secondary || zone->type == dns_zone_mirror)
2359 {
2360 result = dns_db_setgluecachestats(db, zone->gluecachestats);
2361 if (result == ISC_R_NOTIMPLEMENTED) {
2362 result = ISC_R_SUCCESS;
2363 }
2364 if (result != ISC_R_SUCCESS) {
2365 goto cleanup;
2366 }
2367 }
2368
2369 if (!dns_db_ispersistent(db)) {
2370 if (zone->masterfile != NULL || zone->stream != NULL) {
2371 result = zone_startload(db, zone, loadtime);
2372 } else {
2373 result = DNS_R_NOMASTERFILE;
2374 if (zone->type == dns_zone_primary ||
2375 (zone->type == dns_zone_redirect &&
2376 zone->primaries == NULL))
2377 {
2378 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2379 ISC_LOG_ERROR,
2380 "loading zone: "
2381 "no master file configured");
2382 goto cleanup;
2383 }
2384 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2385 ISC_LOG_INFO,
2386 "loading zone: "
2387 "no master file configured: continuing");
2388 }
2389 }
2390
2391 if (result == DNS_R_CONTINUE) {
2392 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING);
2393 if ((flags & DNS_ZONELOADFLAG_THAW) != 0) {
2394 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
2395 }
2396 goto cleanup;
2397 }
2398
2399 result = zone_postload(zone, db, loadtime, result);
2400
2401 cleanup:
2402 if (hasraw) {
2403 UNLOCK_ZONE(zone->raw);
2404 }
2405 if (!locked) {
2406 UNLOCK_ZONE(zone);
2407 }
2408 if (db != NULL) {
2409 dns_db_detach(&db);
2410 }
2411 return (result);
2412 }
2413
2414 isc_result_t
2415 dns_zone_load(dns_zone_t *zone, bool newonly) {
2416 return (zone_load(zone, newonly ? DNS_ZONELOADFLAG_NOSTAT : 0, false));
2417 }
2418
2419 static void
2420 zone_asyncload(isc_task_t *task, isc_event_t *event) {
2421 dns_asyncload_t *asl = event->ev_arg;
2422 dns_zone_t *zone = asl->zone;
2423 isc_result_t result;
2424
2425 UNUSED(task);
2426
2427 REQUIRE(DNS_ZONE_VALID(zone));
2428
2429 isc_event_free(&event);
2430
2431 LOCK_ZONE(zone);
2432 result = zone_load(zone, asl->flags, true);
2433 if (result != DNS_R_CONTINUE) {
2434 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
2435 }
2436 UNLOCK_ZONE(zone);
2437
2438 /* Inform the zone table we've finished loading */
2439 if (asl->loaded != NULL) {
2440 (asl->loaded)(asl->loaded_arg, zone, task);
2441 }
2442
2443 /* Reduce the quantum */
2444 isc_task_setquantum(zone->loadtask, 1);
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_zoneloaded_t done,
2452 void *arg) {
2453 isc_event_t *e;
2454 dns_asyncload_t *asl = NULL;
2455
2456 REQUIRE(DNS_ZONE_VALID(zone));
2457
2458 if (zone->zmgr == NULL) {
2459 return (ISC_R_FAILURE);
2460 }
2461
2462 /* If we already have a load pending, stop now */
2463 LOCK_ZONE(zone);
2464 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING)) {
2465 UNLOCK_ZONE(zone);
2466 return (ISC_R_ALREADYRUNNING);
2467 }
2468
2469 asl = isc_mem_get(zone->mctx, sizeof(*asl));
2470
2471 asl->zone = NULL;
2472 asl->flags = newonly ? DNS_ZONELOADFLAG_NOSTAT : 0;
2473 asl->loaded = done;
2474 asl->loaded_arg = arg;
2475
2476 e = isc_event_allocate(zone->zmgr->mctx, zone->zmgr, DNS_EVENT_ZONELOAD,
2477 zone_asyncload, asl, sizeof(isc_event_t));
2478
2479 zone_iattach(zone, &asl->zone);
2480 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADPENDING);
2481 isc_task_send(zone->loadtask, &e);
2482 UNLOCK_ZONE(zone);
2483
2484 return (ISC_R_SUCCESS);
2485 }
2486
2487 bool
2488 dns__zone_loadpending(dns_zone_t *zone) {
2489 REQUIRE(DNS_ZONE_VALID(zone));
2490
2491 return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING));
2492 }
2493
2494 isc_result_t
2495 dns_zone_loadandthaw(dns_zone_t *zone) {
2496 isc_result_t result;
2497
2498 if (inline_raw(zone)) {
2499 result = zone_load(zone->secure, DNS_ZONELOADFLAG_THAW, false);
2500 } else {
2501 /*
2502 * When thawing a zone, we don't know what changes
2503 * have been made. If we do DNSSEC maintenance on this
2504 * zone, schedule a full sign for this zone.
2505 */
2506 if (zone->type == dns_zone_primary &&
2507 DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
2508 {
2509 DNS_ZONEKEY_SETOPTION(zone, DNS_ZONEKEY_FULLSIGN);
2510 }
2511 result = zone_load(zone, DNS_ZONELOADFLAG_THAW, false);
2512 }
2513
2514 switch (result) {
2515 case DNS_R_CONTINUE:
2516 /* Deferred thaw. */
2517 break;
2518 case DNS_R_UPTODATE:
2519 case ISC_R_SUCCESS:
2520 case DNS_R_SEENINCLUDE:
2521 zone->update_disabled = false;
2522 break;
2523 case DNS_R_NOMASTERFILE:
2524 zone->update_disabled = false;
2525 break;
2526 default:
2527 /* Error, remain in disabled state. */
2528 break;
2529 }
2530 return (result);
2531 }
2532
2533 static unsigned int
2534 get_primary_options(dns_zone_t *zone) {
2535 unsigned int options;
2536
2537 options = DNS_MASTER_ZONE | DNS_MASTER_RESIGN;
2538 if (zone->type == dns_zone_secondary || zone->type == dns_zone_mirror ||
2539 (zone->type == dns_zone_redirect && zone->primaries == NULL))
2540 {
2541 options |= DNS_MASTER_SECONDARY;
2542 }
2543 if (zone->type == dns_zone_key) {
2544 options |= DNS_MASTER_KEY;
2545 }
2546 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS)) {
2547 options |= DNS_MASTER_CHECKNS;
2548 }
2549 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS)) {
2550 options |= DNS_MASTER_FATALNS;
2551 }
2552 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES)) {
2553 options |= DNS_MASTER_CHECKNAMES;
2554 }
2555 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) {
2556 options |= DNS_MASTER_CHECKNAMESFAIL;
2557 }
2558 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMX)) {
2559 options |= DNS_MASTER_CHECKMX;
2560 }
2561 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL)) {
2562 options |= DNS_MASTER_CHECKMXFAIL;
2563 }
2564 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKWILDCARD)) {
2565 options |= DNS_MASTER_CHECKWILDCARD;
2566 }
2567 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKTTL)) {
2568 options |= DNS_MASTER_CHECKTTL;
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 zone_gotreadhandle(isc_task_t *task, isc_event_t *event) {
2611 dns_load_t *load = event->ev_arg;
2612 isc_result_t result = ISC_R_SUCCESS;
2613 unsigned int options;
2614
2615 REQUIRE(DNS_LOAD_VALID(load));
2616
2617 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) {
2618 result = ISC_R_CANCELED;
2619 }
2620 isc_event_free(&event);
2621 if (result == ISC_R_CANCELED) {
2622 goto fail;
2623 }
2624
2625 options = get_primary_options(load->zone);
2626
2627 result = dns_master_loadfileinc(
2628 load->zone->masterfile, dns_db_origin(load->db),
2629 dns_db_origin(load->db), load->zone->rdclass, options, 0,
2630 &load->callbacks, task, zone_loaddone, load, &load->zone->lctx,
2631 zone_registerinclude, load->zone, load->zone->mctx,
2632 load->zone->masterformat, load->zone->maxttl);
2633 if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE &&
2634 result != DNS_R_SEENINCLUDE)
2635 {
2636 goto fail;
2637 }
2638 return;
2639
2640 fail:
2641 zone_loaddone(load, result);
2642 }
2643
2644 static void
2645 get_raw_serial(dns_zone_t *raw, dns_masterrawheader_t *rawdata) {
2646 isc_result_t result;
2647 unsigned int soacount;
2648
2649 LOCK(&raw->lock);
2650 if (raw->db != NULL) {
2651 result = zone_get_from_db(raw, raw->db, NULL, &soacount, NULL,
2652 &rawdata->sourceserial, NULL, NULL,
2653 NULL, NULL, NULL);
2654 if (result == ISC_R_SUCCESS && soacount > 0U) {
2655 rawdata->flags |= DNS_MASTERRAW_SOURCESERIALSET;
2656 }
2657 }
2658 UNLOCK(&raw->lock);
2659 }
2660
2661 static void
2662 zone_gotwritehandle(isc_task_t *task, isc_event_t *event) {
2663 const char me[] = "zone_gotwritehandle";
2664 dns_zone_t *zone = event->ev_arg;
2665 isc_result_t result = ISC_R_SUCCESS;
2666 dns_dbversion_t *version = NULL;
2667 dns_masterrawheader_t rawdata;
2668 dns_db_t *db = NULL;
2669
2670 REQUIRE(DNS_ZONE_VALID(zone));
2671 INSIST(task == zone->task);
2672 ENTER;
2673
2674 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) {
2675 result = ISC_R_CANCELED;
2676 }
2677 isc_event_free(&event);
2678 if (result == ISC_R_CANCELED) {
2679 goto fail;
2680 }
2681
2682 LOCK_ZONE(zone);
2683 INSIST(zone != zone->raw);
2684 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
2685 if (zone->db != NULL) {
2686 dns_db_attach(zone->db, &db);
2687 }
2688 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
2689 if (db != NULL) {
2690 const dns_master_style_t *output_style;
2691 dns_db_currentversion(db, &version);
2692 dns_master_initrawheader(&rawdata);
2693 if (inline_secure(zone)) {
2694 get_raw_serial(zone->raw, &rawdata);
2695 }
2696 if (zone->type == dns_zone_key) {
2697 output_style = &dns_master_style_keyzone;
2698 } else if (zone->masterstyle != NULL) {
2699 output_style = zone->masterstyle;
2700 } else {
2701 output_style = &dns_master_style_default;
2702 }
2703 result = dns_master_dumpasync(
2704 zone->mctx, db, version, output_style, zone->masterfile,
2705 zone->task, dump_done, zone, &zone->dctx,
2706 zone->masterformat, &rawdata);
2707 dns_db_closeversion(db, &version, false);
2708 } else {
2709 result = ISC_R_CANCELED;
2710 }
2711 if (db != NULL) {
2712 dns_db_detach(&db);
2713 }
2714 UNLOCK_ZONE(zone);
2715 if (result != DNS_R_CONTINUE) {
2716 goto fail;
2717 }
2718 return;
2719
2720 fail:
2721 dump_done(zone, result);
2722 }
2723
2724 /*
2725 * Save the raw serial number for inline-signing zones.
2726 * (XXX: Other information from the header will be used
2727 * for other purposes in the future, but for now this is
2728 * all we're interested in.)
2729 */
2730 static void
2731 zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
2732 if ((header->flags & DNS_MASTERRAW_SOURCESERIALSET) == 0) {
2733 return;
2734 }
2735
2736 zone->sourceserial = header->sourceserial;
2737 zone->sourceserialset = true;
2738 }
2739
2740 void
2741 dns_zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
2742 if (zone == NULL) {
2743 return;
2744 }
2745
2746 LOCK_ZONE(zone);
2747 zone_setrawdata(zone, header);
2748 UNLOCK_ZONE(zone);
2749 }
2750
2751 static isc_result_t
2752 zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
2753 const char me[] = "zone_startload";
2754 dns_load_t *load;
2755 isc_result_t result;
2756 isc_result_t tresult;
2757 unsigned int options;
2758
2759 ENTER;
2760
2761 dns_zone_rpz_enable_db(zone, db);
2762 dns_zone_catz_enable_db(zone, db);
2763
2764 options = get_primary_options(zone);
2765 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS)) {
2766 options |= DNS_MASTER_MANYERRORS;
2767 }
2768
2769 if (zone->zmgr != NULL && zone->db != NULL && zone->loadtask != NULL) {
2770 load = isc_mem_get(zone->mctx, sizeof(*load));
2771
2772 load->mctx = NULL;
2773 load->zone = NULL;
2774 load->db = NULL;
2775 load->loadtime = loadtime;
2776 load->magic = LOAD_MAGIC;
2777
2778 isc_mem_attach(zone->mctx, &load->mctx);
2779 zone_iattach(zone, &load->zone);
2780 dns_db_attach(db, &load->db);
2781 dns_rdatacallbacks_init(&load->callbacks);
2782 load->callbacks.rawdata = zone_setrawdata;
2783 zone_iattach(zone, &load->callbacks.zone);
2784 result = dns_db_beginload(db, &load->callbacks);
2785 if (result != ISC_R_SUCCESS) {
2786 goto cleanup;
2787 }
2788 result = zonemgr_getio(zone->zmgr, true, zone->loadtask,
2789 zone_gotreadhandle, load, &zone->readio);
2790 if (result != ISC_R_SUCCESS) {
2791 /*
2792 * We can't report multiple errors so ignore
2793 * the result of dns_db_endload().
2794 */
2795 (void)dns_db_endload(load->db, &load->callbacks);
2796 goto cleanup;
2797 } else {
2798 result = DNS_R_CONTINUE;
2799 }
2800 } else {
2801 dns_rdatacallbacks_t callbacks;
2802
2803 dns_rdatacallbacks_init(&callbacks);
2804 callbacks.rawdata = zone_setrawdata;
2805 zone_iattach(zone, &callbacks.zone);
2806 result = dns_db_beginload(db, &callbacks);
2807 if (result != ISC_R_SUCCESS) {
2808 zone_idetach(&callbacks.zone);
2809 return (result);
2810 }
2811
2812 if (zone->stream != NULL) {
2813 FILE *stream = NULL;
2814 DE_CONST(zone->stream, stream);
2815 result = dns_master_loadstream(
2816 stream, &zone->origin, &zone->origin,
2817 zone->rdclass, options, &callbacks, zone->mctx);
2818 } else {
2819 result = dns_master_loadfile(
2820 zone->masterfile, &zone->origin, &zone->origin,
2821 zone->rdclass, options, 0, &callbacks,
2822 zone_registerinclude, zone, zone->mctx,
2823 zone->masterformat, zone->maxttl);
2824 }
2825
2826 tresult = dns_db_endload(db, &callbacks);
2827 if (result == ISC_R_SUCCESS) {
2828 result = tresult;
2829 }
2830 zone_idetach(&callbacks.zone);
2831 }
2832
2833 return (result);
2834
2835 cleanup:
2836 load->magic = 0;
2837 dns_db_detach(&load->db);
2838 zone_idetach(&load->zone);
2839 zone_idetach(&load->callbacks.zone);
2840 isc_mem_detach(&load->mctx);
2841 isc_mem_put(zone->mctx, load, sizeof(*load));
2842 return (result);
2843 }
2844
2845 static bool
2846 zone_check_mx(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2847 dns_name_t *owner) {
2848 isc_result_t result;
2849 char ownerbuf[DNS_NAME_FORMATSIZE];
2850 char namebuf[DNS_NAME_FORMATSIZE];
2851 char altbuf[DNS_NAME_FORMATSIZE];
2852 dns_fixedname_t fixed;
2853 dns_name_t *foundname;
2854 int level;
2855
2856 /*
2857 * "." means the services does not exist.
2858 */
2859 if (dns_name_equal(name, dns_rootname)) {
2860 return (true);
2861 }
2862
2863 /*
2864 * Outside of zone.
2865 */
2866 if (!dns_name_issubdomain(name, &zone->origin)) {
2867 if (zone->checkmx != NULL) {
2868 return ((zone->checkmx)(zone, name, owner));
2869 }
2870 return (true);
2871 }
2872
2873 if (zone->type == dns_zone_primary) {
2874 level = ISC_LOG_ERROR;
2875 } else {
2876 level = ISC_LOG_WARNING;
2877 }
2878
2879 foundname = dns_fixedname_initname(&fixed);
2880
2881 result = dns_db_find(db, name, NULL, dns_rdatatype_a, 0, 0, NULL,
2882 foundname, NULL, NULL);
2883 if (result == ISC_R_SUCCESS) {
2884 return (true);
2885 }
2886
2887 if (result == DNS_R_NXRRSET) {
2888 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa, 0, 0,
2889 NULL, foundname, NULL, NULL);
2890 if (result == ISC_R_SUCCESS) {
2891 return (true);
2892 }
2893 }
2894
2895 dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2896 dns_name_format(name, namebuf, sizeof namebuf);
2897 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2898 result == DNS_R_EMPTYNAME)
2899 {
2900 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL)) {
2901 level = ISC_LOG_WARNING;
2902 }
2903 dns_zone_log(zone, level,
2904 "%s/MX '%s' has no address records (A or AAAA)",
2905 ownerbuf, namebuf);
2906 return ((level == ISC_LOG_WARNING) ? true : false);
2907 }
2908
2909 if (result == DNS_R_CNAME) {
2910 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
2911 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2912 {
2913 level = ISC_LOG_WARNING;
2914 }
2915 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
2916 dns_zone_log(zone, level,
2917 "%s/MX '%s' is a CNAME (illegal)",
2918 ownerbuf, namebuf);
2919 }
2920 return ((level == ISC_LOG_WARNING) ? true : false);
2921 }
2922
2923 if (result == DNS_R_DNAME) {
2924 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
2925 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2926 {
2927 level = ISC_LOG_WARNING;
2928 }
2929 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
2930 dns_name_format(foundname, altbuf, sizeof altbuf);
2931 dns_zone_log(zone, level,
2932 "%s/MX '%s' is below a DNAME"
2933 " '%s' (illegal)",
2934 ownerbuf, namebuf, altbuf);
2935 }
2936 return ((level == ISC_LOG_WARNING) ? true : false);
2937 }
2938
2939 if (zone->checkmx != NULL && result == DNS_R_DELEGATION) {
2940 return ((zone->checkmx)(zone, name, owner));
2941 }
2942
2943 return (true);
2944 }
2945
2946 static bool
2947 zone_check_srv(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2948 dns_name_t *owner) {
2949 isc_result_t result;
2950 char ownerbuf[DNS_NAME_FORMATSIZE];
2951 char namebuf[DNS_NAME_FORMATSIZE];
2952 char altbuf[DNS_NAME_FORMATSIZE];
2953 dns_fixedname_t fixed;
2954 dns_name_t *foundname;
2955 int level;
2956
2957 /*
2958 * "." means the services does not exist.
2959 */
2960 if (dns_name_equal(name, dns_rootname)) {
2961 return (true);
2962 }
2963
2964 /*
2965 * Outside of zone.
2966 */
2967 if (!dns_name_issubdomain(name, &zone->origin)) {
2968 if (zone->checksrv != NULL) {
2969 return ((zone->checksrv)(zone, name, owner));
2970 }
2971 return (true);
2972 }
2973
2974 if (zone->type == dns_zone_primary) {
2975 level = ISC_LOG_ERROR;
2976 } else {
2977 level = ISC_LOG_WARNING;
2978 }
2979
2980 foundname = dns_fixedname_initname(&fixed);
2981
2982 result = dns_db_find(db, name, NULL, dns_rdatatype_a, 0, 0, NULL,
2983 foundname, NULL, NULL);
2984 if (result == ISC_R_SUCCESS) {
2985 return (true);
2986 }
2987
2988 if (result == DNS_R_NXRRSET) {
2989 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa, 0, 0,
2990 NULL, foundname, NULL, NULL);
2991 if (result == ISC_R_SUCCESS) {
2992 return (true);
2993 }
2994 }
2995
2996 dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2997 dns_name_format(name, namebuf, sizeof namebuf);
2998 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2999 result == DNS_R_EMPTYNAME)
3000 {
3001 dns_zone_log(zone, level,
3002 "%s/SRV '%s' has no address records (A or AAAA)",
3003 ownerbuf, namebuf);
3004 /* XXX950 make fatal for 9.5.0. */
3005 return (true);
3006 }
3007
3008 if (result == DNS_R_CNAME) {
3009 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
3010 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
3011 {
3012 level = ISC_LOG_WARNING;
3013 }
3014 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
3015 dns_zone_log(zone, level,
3016 "%s/SRV '%s' is a CNAME (illegal)",
3017 ownerbuf, namebuf);
3018 }
3019 return ((level == ISC_LOG_WARNING) ? true : false);
3020 }
3021
3022 if (result == DNS_R_DNAME) {
3023 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
3024 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
3025 {
3026 level = ISC_LOG_WARNING;
3027 }
3028 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
3029 dns_name_format(foundname, altbuf, sizeof altbuf);
3030 dns_zone_log(zone, level,
3031 "%s/SRV '%s' is below a "
3032 "DNAME '%s' (illegal)",
3033 ownerbuf, namebuf, altbuf);
3034 }
3035 return ((level == ISC_LOG_WARNING) ? true : false);
3036 }
3037
3038 if (zone->checksrv != NULL && result == DNS_R_DELEGATION) {
3039 return ((zone->checksrv)(zone, name, owner));
3040 }
3041
3042 return (true);
3043 }
3044
3045 static bool
3046 zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
3047 dns_name_t *owner) {
3048 bool answer = true;
3049 isc_result_t result, tresult;
3050 char ownerbuf[DNS_NAME_FORMATSIZE];
3051 char namebuf[DNS_NAME_FORMATSIZE];
3052 char altbuf[DNS_NAME_FORMATSIZE];
3053 dns_fixedname_t fixed;
3054 dns_name_t *foundname;
3055 dns_rdataset_t a;
3056 dns_rdataset_t aaaa;
3057 int level;
3058
3059 /*
3060 * Outside of zone.
3061 */
3062 if (!dns_name_issubdomain(name, &zone->origin)) {
3063 if (zone->checkns != NULL) {
3064 return ((zone->checkns)(zone, name, owner, NULL, NULL));
3065 }
3066 return (true);
3067 }
3068
3069 if (zone->type == dns_zone_primary) {
3070 level = ISC_LOG_ERROR;
3071 } else {
3072 level = ISC_LOG_WARNING;
3073 }
3074
3075 foundname = dns_fixedname_initname(&fixed);
3076 dns_rdataset_init(&a);
3077 dns_rdataset_init(&aaaa);
3078
3079 /*
3080 * Perform a regular lookup to catch DNAME records then look
3081 * for glue.
3082 */
3083 result = dns_db_find(db, name, NULL, dns_rdatatype_a, 0, 0, NULL,
3084 foundname, &a, NULL);
3085 switch (result) {
3086 case ISC_R_SUCCESS:
3087 case DNS_R_DNAME:
3088 case DNS_R_CNAME:
3089 break;
3090 default:
3091 if (dns_rdataset_isassociated(&a)) {
3092 dns_rdataset_disassociate(&a);
3093 }
3094 result = dns_db_find(db, name, NULL, dns_rdatatype_a,
3095 DNS_DBFIND_GLUEOK, 0, NULL, foundname, &a,
3096 NULL);
3097 }
3098 if (result == ISC_R_SUCCESS) {
3099 dns_rdataset_disassociate(&a);
3100 return (true);
3101 } else if (result == DNS_R_DELEGATION) {
3102 dns_rdataset_disassociate(&a);
3103 }
3104
3105 if (result == DNS_R_NXRRSET || result == DNS_R_DELEGATION ||
3106 result == DNS_R_GLUE)
3107 {
3108 tresult = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
3109 DNS_DBFIND_GLUEOK, 0, NULL, foundname,
3110 &aaaa, NULL);
3111 if (tresult == ISC_R_SUCCESS) {
3112 if (dns_rdataset_isassociated(&a)) {
3113 dns_rdataset_disassociate(&a);
3114 }
3115 dns_rdataset_disassociate(&aaaa);
3116 return (true);
3117 }
3118 if (tresult == DNS_R_DELEGATION || tresult == DNS_R_DNAME) {
3119 dns_rdataset_disassociate(&aaaa);
3120 }
3121 if (result == DNS_R_GLUE || tresult == DNS_R_GLUE) {
3122 /*
3123 * Check glue against child zone.
3124 */
3125 if (zone->checkns != NULL) {
3126 answer = (zone->checkns)(zone, name, owner, &a,
3127 &aaaa);
3128 }
3129 if (dns_rdataset_isassociated(&a)) {
3130 dns_rdataset_disassociate(&a);
3131 }
3132 if (dns_rdataset_isassociated(&aaaa)) {
3133 dns_rdataset_disassociate(&aaaa);
3134 }
3135 return (answer);
3136 }
3137 }
3138
3139 dns_name_format(owner, ownerbuf, sizeof ownerbuf);
3140 dns_name_format(name, namebuf, sizeof namebuf);
3141 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
3142 result == DNS_R_EMPTYNAME || result == DNS_R_DELEGATION)
3143 {
3144 const char *what;
3145 bool required = false;
3146 if (dns_name_issubdomain(name, owner)) {
3147 what = "REQUIRED GLUE ";
3148 required = true;
3149 } else if (result == DNS_R_DELEGATION) {
3150 what = "SIBLING GLUE ";
3151 } else {
3152 what = "";
3153 }
3154
3155 if (result != DNS_R_DELEGATION || required ||
3156 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSIBLING))
3157 {
3158 dns_zone_log(zone, level,
3159 "%s/NS '%s' has no %s"
3160 "address records (A or AAAA)",
3161 ownerbuf, namebuf, what);
3162 /*
3163 * Log missing address record.
3164 */
3165 if (result == DNS_R_DELEGATION && zone->checkns != NULL)
3166 {
3167 (void)(zone->checkns)(zone, name, owner, &a,
3168 &aaaa);
3169 }
3170 /* XXX950 make fatal for 9.5.0. */
3171 /* answer = false; */
3172 }
3173 } else if (result == DNS_R_CNAME) {
3174 dns_zone_log(zone, level, "%s/NS '%s' is a CNAME (illegal)",
3175 ownerbuf, namebuf);
3176 /* XXX950 make fatal for 9.5.0. */
3177 /* answer = false; */
3178 } else if (result == DNS_R_DNAME) {
3179 dns_name_format(foundname, altbuf, sizeof altbuf);
3180 dns_zone_log(zone, level,
3181 "%s/NS '%s' is below a DNAME '%s' (illegal)",
3182 ownerbuf, namebuf, altbuf);
3183 /* XXX950 make fatal for 9.5.0. */
3184 /* answer = false; */
3185 }
3186
3187 if (dns_rdataset_isassociated(&a)) {
3188 dns_rdataset_disassociate(&a);
3189 }
3190 if (dns_rdataset_isassociated(&aaaa)) {
3191 dns_rdataset_disassociate(&aaaa);
3192 }
3193 return (answer);
3194 }
3195
3196 static bool
3197 zone_rrset_check_dup(dns_zone_t *zone, dns_name_t *owner,
3198 dns_rdataset_t *rdataset) {
3199 dns_rdataset_t tmprdataset;
3200 isc_result_t result;
3201 bool answer = true;
3202 bool format = true;
3203 int level = ISC_LOG_WARNING;
3204 char ownerbuf[DNS_NAME_FORMATSIZE];
3205 char typebuf[DNS_RDATATYPE_FORMATSIZE];
3206 unsigned int count1 = 0;
3207
3208 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRRFAIL)) {
3209 level = ISC_LOG_ERROR;
3210 }
3211
3212 dns_rdataset_init(&tmprdataset);
3213 for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
3214 result = dns_rdataset_next(rdataset))
3215 {
3216 dns_rdata_t rdata1 = DNS_RDATA_INIT;
3217 unsigned int count2 = 0;
3218
3219 count1++;
3220 dns_rdataset_current(rdataset, &rdata1);
3221 dns_rdataset_clone(rdataset, &tmprdataset);
3222 for (result = dns_rdataset_first(&tmprdataset);
3223 result == ISC_R_SUCCESS;
3224 result = dns_rdataset_next(&tmprdataset))
3225 {
3226 dns_rdata_t rdata2 = DNS_RDATA_INIT;
3227 count2++;
3228 if (count1 >= count2) {
3229 continue;
3230 }
3231 dns_rdataset_current(&tmprdataset, &rdata2);
3232 if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) {
3233 if (format) {
3234 dns_name_format(owner, ownerbuf,
3235 sizeof ownerbuf);
3236 dns_rdatatype_format(rdata1.type,
3237 typebuf,
3238 sizeof(typebuf));
3239 format = false;
3240 }
3241 dns_zone_log(zone, level,
3242 "%s/%s has "
3243 "semantically identical records",
3244 ownerbuf, typebuf);
3245 if (level == ISC_LOG_ERROR) {
3246 answer = false;
3247 }
3248 break;
3249 }
3250 }
3251 dns_rdataset_disassociate(&tmprdataset);
3252 if (!format) {
3253 break;
3254 }
3255 }
3256 return (answer);
3257 }
3258
3259 static bool
3260 zone_check_dup(dns_zone_t *zone, dns_db_t *db) {
3261 dns_dbiterator_t *dbiterator = NULL;
3262 dns_dbnode_t *node = NULL;
3263 dns_fixedname_t fixed;
3264 dns_name_t *name;
3265 dns_rdataset_t rdataset;
3266 dns_rdatasetiter_t *rdsit = NULL;
3267 bool ok = true;
3268 isc_result_t result;
3269
3270 name = dns_fixedname_initname(&fixed);
3271 dns_rdataset_init(&rdataset);
3272
3273 result = dns_db_createiterator(db, 0, &dbiterator);
3274 if (result != ISC_R_SUCCESS) {
3275 return (true);
3276 }
3277
3278 for (result = dns_dbiterator_first(dbiterator); result == ISC_R_SUCCESS;
3279 result = dns_dbiterator_next(dbiterator))
3280 {
3281 result = dns_dbiterator_current(dbiterator, &node, name);
3282 if (result != ISC_R_SUCCESS) {
3283 continue;
3284 }
3285
3286 result = dns_db_allrdatasets(db, node, NULL, 0, 0, &rdsit);
3287 if (result != ISC_R_SUCCESS) {
3288 continue;
3289 }
3290
3291 for (result = dns_rdatasetiter_first(rdsit);
3292 result == ISC_R_SUCCESS;
3293 result = dns_rdatasetiter_next(rdsit))
3294 {
3295 dns_rdatasetiter_current(rdsit, &rdataset);
3296 if (!zone_rrset_check_dup(zone, name, &rdataset)) {
3297 ok = false;
3298 }
3299 dns_rdataset_disassociate(&rdataset);
3300 }
3301 dns_rdatasetiter_destroy(&rdsit);
3302 dns_db_detachnode(db, &node);
3303 }
3304
3305 if (node != NULL) {
3306 dns_db_detachnode(db, &node);
3307 }
3308 dns_dbiterator_destroy(&dbiterator);
3309
3310 return (ok);
3311 }
3312
3313 static bool
3314 isspf(const dns_rdata_t *rdata) {
3315 char buf[1024];
3316 const unsigned char *data = rdata->data;
3317 unsigned int rdl = rdata->length, i = 0, tl, len;
3318
3319 while (rdl > 0U) {
3320 len = tl = *data;
3321 ++data;
3322 --rdl;
3323 INSIST(tl <= rdl);
3324 if (len > sizeof(buf) - i - 1) {
3325 len = sizeof(buf) - i - 1;
3326 }
3327 memmove(buf + i, data, len);
3328 i += len;
3329 data += tl;
3330 rdl -= tl;
3331 }
3332
3333 if (i < 6U) {
3334 return (false);
3335 }
3336
3337 buf[i] = 0;
3338 if (strncmp(buf, "v=spf1", 6) == 0 && (buf[6] == 0 || buf[6] == ' ')) {
3339 return (true);
3340 }
3341 return (false);
3342 }
3343
3344 static bool
3345 integrity_checks(dns_zone_t *zone, dns_db_t *db) {
3346 dns_dbiterator_t *dbiterator = NULL;
3347 dns_dbnode_t *node = NULL;
3348 dns_rdataset_t rdataset;
3349 dns_fixedname_t fixed;
3350 dns_fixedname_t fixedbottom;
3351 dns_rdata_mx_t mx;
3352 dns_rdata_ns_t ns;
3353 dns_rdata_in_srv_t srv;
3354 dns_rdata_t rdata;
3355 dns_name_t *name;
3356 dns_name_t *bottom;
3357 isc_result_t result;
3358 bool ok = true, have_spf, have_txt;
3359
3360 name = dns_fixedname_initname(&fixed);
3361 bottom = dns_fixedname_initname(&fixedbottom);
3362 dns_rdataset_init(&rdataset);
3363 dns_rdata_init(&rdata);
3364
3365 result = dns_db_createiterator(db, 0, &dbiterator);
3366 if (result != ISC_R_SUCCESS) {
3367 return (true);
3368 }
3369
3370 result = dns_dbiterator_first(dbiterator);
3371 while (result == ISC_R_SUCCESS) {
3372 result = dns_dbiterator_current(dbiterator, &node, name);
3373 if (result != ISC_R_SUCCESS) {
3374 goto cleanup;
3375 }
3376
3377 /*
3378 * Is this name visible in the zone?
3379 */
3380 if (!dns_name_issubdomain(name, &zone->origin) ||
3381 (dns_name_countlabels(bottom) > 0 &&
3382 dns_name_issubdomain(name, bottom)))
3383 {
3384 goto next;
3385 }
3386
3387 dns_dbiterator_pause(dbiterator);
3388
3389 /*
3390 * Don't check the NS records at the origin.
3391 */
3392 if (dns_name_equal(name, &zone->origin)) {
3393 goto checkfordname;
3394 }
3395
3396 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ns,
3397 0, 0, &rdataset, NULL);
3398 if (result != ISC_R_SUCCESS) {
3399 goto checkfordname;
3400 }
3401 /*
3402 * Remember bottom of zone due to NS.
3403 */
3404 dns_name_copy(name, bottom);
3405
3406 result = dns_rdataset_first(&rdataset);
3407 while (result == ISC_R_SUCCESS) {
3408 dns_rdataset_current(&rdataset, &rdata);
3409 result = dns_rdata_tostruct(&rdata, &ns, NULL);
3410 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3411 if (!zone_check_glue(zone, db, &ns.name, name)) {
3412 ok = false;
3413 }
3414 dns_rdata_reset(&rdata);
3415 result = dns_rdataset_next(&rdataset);
3416 }
3417 dns_rdataset_disassociate(&rdataset);
3418 goto next;
3419
3420 checkfordname:
3421 result = dns_db_findrdataset(db, node, NULL,
3422 dns_rdatatype_dname, 0, 0,
3423 &rdataset, NULL);
3424 if (result == ISC_R_SUCCESS) {
3425 /*
3426 * Remember bottom of zone due to DNAME.
3427 */
3428 dns_name_copy(name, bottom);
3429 dns_rdataset_disassociate(&rdataset);
3430 }
3431
3432 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_mx,
3433 0, 0, &rdataset, NULL);
3434 if (result != ISC_R_SUCCESS) {
3435 goto checksrv;
3436 }
3437 result = dns_rdataset_first(&rdataset);
3438 while (result == ISC_R_SUCCESS) {
3439 dns_rdataset_current(&rdataset, &rdata);
3440 result = dns_rdata_tostruct(&rdata, &mx, NULL);
3441 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3442 if (!zone_check_mx(zone, db, &mx.mx, name)) {
3443 ok = false;
3444 }
3445 dns_rdata_reset(&rdata);
3446 result = dns_rdataset_next(&rdataset);
3447 }
3448 dns_rdataset_disassociate(&rdataset);
3449
3450 checksrv:
3451 if (zone->rdclass != dns_rdataclass_in) {
3452 goto next;
3453 }
3454 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_srv,
3455 0, 0, &rdataset, NULL);
3456 if (result != ISC_R_SUCCESS) {
3457 goto checkspf;
3458 }
3459 result = dns_rdataset_first(&rdataset);
3460 while (result == ISC_R_SUCCESS) {
3461 dns_rdataset_current(&rdataset, &rdata);
3462 result = dns_rdata_tostruct(&rdata, &srv, NULL);
3463 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3464 if (!zone_check_srv(zone, db, &srv.target, name)) {
3465 ok = false;
3466 }
3467 dns_rdata_reset(&rdata);
3468 result = dns_rdataset_next(&rdataset);
3469 }
3470 dns_rdataset_disassociate(&rdataset);
3471
3472 checkspf:
3473 /*
3474 * Check if there is a type SPF record without an
3475 * SPF-formatted type TXT record also being present.
3476 */
3477 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSPF)) {
3478 goto next;
3479 }
3480 if (zone->rdclass != dns_rdataclass_in) {
3481 goto next;
3482 }
3483 have_spf = have_txt = false;
3484 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_spf,
3485 0, 0, &rdataset, NULL);
3486 if (result == ISC_R_SUCCESS) {
3487 dns_rdataset_disassociate(&rdataset);
3488 have_spf = true;
3489 }
3490 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_txt,
3491 0, 0, &rdataset, NULL);
3492 if (result != ISC_R_SUCCESS) {
3493 goto notxt;
3494 }
3495 result = dns_rdataset_first(&rdataset);
3496 while (result == ISC_R_SUCCESS) {
3497 dns_rdataset_current(&rdataset, &rdata);
3498 have_txt = isspf(&rdata);
3499 dns_rdata_reset(&rdata);
3500 if (have_txt) {
3501 break;
3502 }
3503 result = dns_rdataset_next(&rdataset);
3504 }
3505 dns_rdataset_disassociate(&rdataset);
3506
3507 notxt:
3508 if (have_spf && !have_txt) {
3509 char namebuf[DNS_NAME_FORMATSIZE];
3510
3511 dns_name_format(name, namebuf, sizeof(namebuf));
3512 dns_zone_log(zone, ISC_LOG_WARNING,
3513 "'%s' found type "
3514 "SPF record but no SPF TXT record found, "
3515 "add matching type TXT record",
3516 namebuf);
3517 }
3518
3519 next:
3520 dns_db_detachnode(db, &node);
3521 result = dns_dbiterator_next(dbiterator);
3522 }
3523
3524 cleanup:
3525 if (node != NULL) {
3526 dns_db_detachnode(db, &node);
3527 }
3528 dns_dbiterator_destroy(&dbiterator);
3529
3530 return (ok);
3531 }
3532
3533 /*
3534 * OpenSSL verification of RSA keys with exponent 3 is known to be
3535 * broken prior OpenSSL 0.9.8c/0.9.7k. Look for such keys and warn
3536 * if they are in use.
3537 */
3538 static void
3539 zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
3540 dns_dbnode_t *node = NULL;
3541 dns_dbversion_t *version = NULL;
3542 dns_rdata_dnskey_t dnskey;
3543 dns_rdata_t rdata = DNS_RDATA_INIT;
3544 dns_rdataset_t rdataset;
3545 isc_result_t result;
3546
3547 result = dns_db_findnode(db, &zone->origin, false, &node);
3548 if (result != ISC_R_SUCCESS) {
3549 goto cleanup;
3550 }
3551
3552 dns_db_currentversion(db, &version);
3553 dns_rdataset_init(&rdataset);
3554 result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
3555 dns_rdatatype_none, 0, &rdataset, NULL);
3556 if (result != ISC_R_SUCCESS) {
3557 goto cleanup;
3558 }
3559
3560 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
3561 result = dns_rdataset_next(&rdataset))
3562 {
3563 dns_rdataset_current(&rdataset, &rdata);
3564 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
3565 INSIST(result == ISC_R_SUCCESS);
3566
3567 /*
3568 * RFC 3110, section 4: Performance Considerations:
3569 *
3570 * A public exponent of 3 minimizes the effort needed to verify
3571 * a signature. Use of 3 as the public exponent is weak for
3572 * confidentiality uses since, if the same data can be collected
3573 * encrypted under three different keys with an exponent of 3
3574 * then, using the Chinese Remainder Theorem [NETSEC], the
3575 * original plain text can be easily recovered. If a key is
3576 * known to be used only for authentication, as is the case with
3577 * DNSSEC, then an exponent of 3 is acceptable. However other
3578 * applications in the future may wish to leverage DNS
3579 * distributed keys for applications that do require
3580 * confidentiality. For keys which might have such other uses,
3581 * a more conservative choice would be 65537 (F4, the fourth
3582 * fermat number).
3583 */
3584 if (dnskey.datalen > 1 && dnskey.data[0] == 1 &&
3585 dnskey.data[1] == 3 &&
3586 (dnskey.algorithm == DNS_KEYALG_RSAMD5 ||
3587 dnskey.algorithm == DNS_KEYALG_RSASHA1 ||
3588 dnskey.algorithm == DNS_KEYALG_NSEC3RSASHA1 ||
3589 dnskey.algorithm == DNS_KEYALG_RSASHA256 ||
3590 dnskey.algorithm == DNS_KEYALG_RSASHA512))
3591 {
3592 char algorithm[DNS_SECALG_FORMATSIZE];
3593 isc_region_t r;
3594
3595 dns_rdata_toregion(&rdata, &r);
3596 dns_secalg_format(dnskey.algorithm, algorithm,
3597 sizeof(algorithm));
3598
3599 dnssec_log(zone, ISC_LOG_WARNING,
3600 "weak %s (%u) key found (exponent=3, id=%u)",
3601 algorithm, dnskey.algorithm,
3602 dst_region_computeid(&r));
3603 }
3604 dns_rdata_reset(&rdata);
3605 }
3606 dns_rdataset_disassociate(&rdataset);
3607
3608 cleanup:
3609 if (node != NULL) {
3610 dns_db_detachnode(db, &node);
3611 }
3612 if (version != NULL) {
3613 dns_db_closeversion(db, &version, false);
3614 }
3615 }
3616
3617 static void
3618 resume_signingwithkey(dns_zone_t *zone) {
3619 dns_dbnode_t *node = NULL;
3620 dns_dbversion_t *version = NULL;
3621 dns_rdata_t rdata = DNS_RDATA_INIT;
3622 dns_rdataset_t rdataset;
3623 isc_result_t result;
3624 dns_db_t *db = NULL;
3625
3626 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3627 if (zone->db != NULL) {
3628 dns_db_attach(zone->db, &db);
3629 }
3630 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3631 if (db == NULL) {
3632 goto cleanup;
3633 }
3634
3635 result = dns_db_findnode(db, &zone->origin, false, &node);
3636 if (result != ISC_R_SUCCESS) {
3637 goto cleanup;
3638 }
3639
3640 dns_db_currentversion(db, &version);
3641 dns_rdataset_init(&rdataset);
3642 result = dns_db_findrdataset(db, node, version, zone->privatetype,
3643 dns_rdatatype_none, 0, &rdataset, NULL);
3644 if (result != ISC_R_SUCCESS) {
3645 INSIST(!dns_rdataset_isassociated(&rdataset));
3646 goto cleanup;
3647 }
3648
3649 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
3650 result = dns_rdataset_next(&rdataset))
3651 {
3652 dns_rdataset_current(&rdataset, &rdata);
3653 if (rdata.length != 5 || rdata.data[0] == 0 ||
3654 rdata.data[4] != 0)
3655 {
3656 dns_rdata_reset(&rdata);
3657 continue;
3658 }
3659
3660 result = zone_signwithkey(zone, rdata.data[0],
3661 (rdata.data[1] << 8) | rdata.data[2],
3662 rdata.data[3]);
3663 if (result != ISC_R_SUCCESS) {
3664 dnssec_log(zone, ISC_LOG_ERROR,
3665 "zone_signwithkey failed: %s",
3666 isc_result_totext(result));
3667 }
3668 dns_rdata_reset(&rdata);
3669 }
3670 dns_rdataset_disassociate(&rdataset);
3671
3672 cleanup:
3673 if (db != NULL) {
3674 if (node != NULL) {
3675 dns_db_detachnode(db, &node);
3676 }
3677 if (version != NULL) {
3678 dns_db_closeversion(db, &version, false);
3679 }
3680 dns_db_detach(&db);
3681 }
3682 }
3683
3684 /*
3685 * Initiate adding/removing NSEC3 records belonging to the chain defined by the
3686 * supplied NSEC3PARAM RDATA.
3687 *
3688 * Zone must be locked by caller.
3689 */
3690 static isc_result_t
3691 zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
3692 dns_nsec3chain_t *nsec3chain, *current;
3693 dns_dbversion_t *version = NULL;
3694 bool nseconly = false, nsec3ok = false;
3695 isc_result_t result;
3696 isc_time_t now;
3697 unsigned int options = 0;
3698 char saltbuf[255 * 2 + 1];
3699 char flags[sizeof("INITIAL|REMOVE|CREATE|NONSEC|OPTOUT")];
3700 dns_db_t *db = NULL;
3701
3702 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3703 if (zone->db != NULL) {
3704 dns_db_attach(zone->db, &db);
3705 }
3706 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3707
3708 if (db == NULL) {
3709 result = ISC_R_SUCCESS;
3710 goto cleanup;
3711 }
3712
3713 /*
3714 * If this zone is not NSEC3-capable, attempting to remove any NSEC3
3715 * chain from it is pointless as it would not be possible for the
3716 * latter to exist in the first place.
3717 */
3718 dns_db_currentversion(db, &version);
3719 result = dns_nsec_nseconly(db, version, NULL, &nseconly);
3720 nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
3721 dns_db_closeversion(db, &version, false);
3722 if (!nsec3ok && (nsec3param->flags & DNS_NSEC3FLAG_REMOVE) == 0) {
3723 result = ISC_R_SUCCESS;
3724 goto cleanup;
3725 }
3726
3727 /*
3728 * Allocate and initialize structure preserving state of
3729 * adding/removing records belonging to this NSEC3 chain between
3730 * separate zone_nsec3chain() calls.
3731 */
3732 nsec3chain = isc_mem_get(zone->mctx, sizeof *nsec3chain);
3733
3734 nsec3chain->magic = 0;
3735 nsec3chain->done = false;
3736 nsec3chain->db = NULL;
3737 nsec3chain->dbiterator = NULL;
3738 nsec3chain->nsec3param.common.rdclass = nsec3param->common.rdclass;
3739 nsec3chain->nsec3param.common.rdtype = nsec3param->common.rdtype;
3740 nsec3chain->nsec3param.hash = nsec3param->hash;
3741 nsec3chain->nsec3param.iterations = nsec3param->iterations;
3742 nsec3chain->nsec3param.flags = nsec3param->flags;
3743 nsec3chain->nsec3param.salt_length = nsec3param->salt_length;
3744 memmove(nsec3chain->salt, nsec3param->salt, nsec3param->salt_length);
3745 nsec3chain->nsec3param.salt = nsec3chain->salt;
3746 nsec3chain->seen_nsec = false;
3747 nsec3chain->delete_nsec = false;
3748 nsec3chain->save_delete_nsec = false;
3749
3750 /*
3751 * Log NSEC3 parameters defined by supplied NSEC3PARAM RDATA.
3752 */
3753 if (nsec3param->flags == 0) {
3754 strlcpy(flags, "NONE", sizeof(flags));
3755 } else {
3756 flags[0] = '\0';
3757 if ((nsec3param->flags & DNS_NSEC3FLAG_REMOVE) != 0) {
3758 strlcat(flags, "REMOVE", sizeof(flags));
3759 }
3760 if ((nsec3param->flags & DNS_NSEC3FLAG_INITIAL) != 0) {
3761 if (flags[0] == '\0') {
3762 strlcpy(flags, "INITIAL", sizeof(flags));
3763 } else {
3764 strlcat(flags, "|INITIAL", sizeof(flags));
3765 }
3766 }
3767 if ((nsec3param->flags & DNS_NSEC3FLAG_CREATE) != 0) {
3768 if (flags[0] == '\0') {
3769 strlcpy(flags, "CREATE", sizeof(flags));
3770 } else {
3771 strlcat(flags, "|CREATE", sizeof(flags));
3772 }
3773 }
3774 if ((nsec3param->flags & DNS_NSEC3FLAG_NONSEC) != 0) {
3775 if (flags[0] == '\0') {
3776 strlcpy(flags, "NONSEC", sizeof(flags));
3777 } else {
3778 strlcat(flags, "|NONSEC", sizeof(flags));
3779 }
3780 }
3781 if ((nsec3param->flags & DNS_NSEC3FLAG_OPTOUT) != 0) {
3782 if (flags[0] == '\0') {
3783 strlcpy(flags, "OPTOUT", sizeof(flags));
3784 } else {
3785 strlcat(flags, "|OPTOUT", sizeof(flags));
3786 }
3787 }
3788 }
3789 result = dns_nsec3param_salttotext(nsec3param, saltbuf,
3790 sizeof(saltbuf));
3791 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3792 dnssec_log(zone, ISC_LOG_INFO, "zone_addnsec3chain(%u,%s,%u,%s)",
3793 nsec3param->hash, flags, nsec3param->iterations, saltbuf);
3794
3795 /*
3796 * If the NSEC3 chain defined by the supplied NSEC3PARAM RDATA is
3797 * currently being processed, interrupt its processing to avoid
3798 * simultaneously adding and removing records for the same NSEC3 chain.
3799 */
3800 for (current = ISC_LIST_HEAD(zone->nsec3chain); current != NULL;
3801 current = ISC_LIST_NEXT(current, link))
3802 {
3803 if ((current->db == db) &&
3804 (current->nsec3param.hash == nsec3param->hash) &&
3805 (current->nsec3param.iterations ==
3806 nsec3param->iterations) &&
3807 (current->nsec3param.salt_length ==
3808 nsec3param->salt_length) &&
3809 memcmp(current->nsec3param.salt, nsec3param->salt,
3810 nsec3param->salt_length) == 0)
3811 {
3812 current->done = true;
3813 }
3814 }
3815
3816 /*
3817 * Attach zone database to the structure initialized above and create
3818 * an iterator for it with appropriate options in order to avoid
3819 * creating NSEC3 records for NSEC3 records.
3820 */
3821 dns_db_attach(db, &nsec3chain->db);
3822 if ((nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0) {
3823 options = DNS_DB_NONSEC3;
3824 }
3825 result = dns_db_createiterator(nsec3chain->db, options,
3826 &nsec3chain->dbiterator);
3827 if (result == ISC_R_SUCCESS) {
3828 result = dns_dbiterator_first(nsec3chain->dbiterator);
3829 }
3830 if (result == ISC_R_SUCCESS) {
3831 /*
3832 * Database iterator initialization succeeded. We are now
3833 * ready to kick off adding/removing records belonging to this
3834 * NSEC3 chain. Append the structure initialized above to the
3835 * "nsec3chain" list for the zone and set the appropriate zone
3836 * timer so that zone_nsec3chain() is called as soon as
3837 * possible.
3838 */
3839 dns_dbiterator_pause(nsec3chain->dbiterator);
3840 ISC_LIST_INITANDAPPEND(zone->nsec3chain, nsec3chain, link);
3841 nsec3chain = NULL;
3842 if (isc_time_isepoch(&zone->nsec3chaintime)) {
3843 TIME_NOW(&now);
3844 zone->nsec3chaintime = now;
3845 if (zone->task != NULL) {
3846 zone_settimer(zone, &now);
3847 }
3848 }
3849 }
3850
3851 if (nsec3chain != NULL) {
3852 if (nsec3chain->db != NULL) {
3853 dns_db_detach(&nsec3chain->db);
3854 }
3855 if (nsec3chain->dbiterator != NULL) {
3856 dns_dbiterator_destroy(&nsec3chain->dbiterator);
3857 }
3858 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
3859 }
3860
3861 cleanup:
3862 if (db != NULL) {
3863 dns_db_detach(&db);
3864 }
3865 return (result);
3866 }
3867
3868 /*
3869 * Find private-type records at the zone apex which signal that an NSEC3 chain
3870 * should be added or removed. For each such record, extract NSEC3PARAM RDATA
3871 * and pass it to zone_addnsec3chain().
3872 *
3873 * Zone must be locked by caller.
3874 */
3875 static void
3876 resume_addnsec3chain(dns_zone_t *zone) {
3877 dns_dbnode_t *node = NULL;
3878 dns_dbversion_t *version = NULL;
3879 dns_rdataset_t rdataset;
3880 isc_result_t result;
3881 dns_rdata_nsec3param_t nsec3param;
3882 bool nseconly = false, nsec3ok = false;
3883 dns_db_t *db = NULL;
3884
3885 INSIST(LOCKED_ZONE(zone));
3886
3887 if (zone->privatetype == 0) {
3888 return;
3889 }
3890
3891 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3892 if (zone->db != NULL) {
3893 dns_db_attach(zone->db, &db);
3894 }
3895 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3896 if (db == NULL) {
3897 goto cleanup;
3898 }
3899
3900 result = dns_db_findnode(db, &zone->origin, false, &node);
3901 if (result != ISC_R_SUCCESS) {
3902 goto cleanup;
3903 }
3904
3905 dns_db_currentversion(db, &version);
3906
3907 /*
3908 * In order to create NSEC3 chains we need the DNSKEY RRset at zone
3909 * apex to exist and contain no keys using NSEC-only algorithms.
3910 */
3911 result = dns_nsec_nseconly(db, version, NULL, &nseconly);
3912 nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
3913
3914 /*
3915 * Get the RRset containing all private-type records at the zone apex.
3916 */
3917 dns_rdataset_init(&rdataset);
3918 result = dns_db_findrdataset(db, node, version, zone->privatetype,
3919 dns_rdatatype_none, 0, &rdataset, NULL);
3920 if (result != ISC_R_SUCCESS) {
3921 INSIST(!dns_rdataset_isassociated(&rdataset));
3922 goto cleanup;
3923 }
3924
3925 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
3926 result = dns_rdataset_next(&rdataset))
3927 {
3928 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
3929 dns_rdata_t rdata = DNS_RDATA_INIT;
3930 dns_rdata_t private = DNS_RDATA_INIT;
3931
3932 dns_rdataset_current(&rdataset, &private);
3933 /*
3934 * Try extracting NSEC3PARAM RDATA from this private-type
3935 * record. Failure means this private-type record does not
3936 * represent an NSEC3PARAM record, so skip it.
3937 */
3938 if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
3939 sizeof(buf)))
3940 {
3941 continue;
3942 }
3943 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
3944 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3945 if (((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) ||
3946 ((nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0 && nsec3ok))
3947 {
3948 /*
3949 * Pass the NSEC3PARAM RDATA contained in this
3950 * private-type record to zone_addnsec3chain() so that
3951 * it can kick off adding or removing NSEC3 records.
3952 */
3953 result = zone_addnsec3chain(zone, &nsec3param);
3954 if (result != ISC_R_SUCCESS) {
3955 dnssec_log(zone, ISC_LOG_ERROR,
3956 "zone_addnsec3chain failed: %s",
3957 isc_result_totext(result));
3958 }
3959 }
3960 }
3961 dns_rdataset_disassociate(&rdataset);
3962
3963 cleanup:
3964 if (db != NULL) {
3965 if (node != NULL) {
3966 dns_db_detachnode(db, &node);
3967 }
3968 if (version != NULL) {
3969 dns_db_closeversion(db, &version, false);
3970 }
3971 dns_db_detach(&db);
3972 }
3973 }
3974
3975 static void
3976 set_resigntime(dns_zone_t *zone) {
3977 dns_rdataset_t rdataset;
3978 dns_fixedname_t fixed;
3979 unsigned int resign;
3980 isc_result_t result;
3981 uint32_t nanosecs;
3982 dns_db_t *db = NULL;
3983
3984 INSIST(LOCKED_ZONE(zone));
3985
3986 /* We only re-sign zones that can be dynamically updated */
3987 if (!dns_zone_isdynamic(zone, false)) {
3988 return;
3989 }
3990
3991 if (inline_raw(zone)) {
3992 return;
3993 }
3994
3995 dns_rdataset_init(&rdataset);
3996 dns_fixedname_init(&fixed);
3997
3998 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3999 if (zone->db != NULL) {
4000 dns_db_attach(zone->db, &db);
4001 }
4002 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
4003 if (db == NULL) {
4004 isc_time_settoepoch(&zone->resigntime);
4005 return;
4006 }
4007
4008 result = dns_db_getsigningtime(db, &rdataset,
4009 dns_fixedname_name(&fixed));
4010 if (result != ISC_R_SUCCESS) {
4011 isc_time_settoepoch(&zone->resigntime);
4012 goto cleanup;
4013 }
4014
4015 resign = rdataset.resign - dns_zone_getsigresigninginterval(zone);
4016 dns_rdataset_disassociate(&rdataset);
4017 nanosecs = isc_random_uniform(1000000000);
4018 isc_time_set(&zone->resigntime, resign, nanosecs);
4019
4020 cleanup:
4021 dns_db_detach(&db);
4022 return;
4023 }
4024
4025 static isc_result_t
4026 check_nsec3param(dns_zone_t *zone, dns_db_t *db) {
4027 bool ok = false;
4028 dns_dbnode_t *node = NULL;
4029 dns_dbversion_t *version = NULL;
4030 dns_rdata_nsec3param_t nsec3param;
4031 dns_rdataset_t rdataset;
4032 isc_result_t result;
4033 bool dynamic = (zone->type == dns_zone_primary)
4034 ? dns_zone_isdynamic(zone, false)
4035 : false;
4036
4037 dns_rdataset_init(&rdataset);
4038 result = dns_db_findnode(db, &zone->origin, false, &node);
4039 if (result != ISC_R_SUCCESS) {
4040 dns_zone_log(zone, ISC_LOG_ERROR,
4041 "nsec3param lookup failure: %s",
4042 isc_result_totext(result));
4043 return (result);
4044 }
4045 dns_db_currentversion(db, &version);
4046
4047 result = dns_db_findrdataset(db, node, version,
4048 dns_rdatatype_nsec3param,
4049 dns_rdatatype_none, 0, &rdataset, NULL);
4050 if (result == ISC_R_NOTFOUND) {
4051 INSIST(!dns_rdataset_isassociated(&rdataset));
4052 result = ISC_R_SUCCESS;
4053 goto cleanup;
4054 }
4055 if (result != ISC_R_SUCCESS) {
4056 INSIST(!dns_rdataset_isassociated(&rdataset));
4057 dns_zone_log(zone, ISC_LOG_ERROR,
4058 "nsec3param lookup failure: %s",
4059 isc_result_totext(result));
4060 goto cleanup;
4061 }
4062
4063 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
4064 result = dns_rdataset_next(&rdataset))
4065 {
4066 dns_rdata_t rdata = DNS_RDATA_INIT;
4067
4068 dns_rdataset_current(&rdataset, &rdata);
4069 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
4070 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4071
4072 /*
4073 * For dynamic zones we must support every algorithm so we
4074 * can regenerate all the NSEC3 chains.
4075 * For non-dynamic zones we only need to find a supported
4076 * algorithm.
4077 */
4078 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NSEC3TESTZONE) &&
4079 nsec3param.hash == DNS_NSEC3_UNKNOWNALG && !dynamic)
4080 {
4081 dns_zone_log(zone, ISC_LOG_WARNING,
4082 "nsec3 test \"unknown\" hash algorithm "
4083 "found: %u",
4084 nsec3param.hash);
4085 ok = true;
4086 } else if (!dns_nsec3_supportedhash(nsec3param.hash)) {
4087 if (dynamic) {
4088 dns_zone_log(zone, ISC_LOG_ERROR,
4089 "unsupported nsec3 hash algorithm"
4090 " in dynamic zone: %u",
4091 nsec3param.hash);
4092 result = DNS_R_BADZONE;
4093 /* Stop second error message. */
4094 ok = true;
4095 break;
4096 } else {
4097 dns_zone_log(zone, ISC_LOG_WARNING,
4098 "unsupported nsec3 hash "
4099 "algorithm: %u",
4100 nsec3param.hash);
4101 }
4102 } else {
4103 ok = true;
4104 }
4105
4106 /*
4107 * Warn if the zone has excessive NSEC3 iterations.
4108 */
4109 if (nsec3param.iterations > dns_nsec3_maxiterations()) {
4110 dnssec_log(zone, ISC_LOG_WARNING,
4111 "excessive NSEC3PARAM iterations %u > %u",
4112 nsec3param.iterations,
4113 dns_nsec3_maxiterations());
4114 }
4115 }
4116 if (result == ISC_R_NOMORE) {
4117 result = ISC_R_SUCCESS;
4118 }
4119
4120 if (!ok) {
4121 result = DNS_R_BADZONE;
4122 dns_zone_log(zone, ISC_LOG_ERROR,
4123 "no supported nsec3 hash algorithm");
4124 }
4125
4126 cleanup:
4127 if (dns_rdataset_isassociated(&rdataset)) {
4128 dns_rdataset_disassociate(&rdataset);
4129 }
4130 dns_db_closeversion(db, &version, false);
4131 dns_db_detachnode(db, &node);
4132 return (result);
4133 }
4134
4135 /*
4136 * Set the timer for refreshing the key zone to the soonest future time
4137 * of the set (current timer, keydata->refresh, keydata->addhd,
4138 * keydata->removehd).
4139 */
4140 static void
4141 set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key,
4142 isc_stdtime_t now, bool force) {
4143 const char me[] = "set_refreshkeytimer";
4144 isc_stdtime_t then;
4145 isc_time_t timenow, timethen;
4146 char timebuf[80];
4147
4148 ENTER;
4149 then = key->refresh;
4150 if (force) {
4151 then = now;
4152 }
4153 if (key->addhd > now && key->addhd < then) {
4154 then = key->addhd;
4155 }
4156 if (key->removehd > now && key->removehd < then) {
4157 then = key->removehd;
4158 }
4159
4160 TIME_NOW(&timenow);
4161 if (then > now) {
4162 DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
4163 } else {
4164 timethen = timenow;
4165 }
4166 if (isc_time_compare(&zone->refreshkeytime, &timenow) < 0 ||
4167 isc_time_compare(&timethen, &zone->refreshkeytime) < 0)
4168 {
4169 zone->refreshkeytime = timethen;
4170 }
4171
4172 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
4173 dns_zone_log(zone, ISC_LOG_DEBUG(1), "next key refresh: %s", timebuf);
4174 zone_settimer(zone, &timenow);
4175 }
4176
4177 /*
4178 * If keynode references a key or a DS rdataset, and if the key
4179 * zone does not contain a KEYDATA record for the corresponding name,
4180 * then create an empty KEYDATA and push it into the zone as a placeholder,
4181 * then schedule a key refresh immediately. This new KEYDATA record will be
4182 * updated during the refresh.
4183 *
4184 * If the key zone is changed, set '*changed' to true.
4185 */
4186 static isc_result_t
4187 create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
4188 dns_diff_t *diff, dns_keynode_t *keynode, dns_name_t *keyname,
4189 bool *changed) {
4190 const char me[] = "create_keydata";
4191 isc_result_t result = ISC_R_SUCCESS;
4192 dns_rdata_t rdata = DNS_RDATA_INIT;
4193 dns_rdata_keydata_t kd;
4194 unsigned char rrdata[4096];
4195 isc_buffer_t rrdatabuf;
4196 isc_stdtime_t now;
4197
4198 REQUIRE(keynode != NULL);
4199
4200 ENTER;
4201 isc_stdtime_get(&now);
4202
4203 /*
4204 * If the keynode has no trust anchor set, we shouldn't be here.
4205 */
4206 if (!dns_keynode_dsset(keynode, NULL)) {
4207 return (ISC_R_FAILURE);
4208 }
4209
4210 memset(&kd, 0, sizeof(kd));
4211 kd.common.rdclass = zone->rdclass;
4212 kd.common.rdtype = dns_rdatatype_keydata;
4213 ISC_LINK_INIT(&kd.common, link);
4214
4215 isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
4216
4217 CHECK(dns_rdata_fromstruct(&rdata, zone->rdclass, dns_rdatatype_keydata,
4218 &kd, &rrdatabuf));
4219 /* Add rdata to zone. */
4220 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, keyname, 0, &rdata));
4221 *changed = true;
4222
4223 /* Refresh new keys from the zone apex as soon as possible. */
4224 set_refreshkeytimer(zone, &kd, now, true);
4225 return (ISC_R_SUCCESS);
4226
4227 failure:
4228 return (result);
4229 }
4230
4231 /*
4232 * Remove from the key zone all the KEYDATA records found in rdataset.
4233 */
4234 static isc_result_t
4235 delete_keydata(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
4236 dns_name_t *name, dns_rdataset_t *rdataset) {
4237 dns_rdata_t rdata = DNS_RDATA_INIT;
4238 isc_result_t result, uresult;
4239
4240 for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
4241 result = dns_rdataset_next(rdataset))
4242 {
4243 dns_rdata_reset(&rdata);
4244 dns_rdataset_current(rdataset, &rdata);
4245 uresult = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name, 0,
4246 &rdata);
4247 if (uresult != ISC_R_SUCCESS) {
4248 return (uresult);
4249 }
4250 }
4251 if (result == ISC_R_NOMORE) {
4252 result = ISC_R_SUCCESS;
4253 }
4254 return (result);
4255 }
4256
4257 /*
4258 * Compute the DNSSEC key ID for a DNSKEY record.
4259 */
4260 static isc_result_t
4261 compute_tag(dns_name_t *name, dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx,
4262 dns_keytag_t *tag) {
4263 isc_result_t result;
4264 dns_rdata_t rdata = DNS_RDATA_INIT;
4265 unsigned char data[4096];
4266 isc_buffer_t buffer;
4267 dst_key_t *dstkey = NULL;
4268
4269 isc_buffer_init(&buffer, data, sizeof(data));
4270 dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
4271 dns_rdatatype_dnskey, dnskey, &buffer);
4272
4273 result = dns_dnssec_keyfromrdata(name, &rdata, mctx, &dstkey);
4274 if (result == ISC_R_SUCCESS) {
4275 *tag = dst_key_id(dstkey);
4276 dst_key_free(&dstkey);
4277 }
4278
4279 return (result);
4280 }
4281
4282 /*
4283 * Synth-from-dnssec callbacks to add/delete names from namespace tree.
4284 */
4285 static void
4286 sfd_add(const dns_name_t *name, void *arg) {
4287 if (arg != NULL) {
4288 dns_view_sfd_add(arg, name);
4289 }
4290 }
4291
4292 static void
4293 sfd_del(const dns_name_t *name, void *arg) {
4294 if (arg != NULL) {
4295 dns_view_sfd_del(arg, name);
4296 }
4297 }
4298
4299 /*
4300 * Add key to the security roots.
4301 */
4302 static void
4303 trust_key(dns_zone_t *zone, dns_name_t *keyname, dns_rdata_dnskey_t *dnskey,
4304 bool initial) {
4305 isc_result_t result;
4306 dns_rdata_t rdata = DNS_RDATA_INIT;
4307 unsigned char data[4096], digest[ISC_MAX_MD_SIZE];
4308 isc_buffer_t buffer;
4309 dns_keytable_t *sr = NULL;
4310 dns_rdata_ds_t ds;
4311
4312 result = dns_view_getsecroots(zone->view, &sr);
4313 if (result != ISC_R_SUCCESS) {
4314 return;
4315 }
4316
4317 /* Build DS record for key. */
4318 isc_buffer_init(&buffer, data, sizeof(data));
4319 dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
4320 dns_rdatatype_dnskey, dnskey, &buffer);
4321 CHECK(dns_ds_fromkeyrdata(keyname, &rdata, DNS_DSDIGEST_SHA256, digest,
4322 &ds));
4323 CHECK(dns_keytable_add(sr, true, initial, keyname, &ds, sfd_add,
4324 zone->view));
4325
4326 dns_keytable_detach(&sr);
4327
4328 failure:
4329 if (sr != NULL) {
4330 dns_keytable_detach(&sr);
4331 }
4332 return;
4333 }
4334
4335 /*
4336 * Add a null key to the security roots for so that all queries
4337 * to the zone will fail.
4338 */
4339 static void
4340 fail_secure(dns_zone_t *zone, dns_name_t *keyname) {
4341 isc_result_t result;
4342 dns_keytable_t *sr = NULL;
4343
4344 result = dns_view_getsecroots(zone->view, &sr);
4345 if (result == ISC_R_SUCCESS) {
4346 dns_keytable_marksecure(sr, keyname);
4347 dns_keytable_detach(&sr);
4348 }
4349 }
4350
4351 /*
4352 * Scan a set of KEYDATA records from the key zone. The ones that are
4353 * valid (i.e., the add holddown timer has expired) become trusted keys.
4354 */
4355 static void
4356 load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
4357 isc_result_t result;
4358 dns_rdata_t rdata = DNS_RDATA_INIT;
4359 dns_rdata_keydata_t keydata;
4360 dns_rdata_dnskey_t dnskey;
4361 int trusted = 0, revoked = 0, pending = 0;
4362 isc_stdtime_t now;
4363 dns_keytable_t *sr = NULL;
4364
4365 isc_stdtime_get(&now);
4366
4367 result = dns_view_getsecroots(zone->view, &sr);
4368 if (result == ISC_R_SUCCESS) {
4369 dns_keytable_delete(sr, name, sfd_del, zone->view);
4370 dns_keytable_detach(&sr);
4371 }
4372
4373 /* Now insert all the accepted trust anchors from this keydata set. */
4374 for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
4375 result = dns_rdataset_next(rdataset))
4376 {
4377 dns_rdata_reset(&rdata);
4378 dns_rdataset_current(rdataset, &rdata);
4379
4380 /* Convert rdata to keydata. */
4381 result = dns_rdata_tostruct(&rdata, &keydata, NULL);
4382 if (result == ISC_R_UNEXPECTEDEND) {
4383 continue;
4384 }
4385 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4386
4387 /* Set the key refresh timer to force a fast refresh. */
4388 set_refreshkeytimer(zone, &keydata, now, true);
4389
4390 /* If the removal timer is nonzero, this key was revoked. */
4391 if (keydata.removehd != 0) {
4392 revoked++;
4393 continue;
4394 }
4395
4396 /*
4397 * If the add timer is still pending, this key is not
4398 * trusted yet.
4399 */
4400 if (now < keydata.addhd) {
4401 pending++;
4402 continue;
4403 }
4404
4405 /* Convert keydata to dnskey. */
4406 dns_keydata_todnskey(&keydata, &dnskey, NULL);
4407
4408 /* Add to keytables. */
4409 trusted++;
4410 trust_key(zone, name, &dnskey, (keydata.addhd == 0));
4411 }
4412
4413 if (trusted == 0 && pending != 0) {
4414 char namebuf[DNS_NAME_FORMATSIZE];
4415 dns_name_format(name, namebuf, sizeof namebuf);
4416 dnssec_log(zone, ISC_LOG_ERROR,
4417 "No valid trust anchors for '%s'!", namebuf);
4418 dnssec_log(zone, ISC_LOG_ERROR,
4419 "%d key(s) revoked, %d still pending", revoked,
4420 pending);
4421 dnssec_log(zone, ISC_LOG_ERROR, "All queries to '%s' will fail",
4422 namebuf);
4423 fail_secure(zone, name);
4424 }
4425 }
4426
4427 static isc_result_t
4428 do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
4429 dns_diff_t *diff) {
4430 dns_diff_t temp_diff;
4431 isc_result_t result;
4432
4433 /*
4434 * Create a singleton diff.
4435 */
4436 dns_diff_init(diff->mctx, &temp_diff);
4437 ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
4438
4439 /*
4440 * Apply it to the database.
4441 */
4442 result = dns_diff_apply(&temp_diff, db, ver);
4443 ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
4444 if (result != ISC_R_SUCCESS) {
4445 dns_difftuple_free(tuple);
4446 return (result);
4447 }
4448
4449 /*
4450 * Merge it into the current pending journal entry.
4451 */
4452 dns_diff_appendminimal(diff, tuple);
4453
4454 /*
4455 * Do not clear temp_diff.
4456 */
4457 return (ISC_R_SUCCESS);
4458 }
4459
4460 static isc_result_t
4461 update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
4462 dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
4463 dns_rdata_t *rdata) {
4464 dns_difftuple_t *tuple = NULL;
4465 isc_result_t result;
4466 result = dns_difftuple_create(diff->mctx, op, name, ttl, rdata, &tuple);
4467 if (result != ISC_R_SUCCESS) {
4468 return (result);
4469 }
4470 return (do_one_tuple(&tuple, db, ver, diff));
4471 }
4472
4473 static isc_result_t
4474 update_soa_serial(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
4475 dns_diff_t *diff, isc_mem_t *mctx,
4476 dns_updatemethod_t method) {
4477 dns_difftuple_t *deltuple = NULL;
4478 dns_difftuple_t *addtuple = NULL;
4479 uint32_t serial;
4480 isc_result_t result;
4481 dns_updatemethod_t used = dns_updatemethod_none;
4482
4483 INSIST(method != dns_updatemethod_none);
4484
4485 CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple));
4486 CHECK(dns_difftuple_copy(deltuple, &addtuple));
4487 addtuple->op = DNS_DIFFOP_ADD;
4488
4489 serial = dns_soa_getserial(&addtuple->rdata);
4490 serial = dns_update_soaserial(serial, method, &used);
4491 if (method != used) {
4492 dns_zone_log(zone, ISC_LOG_WARNING,
4493 "update_soa_serial:new serial would be lower than "
4494 "old serial, using increment method instead");
4495 }
4496 dns_soa_setserial(serial, &addtuple->rdata);
4497 CHECK(do_one_tuple(&deltuple, db, ver, diff));
4498 CHECK(do_one_tuple(&addtuple, db, ver, diff));
4499 result = ISC_R_SUCCESS;
4500
4501 failure:
4502 if (addtuple != NULL) {
4503 dns_difftuple_free(&addtuple);
4504 }
4505 if (deltuple != NULL) {
4506 dns_difftuple_free(&deltuple);
4507 }
4508 return (result);
4509 }
4510
4511 /*
4512 * Write all transactions in 'diff' to the zone journal file.
4513 */
4514 static isc_result_t
4515 zone_journal(dns_zone_t *zone, dns_diff_t *diff, uint32_t *sourceserial,
4516 const char *caller) {
4517 const char me[] = "zone_journal";
4518 const char *journalfile;
4519 isc_result_t result = ISC_R_SUCCESS;
4520 dns_journal_t *journal = NULL;
4521 unsigned int mode = DNS_JOURNAL_CREATE | DNS_JOURNAL_WRITE;
4522
4523 ENTER;
4524 journalfile = dns_zone_getjournal(zone);
4525 if (journalfile != NULL) {
4526 result = dns_journal_open(zone->mctx, journalfile, mode,
4527 &journal);
4528 if (result != ISC_R_SUCCESS) {
4529 dns_zone_log(zone, ISC_LOG_ERROR,
4530 "%s:dns_journal_open -> %s", caller,
4531 isc_result_totext(result));
4532 return (result);
4533 }
4534
4535 if (sourceserial != NULL) {
4536 dns_journal_set_sourceserial(journal, *sourceserial);
4537 }
4538
4539 result = dns_journal_write_transaction(journal, diff);
4540 if (result != ISC_R_SUCCESS) {
4541 dns_zone_log(zone, ISC_LOG_ERROR,
4542 "%s:dns_journal_write_transaction -> %s",
4543 caller, isc_result_totext(result));
4544 }
4545 dns_journal_destroy(&journal);
4546 }
4547
4548 return (result);
4549 }
4550
4551 /*
4552 * Create an SOA record for a newly-created zone
4553 */
4554 static isc_result_t
4555 add_soa(dns_zone_t *zone, dns_db_t *db) {
4556 isc_result_t result;
4557 dns_rdata_t rdata = DNS_RDATA_INIT;
4558 unsigned char buf[DNS_SOA_BUFFERSIZE];
4559 dns_dbversion_t *ver = NULL;
4560 dns_diff_t diff;
4561
4562 dns_zone_log(zone, ISC_LOG_DEBUG(1), "creating SOA");
4563
4564 dns_diff_init(zone->mctx, &diff);
4565 result = dns_db_newversion(db, &ver);
4566 if (result != ISC_R_SUCCESS) {
4567 dns_zone_log(zone, ISC_LOG_ERROR,
4568 "add_soa:dns_db_newversion -> %s",
4569 isc_result_totext(result));
4570 goto failure;
4571 }
4572
4573 /* Build SOA record */
4574 result = dns_soa_buildrdata(&zone->origin, dns_rootname, zone->rdclass,
4575 0, 0, 0, 0, 0, buf, &rdata);
4576 if (result != ISC_R_SUCCESS) {
4577 dns_zone_log(zone, ISC_LOG_ERROR,
4578 "add_soa:dns_soa_buildrdata -> %s",
4579 isc_result_totext(result));
4580 goto failure;
4581 }
4582
4583 result = update_one_rr(db, ver, &diff, DNS_DIFFOP_ADD, &zone->origin, 0,
4584 &rdata);
4585
4586 failure:
4587 dns_diff_clear(&diff);
4588 if (ver != NULL) {
4589 dns_db_closeversion(db, &ver, (result == ISC_R_SUCCESS));
4590 }
4591
4592 INSIST(ver == NULL);
4593
4594 return (result);
4595 }
4596
4597 struct addifmissing_arg {
4598 dns_db_t *db;
4599 dns_dbversion_t *ver;
4600 dns_diff_t *diff;
4601 dns_zone_t *zone;
4602 bool *changed;
4603 isc_result_t result;
4604 };
4605
4606 static void
4607 addifmissing(dns_keytable_t *keytable, dns_keynode_t *keynode,
4608 dns_name_t *keyname, void *arg) {
4609 dns_db_t *db = ((struct addifmissing_arg *)arg)->db;
4610 dns_dbversion_t *ver = ((struct addifmissing_arg *)arg)->ver;
4611 dns_diff_t *diff = ((struct addifmissing_arg *)arg)->diff;
4612 dns_zone_t *zone = ((struct addifmissing_arg *)arg)->zone;
4613 bool *changed = ((struct addifmissing_arg *)arg)->changed;
4614 isc_result_t result;
4615 dns_fixedname_t fname;
4616
4617 UNUSED(keytable);
4618
4619 if (((struct addifmissing_arg *)arg)->result != ISC_R_SUCCESS) {
4620 return;
4621 }
4622
4623 if (!dns_keynode_managed(keynode)) {
4624 return;
4625 }
4626
4627 /*
4628 * If the keynode has no trust anchor set, return.
4629 */
4630 if (!dns_keynode_dsset(keynode, NULL)) {
4631 return;
4632 }
4633
4634 /*
4635 * Check whether there's already a KEYDATA entry for this name;
4636 * if so, we don't need to add another.
4637 */
4638 dns_fixedname_init(&fname);
4639 result = dns_db_find(db, keyname, ver, dns_rdatatype_keydata,
4640 DNS_DBFIND_NOWILD, 0, NULL,
4641 dns_fixedname_name(&fname), NULL, NULL);
4642 if (result == ISC_R_SUCCESS) {
4643 return;
4644 }
4645
4646 /*
4647 * Create the keydata.
4648 */
4649 result = create_keydata(zone, db, ver, diff, keynode, keyname, changed);
4650 if (result != ISC_R_SUCCESS && result != ISC_R_NOMORE) {
4651 ((struct addifmissing_arg *)arg)->result = result;
4652 }
4653 }
4654
4655 /*
4656 * Synchronize the set of initializing keys found in managed-keys {}
4657 * statements with the set of trust anchors found in the managed-keys.bind
4658 * zone. If a domain is no longer named in managed-keys, delete all keys
4659 * from that domain from the key zone. If a domain is configured as an
4660 * initial-key in trust-anchors, but there are no references to it in the
4661 * key zone, load the key zone with the initializing key(s) for that
4662 * domain and schedule a key refresh. If a domain is configured as
4663 * an initial-ds in trust-anchors, fetch the DNSKEY RRset, load the key
4664 * zone with the matching key, and schedule a key refresh.
4665 */
4666 static isc_result_t
4667 sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
4668 isc_result_t result = ISC_R_SUCCESS;
4669 bool changed = false;
4670 bool commit = false;
4671 dns_keynode_t *keynode = NULL;
4672 dns_view_t *view = zone->view;
4673 dns_keytable_t *sr = NULL;
4674 dns_dbversion_t *ver = NULL;
4675 dns_diff_t diff;
4676 dns_rriterator_t rrit;
4677 struct addifmissing_arg arg;
4678
4679 dns_zone_log(zone, ISC_LOG_DEBUG(1), "synchronizing trusted keys");
4680
4681 dns_diff_init(zone->mctx, &diff);
4682
4683 CHECK(dns_view_getsecroots(view, &sr));
4684
4685 result = dns_db_newversion(db, &ver);
4686 if (result != ISC_R_SUCCESS) {
4687 dnssec_log(zone, ISC_LOG_ERROR,
4688 "sync_keyzone:dns_db_newversion -> %s",
4689 isc_result_totext(result));
4690 goto failure;
4691 }
4692
4693 /*
4694 * Walk the zone DB. If we find any keys whose names are no longer
4695 * in trust-anchors, or which have been changed from initial to static,
4696 * (meaning they are permanent and not RFC5011-maintained), delete
4697 * them from the zone. Otherwise call load_secroots(), which
4698 * loads keys into secroots as appropriate.
4699 */
4700 dns_rriterator_init(&rrit, db, ver, 0);
4701 for (result = dns_rriterator_first(&rrit); result == ISC_R_SUCCESS;
4702 result = dns_rriterator_nextrrset(&rrit))
4703 {
4704 dns_rdataset_t *rdataset = NULL;
4705 dns_rdata_t rdata = DNS_RDATA_INIT;
4706 dns_rdata_keydata_t keydata;
4707 isc_stdtime_t now;
4708 bool load = true;
4709 dns_name_t *rrname = NULL;
4710 uint32_t ttl;
4711
4712 isc_stdtime_get(&now);
4713
4714 dns_rriterator_current(&rrit, &rrname, &ttl, &rdataset, NULL);
4715 if (!dns_rdataset_isassociated(rdataset)) {
4716 dns_rriterator_destroy(&rrit);
4717 goto failure;
4718 }
4719
4720 if (rdataset->type != dns_rdatatype_keydata) {
4721 continue;
4722 }
4723
4724 /*
4725 * The managed-keys zone can contain a placeholder instead of
4726 * legitimate data, in which case we will not use it, and we
4727 * will try to refresh it.
4728 */
4729 for (result = dns_rdataset_first(rdataset);
4730 result == ISC_R_SUCCESS;
4731 result = dns_rdataset_next(rdataset))
4732 {
4733 isc_result_t iresult;
4734
4735 dns_rdata_reset(&rdata);
4736 dns_rdataset_current(rdataset, &rdata);
4737
4738 iresult = dns_rdata_tostruct(&rdata, &keydata, NULL);
4739 /* Do we have a valid placeholder KEYDATA record? */
4740 if (iresult == ISC_R_SUCCESS && keydata.flags == 0 &&
4741 keydata.protocol == 0 && keydata.algorithm == 0)
4742 {
4743 set_refreshkeytimer(zone, &keydata, now, true);
4744 load = false;
4745 }
4746 }
4747
4748 /*
4749 * Release db wrlock to prevent LOR reports against
4750 * dns_keytable_forall() call below.
4751 */
4752 dns_rriterator_pause(&rrit);
4753 result = dns_keytable_find(sr, rrname, &keynode);
4754 if (result != ISC_R_SUCCESS || !dns_keynode_managed(keynode)) {
4755 CHECK(delete_keydata(db, ver, &diff, rrname, rdataset));
4756 changed = true;
4757 } else if (load) {
4758 load_secroots(zone, rrname, rdataset);
4759 }
4760
4761 if (keynode != NULL) {
4762 dns_keytable_detachkeynode(sr, &keynode);
4763 }
4764 }
4765 dns_rriterator_destroy(&rrit);
4766
4767 /*
4768 * Walk secroots to find any initial keys that aren't in
4769 * the zone. If we find any, add them to the zone directly.
4770 * If any DS-style initial keys are found, refresh the key
4771 * zone so that they'll be looked up.
4772 */
4773 arg.db = db;
4774 arg.ver = ver;
4775 arg.result = ISC_R_SUCCESS;
4776 arg.diff = &diff;
4777 arg.zone = zone;
4778 arg.changed = &changed;
4779 dns_keytable_forall(sr, addifmissing, &arg);
4780 result = arg.result;
4781 if (changed) {
4782 /* Write changes to journal file. */
4783 CHECK(update_soa_serial(zone, db, ver, &diff, zone->mctx,
4784 zone->updatemethod));
4785 CHECK(zone_journal(zone, &diff, NULL, "sync_keyzone"));
4786
4787 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
4788 zone_needdump(zone, 30);
4789 commit = true;
4790 }
4791
4792 failure:
4793 if (result != ISC_R_SUCCESS) {
4794 dnssec_log(zone, ISC_LOG_ERROR,
4795 "unable to synchronize managed keys: %s",
4796 isc_result_totext(result));
4797 isc_time_settoepoch(&zone->refreshkeytime);
4798 }
4799 if (keynode != NULL) {
4800 dns_keytable_detachkeynode(sr, &keynode);
4801 }
4802 if (sr != NULL) {
4803 dns_keytable_detach(&sr);
4804 }
4805 if (ver != NULL) {
4806 dns_db_closeversion(db, &ver, commit);
4807 }
4808 dns_diff_clear(&diff);
4809
4810 INSIST(ver == NULL);
4811
4812 return (result);
4813 }
4814
4815 isc_result_t
4816 dns_zone_synckeyzone(dns_zone_t *zone) {
4817 isc_result_t result;
4818 dns_db_t *db = NULL;
4819
4820 if (zone->type != dns_zone_key) {
4821 return (DNS_R_BADZONE);
4822 }
4823
4824 CHECK(dns_zone_getdb(zone, &db));
4825
4826 LOCK_ZONE(zone);
4827 result = sync_keyzone(zone, db);
4828 UNLOCK_ZONE(zone);
4829
4830 failure:
4831 if (db != NULL) {
4832 dns_db_detach(&db);
4833 }
4834 return (result);
4835 }
4836
4837 static void
4838 maybe_send_secure(dns_zone_t *zone) {
4839 isc_result_t result;
4840
4841 /*
4842 * We've finished loading, or else failed to load, an inline-signing
4843 * 'secure' zone. We now need information about the status of the
4844 * 'raw' zone. If we failed to load, then we need it to send a
4845 * copy of its database; if we succeeded, we need it to send its
4846 * serial number so that we can sync with it. If it has not yet
4847 * loaded, we set a flag so that it will send the necessary
4848 * information when it has finished loading.
4849 */
4850 if (zone->raw->db != NULL) {
4851 if (zone->db != NULL) {
4852 uint32_t serial;
4853 unsigned int soacount;
4854
4855 result = zone_get_from_db(
4856 zone->raw, zone->raw->db, NULL, &soacount, NULL,
4857 &serial, NULL, NULL, NULL, NULL, NULL);
4858 if (result == ISC_R_SUCCESS && soacount > 0U) {
4859 zone_send_secureserial(zone->raw, serial);
4860 }
4861 } else {
4862 zone_send_securedb(zone->raw, zone->raw->db);
4863 }
4864 } else {
4865 DNS_ZONE_SETFLAG(zone->raw, DNS_ZONEFLG_SENDSECURE);
4866 }
4867 }
4868
4869 static bool
4870 zone_unchanged(dns_db_t *db1, dns_db_t *db2, isc_mem_t *mctx) {
4871 isc_result_t result;
4872 bool answer = false;
4873 dns_diff_t diff;
4874
4875 dns_diff_init(mctx, &diff);
4876 result = dns_db_diffx(&diff, db1, NULL, db2, NULL, NULL);
4877 if (result == ISC_R_SUCCESS && ISC_LIST_EMPTY(diff.tuples)) {
4878 answer = true;
4879 }
4880 dns_diff_clear(&diff);
4881 return (answer);
4882 }
4883
4884 /*
4885 * The zone is presumed to be locked.
4886 * If this is a inline_raw zone the secure version is also locked.
4887 */
4888 static isc_result_t
4889 zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
4890 isc_result_t result) {
4891 unsigned int soacount = 0;
4892 unsigned int nscount = 0;
4893 unsigned int errors = 0;
4894 uint32_t serial, oldserial, refresh, retry, expire, minimum, soattl;
4895 isc_time_t now;
4896 bool needdump = false;
4897 bool fixjournal = false;
4898 bool hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE);
4899 bool noprimary = false;
4900 bool had_db = false;
4901 dns_include_t *inc;
4902 bool is_dynamic = false;
4903
4904 INSIST(LOCKED_ZONE(zone));
4905 if (inline_raw(zone)) {
4906 INSIST(LOCKED_ZONE(zone->secure));
4907 }
4908
4909 TIME_NOW(&now);
4910
4911 /*
4912 * Initiate zone transfer? We may need a error code that
4913 * indicates that the "permanent" form does not exist.
4914 * XXX better error feedback to log.
4915 */
4916 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
4917 if (zone->type == dns_zone_secondary ||
4918 zone->type == dns_zone_mirror ||
4919 zone->type == dns_zone_stub ||
4920 (zone->type == dns_zone_redirect &&
4921 zone->primaries == NULL))
4922 {
4923 if (result == ISC_R_FILENOTFOUND) {
4924 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4925 ISC_LOG_DEBUG(1),
4926 "no master file");
4927 } else if (result != DNS_R_NOMASTERFILE) {
4928 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4929 ISC_LOG_ERROR,
4930 "loading from master file %s "
4931 "failed: %s",
4932 zone->masterfile,
4933 isc_result_totext(result));
4934 }
4935 } else if (zone->type == dns_zone_primary &&
4936 inline_secure(zone) && result == ISC_R_FILENOTFOUND)
4937 {
4938 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4939 ISC_LOG_DEBUG(1),
4940 "no master file, requesting db");
4941 maybe_send_secure(zone);
4942 } else {
4943 int level = ISC_LOG_ERROR;
4944 if (zone->type == dns_zone_key &&
4945 result == ISC_R_FILENOTFOUND)
4946 {
4947 level = ISC_LOG_DEBUG(1);
4948 }
4949 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, level,
4950 "loading from master file %s failed: %s",
4951 zone->masterfile,
4952 isc_result_totext(result));
4953 noprimary = true;
4954 }
4955
4956 if (zone->type != dns_zone_key) {
4957 goto cleanup;
4958 }
4959 }
4960
4961 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(2),
4962 "number of nodes in database: %u",
4963 dns_db_nodecount(db, dns_dbtree_main));
4964
4965 if (result == DNS_R_SEENINCLUDE) {
4966 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
4967 } else {
4968 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
4969 }
4970
4971 /*
4972 * If there's no master file for a key zone, then the zone is new:
4973 * create an SOA record. (We do this now, instead of later, so that
4974 * if there happens to be a journal file, we can roll forward from
4975 * a sane starting point.)
4976 */
4977 if (noprimary && zone->type == dns_zone_key) {
4978 result = add_soa(zone, db);
4979 if (result != ISC_R_SUCCESS) {
4980 goto cleanup;
4981 }
4982 }
4983
4984 /*
4985 * Apply update log, if any, on initial load.
4986 */
4987 if (zone->journal != NULL &&
4988 !DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE) &&
4989 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
4990 {
4991 result = zone_journal_rollforward(zone, db, &needdump,
4992 &fixjournal);
4993 if (result != ISC_R_SUCCESS) {
4994 goto cleanup;
4995 }
4996 }
4997
4998 /*
4999 * Obtain ns, soa and cname counts for top of zone.
5000 */
5001 INSIST(db != NULL);
5002 result = zone_get_from_db(zone, db, &nscount, &soacount, &soattl,
5003 &serial, &refresh, &retry, &expire, &minimum,
5004 &errors);
5005 if (result != ISC_R_SUCCESS && zone->type != dns_zone_key) {
5006 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
5007 "could not find NS and/or SOA records");
5008 }
5009
5010 /*
5011 * Process any queued NSEC3PARAM change requests. Only for dynamic
5012 * zones, an inline-signing zone will perform this action when
5013 * receiving the secure db (receive_secure_db).
5014 */
5015 is_dynamic = dns_zone_isdynamic(zone, true);
5016 if (is_dynamic) {
5017 isc_event_t *setnsec3param_event;
5018 dns_zone_t *dummy;
5019
5020 while (!ISC_LIST_EMPTY(zone->setnsec3param_queue)) {
5021 setnsec3param_event =
5022 ISC_LIST_HEAD(zone->setnsec3param_queue);
5023 ISC_LIST_UNLINK(zone->setnsec3param_queue,
5024 setnsec3param_event, ev_link);
5025 dummy = NULL;
5026 zone_iattach(zone, &dummy);
5027 isc_task_send(zone->task, &setnsec3param_event);
5028 }
5029 }
5030
5031 /*
5032 * Check to make sure the journal is up to date, and remove the
5033 * journal file if it isn't, as we wouldn't be able to apply
5034 * updates otherwise.
5035 */
5036 if (zone->journal != NULL && is_dynamic &&
5037 !DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS))
5038 {
5039 uint32_t jserial;
5040 dns_journal_t *journal = NULL;
5041 bool empty = false;
5042
5043 result = dns_journal_open(zone->mctx, zone->journal,
5044 DNS_JOURNAL_READ, &journal);
5045 if (result == ISC_R_SUCCESS) {
5046 jserial = dns_journal_last_serial(journal);
5047 empty = dns_journal_empty(journal);
5048 dns_journal_destroy(&journal);
5049 } else {
5050 jserial = serial;
5051 result = ISC_R_SUCCESS;
5052 }
5053
5054 if (jserial != serial) {
5055 if (!empty) {
5056 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5057 ISC_LOG_INFO,
5058 "journal file is out of date: "
5059 "removing journal file");
5060 }
5061 if (remove(zone->journal) < 0 && errno != ENOENT) {
5062 char strbuf[ISC_STRERRORSIZE];
5063 strerror_r(errno, strbuf, sizeof(strbuf));
5064 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
5065 DNS_LOGMODULE_ZONE,
5066 ISC_LOG_WARNING,
5067 "unable to remove journal "
5068 "'%s': '%s'",
5069 zone->journal, strbuf);
5070 }
5071 }
5072 }
5073
5074 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
5075 "loaded; checking validity");
5076
5077 /*
5078 * Primary / Secondary / Mirror / Stub zones require both NS and SOA
5079 * records at the top of the zone.
5080 */
5081
5082 switch (zone->type) {
5083 case dns_zone_dlz:
5084 case dns_zone_primary:
5085 case dns_zone_secondary:
5086 case dns_zone_mirror:
5087 case dns_zone_stub:
5088 case dns_zone_redirect:
5089 if (soacount != 1) {
5090 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5091 ISC_LOG_ERROR, "has %d SOA records",
5092 soacount);
5093 result = DNS_R_BADZONE;
5094 }
5095 if (nscount == 0) {
5096 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5097 ISC_LOG_ERROR, "has no NS records");
5098 result = DNS_R_BADZONE;
5099 }
5100 if (result != ISC_R_SUCCESS) {
5101 goto cleanup;
5102 }
5103 if (zone->type == dns_zone_primary && errors != 0) {
5104 result = DNS_R_BADZONE;
5105 goto cleanup;
5106 }
5107 if (zone->type != dns_zone_stub &&
5108 zone->type != dns_zone_redirect)
5109 {
5110 result = check_nsec3param(zone, db);
5111 if (result != ISC_R_SUCCESS) {
5112 goto cleanup;
5113 }
5114 }
5115 if (zone->type == dns_zone_primary &&
5116 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKINTEGRITY) &&
5117 !integrity_checks(zone, db))
5118 {
5119 result = DNS_R_BADZONE;
5120 goto cleanup;
5121 }
5122 if (zone->type == dns_zone_primary &&
5123 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRR) &&
5124 !zone_check_dup(zone, db))
5125 {
5126 result = DNS_R_BADZONE;
5127 goto cleanup;
5128 }
5129
5130 if (zone->type == dns_zone_primary) {
5131 result = dns_zone_cdscheck(zone, db, NULL);
5132 if (result != ISC_R_SUCCESS) {
5133 dns_zone_log(zone, ISC_LOG_ERROR,
5134 "CDS/CDNSKEY consistency checks "
5135 "failed");
5136 goto cleanup;
5137 }
5138 }
5139
5140 result = dns_zone_verifydb(zone, db, NULL);
5141 if (result != ISC_R_SUCCESS) {
5142 goto cleanup;
5143 }
5144
5145 if (zone->db != NULL) {
5146 unsigned int oldsoacount;
5147
5148 /*
5149 * This is checked in zone_replacedb() for
5150 * secondary zones as they don't reload from disk.
5151 */
5152 result = zone_get_from_db(
5153 zone, zone->db, NULL, &oldsoacount, NULL,
5154 &oldserial, NULL, NULL, NULL, NULL, NULL);
5155 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5156 RUNTIME_CHECK(oldsoacount > 0U);
5157 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
5158 !isc_serial_gt(serial, oldserial))
5159 {
5160 uint32_t serialmin, serialmax;
5161
5162 INSIST(zone->type == dns_zone_primary);
5163 INSIST(zone->raw == NULL);
5164
5165 if (serial == oldserial &&
5166 zone_unchanged(zone->db, db, zone->mctx))
5167 {
5168 dns_zone_logc(zone,
5169 DNS_LOGCATEGORY_ZONELOAD,
5170 ISC_LOG_INFO,
5171 "ixfr-from-differences: "
5172 "unchanged");
5173 zone->loadtime = loadtime;
5174 goto done;
5175 }
5176
5177 serialmin = (oldserial + 1) & 0xffffffffU;
5178 serialmax = (oldserial + 0x7fffffffU) &
5179 0xffffffffU;
5180 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5181 ISC_LOG_ERROR,
5182 "ixfr-from-differences: "
5183 "new serial (%u) out of range "
5184 "[%u - %u]",
5185 serial, serialmin, serialmax);
5186 result = DNS_R_BADZONE;
5187 goto cleanup;
5188 } else if (!isc_serial_ge(serial, oldserial)) {
5189 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5190 ISC_LOG_ERROR,
5191 "zone serial (%u/%u) has gone "
5192 "backwards",
5193 serial, oldserial);
5194 } else if (serial == oldserial && !hasinclude &&
5195 strcmp(zone->db_argv[0], "_builtin") != 0)
5196 {
5197 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5198 ISC_LOG_ERROR,
5199 "zone serial (%u) unchanged. "
5200 "zone may fail to transfer "
5201 "to secondaries.",
5202 serial);
5203 }
5204 }
5205
5206 if (zone->type == dns_zone_primary &&
5207 (zone->update_acl != NULL || zone->ssutable != NULL) &&
5208 dns_zone_getsigresigninginterval(zone) < (3 * refresh) &&
5209 dns_db_issecure(db))
5210 {
5211 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5212 ISC_LOG_WARNING,
5213 "sig-re-signing-interval less than "
5214 "3 * refresh.");
5215 }
5216
5217 zone->refresh = RANGE(refresh, zone->minrefresh,
5218 zone->maxrefresh);
5219 zone->retry = RANGE(retry, zone->minretry, zone->maxretry);
5220 zone->expire = RANGE(expire, zone->refresh + zone->retry,
5221 DNS_MAX_EXPIRE);
5222 zone->soattl = soattl;
5223 zone->minimum = minimum;
5224 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
5225
5226 if (zone->type == dns_zone_secondary ||
5227 zone->type == dns_zone_mirror ||
5228 zone->type == dns_zone_stub ||
5229 (zone->type == dns_zone_redirect &&
5230 zone->primaries != NULL))
5231 {
5232 isc_time_t t;
5233 uint32_t delay;
5234
5235 result = isc_file_getmodtime(zone->journal, &t);
5236 if (result != ISC_R_SUCCESS) {
5237 result = isc_file_getmodtime(zone->masterfile,
5238 &t);
5239 }
5240 if (result == ISC_R_SUCCESS) {
5241 DNS_ZONE_TIME_ADD(&t, zone->expire,
5242 &zone->expiretime);
5243 } else {
5244 DNS_ZONE_TIME_ADD(&now, zone->retry,
5245 &zone->expiretime);
5246 }
5247
5248 delay = (zone->retry -
5249 isc_random_uniform((zone->retry * 3) / 4));
5250 DNS_ZONE_TIME_ADD(&now, delay, &zone->refreshtime);
5251 if (isc_time_compare(&zone->refreshtime,
5252 &zone->expiretime) >= 0)
5253 {
5254 zone->refreshtime = now;
5255 }
5256 }
5257
5258 break;
5259
5260 case dns_zone_key:
5261 /* Nothing needs to be done now */
5262 break;
5263
5264 default:
5265 UNEXPECTED_ERROR("unexpected zone type %d", zone->type);
5266 result = ISC_R_UNEXPECTED;
5267 goto cleanup;
5268 }
5269
5270 /*
5271 * Check for weak DNSKEY's.
5272 */
5273 if (zone->type == dns_zone_primary) {
5274 zone_check_dnskeys(zone, db);
5275 }
5276
5277 /*
5278 * Schedule DNSSEC key refresh.
5279 */
5280 if (zone->type == dns_zone_primary &&
5281 DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
5282 {
5283 zone->refreshkeytime = now;
5284 }
5285
5286 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
5287 if (zone->db != NULL) {
5288 had_db = true;
5289 result = zone_replacedb(zone, db, false);
5290 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
5291 if (result != ISC_R_SUCCESS) {
5292 goto cleanup;
5293 }
5294 } else {
5295 zone_attachdb(zone, db);
5296 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
5297 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED |
5298 DNS_ZONEFLG_NEEDSTARTUPNOTIFY);
5299 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SENDSECURE) &&
5300 inline_raw(zone))
5301 {
5302 if (zone->secure->db == NULL) {
5303 zone_send_securedb(zone, db);
5304 } else {
5305 zone_send_secureserial(zone, serial);
5306 }
5307 }
5308 }
5309
5310 /*
5311 * Finished loading inline-signing zone; need to get status
5312 * from the raw side now.
5313 */
5314 if (zone->type == dns_zone_primary && inline_secure(zone)) {
5315 maybe_send_secure(zone);
5316 }
5317
5318 result = ISC_R_SUCCESS;
5319
5320 if (fixjournal) {
5321 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FIXJOURNAL);
5322 zone_journal_compact(zone, zone->db, 0);
5323 }
5324 if (needdump) {
5325 if (zone->type == dns_zone_key) {
5326 zone_needdump(zone, 30);
5327 } else {
5328 zone_needdump(zone, DNS_DUMP_DELAY);
5329 }
5330 }
5331
5332 if (zone->task != NULL) {
5333 if (zone->type == dns_zone_primary) {
5334 set_resigntime(zone);
5335 resume_signingwithkey(zone);
5336 resume_addnsec3chain(zone);
5337 }
5338
5339 is_dynamic = dns_zone_isdynamic(zone, false);
5340 if (zone->type == dns_zone_primary &&
5341 !DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN) &&
5342 is_dynamic && dns_db_issecure(db) && !inline_raw(zone))
5343 {
5344 dns_name_t *name;
5345 dns_fixedname_t fixed;
5346 dns_rdataset_t next;
5347
5348 dns_rdataset_init(&next);
5349 name = dns_fixedname_initname(&fixed);
5350
5351 result = dns_db_getsigningtime(db, &next, name);
5352 if (result == ISC_R_SUCCESS) {
5353 isc_stdtime_t timenow;
5354 char namebuf[DNS_NAME_FORMATSIZE];
5355 char typebuf[DNS_RDATATYPE_FORMATSIZE];
5356
5357 isc_stdtime_get(&timenow);
5358 dns_name_format(name, namebuf, sizeof(namebuf));
5359 dns_rdatatype_format(next.covers, typebuf,
5360 sizeof(typebuf));
5361 dnssec_log(
5362 zone, ISC_LOG_DEBUG(3),
5363 "next resign: %s/%s "
5364 "in %d seconds",
5365 namebuf, typebuf,
5366 next.resign - timenow -
5367 dns_zone_getsigresigninginterval(
5368 zone));
5369 dns_rdataset_disassociate(&next);
5370 } else {
5371 dnssec_log(zone, ISC_LOG_WARNING,
5372 "signed dynamic zone has no "
5373 "resign event scheduled");
5374 }
5375 }
5376
5377 zone_settimer(zone, &now);
5378 }
5379
5380 /*
5381 * Clear old include list.
5382 */
5383 for (inc = ISC_LIST_HEAD(zone->includes); inc != NULL;
5384 inc = ISC_LIST_HEAD(zone->includes))
5385 {
5386 ISC_LIST_UNLINK(zone->includes, inc, link);
5387 isc_mem_free(zone->mctx, inc->name);
5388 isc_mem_put(zone->mctx, inc, sizeof(*inc));
5389 }
5390 zone->nincludes = 0;
5391
5392 /*
5393 * Transfer new include list.
5394 */
5395 for (inc = ISC_LIST_HEAD(zone->newincludes); inc != NULL;
5396 inc = ISC_LIST_HEAD(zone->newincludes))
5397 {
5398 ISC_LIST_UNLINK(zone->newincludes, inc, link);
5399 ISC_LIST_APPEND(zone->includes, inc, link);
5400 zone->nincludes++;
5401 }
5402
5403 if (!dns_db_ispersistent(db)) {
5404 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_INFO,
5405 "loaded serial %u%s", serial,
5406 dns_db_issecure(db) ? " (DNSSEC signed)" : "");
5407 }
5408
5409 if (!had_db && zone->type == dns_zone_mirror) {
5410 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_INFO,
5411 "mirror zone is now in use");
5412 }
5413
5414 zone->loadtime = loadtime;
5415 goto done;
5416
5417 cleanup:
5418 if (result != ISC_R_SUCCESS) {
5419 dns_zone_rpz_disable_db(zone, db);
5420 dns_zone_catz_disable_db(zone, db);
5421 }
5422
5423 for (inc = ISC_LIST_HEAD(zone->newincludes); inc != NULL;
5424 inc = ISC_LIST_HEAD(zone->newincludes))
5425 {
5426 ISC_LIST_UNLINK(zone->newincludes, inc, link);
5427 isc_mem_free(zone->mctx, inc->name);
5428 isc_mem_put(zone->mctx, inc, sizeof(*inc));
5429 }
5430 if (zone->type == dns_zone_secondary || zone->type == dns_zone_mirror ||
5431 zone->type == dns_zone_stub || zone->type == dns_zone_key ||
5432 (zone->type == dns_zone_redirect && zone->primaries != NULL))
5433 {
5434 if (result != ISC_R_NOMEMORY) {
5435 if (zone->journal != NULL) {
5436 zone_saveunique(zone, zone->journal,
5437 "jn-XXXXXXXX");
5438 }
5439 if (zone->masterfile != NULL) {
5440 zone_saveunique(zone, zone->masterfile,
5441 "db-XXXXXXXX");
5442 }
5443 }
5444
5445 /* Mark the zone for immediate refresh. */
5446 zone->refreshtime = now;
5447 if (zone->task != NULL) {
5448 zone_settimer(zone, &now);
5449 }
5450 result = ISC_R_SUCCESS;
5451 } else if (zone->type == dns_zone_primary ||
5452 zone->type == dns_zone_redirect)
5453 {
5454 if (!(inline_secure(zone) && result == ISC_R_FILENOTFOUND)) {
5455 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5456 ISC_LOG_ERROR,
5457 "not loaded due to errors.");
5458 } else if (zone->type == dns_zone_primary) {
5459 result = ISC_R_SUCCESS;
5460 }
5461 }
5462
5463 done:
5464 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
5465 /*
5466 * If this is an inline-signed zone and we were called for the raw
5467 * zone, we need to clear DNS_ZONEFLG_LOADPENDING for the secure zone
5468 * as well, but only if this is a reload, not an initial zone load: in
5469 * the former case, zone_postload() will not be run for the secure
5470 * zone; in the latter case, it will be. Check which case we are
5471 * dealing with by consulting the DNS_ZONEFLG_LOADED flag for the
5472 * secure zone: if it is set, this must be a reload.
5473 */
5474 if (inline_raw(zone) && DNS_ZONE_FLAG(zone->secure, DNS_ZONEFLG_LOADED))
5475 {
5476 DNS_ZONE_CLRFLAG(zone->secure, DNS_ZONEFLG_LOADPENDING);
5477 /*
5478 * Re-start zone maintenance if it had been stalled
5479 * due to DNS_ZONEFLG_LOADPENDING being set when
5480 * zone_maintenance was called.
5481 */
5482 if (zone->secure->task != NULL) {
5483 zone_settimer(zone->secure, &now);
5484 }
5485 }
5486
5487 zone_debuglog(zone, "zone_postload", 99, "done");
5488
5489 return (result);
5490 }
5491
5492 static bool
5493 exit_check(dns_zone_t *zone) {
5494 REQUIRE(LOCKED_ZONE(zone));
5495
5496 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) &&
5497 isc_refcount_current(&zone->irefs) == 0)
5498 {
5499 /*
5500 * DNS_ZONEFLG_SHUTDOWN can only be set if erefs == 0.
5501 */
5502 INSIST(isc_refcount_current(&zone->erefs) == 0);
5503 return (true);
5504 }
5505 return (false);
5506 }
5507
5508 static bool
5509 zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
5510 dns_name_t *name, bool logit) {
5511 isc_result_t result;
5512 char namebuf[DNS_NAME_FORMATSIZE];
5513 char altbuf[DNS_NAME_FORMATSIZE];
5514 dns_fixedname_t fixed;
5515 dns_name_t *foundname;
5516 int level;
5517
5518 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOCHECKNS)) {
5519 return (true);
5520 }
5521
5522 if (zone->type == dns_zone_primary) {
5523 level = ISC_LOG_ERROR;
5524 } else {
5525 level = ISC_LOG_WARNING;
5526 }
5527
5528 foundname = dns_fixedname_initname(&fixed);
5529
5530 result = dns_db_find(db, name, version, dns_rdatatype_a, 0, 0, NULL,
5531 foundname, NULL, NULL);
5532 if (result == ISC_R_SUCCESS) {
5533 return (true);
5534 }
5535
5536 if (result == DNS_R_NXRRSET) {
5537 result = dns_db_find(db, name, version, dns_rdatatype_aaaa, 0,
5538 0, NULL, foundname, NULL, NULL);
5539 if (result == ISC_R_SUCCESS) {
5540 return (true);
5541 }
5542 }
5543
5544 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
5545 result == DNS_R_EMPTYNAME)
5546 {
5547 if (logit) {
5548 dns_name_format(name, namebuf, sizeof namebuf);
5549 dns_zone_log(zone, level,
5550 "NS '%s' has no address "
5551 "records (A or AAAA)",
5552 namebuf);
5553 }
5554 return (false);
5555 }
5556
5557 if (result == DNS_R_CNAME) {
5558 if (logit) {
5559 dns_name_format(name, namebuf, sizeof namebuf);
5560 dns_zone_log(zone, level,
5561 "NS '%s' is a CNAME "
5562 "(illegal)",
5563 namebuf);
5564 }
5565 return (false);
5566 }
5567
5568 if (result == DNS_R_DNAME) {
5569 if (logit) {
5570 dns_name_format(name, namebuf, sizeof namebuf);
5571 dns_name_format(foundname, altbuf, sizeof altbuf);
5572 dns_zone_log(zone, level,
5573 "NS '%s' is below a DNAME "
5574 "'%s' (illegal)",
5575 namebuf, altbuf);
5576 }
5577 return (false);
5578 }
5579
5580 return (true);
5581 }
5582
5583 static isc_result_t
5584 zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
5585 dns_dbversion_t *version, unsigned int *nscount,
5586 unsigned int *errors, bool logit) {
5587 isc_result_t result;
5588 unsigned int count = 0;
5589 unsigned int ecount = 0;
5590 dns_rdataset_t rdataset;
5591 dns_rdata_t rdata;
5592 dns_rdata_ns_t ns;
5593
5594 dns_rdataset_init(&rdataset);
5595 result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns,
5596 dns_rdatatype_none, 0, &rdataset, NULL);
5597 if (result == ISC_R_NOTFOUND) {
5598 INSIST(!dns_rdataset_isassociated(&rdataset));
5599 goto success;
5600 }
5601 if (result != ISC_R_SUCCESS) {
5602 INSIST(!dns_rdataset_isassociated(&rdataset));
5603 goto invalidate_rdataset;
5604 }
5605
5606 result = dns_rdataset_first(&rdataset);
5607 while (result == ISC_R_SUCCESS) {
5608 if (errors != NULL && zone->rdclass == dns_rdataclass_in &&
5609 (zone->type == dns_zone_primary ||
5610 zone->type == dns_zone_secondary ||
5611 zone->type == dns_zone_mirror))
5612 {
5613 dns_rdata_init(&rdata);
5614 dns_rdataset_current(&rdataset, &rdata);
5615 result = dns_rdata_tostruct(&rdata, &ns, NULL);
5616 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5617 if (dns_name_issubdomain(&ns.name, &zone->origin) &&
5618 !zone_check_ns(zone, db, version, &ns.name, logit))
5619 {
5620 ecount++;
5621 }
5622 }
5623 count++;
5624 result = dns_rdataset_next(&rdataset);
5625 }
5626 dns_rdataset_disassociate(&rdataset);
5627
5628 success:
5629 if (nscount != NULL) {
5630 *nscount = count;
5631 }
5632 if (errors != NULL) {
5633 *errors = ecount;
5634 }
5635
5636 result = ISC_R_SUCCESS;
5637
5638 invalidate_rdataset:
5639 dns_rdataset_invalidate(&rdataset);
5640
5641 return (result);
5642 }
5643
5644 #define SET_IF_NOT_NULL(obj, val) \
5645 if (obj != NULL) { \
5646 *obj = val; \
5647 }
5648
5649 #define SET_SOA_VALUES(soattl_v, serial_v, refresh_v, retry_v, expire_v, \
5650 minimum_v) \
5651 { \
5652 SET_IF_NOT_NULL(soattl, soattl_v); \
5653 SET_IF_NOT_NULL(serial, serial_v); \
5654 SET_IF_NOT_NULL(refresh, refresh_v); \
5655 SET_IF_NOT_NULL(retry, retry_v); \
5656 SET_IF_NOT_NULL(expire, expire_v); \
5657 SET_IF_NOT_NULL(minimum, minimum_v); \
5658 }
5659
5660 #define CLR_SOA_VALUES() \
5661 { \
5662 SET_SOA_VALUES(0, 0, 0, 0, 0, 0); \
5663 }
5664
5665 static isc_result_t
5666 zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
5667 unsigned int *soacount, uint32_t *soattl, uint32_t *serial,
5668 uint32_t *refresh, uint32_t *retry, uint32_t *expire,
5669 uint32_t *minimum) {
5670 isc_result_t result;
5671 unsigned int count = 0;
5672 dns_rdataset_t rdataset;
5673 dns_rdata_t rdata = DNS_RDATA_INIT;
5674
5675 dns_rdataset_init(&rdataset);
5676 result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
5677 dns_rdatatype_none, 0, &rdataset, NULL);
5678 if (result == ISC_R_NOTFOUND) {
5679 INSIST(!dns_rdataset_isassociated(&rdataset));
5680 result = ISC_R_SUCCESS;
5681 goto invalidate_rdataset;
5682 }
5683 if (result != ISC_R_SUCCESS) {
5684 INSIST(!dns_rdataset_isassociated(&rdataset));
5685 goto invalidate_rdataset;
5686 }
5687
5688 result = dns_rdataset_first(&rdataset);
5689 while (result == ISC_R_SUCCESS) {
5690 dns_rdata_init(&rdata);
5691 dns_rdataset_current(&rdataset, &rdata);
5692 count++;
5693 if (count == 1) {
5694 dns_rdata_soa_t soa;
5695 result = dns_rdata_tostruct(&rdata, &soa, NULL);
5696 SET_SOA_VALUES(rdataset.ttl, soa.serial, soa.refresh,
5697 soa.retry, soa.expire, soa.minimum);
5698 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5699 }
5700
5701 result = dns_rdataset_next(&rdataset);
5702 dns_rdata_reset(&rdata);
5703 }
5704 dns_rdataset_disassociate(&rdataset);
5705
5706 result = ISC_R_SUCCESS;
5707
5708 invalidate_rdataset:
5709 SET_IF_NOT_NULL(soacount, count);
5710 if (count == 0) {
5711 CLR_SOA_VALUES();
5712 }
5713
5714 dns_rdataset_invalidate(&rdataset);
5715
5716 return (result);
5717 }
5718
5719 /*
5720 * zone must be locked.
5721 */
5722 static isc_result_t
5723 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
5724 unsigned int *soacount, uint32_t *soattl, uint32_t *serial,
5725 uint32_t *refresh, uint32_t *retry, uint32_t *expire,
5726 uint32_t *minimum, unsigned int *errors) {
5727 isc_result_t result;
5728 isc_result_t answer = ISC_R_SUCCESS;
5729 dns_dbversion_t *version = NULL;
5730 dns_dbnode_t *node;
5731
5732 REQUIRE(db != NULL);
5733 REQUIRE(zone != NULL);
5734
5735 dns_db_currentversion(db, &version);
5736
5737 SET_IF_NOT_NULL(nscount, 0);
5738 SET_IF_NOT_NULL(soacount, 0);
5739 SET_IF_NOT_NULL(errors, 0);
5740 CLR_SOA_VALUES();
5741
5742 node = NULL;
5743 result = dns_db_findnode(db, &zone->origin, false, &node);
5744 if (result != ISC_R_SUCCESS) {
5745 answer = result;
5746 goto closeversion;
5747 }
5748
5749 if (nscount != NULL || errors != NULL) {
5750 result = zone_count_ns_rr(zone, db, node, version, nscount,
5751 errors, true);
5752 if (result != ISC_R_SUCCESS) {
5753 answer = result;
5754 }
5755 }
5756
5757 if (soacount != NULL || soattl != NULL || serial != NULL ||
5758 refresh != NULL || retry != NULL || expire != NULL ||
5759 minimum != NULL)
5760 {
5761 result = zone_load_soa_rr(db, node, version, soacount, soattl,
5762 serial, refresh, retry, expire,
5763 minimum);
5764 if (result != ISC_R_SUCCESS) {
5765 answer = result;
5766 }
5767 }
5768
5769 dns_db_detachnode(db, &node);
5770 closeversion:
5771 dns_db_closeversion(db, &version, false);
5772
5773 return (answer);
5774 }
5775
5776 void
5777 dns_zone_attach(dns_zone_t *source, dns_zone_t **target) {
5778 REQUIRE(DNS_ZONE_VALID(source));
5779 REQUIRE(target != NULL && *target == NULL);
5780 isc_refcount_increment(&source->erefs);
5781 *target = source;
5782 }
5783
5784 void
5785 dns_zone_detach(dns_zone_t **zonep) {
5786 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
5787
5788 dns_zone_t *zone = *zonep;
5789 *zonep = NULL;
5790
5791 if (isc_refcount_decrement(&zone->erefs) == 1) {
5792 isc_event_t *ev = &zone->ctlevent;
5793
5794 isc_refcount_destroy(&zone->erefs);
5795
5796 /*
5797 * Stop things being restarted after we cancel them below.
5798 */
5799 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
5800 dns_zone_log(zone, ISC_LOG_DEBUG(1),
5801 "final reference detached");
5802 if (zone->task != NULL) {
5803 /*
5804 * This zone has a task; it can clean
5805 * itself up asynchronously.
5806 */
5807 isc_task_send(zone->task, &ev);
5808 return;
5809 }
5810
5811 /*
5812 * This zone is unmanaged; we're probably running in
5813 * named-checkzone or a unit test. There's no task,
5814 * so we need to free it immediately.
5815 *
5816 * Unmanaged zones must not have null views; we have no way
5817 * of detaching from the view here without causing deadlock
5818 * because this code is called with the view already
5819 * locked.
5820 */
5821 INSIST(zone->view == NULL);
5822
5823 zone_shutdown(zone->task, ev);
5824 ev = NULL;
5825 }
5826 }
5827
5828 void
5829 dns_zone_iattach(dns_zone_t *source, dns_zone_t **target) {
5830 REQUIRE(DNS_ZONE_VALID(source));
5831
5832 LOCK_ZONE(source);
5833 zone_iattach(source, target);
5834 UNLOCK_ZONE(source);
5835 }
5836
5837 static void
5838 zone_iattach(dns_zone_t *source, dns_zone_t **target) {
5839 REQUIRE(DNS_ZONE_VALID(source));
5840 REQUIRE(LOCKED_ZONE(source));
5841 REQUIRE(target != NULL && *target == NULL);
5842 INSIST(isc_refcount_increment0(&source->irefs) +
5843 isc_refcount_current(&source->erefs) >
5844 0);
5845 *target = source;
5846 }
5847
5848 static void
5849 zone_idetach(dns_zone_t **zonep) {
5850 dns_zone_t *zone;
5851
5852 /*
5853 * 'zone' locked by caller.
5854 */
5855 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
5856 REQUIRE(LOCKED_ZONE(*zonep));
5857
5858 zone = *zonep;
5859 *zonep = NULL;
5860
5861 INSIST(isc_refcount_decrement(&zone->irefs) - 1 +
5862 isc_refcount_current(&zone->erefs) >
5863 0);
5864 }
5865
5866 void
5867 dns_zone_idetach(dns_zone_t **zonep) {
5868 dns_zone_t *zone;
5869
5870 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
5871
5872 zone = *zonep;
5873 *zonep = NULL;
5874
5875 if (isc_refcount_decrement(&zone->irefs) == 1) {
5876 bool free_needed;
5877 LOCK_ZONE(zone);
5878 free_needed = exit_check(zone);
5879 UNLOCK_ZONE(zone);
5880 if (free_needed) {
5881 zone_free(zone);
5882 }
5883 }
5884 }
5885
5886 isc_mem_t *
5887 dns_zone_getmctx(dns_zone_t *zone) {
5888 REQUIRE(DNS_ZONE_VALID(zone));
5889
5890 return (zone->mctx);
5891 }
5892
5893 dns_zonemgr_t *
5894 dns_zone_getmgr(dns_zone_t *zone) {
5895 REQUIRE(DNS_ZONE_VALID(zone));
5896
5897 return (zone->zmgr);
5898 }
5899
5900 void
5901 dns_zone_setkasp(dns_zone_t *zone, dns_kasp_t *kasp) {
5902 REQUIRE(DNS_ZONE_VALID(zone));
5903
5904 LOCK_ZONE(zone);
5905 if (zone->kasp != NULL) {
5906 dns_kasp_detach(&zone->kasp);
5907 }
5908 if (kasp != NULL) {
5909 dns_kasp_attach(kasp, &zone->kasp);
5910 }
5911 UNLOCK_ZONE(zone);
5912 }
5913
5914 dns_kasp_t *
5915 dns_zone_getkasp(dns_zone_t *zone) {
5916 REQUIRE(DNS_ZONE_VALID(zone));
5917
5918 return (zone->kasp);
5919 }
5920
5921 void
5922 dns_zone_setoption(dns_zone_t *zone, dns_zoneopt_t option, bool value) {
5923 REQUIRE(DNS_ZONE_VALID(zone));
5924
5925 if (value) {
5926 DNS_ZONE_SETOPTION(zone, option);
5927 } else {
5928 DNS_ZONE_CLROPTION(zone, option);
5929 }
5930 }
5931
5932 dns_zoneopt_t
5933 dns_zone_getoptions(dns_zone_t *zone) {
5934 REQUIRE(DNS_ZONE_VALID(zone));
5935
5936 return (atomic_load_relaxed(&zone->options));
5937 }
5938
5939 void
5940 dns_zone_setkeyopt(dns_zone_t *zone, unsigned int keyopt, bool value) {
5941 REQUIRE(DNS_ZONE_VALID(zone));
5942
5943 if (value) {
5944 DNS_ZONEKEY_SETOPTION(zone, keyopt);
5945 } else {
5946 DNS_ZONEKEY_CLROPTION(zone, keyopt);
5947 }
5948 }
5949
5950 unsigned int
5951 dns_zone_getkeyopts(dns_zone_t *zone) {
5952 REQUIRE(DNS_ZONE_VALID(zone));
5953
5954 return (atomic_load_relaxed(&zone->keyopts));
5955 }
5956
5957 isc_result_t
5958 dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
5959 REQUIRE(DNS_ZONE_VALID(zone));
5960
5961 LOCK_ZONE(zone);
5962 zone->xfrsource4 = *xfrsource;
5963 UNLOCK_ZONE(zone);
5964
5965 return (ISC_R_SUCCESS);
5966 }
5967
5968 isc_sockaddr_t *
5969 dns_zone_getxfrsource4(dns_zone_t *zone) {
5970 REQUIRE(DNS_ZONE_VALID(zone));
5971 return (&zone->xfrsource4);
5972 }
5973
5974 isc_result_t
5975 dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
5976 REQUIRE(DNS_ZONE_VALID(zone));
5977
5978 LOCK_ZONE(zone);
5979 zone->xfrsource6 = *xfrsource;
5980 UNLOCK_ZONE(zone);
5981
5982 return (ISC_R_SUCCESS);
5983 }
5984
5985 isc_sockaddr_t *
5986 dns_zone_getxfrsource6(dns_zone_t *zone) {
5987 REQUIRE(DNS_ZONE_VALID(zone));
5988 return (&zone->xfrsource6);
5989 }
5990
5991 isc_result_t
5992 dns_zone_setaltxfrsource4(dns_zone_t *zone,
5993 const isc_sockaddr_t *altxfrsource) {
5994 REQUIRE(DNS_ZONE_VALID(zone));
5995
5996 LOCK_ZONE(zone);
5997 zone->altxfrsource4 = *altxfrsource;
5998 UNLOCK_ZONE(zone);
5999
6000 return (ISC_R_SUCCESS);
6001 }
6002
6003 isc_sockaddr_t *
6004 dns_zone_getaltxfrsource4(dns_zone_t *zone) {
6005 REQUIRE(DNS_ZONE_VALID(zone));
6006 return (&zone->altxfrsource4);
6007 }
6008
6009 isc_result_t
6010 dns_zone_setaltxfrsource6(dns_zone_t *zone,
6011 const isc_sockaddr_t *altxfrsource) {
6012 REQUIRE(DNS_ZONE_VALID(zone));
6013
6014 LOCK_ZONE(zone);
6015 zone->altxfrsource6 = *altxfrsource;
6016 UNLOCK_ZONE(zone);
6017
6018 return (ISC_R_SUCCESS);
6019 }
6020
6021 isc_sockaddr_t *
6022 dns_zone_getaltxfrsource6(dns_zone_t *zone) {
6023 REQUIRE(DNS_ZONE_VALID(zone));
6024 return (&zone->altxfrsource6);
6025 }
6026
6027 isc_result_t
6028 dns_zone_setparentalsrc4(dns_zone_t *zone, const isc_sockaddr_t *parentalsrc) {
6029 REQUIRE(DNS_ZONE_VALID(zone));
6030
6031 LOCK_ZONE(zone);
6032 zone->parentalsrc4 = *parentalsrc;
6033 UNLOCK_ZONE(zone);
6034
6035 return (ISC_R_SUCCESS);
6036 }
6037
6038 isc_sockaddr_t *
6039 dns_zone_getparentalsrc4(dns_zone_t *zone) {
6040 REQUIRE(DNS_ZONE_VALID(zone));
6041 return (&zone->parentalsrc4);
6042 }
6043
6044 isc_result_t
6045 dns_zone_setparentalsrc6(dns_zone_t *zone, const isc_sockaddr_t *parentalsrc) {
6046 REQUIRE(DNS_ZONE_VALID(zone));
6047
6048 LOCK_ZONE(zone);
6049 zone->parentalsrc6 = *parentalsrc;
6050 UNLOCK_ZONE(zone);
6051
6052 return (ISC_R_SUCCESS);
6053 }
6054
6055 isc_sockaddr_t *
6056 dns_zone_getparentalsrc6(dns_zone_t *zone) {
6057 REQUIRE(DNS_ZONE_VALID(zone));
6058 return (&zone->parentalsrc6);
6059 }
6060
6061 isc_result_t
6062 dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
6063 REQUIRE(DNS_ZONE_VALID(zone));
6064
6065 LOCK_ZONE(zone);
6066 zone->notifysrc4 = *notifysrc;
6067 UNLOCK_ZONE(zone);
6068
6069 return (ISC_R_SUCCESS);
6070 }
6071
6072 isc_sockaddr_t *
6073 dns_zone_getnotifysrc4(dns_zone_t *zone) {
6074 REQUIRE(DNS_ZONE_VALID(zone));
6075 return (&zone->notifysrc4);
6076 }
6077
6078 isc_result_t
6079 dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
6080 REQUIRE(DNS_ZONE_VALID(zone));
6081
6082 LOCK_ZONE(zone);
6083 zone->notifysrc6 = *notifysrc;
6084 UNLOCK_ZONE(zone);
6085
6086 return (ISC_R_SUCCESS);
6087 }
6088
6089 isc_sockaddr_t *
6090 dns_zone_getnotifysrc6(dns_zone_t *zone) {
6091 REQUIRE(DNS_ZONE_VALID(zone));
6092 return (&zone->notifysrc6);
6093 }
6094
6095 static bool
6096 same_addrs(isc_sockaddr_t const *oldlist, isc_sockaddr_t const *newlist,
6097 uint32_t count) {
6098 unsigned int i;
6099
6100 for (i = 0; i < count; i++) {
6101 if (!isc_sockaddr_equal(&oldlist[i], &newlist[i])) {
6102 return (false);
6103 }
6104 }
6105 return (true);
6106 }
6107
6108 static bool
6109 same_names(dns_name_t *const *oldlist, dns_name_t *const *newlist,
6110 uint32_t count) {
6111 unsigned int i;
6112
6113 if (oldlist == NULL && newlist == NULL) {
6114 return (true);
6115 }
6116 if (oldlist == NULL || newlist == NULL) {
6117 return (false);
6118 }
6119
6120 for (i = 0; i < count; i++) {
6121 if (oldlist[i] == NULL && newlist[i] == NULL) {
6122 continue;
6123 }
6124 if (oldlist[i] == NULL || newlist[i] == NULL ||
6125 !dns_name_equal(oldlist[i], newlist[i]))
6126 {
6127 return (false);
6128 }
6129 }
6130 return (true);
6131 }
6132
6133 static void
6134 clear_serverslist(isc_sockaddr_t **addrsp, dns_name_t ***keynamesp,
6135 dns_name_t ***tlsnamesp, unsigned int *countp,
6136 isc_mem_t *mctx) {
6137 unsigned int count;
6138 isc_sockaddr_t *addrs;
6139 dns_name_t **keynames;
6140 dns_name_t **tlsnames;
6141
6142 REQUIRE(countp != NULL);
6143 REQUIRE(addrsp != NULL);
6144 REQUIRE(keynamesp != NULL);
6145 REQUIRE(tlsnamesp != NULL);
6146
6147 count = *countp;
6148 *countp = 0;
6149 addrs = *addrsp;
6150 *addrsp = NULL;
6151 keynames = *keynamesp;
6152 *keynamesp = NULL;
6153 tlsnames = *tlsnamesp;
6154 *tlsnamesp = NULL;
6155
6156 if (addrs != NULL) {
6157 isc_mem_put(mctx, addrs, count * sizeof(isc_sockaddr_t));
6158 }
6159
6160 if (keynames != NULL) {
6161 unsigned int i;
6162 for (i = 0; i < count; i++) {
6163 if (keynames[i] != NULL) {
6164 dns_name_free(keynames[i], mctx);
6165 isc_mem_put(mctx, keynames[i],
6166 sizeof(dns_name_t));
6167 keynames[i] = NULL;
6168 }
6169 }
6170 isc_mem_put(mctx, keynames, count * sizeof(dns_name_t *));
6171 }
6172
6173 if (tlsnames != NULL) {
6174 unsigned int i;
6175 for (i = 0; i < count; i++) {
6176 if (tlsnames[i] != NULL) {
6177 dns_name_free(tlsnames[i], mctx);
6178 isc_mem_put(mctx, tlsnames[i],
6179 sizeof(dns_name_t));
6180 tlsnames[i] = NULL;
6181 }
6182 }
6183 isc_mem_put(mctx, tlsnames, count * sizeof(dns_name_t *));
6184 }
6185 }
6186
6187 static void
6188 set_serverslist(unsigned int count, const isc_sockaddr_t *addrs,
6189 isc_sockaddr_t **newaddrsp, dns_name_t **keynames,
6190 dns_name_t ***newkeynamesp, dns_name_t **tlsnames,
6191 dns_name_t ***newtlsnamesp, isc_mem_t *mctx) {
6192 isc_sockaddr_t *newaddrs = NULL;
6193 dns_name_t **newkeynames = NULL;
6194 dns_name_t **newtlsnames = NULL;
6195 unsigned int i;
6196
6197 REQUIRE(newaddrsp != NULL && *newaddrsp == NULL);
6198 REQUIRE(newkeynamesp != NULL && *newkeynamesp == NULL);
6199 REQUIRE(newtlsnamesp != NULL && *newtlsnamesp == NULL);
6200
6201 newaddrs = isc_mem_get(mctx, count * sizeof(*newaddrs));
6202 memmove(newaddrs, addrs, count * sizeof(*newaddrs));
6203
6204 if (keynames != NULL) {
6205 newkeynames = isc_mem_get(mctx, count * sizeof(*newkeynames));
6206 for (i = 0; i < count; i++) {
6207 newkeynames[i] = NULL;
6208 }
6209 for (i = 0; i < count; i++) {
6210 if (keynames[i] != NULL) {
6211 newkeynames[i] =
6212 isc_mem_get(mctx, sizeof(dns_name_t));
6213 dns_name_init(newkeynames[i], NULL);
6214 dns_name_dup(keynames[i], mctx, newkeynames[i]);
6215 }
6216 }
6217 }
6218
6219 if (tlsnames != NULL) {
6220 newtlsnames = isc_mem_get(mctx, count * sizeof(*newtlsnames));
6221 for (i = 0; i < count; i++) {
6222 newtlsnames[i] = NULL;
6223 }
6224 for (i = 0; i < count; i++) {
6225 if (tlsnames[i] != NULL) {
6226 newtlsnames[i] =
6227 isc_mem_get(mctx, sizeof(dns_name_t));
6228 dns_name_init(newtlsnames[i], NULL);
6229 dns_name_dup(tlsnames[i], mctx, newtlsnames[i]);
6230 }
6231 }
6232 }
6233
6234 *newaddrsp = newaddrs;
6235 *newkeynamesp = newkeynames;
6236 *newtlsnamesp = newtlsnames;
6237 }
6238
6239 void
6240 dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify,
6241 dns_name_t **keynames, dns_name_t **tlsnames,
6242 uint32_t count) {
6243 isc_sockaddr_t *newaddrs = NULL;
6244 dns_name_t **newkeynames = NULL;
6245 dns_name_t **newtlsnames = NULL;
6246
6247 REQUIRE(DNS_ZONE_VALID(zone));
6248 REQUIRE(count == 0 || notify != NULL);
6249 if (keynames != NULL) {
6250 REQUIRE(count != 0);
6251 }
6252
6253 LOCK_ZONE(zone);
6254
6255 if (count == zone->notifycnt &&
6256 same_addrs(zone->notify, notify, count) &&
6257 same_names(zone->notifykeynames, keynames, count) &&
6258 same_names(zone->notifytlsnames, tlsnames, count))
6259 {
6260 goto unlock;
6261 }
6262
6263 clear_serverslist(&zone->notify, &zone->notifykeynames,
6264 &zone->notifytlsnames, &zone->notifycnt, zone->mctx);
6265
6266 if (count == 0) {
6267 goto unlock;
6268 }
6269
6270 /*
6271 * Set up the notify and notifykey lists
6272 */
6273 set_serverslist(count, notify, &newaddrs, keynames, &newkeynames,
6274 tlsnames, &newtlsnames, zone->mctx);
6275
6276 /*
6277 * Everything is ok so attach to the zone.
6278 */
6279 zone->notify = newaddrs;
6280 zone->notifykeynames = newkeynames;
6281 zone->notifytlsnames = newtlsnames;
6282 zone->notifycnt = count;
6283 unlock:
6284 UNLOCK_ZONE(zone);
6285 }
6286
6287 void
6288 dns_zone_setprimaries(dns_zone_t *zone, const isc_sockaddr_t *primaries,
6289 dns_name_t **keynames, dns_name_t **tlsnames,
6290 uint32_t count) {
6291 isc_sockaddr_t *newaddrs = NULL;
6292 dns_name_t **newkeynames = NULL;
6293 dns_name_t **newtlsnames = NULL;
6294 bool *newok;
6295 unsigned int i;
6296
6297 REQUIRE(DNS_ZONE_VALID(zone));
6298 REQUIRE(count == 0 || primaries != NULL);
6299 if (keynames != NULL || tlsnames != NULL) {
6300 REQUIRE(count != 0);
6301 }
6302
6303 LOCK_ZONE(zone);
6304 /*
6305 * The refresh code assumes that 'primaries' wouldn't change under it.
6306 * If it will change then kill off any current refresh in progress
6307 * and update the primaries info. If it won't change then we can just
6308 * unlock and exit.
6309 */
6310 if (count != zone->primariescnt ||
6311 !same_addrs(zone->primaries, primaries, count) ||
6312 !same_names(zone->primarykeynames, keynames, count) ||
6313 !same_names(zone->primarytlsnames, tlsnames, count))
6314 {
6315 if (zone->request != NULL) {
6316 dns_request_cancel(zone->request);
6317 }
6318 } else {
6319 goto unlock;
6320 }
6321
6322 /*
6323 * This needs to happen before clear_addresskeylist() sets
6324 * zone->primariescnt to 0:
6325 */
6326 if (zone->primariesok != NULL) {
6327 isc_mem_put(zone->mctx, zone->primariesok,
6328 zone->primariescnt * sizeof(bool));
6329 zone->primariesok = NULL;
6330 }
6331 clear_serverslist(&zone->primaries, &zone->primarykeynames,
6332 &zone->primarytlsnames, &zone->primariescnt,
6333 zone->mctx);
6334 /*
6335 * If count == 0, don't allocate any space for primaries, primariesok or
6336 * keynames so internally, those pointers are NULL if count == 0
6337 */
6338 if (count == 0) {
6339 goto unlock;
6340 }
6341
6342 /*
6343 * primariesok must contain count elements
6344 */
6345 newok = isc_mem_get(zone->mctx, count * sizeof(*newok));
6346 for (i = 0; i < count; i++) {
6347 newok[i] = false;
6348 }
6349
6350 /*
6351 * Now set up the primaries and primary key lists
6352 */
6353 set_serverslist(count, primaries, &newaddrs, keynames, &newkeynames,
6354 tlsnames, &newtlsnames, zone->mctx);
6355
6356 /*
6357 * Everything is ok so attach to the zone.
6358 */
6359 zone->curprimary = 0;
6360 zone->primariesok = newok;
6361 zone->primaries = newaddrs;
6362 zone->primarykeynames = newkeynames;
6363 zone->primarytlsnames = newtlsnames;
6364 zone->primariescnt = count;
6365 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOPRIMARIES);
6366
6367 unlock:
6368 UNLOCK_ZONE(zone);
6369 }
6370
6371 void
6372 dns_zone_setparentals(dns_zone_t *zone, const isc_sockaddr_t *parentals,
6373 dns_name_t **keynames, dns_name_t **tlsnames,
6374 uint32_t count) {
6375 isc_sockaddr_t *newaddrs = NULL;
6376 dns_name_t **newkeynames = NULL;
6377 dns_name_t **newtlsnames = NULL;
6378
6379 REQUIRE(DNS_ZONE_VALID(zone));
6380 REQUIRE(count == 0 || parentals != NULL);
6381 if (keynames != NULL || tlsnames != NULL) {
6382 REQUIRE(count != 0);
6383 }
6384
6385 LOCK_ZONE(zone);
6386
6387 clear_serverslist(&zone->parentals, &zone->parentalkeynames,
6388 &zone->parentaltlsnames, &zone->parentalscnt,
6389 zone->mctx);
6390 /*
6391 * If count == 0, don't allocate any space for parentals, or keynames
6392 * so internally, those pointers are NULL if count == 0
6393 */
6394 if (count == 0) {
6395 goto unlock;
6396 }
6397
6398 /*
6399 * Now set up the parentals and parental key lists
6400 */
6401 set_serverslist(count, parentals, &newaddrs, keynames, &newkeynames,
6402 tlsnames, &newtlsnames, zone->mctx);
6403
6404 /*
6405 * Everything is ok so attach to the zone.
6406 */
6407 zone->parentals = newaddrs;
6408 zone->parentalkeynames = newkeynames;
6409 zone->parentaltlsnames = newtlsnames;
6410 zone->parentalscnt = count;
6411
6412 dns_zone_log(zone, ISC_LOG_NOTICE, "checkds: set %u parentals", count);
6413
6414 unlock:
6415 UNLOCK_ZONE(zone);
6416 }
6417
6418 isc_result_t
6419 dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) {
6420 isc_result_t result = ISC_R_SUCCESS;
6421
6422 REQUIRE(DNS_ZONE_VALID(zone));
6423
6424 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6425 if (zone->db == NULL) {
6426 result = DNS_R_NOTLOADED;
6427 } else {
6428 dns_db_attach(zone->db, dpb);
6429 }
6430 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6431
6432 return (result);
6433 }
6434
6435 void
6436 dns_zone_setdb(dns_zone_t *zone, dns_db_t *db) {
6437 REQUIRE(DNS_ZONE_VALID(zone));
6438 REQUIRE(zone->type == dns_zone_staticstub);
6439
6440 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
6441 REQUIRE(zone->db == NULL);
6442 dns_db_attach(db, &zone->db);
6443 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
6444 }
6445
6446 /*
6447 * Coordinates the starting of routine jobs.
6448 */
6449 void
6450 dns_zone_maintenance(dns_zone_t *zone) {
6451 const char me[] = "dns_zone_maintenance";
6452 isc_time_t now;
6453
6454 REQUIRE(DNS_ZONE_VALID(zone));
6455 ENTER;
6456
6457 LOCK_ZONE(zone);
6458 TIME_NOW(&now);
6459 zone_settimer(zone, &now);
6460 UNLOCK_ZONE(zone);
6461 }
6462
6463 static bool
6464 was_dumping(dns_zone_t *zone) {
6465 REQUIRE(LOCKED_ZONE(zone));
6466
6467 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
6468 return (true);
6469 }
6470
6471 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
6472 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
6473 isc_time_settoepoch(&zone->dumptime);
6474 return (false);
6475 }
6476
6477 /*%
6478 * Find up to 'maxkeys' DNSSEC keys used for signing version 'ver' of database
6479 * 'db' for zone 'zone' in its key directory, then load these keys into 'keys'.
6480 * Only load the public part of a given key if it is not active at timestamp
6481 * 'now'. Store the number of keys found in 'nkeys'.
6482 */
6483 isc_result_t
6484 dns__zone_findkeys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
6485 isc_stdtime_t now, isc_mem_t *mctx, unsigned int maxkeys,
6486 dst_key_t **keys, unsigned int *nkeys) {
6487 isc_result_t result;
6488 dns_dbnode_t *node = NULL;
6489 const char *directory = dns_zone_getkeydirectory(zone);
6490
6491 CHECK(dns_db_findnode(db, dns_db_origin(db), false, &node));
6492 memset(keys, 0, sizeof(*keys) * maxkeys);
6493
6494 dns_zone_lock_keyfiles(zone);
6495
6496 result = dns_dnssec_findzonekeys(db, ver, node, dns_db_origin(db),
6497 directory, now, mctx, maxkeys, keys,
6498 nkeys);
6499
6500 dns_zone_unlock_keyfiles(zone);
6501
6502 if (result == ISC_R_NOTFOUND) {
6503 result = ISC_R_SUCCESS;
6504 }
6505
6506 failure:
6507
6508 if (node != NULL) {
6509 dns_db_detachnode(db, &node);
6510 }
6511 return (result);
6512 }
6513
6514 /*%
6515 * Find DNSSEC keys used for signing zone with dnssec-policy. Load these keys
6516 * into 'keys'. Requires KASP to be locked.
6517 */
6518 isc_result_t
6519 dns_zone_getdnsseckeys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
6520 isc_stdtime_t now, dns_dnsseckeylist_t *keys) {
6521 isc_result_t result;
6522 const char *dir = dns_zone_getkeydirectory(zone);
6523 dns_dbnode_t *node = NULL;
6524 dns_dnsseckey_t *key, *key_next;
6525 dns_dnsseckeylist_t dnskeys;
6526 dns_name_t *origin = dns_zone_getorigin(zone);
6527 dns_kasp_t *kasp = dns_zone_getkasp(zone);
6528 dns_rdataset_t keyset;
6529
6530 REQUIRE(DNS_ZONE_VALID(zone));
6531 REQUIRE(kasp != NULL);
6532
6533 ISC_LIST_INIT(dnskeys);
6534
6535 dns_rdataset_init(&keyset);
6536
6537 CHECK(dns_db_findnode(db, origin, false, &node));
6538
6539 /* Get keys from private key files. */
6540 dns_zone_lock_keyfiles(zone);
6541 result = dns_dnssec_findmatchingkeys(origin, dir, now,
6542 dns_zone_getmctx(zone), keys);
6543 dns_zone_unlock_keyfiles(zone);
6544
6545 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
6546 goto failure;
6547 }
6548
6549 /* Get public keys (dnskeys). */
6550 dns_rdataset_init(&keyset);
6551 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
6552 dns_rdatatype_none, 0, &keyset, NULL);
6553 if (result == ISC_R_SUCCESS) {
6554 CHECK(dns_dnssec_keylistfromrdataset(
6555 origin, dir, dns_zone_getmctx(zone), &keyset, NULL,
6556 NULL, false, false, &dnskeys));
6557 } else if (result != ISC_R_NOTFOUND) {
6558 CHECK(result);
6559 }
6560
6561 /* Add new 'dnskeys' to 'keys'. */
6562 for (dns_dnsseckey_t *k1 = ISC_LIST_HEAD(dnskeys); k1 != NULL;
6563 k1 = key_next)
6564 {
6565 dns_dnsseckey_t *k2 = NULL;
6566 key_next = ISC_LIST_NEXT(k1, link);
6567
6568 for (k2 = ISC_LIST_HEAD(*keys); k2 != NULL;
6569 k2 = ISC_LIST_NEXT(k2, link))
6570 {
6571 if (dst_key_compare(k1->key, k2->key)) {
6572 break;
6573 }
6574 }
6575 /* No match found, add the new key. */
6576 if (k2 == NULL) {
6577 ISC_LIST_UNLINK(dnskeys, k1, link);
6578 ISC_LIST_APPEND(*keys, k1, link);
6579 }
6580 }
6581
6582 failure:
6583 if (dns_rdataset_isassociated(&keyset)) {
6584 dns_rdataset_disassociate(&keyset);
6585 }
6586 if (node != NULL) {
6587 dns_db_detachnode(db, &node);
6588 }
6589 while (!ISC_LIST_EMPTY(dnskeys)) {
6590 key = ISC_LIST_HEAD(dnskeys);
6591 ISC_LIST_UNLINK(dnskeys, key, link);
6592 dns_dnsseckey_destroy(dns_zone_getmctx(zone), &key);
6593 }
6594 return (result);
6595 }
6596
6597 static isc_result_t
6598 offline(dns_db_t *db, dns_dbversion_t *ver, dns__zonediff_t *zonediff,
6599 dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata) {
6600 isc_result_t result;
6601
6602 if ((rdata->flags & DNS_RDATA_OFFLINE) != 0) {
6603 return (ISC_R_SUCCESS);
6604 }
6605 result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_DELRESIGN,
6606 name, ttl, rdata);
6607 if (result != ISC_R_SUCCESS) {
6608 return (result);
6609 }
6610 rdata->flags |= DNS_RDATA_OFFLINE;
6611 result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_ADDRESIGN,
6612 name, ttl, rdata);
6613 zonediff->offline = true;
6614 return (result);
6615 }
6616
6617 static void
6618 set_key_expiry_warning(dns_zone_t *zone, isc_stdtime_t when,
6619 isc_stdtime_t now) {
6620 unsigned int delta;
6621 char timebuf[80];
6622
6623 LOCK_ZONE(zone);
6624 zone->key_expiry = when;
6625 if (when <= now) {
6626 dns_zone_log(zone, ISC_LOG_ERROR,
6627 "DNSKEY RRSIG(s) have expired");
6628 isc_time_settoepoch(&zone->keywarntime);
6629 } else if (when < now + 7 * 24 * 3600) {
6630 isc_time_t t;
6631 isc_time_set(&t, when, 0);
6632 isc_time_formattimestamp(&t, timebuf, 80);
6633 dns_zone_log(zone, ISC_LOG_WARNING,
6634 "DNSKEY RRSIG(s) will expire within 7 days: %s",
6635 timebuf);
6636 delta = when - now;
6637 delta--; /* loop prevention */
6638 delta /= 24 * 3600; /* to whole days */
6639 delta *= 24 * 3600; /* to seconds */
6640 isc_time_set(&zone->keywarntime, when - delta, 0);
6641 } else {
6642 isc_time_set(&zone->keywarntime, when - 7 * 24 * 3600, 0);
6643 isc_time_formattimestamp(&zone->keywarntime, timebuf, 80);
6644 dns_zone_log(zone, ISC_LOG_NOTICE, "setting keywarntime to %s",
6645 timebuf);
6646 }
6647 UNLOCK_ZONE(zone);
6648 }
6649
6650 /*
6651 * Helper function to del_sigs(). We don't want to delete RRSIGs that
6652 * have no new key.
6653 */
6654 static bool
6655 delsig_ok(dns_rdata_rrsig_t *rrsig_ptr, dst_key_t **keys, unsigned int nkeys,
6656 bool kasp, bool *warn) {
6657 unsigned int i = 0;
6658 isc_result_t ret;
6659 bool have_ksk = false, have_zsk = false;
6660 bool have_pksk = false, have_pzsk = false;
6661
6662 for (i = 0; i < nkeys; i++) {
6663 bool ksk, zsk;
6664
6665 if (have_pksk && have_ksk && have_pzsk && have_zsk) {
6666 break;
6667 }
6668
6669 if (rrsig_ptr->algorithm != dst_key_alg(keys[i])) {
6670 continue;
6671 }
6672
6673 ret = dst_key_getbool(keys[i], DST_BOOL_KSK, &ksk);
6674 if (ret != ISC_R_SUCCESS) {
6675 ksk = KSK(keys[i]);
6676 }
6677 ret = dst_key_getbool(keys[i], DST_BOOL_ZSK, &zsk);
6678 if (ret != ISC_R_SUCCESS) {
6679 zsk = !KSK(keys[i]);
6680 }
6681
6682 if (ksk) {
6683 have_ksk = true;
6684 if (dst_key_isprivate(keys[i])) {
6685 have_pksk = true;
6686 }
6687 }
6688 if (zsk) {
6689 have_zsk = true;
6690 if (dst_key_isprivate(keys[i])) {
6691 have_pzsk = true;
6692 }
6693 }
6694 }
6695
6696 if (have_zsk && have_ksk && !have_pzsk) {
6697 *warn = true;
6698 }
6699
6700 if (have_pksk && have_pzsk) {
6701 return (true);
6702 }
6703
6704 /*
6705 * Deleting the SOA RRSIG is always okay.
6706 */
6707 if (rrsig_ptr->covered == dns_rdatatype_soa) {
6708 return (true);
6709 }
6710
6711 /*
6712 * It's okay to delete a signature if there is an active key with the
6713 * same algorithm to replace it, unless that violates the DNSSEC
6714 * policy.
6715 */
6716 if (have_pksk || have_pzsk) {
6717 if (kasp && have_pzsk) {
6718 return (true);
6719 }
6720 return (!kasp);
6721 }
6722
6723 /*
6724 * Failing that, it is *not* okay to delete a signature
6725 * if the associated public key is still in the DNSKEY RRset
6726 */
6727 for (i = 0; i < nkeys; i++) {
6728 if ((rrsig_ptr->algorithm == dst_key_alg(keys[i])) &&
6729 (rrsig_ptr->keyid == dst_key_id(keys[i])))
6730 {
6731 return (false);
6732 }
6733 }
6734
6735 /*
6736 * But if the key is gone, then go ahead.
6737 */
6738 return (true);
6739 }
6740
6741 /*
6742 * Delete expired RRsigs and any RRsigs we are about to re-sign.
6743 * See also update.c:del_keysigs().
6744 */
6745 static isc_result_t
6746 del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
6747 dns_rdatatype_t type, dns__zonediff_t *zonediff, dst_key_t **keys,
6748 unsigned int nkeys, isc_stdtime_t now, bool incremental) {
6749 isc_result_t result;
6750 dns_dbnode_t *node = NULL;
6751 dns_rdataset_t rdataset;
6752 unsigned int i;
6753 dns_rdata_rrsig_t rrsig;
6754 bool kasp = (dns_zone_getkasp(zone) != NULL);
6755 bool found;
6756 int64_t timewarn = 0, timemaybe = 0;
6757
6758 dns_rdataset_init(&rdataset);
6759
6760 if (type == dns_rdatatype_nsec3) {
6761 result = dns_db_findnsec3node(db, name, false, &node);
6762 } else {
6763 result = dns_db_findnode(db, name, false, &node);
6764 }
6765 if (result == ISC_R_NOTFOUND) {
6766 return (ISC_R_SUCCESS);
6767 }
6768 if (result != ISC_R_SUCCESS) {
6769 goto failure;
6770 }
6771 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig, type,
6772 (isc_stdtime_t)0, &rdataset, NULL);
6773 dns_db_detachnode(db, &node);
6774
6775 if (result == ISC_R_NOTFOUND) {
6776 INSIST(!dns_rdataset_isassociated(&rdataset));
6777 return (ISC_R_SUCCESS);
6778 }
6779 if (result != ISC_R_SUCCESS) {
6780 INSIST(!dns_rdataset_isassociated(&rdataset));
6781 goto failure;
6782 }
6783
6784 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
6785 result = dns_rdataset_next(&rdataset))
6786 {
6787 dns_rdata_t rdata = DNS_RDATA_INIT;
6788
6789 dns_rdataset_current(&rdataset, &rdata);
6790 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
6791 RUNTIME_CHECK(result == ISC_R_SUCCESS);
6792
6793 if (type != dns_rdatatype_dnskey && type != dns_rdatatype_cds &&
6794 type != dns_rdatatype_cdnskey)
6795 {
6796 bool warn = false, deleted = false;
6797 if (delsig_ok(&rrsig, keys, nkeys, kasp, &warn)) {
6798 result = update_one_rr(db, ver, zonediff->diff,
6799 DNS_DIFFOP_DELRESIGN,
6800 name, rdataset.ttl,
6801 &rdata);
6802 if (result != ISC_R_SUCCESS) {
6803 break;
6804 }
6805 deleted = true;
6806 }
6807 if (warn && !deleted) {
6808 /*
6809 * At this point, we've got an RRSIG,
6810 * which is signed by an inactive key.
6811 * An administrator needs to provide a new
6812 * key/alg, but until that time, we want to
6813 * keep the old RRSIG. Marking the key as
6814 * offline will prevent us spinning waiting
6815 * for the private part.
6816 */
6817 if (incremental) {
6818 result = offline(db, ver, zonediff,
6819 name, rdataset.ttl,
6820 &rdata);
6821 if (result != ISC_R_SUCCESS) {
6822 break;
6823 }
6824 }
6825
6826 /*
6827 * Log the key id and algorithm of
6828 * the inactive key with no replacement
6829 */
6830 if (zone->log_key_expired_timer <= now) {
6831 char origin[DNS_NAME_FORMATSIZE];
6832 char algbuf[DNS_NAME_FORMATSIZE];
6833 dns_name_format(&zone->origin, origin,
6834 sizeof(origin));
6835 dns_secalg_format(rrsig.algorithm,
6836 algbuf,
6837 sizeof(algbuf));
6838 dns_zone_log(zone, ISC_LOG_WARNING,
6839 "Key %s/%s/%d "
6840 "missing or inactive "
6841 "and has no replacement: "
6842 "retaining signatures.",
6843 origin, algbuf,
6844 rrsig.keyid);
6845 zone->log_key_expired_timer = now +
6846 3600;
6847 }
6848 }
6849 continue;
6850 }
6851
6852 /*
6853 * KSK RRSIGs requires special processing.
6854 */
6855 found = false;
6856 for (i = 0; i < nkeys; i++) {
6857 if (rrsig.algorithm == dst_key_alg(keys[i]) &&
6858 rrsig.keyid == dst_key_id(keys[i]))
6859 {
6860 found = true;
6861 /*
6862 * Mark offline DNSKEY.
6863 * We want the earliest offline expire time
6864 * iff there is a new offline signature.
6865 */
6866 if (!dst_key_inactive(keys[i]) &&
6867 !dst_key_isprivate(keys[i]))
6868 {
6869 int64_t timeexpire = dns_time64_from32(
6870 rrsig.timeexpire);
6871 if (timewarn != 0 &&
6872 timewarn > timeexpire)
6873 {
6874 timewarn = timeexpire;
6875 }
6876 if (rdata.flags & DNS_RDATA_OFFLINE) {
6877 if (timemaybe == 0 ||
6878 timemaybe > timeexpire)
6879 {
6880 timemaybe = timeexpire;
6881 }
6882 break;
6883 }
6884 if (timewarn == 0) {
6885 timewarn = timemaybe;
6886 }
6887 if (timewarn == 0 ||
6888 timewarn > timeexpire)
6889 {
6890 timewarn = timeexpire;
6891 }
6892 result = offline(db, ver, zonediff,
6893 name, rdataset.ttl,
6894 &rdata);
6895 break;
6896 }
6897 result = update_one_rr(db, ver, zonediff->diff,
6898 DNS_DIFFOP_DELRESIGN,
6899 name, rdataset.ttl,
6900 &rdata);
6901 break;
6902 }
6903 }
6904
6905 /*
6906 * If there is not a matching DNSKEY then
6907 * delete the RRSIG.
6908 */
6909 if (!found) {
6910 result = update_one_rr(db, ver, zonediff->diff,
6911 DNS_DIFFOP_DELRESIGN, name,
6912 rdataset.ttl, &rdata);
6913 }
6914 if (result != ISC_R_SUCCESS) {
6915 break;
6916 }
6917 }
6918
6919 dns_rdataset_disassociate(&rdataset);
6920 if (result == ISC_R_NOMORE) {
6921 result = ISC_R_SUCCESS;
6922 }
6923 if (timewarn > 0) {
6924 isc_stdtime_t stdwarn = (isc_stdtime_t)timewarn;
6925 if (timewarn == stdwarn) {
6926 set_key_expiry_warning(zone, (isc_stdtime_t)timewarn,
6927 now);
6928 } else {
6929 dns_zone_log(zone, ISC_LOG_ERROR,
6930 "key expiry warning time out of range");
6931 }
6932 }
6933 failure:
6934 if (node != NULL) {
6935 dns_db_detachnode(db, &node);
6936 }
6937 return (result);
6938 }
6939
6940 static isc_result_t
6941 add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_zone_t *zone,
6942 dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
6943 unsigned int nkeys, isc_mem_t *mctx, isc_stdtime_t now,
6944 isc_stdtime_t inception, isc_stdtime_t expire, bool check_ksk,
6945 bool keyset_kskonly) {
6946 isc_result_t result;
6947 dns_dbnode_t *node = NULL;
6948 dns_stats_t *dnssecsignstats;
6949 dns_rdataset_t rdataset;
6950 dns_rdata_t sig_rdata = DNS_RDATA_INIT;
6951 unsigned char data[1024]; /* XXX */
6952 isc_buffer_t buffer;
6953 unsigned int i, j;
6954 bool use_kasp = false;
6955
6956 if (dns_zone_getkasp(zone) != NULL) {
6957 check_ksk = false;
6958 keyset_kskonly = true;
6959 use_kasp = true;
6960 }
6961
6962 dns_rdataset_init(&rdataset);
6963 isc_buffer_init(&buffer, data, sizeof(data));
6964
6965 if (type == dns_rdatatype_nsec3) {
6966 result = dns_db_findnsec3node(db, name, false, &node);
6967 } else {
6968 result = dns_db_findnode(db, name, false, &node);
6969 }
6970 if (result == ISC_R_NOTFOUND) {
6971 return (ISC_R_SUCCESS);
6972 }
6973 if (result != ISC_R_SUCCESS) {
6974 goto failure;
6975 }
6976 result = dns_db_findrdataset(db, node, ver, type, 0, (isc_stdtime_t)0,
6977 &rdataset, NULL);
6978 dns_db_detachnode(db, &node);
6979 if (result == ISC_R_NOTFOUND) {
6980 INSIST(!dns_rdataset_isassociated(&rdataset));
6981 return (ISC_R_SUCCESS);
6982 }
6983 if (result != ISC_R_SUCCESS) {
6984 INSIST(!dns_rdataset_isassociated(&rdataset));
6985 goto failure;
6986 }
6987
6988 for (i = 0; i < nkeys; i++) {
6989 bool both = false;
6990
6991 /* Don't add signatures for offline or inactive keys */
6992 if (!dst_key_isprivate(keys[i])) {
6993 continue;
6994 }
6995 if (dst_key_inactive(keys[i])) {
6996 continue;
6997 }
6998
6999 if (check_ksk && !REVOKE(keys[i])) {
7000 bool have_ksk, have_nonksk;
7001 if (KSK(keys[i])) {
7002 have_ksk = true;
7003 have_nonksk = false;
7004 } else {
7005 have_ksk = false;
7006 have_nonksk = true;
7007 }
7008
7009 for (j = 0; j < nkeys; j++) {
7010 if (j == i || ALG(keys[i]) != ALG(keys[j])) {
7011 continue;
7012 }
7013
7014 /*
7015 * Don't consider inactive keys, however
7016 * the KSK may be temporary offline, so do
7017 * consider keys which private key files are
7018 * unavailable.
7019 */
7020 if (dst_key_inactive(keys[j])) {
7021 continue;
7022 }
7023
7024 if (REVOKE(keys[j])) {
7025 continue;
7026 }
7027 if (KSK(keys[j])) {
7028 have_ksk = true;
7029 } else if (dst_key_isprivate(keys[j])) {
7030 have_nonksk = true;
7031 }
7032 both = have_ksk && have_nonksk;
7033 if (both) {
7034 break;
7035 }
7036 }
7037 }
7038 if (use_kasp) {
7039 /*
7040 * A dnssec-policy is found. Check what RRsets this
7041 * key should sign.
7042 */
7043 isc_result_t kresult;
7044 isc_stdtime_t when;
7045 bool ksk = false;
7046 bool zsk = false;
7047 bool have_ksk = false;
7048 bool have_zsk = false;
7049
7050 kresult = dst_key_getbool(keys[i], DST_BOOL_KSK, &ksk);
7051 if (kresult != ISC_R_SUCCESS) {
7052 if (KSK(keys[i])) {
7053 ksk = true;
7054 }
7055 }
7056 kresult = dst_key_getbool(keys[i], DST_BOOL_ZSK, &zsk);
7057 if (kresult != ISC_R_SUCCESS) {
7058 if (!KSK(keys[i])) {
7059 zsk = true;
7060 }
7061 }
7062
7063 have_ksk = ksk;
7064 have_zsk = zsk;
7065 both = have_ksk && have_zsk;
7066
7067 for (j = 0; j < nkeys; j++) {
7068 if (both) {
7069 break;
7070 }
7071
7072 if (j == i || ALG(keys[i]) != ALG(keys[j])) {
7073 continue;
7074 }
7075
7076 /*
7077 * Don't consider inactive keys or offline keys.
7078 */
7079 if (!dst_key_isprivate(keys[j])) {
7080 continue;
7081 }
7082 if (dst_key_inactive(keys[j])) {
7083 continue;
7084 }
7085
7086 if (REVOKE(keys[j])) {
7087 continue;
7088 }
7089
7090 if (!have_ksk) {
7091 kresult = dst_key_getbool(keys[j],
7092 DST_BOOL_KSK,
7093 &have_ksk);
7094 if (kresult != ISC_R_SUCCESS) {
7095 if (KSK(keys[j])) {
7096 have_ksk = true;
7097 }
7098 }
7099 }
7100 if (!have_zsk) {
7101 kresult = dst_key_getbool(keys[j],
7102 DST_BOOL_ZSK,
7103 &have_zsk);
7104 if (kresult != ISC_R_SUCCESS) {
7105 if (!KSK(keys[j])) {
7106 have_zsk = true;
7107 }
7108 }
7109 }
7110 both = have_ksk && have_zsk;
7111 }
7112
7113 if (type == dns_rdatatype_dnskey ||
7114 type == dns_rdatatype_cdnskey ||
7115 type == dns_rdatatype_cds)
7116 {
7117 /*
7118 * DNSKEY RRset is signed with KSK.
7119 * CDS and CDNSKEY RRsets too (RFC 7344, 4.1).
7120 */
7121 if (!ksk) {
7122 continue;
7123 }
7124 } else if (!zsk) {
7125 /*
7126 * Other RRsets are signed with ZSK.
7127 */
7128 if (type != dns_rdatatype_soa &&
7129 type != zone->privatetype)
7130 {
7131 continue;
7132 }
7133 if (have_zsk) {
7134 continue;
7135 }
7136 } else if (!dst_key_is_signing(keys[i], DST_BOOL_ZSK,
7137 now, &when))
7138 {
7139 /*
7140 * This key is not active for zone-signing.
7141 */
7142 continue;
7143 }
7144
7145 /*
7146 * If this key is revoked, it may only sign the
7147 * DNSKEY RRset.
7148 */
7149 if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey) {
7150 continue;
7151 }
7152 } else if (both) {
7153 /*
7154 * CDS and CDNSKEY are signed with KSK (RFC 7344, 4.1).
7155 */
7156 if (type == dns_rdatatype_dnskey ||
7157 type == dns_rdatatype_cdnskey ||
7158 type == dns_rdatatype_cds)
7159 {
7160 if (!KSK(keys[i]) && keyset_kskonly) {
7161 continue;
7162 }
7163 } else if (KSK(keys[i])) {
7164 continue;
7165 }
7166 } else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey) {
7167 continue;
7168 }
7169
7170 /* Calculate the signature, creating a RRSIG RDATA. */
7171 isc_buffer_clear(&buffer);
7172 CHECK(dns_dnssec_sign(name, &rdataset, keys[i], &inception,
7173 &expire, mctx, &buffer, &sig_rdata));
7174
7175 /* Update the database and journal with the RRSIG. */
7176 /* XXX inefficient - will cause dataset merging */
7177 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN, name,
7178 rdataset.ttl, &sig_rdata));
7179 dns_rdata_reset(&sig_rdata);
7180 isc_buffer_init(&buffer, data, sizeof(data));
7181
7182 /* Update DNSSEC sign statistics. */
7183 dnssecsignstats = dns_zone_getdnssecsignstats(zone);
7184 if (dnssecsignstats != NULL) {
7185 /* Generated a new signature. */
7186 dns_dnssecsignstats_increment(dnssecsignstats,
7187 ID(keys[i]),
7188 (uint8_t)ALG(keys[i]),
7189 dns_dnssecsignstats_sign);
7190 /* This is a refresh. */
7191 dns_dnssecsignstats_increment(
7192 dnssecsignstats, ID(keys[i]),
7193 (uint8_t)ALG(keys[i]),
7194 dns_dnssecsignstats_refresh);
7195 }
7196 }
7197
7198 failure:
7199 if (dns_rdataset_isassociated(&rdataset)) {
7200 dns_rdataset_disassociate(&rdataset);
7201 }
7202 if (node != NULL) {
7203 dns_db_detachnode(db, &node);
7204 }
7205 return (result);
7206 }
7207
7208 static void
7209 zone_resigninc(dns_zone_t *zone) {
7210 const char *me = "zone_resigninc";
7211 dns_db_t *db = NULL;
7212 dns_dbversion_t *version = NULL;
7213 dns_diff_t _sig_diff;
7214 dns__zonediff_t zonediff;
7215 dns_fixedname_t fixed;
7216 dns_name_t *name;
7217 dns_rdataset_t rdataset;
7218 dns_rdatatype_t covers;
7219 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
7220 bool check_ksk, keyset_kskonly = false;
7221 isc_result_t result;
7222 isc_stdtime_t now, inception, soaexpire, expire, fullexpire, stop;
7223 uint32_t sigvalidityinterval, expiryinterval;
7224 unsigned int i;
7225 unsigned int nkeys = 0;
7226 unsigned int resign;
7227
7228 ENTER;
7229
7230 dns_rdataset_init(&rdataset);
7231 dns_diff_init(zone->mctx, &_sig_diff);
7232 zonediff_init(&zonediff, &_sig_diff);
7233
7234 /*
7235 * Zone is frozen or automatic resigning is disabled.
7236 * Pause for 5 minutes.
7237 */
7238 if (zone->update_disabled ||
7239 DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN))
7240 {
7241 result = ISC_R_FAILURE;
7242 goto failure;
7243 }
7244
7245 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
7246 if (zone->db != NULL) {
7247 dns_db_attach(zone->db, &db);
7248 }
7249 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7250 if (db == NULL) {
7251 result = ISC_R_FAILURE;
7252 goto failure;
7253 }
7254
7255 result = dns_db_newversion(db, &version);
7256 if (result != ISC_R_SUCCESS) {
7257 dns_zone_log(zone, ISC_LOG_ERROR,
7258 "zone_resigninc:dns_db_newversion -> %s",
7259 isc_result_totext(result));
7260 goto failure;
7261 }
7262
7263 isc_stdtime_get(&now);
7264
7265 result = dns__zone_findkeys(zone, db, version, now, zone->mctx,
7266 DNS_MAXZONEKEYS, zone_keys, &nkeys);
7267 if (result != ISC_R_SUCCESS) {
7268 dns_zone_log(zone, ISC_LOG_ERROR,
7269 "zone_resigninc:dns__zone_findkeys -> %s",
7270 isc_result_totext(result));
7271 goto failure;
7272 }
7273
7274 sigvalidityinterval = dns_zone_getsigvalidityinterval(zone);
7275 inception = now - 3600; /* Allow for clock skew. */
7276 soaexpire = now + sigvalidityinterval;
7277 expiryinterval = dns_zone_getsigresigninginterval(zone);
7278 if (expiryinterval > sigvalidityinterval) {
7279 expiryinterval = sigvalidityinterval;
7280 } else {
7281 expiryinterval = sigvalidityinterval - expiryinterval;
7282 }
7283
7284 /*
7285 * Spread out signatures over time if they happen to be
7286 * clumped. We don't do this for each add_sigs() call as
7287 * we still want some clustering to occur. In normal operations
7288 * the records should be re-signed as they fall due and they should
7289 * already be spread out. However if the server is off for a
7290 * period we need to ensure that the clusters don't become
7291 * synchronised by using the full jitter range.
7292 */
7293 if (sigvalidityinterval >= 3600U) {
7294 uint32_t normaljitter, fulljitter;
7295 if (sigvalidityinterval > 7200U) {
7296 normaljitter = isc_random_uniform(3600);
7297 fulljitter = isc_random_uniform(expiryinterval);
7298 } else {
7299 normaljitter = fulljitter = isc_random_uniform(1200);
7300 }
7301 expire = soaexpire - normaljitter - 1;
7302 fullexpire = soaexpire - fulljitter - 1;
7303 } else {
7304 expire = fullexpire = soaexpire - 1;
7305 }
7306 stop = now + 5;
7307
7308 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
7309 keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
7310
7311 name = dns_fixedname_initname(&fixed);
7312 result = dns_db_getsigningtime(db, &rdataset, name);
7313 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
7314 dns_zone_log(zone, ISC_LOG_ERROR,
7315 "zone_resigninc:dns_db_getsigningtime -> %s",
7316 isc_result_totext(result));
7317 }
7318
7319 i = 0;
7320 while (result == ISC_R_SUCCESS) {
7321 resign = rdataset.resign -
7322 dns_zone_getsigresigninginterval(zone);
7323 covers = rdataset.covers;
7324 dns_rdataset_disassociate(&rdataset);
7325
7326 /*
7327 * Stop if we hit the SOA as that means we have walked the
7328 * entire zone. The SOA record should always be the most
7329 * recent signature.
7330 */
7331 /* XXXMPA increase number of RRsets signed pre call */
7332 if ((covers == dns_rdatatype_soa &&
7333 dns_name_equal(name, &zone->origin)) ||
7334 i++ > zone->signatures || resign > stop)
7335 {
7336 break;
7337 }
7338
7339 result = del_sigs(zone, db, version, name, covers, &zonediff,
7340 zone_keys, nkeys, now, true);
7341 if (result != ISC_R_SUCCESS) {
7342 dns_zone_log(zone, ISC_LOG_ERROR,
7343 "zone_resigninc:del_sigs -> %s",
7344 isc_result_totext(result));
7345 break;
7346 }
7347
7348 /*
7349 * If re-signing is over 5 minutes late use 'fullexpire'
7350 * to redistribute the signature over the complete
7351 * re-signing window, otherwise only add a small amount
7352 * of jitter.
7353 */
7354 result = add_sigs(db, version, name, zone, covers,
7355 zonediff.diff, zone_keys, nkeys, zone->mctx,
7356 now, inception,
7357 resign > (now - 300) ? expire : fullexpire,
7358 check_ksk, keyset_kskonly);
7359 if (result != ISC_R_SUCCESS) {
7360 dns_zone_log(zone, ISC_LOG_ERROR,
7361 "zone_resigninc:add_sigs -> %s",
7362 isc_result_totext(result));
7363 break;
7364 }
7365 result = dns_db_getsigningtime(db, &rdataset, name);
7366 if (nkeys == 0 && result == ISC_R_NOTFOUND) {
7367 result = ISC_R_SUCCESS;
7368 break;
7369 }
7370 if (result != ISC_R_SUCCESS) {
7371 dns_zone_log(zone, ISC_LOG_ERROR,
7372 "zone_resigninc:dns_db_getsigningtime -> "
7373 "%s",
7374 isc_result_totext(result));
7375 }
7376 }
7377
7378 if (result != ISC_R_NOMORE && result != ISC_R_SUCCESS) {
7379 goto failure;
7380 }
7381
7382 result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
7383 &zonediff, zone_keys, nkeys, now, true);
7384 if (result != ISC_R_SUCCESS) {
7385 dns_zone_log(zone, ISC_LOG_ERROR,
7386 "zone_resigninc:del_sigs -> %s",
7387 isc_result_totext(result));
7388 goto failure;
7389 }
7390
7391 /*
7392 * Did we change anything in the zone?
7393 */
7394 if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
7395 /*
7396 * Commit the changes if any key has been marked as offline.
7397 */
7398 if (zonediff.offline) {
7399 dns_db_closeversion(db, &version, true);
7400 }
7401 goto failure;
7402 }
7403
7404 /* Increment SOA serial if we have made changes */
7405 result = update_soa_serial(zone, db, version, zonediff.diff, zone->mctx,
7406 zone->updatemethod);
7407 if (result != ISC_R_SUCCESS) {
7408 dns_zone_log(zone, ISC_LOG_ERROR,
7409 "zone_resigninc:update_soa_serial -> %s",
7410 isc_result_totext(result));
7411 goto failure;
7412 }
7413
7414 /*
7415 * Generate maximum life time signatures so that the above loop
7416 * termination is sensible.
7417 */
7418 result = add_sigs(db, version, &zone->origin, zone, dns_rdatatype_soa,
7419 zonediff.diff, zone_keys, nkeys, zone->mctx, now,
7420 inception, soaexpire, check_ksk, keyset_kskonly);
7421 if (result != ISC_R_SUCCESS) {
7422 dns_zone_log(zone, ISC_LOG_ERROR,
7423 "zone_resigninc:add_sigs -> %s",
7424 isc_result_totext(result));
7425 goto failure;
7426 }
7427
7428 /* Write changes to journal file. */
7429 CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_resigninc"));
7430
7431 /* Everything has succeeded. Commit the changes. */
7432 dns_db_closeversion(db, &version, true);
7433
7434 failure:
7435 dns_diff_clear(&_sig_diff);
7436 for (i = 0; i < nkeys; i++) {
7437 dst_key_free(&zone_keys[i]);
7438 }
7439 if (version != NULL) {
7440 dns_db_closeversion(db, &version, false);
7441 dns_db_detach(&db);
7442 } else if (db != NULL) {
7443 dns_db_detach(&db);
7444 }
7445
7446 LOCK_ZONE(zone);
7447 if (result == ISC_R_SUCCESS) {
7448 set_resigntime(zone);
7449 zone_needdump(zone, DNS_DUMP_DELAY);
7450 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
7451 } else {
7452 /*
7453 * Something failed. Retry in 5 minutes.
7454 */
7455 isc_interval_t ival;
7456 isc_interval_set(&ival, 300, 0);
7457 isc_time_nowplusinterval(&zone->resigntime, &ival);
7458 }
7459 UNLOCK_ZONE(zone);
7460
7461 INSIST(version == NULL);
7462 }
7463
7464 static isc_result_t
7465 next_active(dns_db_t *db, dns_dbversion_t *version, dns_name_t *oldname,
7466 dns_name_t *newname, bool bottom) {
7467 isc_result_t result;
7468 dns_dbiterator_t *dbit = NULL;
7469 dns_rdatasetiter_t *rdsit = NULL;
7470 dns_dbnode_t *node = NULL;
7471
7472 CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit));
7473 CHECK(dns_dbiterator_seek(dbit, oldname));
7474 do {
7475 result = dns_dbiterator_next(dbit);
7476 if (result == ISC_R_NOMORE) {
7477 CHECK(dns_dbiterator_first(dbit));
7478 }
7479 CHECK(dns_dbiterator_current(dbit, &node, newname));
7480 if (bottom && dns_name_issubdomain(newname, oldname) &&
7481 !dns_name_equal(newname, oldname))
7482 {
7483 dns_db_detachnode(db, &node);
7484 continue;
7485 }
7486 /*
7487 * Is this node empty?
7488 */
7489 CHECK(dns_db_allrdatasets(db, node, version, 0, 0, &rdsit));
7490 result = dns_rdatasetiter_first(rdsit);
7491 dns_db_detachnode(db, &node);
7492 dns_rdatasetiter_destroy(&rdsit);
7493 if (result != ISC_R_NOMORE) {
7494 break;
7495 }
7496 } while (1);
7497 failure:
7498 if (node != NULL) {
7499 dns_db_detachnode(db, &node);
7500 }
7501 if (dbit != NULL) {
7502 dns_dbiterator_destroy(&dbit);
7503 }
7504 return (result);
7505 }
7506
7507 static bool
7508 signed_with_good_key(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
7509 dns_dbversion_t *version, dns_rdatatype_t type,
7510 dst_key_t *key) {
7511 isc_result_t result;
7512 dns_rdataset_t rdataset;
7513 dns_rdata_t rdata = DNS_RDATA_INIT;
7514 dns_rdata_rrsig_t rrsig;
7515 int count = 0;
7516 dns_kasp_t *kasp = dns_zone_getkasp(zone);
7517
7518 dns_rdataset_init(&rdataset);
7519 result = dns_db_findrdataset(db, node, version, dns_rdatatype_rrsig,
7520 type, 0, &rdataset, NULL);
7521 if (result != ISC_R_SUCCESS) {
7522 INSIST(!dns_rdataset_isassociated(&rdataset));
7523 return (false);
7524 }
7525 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
7526 result = dns_rdataset_next(&rdataset))
7527 {
7528 dns_rdataset_current(&rdataset, &rdata);
7529 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
7530 INSIST(result == ISC_R_SUCCESS);
7531 if (rrsig.algorithm == dst_key_alg(key) &&
7532 rrsig.keyid == dst_key_id(key))
7533 {
7534 dns_rdataset_disassociate(&rdataset);
7535 return (true);
7536 }
7537 if (rrsig.algorithm == dst_key_alg(key)) {
7538 count++;
7539 }
7540 dns_rdata_reset(&rdata);
7541 }
7542
7543 if (dns_zone_getkasp(zone) != NULL) {
7544 dns_kasp_key_t *kkey;
7545 int zsk_count = 0;
7546 bool approved;
7547
7548 KASP_LOCK(kasp);
7549 for (kkey = ISC_LIST_HEAD(dns_kasp_keys(kasp)); kkey != NULL;
7550 kkey = ISC_LIST_NEXT(kkey, link))
7551 {
7552 if (dns_kasp_key_algorithm(kkey) != dst_key_alg(key)) {
7553 continue;
7554 }
7555 if (dns_kasp_key_zsk(kkey)) {
7556 zsk_count++;
7557 }
7558 }
7559 KASP_UNLOCK(kasp);
7560
7561 if (type == dns_rdatatype_dnskey ||
7562 type == dns_rdatatype_cdnskey || type == dns_rdatatype_cds)
7563 {
7564 /*
7565 * CDS and CDNSKEY are signed with KSK like DNSKEY.
7566 * (RFC 7344, section 4.1 specifies that they must
7567 * be signed with a key in the current DS RRset,
7568 * which would only include KSK's.)
7569 */
7570 approved = false;
7571 } else {
7572 approved = (zsk_count == count);
7573 }
7574
7575 dns_rdataset_disassociate(&rdataset);
7576 return (approved);
7577 }
7578
7579 dns_rdataset_disassociate(&rdataset);
7580 return (false);
7581 }
7582
7583 static isc_result_t
7584 add_nsec(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
7585 dns_dbnode_t *node, dns_ttl_t ttl, bool bottom, dns_diff_t *diff) {
7586 dns_fixedname_t fixed;
7587 dns_name_t *next;
7588 dns_rdata_t rdata = DNS_RDATA_INIT;
7589 isc_result_t result;
7590 unsigned char nsecbuffer[DNS_NSEC_BUFFERSIZE];
7591
7592 next = dns_fixedname_initname(&fixed);
7593
7594 CHECK(next_active(db, version, name, next, bottom));
7595 CHECK(dns_nsec_buildrdata(db, version, node, next, nsecbuffer, &rdata));
7596 CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADD, name, ttl,
7597 &rdata));
7598 failure:
7599 return (result);
7600 }
7601
7602 static isc_result_t
7603 check_if_bottom_of_zone(dns_db_t *db, dns_dbnode_t *node,
7604 dns_dbversion_t *version, bool *is_bottom_of_zone) {
7605 isc_result_t result;
7606 dns_rdatasetiter_t *iterator = NULL;
7607 dns_rdataset_t rdataset;
7608 bool seen_soa = false, seen_ns = false, seen_dname = false;
7609
7610 REQUIRE(is_bottom_of_zone != NULL);
7611
7612 result = dns_db_allrdatasets(db, node, version, 0, 0, &iterator);
7613 if (result != ISC_R_SUCCESS) {
7614 if (result == ISC_R_NOTFOUND) {
7615 result = ISC_R_SUCCESS;
7616 }
7617 return (result);
7618 }
7619
7620 dns_rdataset_init(&rdataset);
7621 for (result = dns_rdatasetiter_first(iterator); result == ISC_R_SUCCESS;
7622 result = dns_rdatasetiter_next(iterator))
7623 {
7624 dns_rdatasetiter_current(iterator, &rdataset);
7625 switch (rdataset.type) {
7626 case dns_rdatatype_soa:
7627 seen_soa = true;
7628 break;
7629 case dns_rdatatype_ns:
7630 seen_ns = true;
7631 break;
7632 case dns_rdatatype_dname:
7633 seen_dname = true;
7634 break;
7635 }
7636 dns_rdataset_disassociate(&rdataset);
7637 }
7638 if (result != ISC_R_NOMORE) {
7639 goto failure;
7640 }
7641 if ((seen_ns && !seen_soa) || seen_dname) {
7642 *is_bottom_of_zone = true;
7643 }
7644 result = ISC_R_SUCCESS;
7645
7646 failure:
7647 dns_rdatasetiter_destroy(&iterator);
7648
7649 return (result);
7650 }
7651
7652 static isc_result_t
7653 sign_a_node(dns_db_t *db, dns_zone_t *zone, dns_name_t *name,
7654 dns_dbnode_t *node, dns_dbversion_t *version, bool build_nsec3,
7655 bool build_nsec, dst_key_t *key, isc_stdtime_t now,
7656 isc_stdtime_t inception, isc_stdtime_t expire, dns_ttl_t nsecttl,
7657 bool is_ksk, bool is_zsk, bool keyset_kskonly,
7658 bool is_bottom_of_zone, dns_diff_t *diff, int32_t *signatures,
7659 isc_mem_t *mctx) {
7660 isc_result_t result;
7661 dns_rdatasetiter_t *iterator = NULL;
7662 dns_rdataset_t rdataset;
7663 dns_rdata_t rdata = DNS_RDATA_INIT;
7664 dns_stats_t *dnssecsignstats;
7665
7666 isc_buffer_t buffer;
7667 unsigned char data[1024];
7668 bool seen_soa, seen_ns, seen_rr, seen_nsec, seen_nsec3, seen_ds;
7669
7670 result = dns_db_allrdatasets(db, node, version, 0, 0, &iterator);
7671 if (result != ISC_R_SUCCESS) {
7672 if (result == ISC_R_NOTFOUND) {
7673 result = ISC_R_SUCCESS;
7674 }
7675 return (result);
7676 }
7677
7678 dns_rdataset_init(&rdataset);
7679 isc_buffer_init(&buffer, data, sizeof(data));
7680 seen_rr = seen_soa = seen_ns = seen_nsec = seen_nsec3 = seen_ds = false;
7681 for (result = dns_rdatasetiter_first(iterator); result == ISC_R_SUCCESS;
7682 result = dns_rdatasetiter_next(iterator))
7683 {
7684 dns_rdatasetiter_current(iterator, &rdataset);
7685 if (rdataset.type == dns_rdatatype_soa) {
7686 seen_soa = true;
7687 } else if (rdataset.type == dns_rdatatype_ns) {
7688 seen_ns = true;
7689 } else if (rdataset.type == dns_rdatatype_ds) {
7690 seen_ds = true;
7691 } else if (rdataset.type == dns_rdatatype_nsec) {
7692 seen_nsec = true;
7693 } else if (rdataset.type == dns_rdatatype_nsec3) {
7694 seen_nsec3 = true;
7695 }
7696 if (rdataset.type != dns_rdatatype_rrsig) {
7697 seen_rr = true;
7698 }
7699 dns_rdataset_disassociate(&rdataset);
7700 }
7701 if (result != ISC_R_NOMORE) {
7702 goto failure;
7703 }
7704 /*
7705 * Going from insecure to NSEC3.
7706 * Don't generate NSEC3 records for NSEC3 records.
7707 */
7708 if (build_nsec3 && !seen_nsec3 && seen_rr) {
7709 bool unsecure = !seen_ds && seen_ns && !seen_soa;
7710 CHECK(dns_nsec3_addnsec3s(db, version, name, nsecttl, unsecure,
7711 diff));
7712 (*signatures)--;
7713 }
7714 /*
7715 * Going from insecure to NSEC.
7716 * Don't generate NSEC records for NSEC3 records.
7717 */
7718 if (build_nsec && !seen_nsec3 && !seen_nsec && seen_rr) {
7719 /*
7720 * Build a NSEC record except at the origin.
7721 */
7722 if (!dns_name_equal(name, dns_db_origin(db))) {
7723 CHECK(add_nsec(db, version, name, node, nsecttl,
7724 is_bottom_of_zone, diff));
7725 /* Count a NSEC generation as a signature generation. */
7726 (*signatures)--;
7727 }
7728 }
7729 result = dns_rdatasetiter_first(iterator);
7730 while (result == ISC_R_SUCCESS) {
7731 isc_stdtime_t when;
7732
7733 dns_rdatasetiter_current(iterator, &rdataset);
7734 if (rdataset.type == dns_rdatatype_soa ||
7735 rdataset.type == dns_rdatatype_rrsig)
7736 {
7737 goto next_rdataset;
7738 }
7739 if (rdataset.type == dns_rdatatype_dnskey ||
7740 rdataset.type == dns_rdatatype_cdnskey ||
7741 rdataset.type == dns_rdatatype_cds)
7742 {
7743 /*
7744 * CDS and CDNSKEY are signed with KSK like DNSKEY.
7745 * (RFC 7344, section 4.1 specifies that they must
7746 * be signed with a key in the current DS RRset,
7747 * which would only include KSK's.)
7748 */
7749 if (!is_ksk && keyset_kskonly) {
7750 goto next_rdataset;
7751 }
7752 } else if (!is_zsk) {
7753 goto next_rdataset;
7754 } else if (is_zsk &&
7755 !dst_key_is_signing(key, DST_BOOL_ZSK, now, &when))
7756 {
7757 /* Only applies to dnssec-policy. */
7758 if (dns_zone_getkasp(zone) != NULL) {
7759 goto next_rdataset;
7760 }
7761 }
7762
7763 if (seen_ns && !seen_soa && rdataset.type != dns_rdatatype_ds &&
7764 rdataset.type != dns_rdatatype_nsec)
7765 {
7766 goto next_rdataset;
7767 }
7768 if (signed_with_good_key(zone, db, node, version, rdataset.type,
7769 key))
7770 {
7771 goto next_rdataset;
7772 }
7773
7774 /* Calculate the signature, creating a RRSIG RDATA. */
7775 isc_buffer_clear(&buffer);
7776 CHECK(dns_dnssec_sign(name, &rdataset, key, &inception, &expire,
7777 mctx, &buffer, &rdata));
7778 /* Update the database and journal with the RRSIG. */
7779 /* XXX inefficient - will cause dataset merging */
7780 CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADDRESIGN,
7781 name, rdataset.ttl, &rdata));
7782 dns_rdata_reset(&rdata);
7783
7784 /* Update DNSSEC sign statistics. */
7785 dnssecsignstats = dns_zone_getdnssecsignstats(zone);
7786 if (dnssecsignstats != NULL) {
7787 /* Generated a new signature. */
7788 dns_dnssecsignstats_increment(dnssecsignstats, ID(key),
7789 ALG(key),
7790 dns_dnssecsignstats_sign);
7791 /* This is a refresh. */
7792 dns_dnssecsignstats_increment(
7793 dnssecsignstats, ID(key), ALG(key),
7794 dns_dnssecsignstats_refresh);
7795 }
7796
7797 (*signatures)--;
7798 next_rdataset:
7799 dns_rdataset_disassociate(&rdataset);
7800 result = dns_rdatasetiter_next(iterator);
7801 }
7802 if (result == ISC_R_NOMORE) {
7803 result = ISC_R_SUCCESS;
7804 }
7805 failure:
7806 if (dns_rdataset_isassociated(&rdataset)) {
7807 dns_rdataset_disassociate(&rdataset);
7808 }
7809 if (iterator != NULL) {
7810 dns_rdatasetiter_destroy(&iterator);
7811 }
7812 return (result);
7813 }
7814
7815 /*
7816 * If 'update_only' is set then don't create a NSEC RRset if it doesn't exist.
7817 */
7818 static isc_result_t
7819 updatesecure(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
7820 dns_ttl_t nsecttl, bool update_only, dns_diff_t *diff) {
7821 isc_result_t result;
7822 dns_rdataset_t rdataset;
7823 dns_dbnode_t *node = NULL;
7824
7825 CHECK(dns_db_getoriginnode(db, &node));
7826 if (update_only) {
7827 dns_rdataset_init(&rdataset);
7828 result = dns_db_findrdataset(
7829 db, node, version, dns_rdatatype_nsec,
7830 dns_rdatatype_none, 0, &rdataset, NULL);
7831 if (dns_rdataset_isassociated(&rdataset)) {
7832 dns_rdataset_disassociate(&rdataset);
7833 }
7834 if (result == ISC_R_NOTFOUND) {
7835 goto success;
7836 }
7837 if (result != ISC_R_SUCCESS) {
7838 goto failure;
7839 }
7840 }
7841 CHECK(delete_nsec(db, version, node, name, diff));
7842 CHECK(add_nsec(db, version, name, node, nsecttl, false, diff));
7843 success:
7844 result = ISC_R_SUCCESS;
7845 failure:
7846 if (node != NULL) {
7847 dns_db_detachnode(db, &node);
7848 }
7849 return (result);
7850 }
7851
7852 static isc_result_t
7853 updatesignwithkey(dns_zone_t *zone, dns_signing_t *signing,
7854 dns_dbversion_t *version, bool build_nsec3, dns_ttl_t nsecttl,
7855 dns_diff_t *diff) {
7856 isc_result_t result;
7857 dns_dbnode_t *node = NULL;
7858 dns_rdataset_t rdataset;
7859 dns_rdata_t rdata = DNS_RDATA_INIT;
7860 unsigned char data[5];
7861 bool seen_done = false;
7862 bool have_rr = false;
7863
7864 dns_rdataset_init(&rdataset);
7865 result = dns_db_getoriginnode(signing->db, &node);
7866 if (result != ISC_R_SUCCESS) {
7867 goto failure;
7868 }
7869
7870 result = dns_db_findrdataset(signing->db, node, version,
7871 zone->privatetype, dns_rdatatype_none, 0,
7872 &rdataset, NULL);
7873 if (result == ISC_R_NOTFOUND) {
7874 INSIST(!dns_rdataset_isassociated(&rdataset));
7875 result = ISC_R_SUCCESS;
7876 goto failure;
7877 }
7878 if (result != ISC_R_SUCCESS) {
7879 INSIST(!dns_rdataset_isassociated(&rdataset));
7880 goto failure;
7881 }
7882 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
7883 result = dns_rdataset_next(&rdataset))
7884 {
7885 dns_rdataset_current(&rdataset, &rdata);
7886 /*
7887 * If we don't match the algorithm or keyid skip the record.
7888 */
7889 if (rdata.length != 5 || rdata.data[0] != signing->algorithm ||
7890 rdata.data[1] != ((signing->keyid >> 8) & 0xff) ||
7891 rdata.data[2] != (signing->keyid & 0xff))
7892 {
7893 have_rr = true;
7894 dns_rdata_reset(&rdata);
7895 continue;
7896 }
7897 /*
7898 * We have a match. If we were signing (!signing->deleteit)
7899 * and we already have a record indicating that we have
7900 * finished signing (rdata.data[4] != 0) then keep it.
7901 * Otherwise it needs to be deleted as we have removed all
7902 * the signatures (signing->deleteit), so any record indicating
7903 * completion is now out of date, or we have finished signing
7904 * with the new record so we no longer need to remember that
7905 * we need to sign the zone with the matching key across a
7906 * nameserver re-start.
7907 */
7908 if (!signing->deleteit && rdata.data[4] != 0) {
7909 seen_done = true;
7910 have_rr = true;
7911 } else {
7912 CHECK(update_one_rr(signing->db, version, diff,
7913 DNS_DIFFOP_DEL, &zone->origin,
7914 rdataset.ttl, &rdata));
7915 }
7916 dns_rdata_reset(&rdata);
7917 }
7918 if (result == ISC_R_NOMORE) {
7919 result = ISC_R_SUCCESS;
7920 }
7921 if (!signing->deleteit && !seen_done) {
7922 /*
7923 * If we were signing then we need to indicate that we have
7924 * finished signing the zone with this key. If it is already
7925 * there we don't need to add it a second time.
7926 */
7927 data[0] = signing->algorithm;
7928 data[1] = (signing->keyid >> 8) & 0xff;
7929 data[2] = signing->keyid & 0xff;
7930 data[3] = 0;
7931 data[4] = 1;
7932 rdata.length = sizeof(data);
7933 rdata.data = data;
7934 rdata.type = zone->privatetype;
7935 rdata.rdclass = dns_db_class(signing->db);
7936 CHECK(update_one_rr(signing->db, version, diff, DNS_DIFFOP_ADD,
7937 &zone->origin, rdataset.ttl, &rdata));
7938 } else if (!have_rr) {
7939 dns_name_t *origin = dns_db_origin(signing->db);
7940 /*
7941 * Rebuild the NSEC/NSEC3 record for the origin as we no
7942 * longer have any private records.
7943 */
7944 if (build_nsec3) {
7945 CHECK(dns_nsec3_addnsec3s(signing->db, version, origin,
7946 nsecttl, false, diff));
7947 }
7948 CHECK(updatesecure(signing->db, version, origin, nsecttl, true,
7949 diff));
7950 }
7951
7952 failure:
7953 if (dns_rdataset_isassociated(&rdataset)) {
7954 dns_rdataset_disassociate(&rdataset);
7955 }
7956 if (node != NULL) {
7957 dns_db_detachnode(signing->db, &node);
7958 }
7959 return (result);
7960 }
7961
7962 /*
7963 * Called from zone_nsec3chain() in order to update zone records indicating
7964 * processing status of given NSEC3 chain:
7965 *
7966 * - If the supplied dns_nsec3chain_t structure has been fully processed
7967 * (which is indicated by "active" being set to false):
7968 *
7969 * - remove all NSEC3PARAM records matching the relevant NSEC3 chain,
7970 *
7971 * - remove all private-type records containing NSEC3PARAM RDATA matching
7972 * the relevant NSEC3 chain.
7973 *
7974 * - If the supplied dns_nsec3chain_t structure has not been fully processed
7975 * (which is indicated by "active" being set to true), only remove the
7976 * NSEC3PARAM record which matches the relevant NSEC3 chain and has the
7977 * "flags" field set to 0.
7978 *
7979 * - If given NSEC3 chain is being added, add an NSEC3PARAM record contained
7980 * in the relevant private-type record, but with the "flags" field set to
7981 * 0, indicating that this NSEC3 chain is now complete for this zone.
7982 *
7983 * Note that this function is called at different processing stages for NSEC3
7984 * chain additions vs. removals and needs to handle all cases properly.
7985 */
7986 static isc_result_t
7987 fixup_nsec3param(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3chain_t *chain,
7988 bool active, dns_rdatatype_t privatetype, dns_diff_t *diff) {
7989 dns_dbnode_t *node = NULL;
7990 dns_name_t *name = dns_db_origin(db);
7991 dns_rdata_t rdata = DNS_RDATA_INIT;
7992 dns_rdataset_t rdataset;
7993 dns_rdata_nsec3param_t nsec3param;
7994 isc_result_t result;
7995 isc_buffer_t buffer;
7996 unsigned char parambuf[DNS_NSEC3PARAM_BUFFERSIZE];
7997 dns_ttl_t ttl = 0;
7998 bool nseconly = false, nsec3ok = false;
7999
8000 dns_rdataset_init(&rdataset);
8001
8002 result = dns_db_getoriginnode(db, &node);
8003 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8004 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param, 0,
8005 0, &rdataset, NULL);
8006 if (result == ISC_R_NOTFOUND) {
8007 goto try_private;
8008 }
8009 if (result != ISC_R_SUCCESS) {
8010 goto failure;
8011 }
8012
8013 /*
8014 * Preserve the existing ttl.
8015 */
8016 ttl = rdataset.ttl;
8017
8018 /*
8019 * Delete all NSEC3PARAM records which match that in nsec3chain.
8020 */
8021 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
8022 result = dns_rdataset_next(&rdataset))
8023 {
8024 dns_rdataset_current(&rdataset, &rdata);
8025 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
8026
8027 if (nsec3param.hash != chain->nsec3param.hash ||
8028 (active && nsec3param.flags != 0) ||
8029 nsec3param.iterations != chain->nsec3param.iterations ||
8030 nsec3param.salt_length != chain->nsec3param.salt_length ||
8031 memcmp(nsec3param.salt, chain->nsec3param.salt,
8032 nsec3param.salt_length))
8033 {
8034 dns_rdata_reset(&rdata);
8035 continue;
8036 }
8037
8038 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
8039 rdataset.ttl, &rdata));
8040 dns_rdata_reset(&rdata);
8041 }
8042 if (result != ISC_R_NOMORE) {
8043 goto failure;
8044 }
8045
8046 dns_rdataset_disassociate(&rdataset);
8047
8048 try_private:
8049
8050 if (active) {
8051 goto add;
8052 }
8053
8054 result = dns_nsec_nseconly(db, ver, diff, &nseconly);
8055 nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
8056
8057 /*
8058 * Delete all private records which match that in nsec3chain.
8059 */
8060 result = dns_db_findrdataset(db, node, ver, privatetype, 0, 0,
8061 &rdataset, NULL);
8062 if (result == ISC_R_NOTFOUND) {
8063 goto add;
8064 }
8065 if (result != ISC_R_SUCCESS) {
8066 goto failure;
8067 }
8068
8069 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
8070 result = dns_rdataset_next(&rdataset))
8071 {
8072 dns_rdata_t private = DNS_RDATA_INIT;
8073 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
8074
8075 dns_rdataset_current(&rdataset, &private);
8076 if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
8077 sizeof(buf)))
8078 {
8079 continue;
8080 }
8081 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
8082
8083 if ((!nsec3ok &&
8084 (nsec3param.flags & DNS_NSEC3FLAG_INITIAL) != 0) ||
8085 nsec3param.hash != chain->nsec3param.hash ||
8086 nsec3param.iterations != chain->nsec3param.iterations ||
8087 nsec3param.salt_length != chain->nsec3param.salt_length ||
8088 memcmp(nsec3param.salt, chain->nsec3param.salt,
8089 nsec3param.salt_length))
8090 {
8091 dns_rdata_reset(&rdata);
8092 continue;
8093 }
8094
8095 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
8096 rdataset.ttl, &private));
8097 dns_rdata_reset(&rdata);
8098 }
8099 if (result != ISC_R_NOMORE) {
8100 goto failure;
8101 }
8102
8103 add:
8104 if ((chain->nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
8105 result = ISC_R_SUCCESS;
8106 goto failure;
8107 }
8108
8109 /*
8110 * Add a NSEC3PARAM record which matches that in nsec3chain but
8111 * with all flags bits cleared.
8112 *
8113 * Note: we do not clear chain->nsec3param.flags as this change
8114 * may be reversed.
8115 */
8116 isc_buffer_init(&buffer, ¶mbuf, sizeof(parambuf));
8117 CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db),
8118 dns_rdatatype_nsec3param, &chain->nsec3param,
8119 &buffer));
8120 rdata.data[1] = 0; /* Clear flag bits. */
8121 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, name, ttl, &rdata));
8122
8123 failure:
8124 dns_db_detachnode(db, &node);
8125 if (dns_rdataset_isassociated(&rdataset)) {
8126 dns_rdataset_disassociate(&rdataset);
8127 }
8128 return (result);
8129 }
8130
8131 static isc_result_t
8132 delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
8133 dns_name_t *name, dns_diff_t *diff) {
8134 dns_rdataset_t rdataset;
8135 isc_result_t result;
8136
8137 dns_rdataset_init(&rdataset);
8138
8139 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec, 0, 0,
8140 &rdataset, NULL);
8141 if (result == ISC_R_NOTFOUND) {
8142 return (ISC_R_SUCCESS);
8143 }
8144 if (result != ISC_R_SUCCESS) {
8145 return (result);
8146 }
8147 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
8148 result = dns_rdataset_next(&rdataset))
8149 {
8150 dns_rdata_t rdata = DNS_RDATA_INIT;
8151
8152 dns_rdataset_current(&rdataset, &rdata);
8153 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
8154 rdataset.ttl, &rdata));
8155 }
8156 if (result == ISC_R_NOMORE) {
8157 result = ISC_R_SUCCESS;
8158 }
8159 failure:
8160 dns_rdataset_disassociate(&rdataset);
8161 return (result);
8162 }
8163
8164 static isc_result_t
8165 deletematchingnsec3(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
8166 dns_name_t *name, const dns_rdata_nsec3param_t *param,
8167 dns_diff_t *diff) {
8168 dns_rdataset_t rdataset;
8169 dns_rdata_nsec3_t nsec3;
8170 isc_result_t result;
8171
8172 dns_rdataset_init(&rdataset);
8173 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3, 0, 0,
8174 &rdataset, NULL);
8175 if (result == ISC_R_NOTFOUND) {
8176 return (ISC_R_SUCCESS);
8177 }
8178 if (result != ISC_R_SUCCESS) {
8179 return (result);
8180 }
8181
8182 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
8183 result = dns_rdataset_next(&rdataset))
8184 {
8185 dns_rdata_t rdata = DNS_RDATA_INIT;
8186
8187 dns_rdataset_current(&rdataset, &rdata);
8188 CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
8189 if (nsec3.hash != param->hash ||
8190 nsec3.iterations != param->iterations ||
8191 nsec3.salt_length != param->salt_length ||
8192 memcmp(nsec3.salt, param->salt, nsec3.salt_length))
8193 {
8194 continue;
8195 }
8196 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
8197 rdataset.ttl, &rdata));
8198 }
8199 if (result == ISC_R_NOMORE) {
8200 result = ISC_R_SUCCESS;
8201 }
8202 failure:
8203 dns_rdataset_disassociate(&rdataset);
8204 return (result);
8205 }
8206
8207 static isc_result_t
8208 need_nsec_chain(dns_db_t *db, dns_dbversion_t *ver,
8209 const dns_rdata_nsec3param_t *param, bool *answer) {
8210 dns_dbnode_t *node = NULL;
8211 dns_rdata_t rdata = DNS_RDATA_INIT;
8212 dns_rdata_nsec3param_t myparam;
8213 dns_rdataset_t rdataset;
8214 isc_result_t result;
8215
8216 *answer = false;
8217
8218 result = dns_db_getoriginnode(db, &node);
8219 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8220
8221 dns_rdataset_init(&rdataset);
8222
8223 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec, 0, 0,
8224 &rdataset, NULL);
8225 if (result == ISC_R_SUCCESS) {
8226 dns_rdataset_disassociate(&rdataset);
8227 dns_db_detachnode(db, &node);
8228 return (result);
8229 }
8230 if (result != ISC_R_NOTFOUND) {
8231 dns_db_detachnode(db, &node);
8232 return (result);
8233 }
8234
8235 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param, 0,
8236 0, &rdataset, NULL);
8237 if (result == ISC_R_NOTFOUND) {
8238 *answer = true;
8239 dns_db_detachnode(db, &node);
8240 return (ISC_R_SUCCESS);
8241 }
8242 if (result != ISC_R_SUCCESS) {
8243 dns_db_detachnode(db, &node);
8244 return (result);
8245 }
8246
8247 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
8248 result = dns_rdataset_next(&rdataset))
8249 {
8250 dns_rdataset_current(&rdataset, &rdata);
8251 CHECK(dns_rdata_tostruct(&rdata, &myparam, NULL));
8252 dns_rdata_reset(&rdata);
8253 /*
8254 * Ignore any NSEC3PARAM removals.
8255 */
8256 if (NSEC3REMOVE(myparam.flags)) {
8257 continue;
8258 }
8259 /*
8260 * Ignore the chain that we are in the process of deleting.
8261 */
8262 if (myparam.hash == param->hash &&
8263 myparam.iterations == param->iterations &&
8264 myparam.salt_length == param->salt_length &&
8265 !memcmp(myparam.salt, param->salt, myparam.salt_length))
8266 {
8267 continue;
8268 }
8269 /*
8270 * Found an active NSEC3 chain.
8271 */
8272 break;
8273 }
8274 if (result == ISC_R_NOMORE) {
8275 *answer = true;
8276 result = ISC_R_SUCCESS;
8277 }
8278
8279 failure:
8280 if (dns_rdataset_isassociated(&rdataset)) {
8281 dns_rdataset_disassociate(&rdataset);
8282 }
8283 dns_db_detachnode(db, &node);
8284 return (result);
8285 }
8286
8287 /*%
8288 * Given a tuple which is part of a diff, return a pointer to the next tuple in
8289 * that diff which has the same name and type (or NULL if no such tuple is
8290 * found).
8291 */
8292 static dns_difftuple_t *
8293 find_next_matching_tuple(dns_difftuple_t *cur) {
8294 dns_difftuple_t *next = cur;
8295
8296 while ((next = ISC_LIST_NEXT(next, link)) != NULL) {
8297 if (cur->rdata.type == next->rdata.type &&
8298 dns_name_equal(&cur->name, &next->name))
8299 {
8300 return (next);
8301 }
8302 }
8303
8304 return (NULL);
8305 }
8306
8307 /*%
8308 * Remove all tuples with the same name and type as 'cur' from 'src' and append
8309 * them to 'dst'.
8310 */
8311 static void
8312 move_matching_tuples(dns_difftuple_t *cur, dns_diff_t *src, dns_diff_t *dst) {
8313 do {
8314 dns_difftuple_t *next = find_next_matching_tuple(cur);
8315 ISC_LIST_UNLINK(src->tuples, cur, link);
8316 dns_diff_appendminimal(dst, &cur);
8317 cur = next;
8318 } while (cur != NULL);
8319 }
8320
8321 /*%
8322 * Add/remove DNSSEC signatures for the list of "raw" zone changes supplied in
8323 * 'diff'. Gradually remove tuples from 'diff' and append them to 'zonediff'
8324 * along with tuples representing relevant signature changes.
8325 */
8326 isc_result_t
8327 dns__zone_updatesigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version,
8328 dst_key_t *zone_keys[], unsigned int nkeys,
8329 dns_zone_t *zone, isc_stdtime_t inception,
8330 isc_stdtime_t expire, isc_stdtime_t keyexpire,
8331 isc_stdtime_t now, bool check_ksk, bool keyset_kskonly,
8332 dns__zonediff_t *zonediff) {
8333 dns_difftuple_t *tuple;
8334 isc_result_t result;
8335
8336 while ((tuple = ISC_LIST_HEAD(diff->tuples)) != NULL) {
8337 isc_stdtime_t exp = expire;
8338
8339 if (keyexpire != 0 &&
8340 (tuple->rdata.type == dns_rdatatype_dnskey ||
8341 tuple->rdata.type == dns_rdatatype_cdnskey ||
8342 tuple->rdata.type == dns_rdatatype_cds))
8343 {
8344 exp = keyexpire;
8345 }
8346
8347 result = del_sigs(zone, db, version, &tuple->name,
8348 tuple->rdata.type, zonediff, zone_keys, nkeys,
8349 now, false);
8350 if (result != ISC_R_SUCCESS) {
8351 dns_zone_log(zone, ISC_LOG_ERROR,
8352 "dns__zone_updatesigs:del_sigs -> %s",
8353 isc_result_totext(result));
8354 return (result);
8355 }
8356 result = add_sigs(db, version, &tuple->name, zone,
8357 tuple->rdata.type, zonediff->diff, zone_keys,
8358 nkeys, zone->mctx, now, inception, exp,
8359 check_ksk, keyset_kskonly);
8360 if (result != ISC_R_SUCCESS) {
8361 dns_zone_log(zone, ISC_LOG_ERROR,
8362 "dns__zone_updatesigs:add_sigs -> %s",
8363 isc_result_totext(result));
8364 return (result);
8365 }
8366
8367 /*
8368 * Signature changes for all RRs with name tuple->name and type
8369 * tuple->rdata.type were appended to zonediff->diff. Now we
8370 * remove all the "raw" changes with the same name and type
8371 * from diff (so that they are not processed by this loop
8372 * again) and append them to zonediff so that they get applied.
8373 */
8374 move_matching_tuples(tuple, diff, zonediff->diff);
8375 }
8376 return (ISC_R_SUCCESS);
8377 }
8378
8379 /*
8380 * Incrementally build and sign a new NSEC3 chain using the parameters
8381 * requested.
8382 */
8383 static void
8384 zone_nsec3chain(dns_zone_t *zone) {
8385 const char *me = "zone_nsec3chain";
8386 dns_db_t *db = NULL;
8387 dns_dbnode_t *node = NULL;
8388 dns_dbversion_t *version = NULL;
8389 dns_diff_t _sig_diff;
8390 dns_diff_t nsec_diff;
8391 dns_diff_t nsec3_diff;
8392 dns_diff_t param_diff;
8393 dns__zonediff_t zonediff;
8394 dns_fixedname_t fixed;
8395 dns_fixedname_t nextfixed;
8396 dns_name_t *name, *nextname;
8397 dns_rdataset_t rdataset;
8398 dns_nsec3chain_t *nsec3chain = NULL, *nextnsec3chain;
8399 dns_nsec3chainlist_t cleanup;
8400 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
8401 int32_t signatures;
8402 bool check_ksk, keyset_kskonly;
8403 bool delegation;
8404 bool first;
8405 isc_result_t result;
8406 isc_stdtime_t now, inception, soaexpire, expire;
8407 uint32_t jitter, sigvalidityinterval, expiryinterval;
8408 unsigned int i;
8409 unsigned int nkeys = 0;
8410 uint32_t nodes;
8411 bool unsecure = false;
8412 bool seen_soa, seen_ns, seen_dname, seen_ds;
8413 bool seen_nsec, seen_nsec3, seen_rr;
8414 dns_rdatasetiter_t *iterator = NULL;
8415 bool buildnsecchain;
8416 bool updatensec = false;
8417 dns_rdatatype_t privatetype = zone->privatetype;
8418
8419 ENTER;
8420
8421 dns_rdataset_init(&rdataset);
8422 name = dns_fixedname_initname(&fixed);
8423 nextname = dns_fixedname_initname(&nextfixed);
8424 dns_diff_init(zone->mctx, ¶m_diff);
8425 dns_diff_init(zone->mctx, &nsec3_diff);
8426 dns_diff_init(zone->mctx, &nsec_diff);
8427 dns_diff_init(zone->mctx, &_sig_diff);
8428 zonediff_init(&zonediff, &_sig_diff);
8429 ISC_LIST_INIT(cleanup);
8430
8431 /*
8432 * Updates are disabled. Pause for 5 minutes.
8433 */
8434 if (zone->update_disabled) {
8435 result = ISC_R_FAILURE;
8436 goto failure;
8437 }
8438
8439 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8440 /*
8441 * This function is called when zone timer fires, after the latter gets
8442 * set by zone_addnsec3chain(). If the action triggering the call to
8443 * zone_addnsec3chain() is closely followed by a zone deletion request,
8444 * it might turn out that the timer thread will not be woken up until
8445 * after the zone is deleted by rmzone(), which calls dns_db_detach()
8446 * for zone->db, causing the latter to become NULL. Return immediately
8447 * if that happens.
8448 */
8449 if (zone->db != NULL) {
8450 dns_db_attach(zone->db, &db);
8451 }
8452 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8453 if (db == NULL) {
8454 return;
8455 }
8456
8457 result = dns_db_newversion(db, &version);
8458 if (result != ISC_R_SUCCESS) {
8459 dnssec_log(zone, ISC_LOG_ERROR,
8460 "zone_nsec3chain:dns_db_newversion -> %s",
8461 isc_result_totext(result));
8462 goto failure;
8463 }
8464
8465 isc_stdtime_get(&now);
8466
8467 result = dns__zone_findkeys(zone, db, version, now, zone->mctx,
8468 DNS_MAXZONEKEYS, zone_keys, &nkeys);
8469 if (result != ISC_R_SUCCESS) {
8470 dnssec_log(zone, ISC_LOG_ERROR,
8471 "zone_nsec3chain:dns__zone_findkeys -> %s",
8472 isc_result_totext(result));
8473 goto failure;
8474 }
8475
8476 sigvalidityinterval = dns_zone_getsigvalidityinterval(zone);
8477 inception = now - 3600; /* Allow for clock skew. */
8478 soaexpire = now + sigvalidityinterval;
8479 expiryinterval = dns_zone_getsigresigninginterval(zone);
8480 if (expiryinterval > sigvalidityinterval) {
8481 expiryinterval = sigvalidityinterval;
8482 } else {
8483 expiryinterval = sigvalidityinterval - expiryinterval;
8484 }
8485
8486 /*
8487 * Spread out signatures over time if they happen to be
8488 * clumped. We don't do this for each add_sigs() call as
8489 * we still want some clustering to occur.
8490 */
8491 if (sigvalidityinterval >= 3600U) {
8492 if (sigvalidityinterval > 7200U) {
8493 jitter = isc_random_uniform(expiryinterval);
8494 } else {
8495 jitter = isc_random_uniform(1200);
8496 }
8497 expire = soaexpire - jitter - 1;
8498 } else {
8499 expire = soaexpire - 1;
8500 }
8501
8502 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
8503 keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
8504
8505 /*
8506 * We keep pulling nodes off each iterator in turn until
8507 * we have no more nodes to pull off or we reach the limits
8508 * for this quantum.
8509 */
8510 nodes = zone->nodes;
8511 signatures = zone->signatures;
8512 LOCK_ZONE(zone);
8513 nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
8514 UNLOCK_ZONE(zone);
8515 first = true;
8516
8517 if (nsec3chain != NULL) {
8518 nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
8519 }
8520 /*
8521 * Generate new NSEC3 chains first.
8522 *
8523 * The following while loop iterates over nodes in the zone database,
8524 * updating the NSEC3 chain by calling dns_nsec3_addnsec3() for each of
8525 * them. Once all nodes are processed, the "delete_nsec" field is
8526 * consulted to check whether we are supposed to remove NSEC records
8527 * from the zone database; if so, the database iterator is reset to
8528 * point to the first node and the loop traverses all of them again,
8529 * this time removing NSEC records. If we hit a node which is obscured
8530 * by a delegation or a DNAME, nodes are skipped over until we find one
8531 * that is not obscured by the same obscuring name and then normal
8532 * processing is resumed.
8533 *
8534 * The above is repeated until all requested NSEC3 chain changes are
8535 * applied or when we reach the limits for this quantum, whichever
8536 * happens first.
8537 *
8538 * Note that the "signatures" variable is only used here to limit the
8539 * amount of work performed. Actual DNSSEC signatures are only
8540 * generated by dns__zone_updatesigs() calls later in this function.
8541 */
8542 while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
8543 dns_dbiterator_pause(nsec3chain->dbiterator);
8544
8545 LOCK_ZONE(zone);
8546 nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
8547
8548 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8549 if (nsec3chain->done || nsec3chain->db != zone->db) {
8550 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
8551 ISC_LIST_APPEND(cleanup, nsec3chain, link);
8552 }
8553 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8554 UNLOCK_ZONE(zone);
8555 if (ISC_LIST_TAIL(cleanup) == nsec3chain) {
8556 goto next_addchain;
8557 }
8558
8559 /*
8560 * Possible future db.
8561 */
8562 if (nsec3chain->db != db) {
8563 goto next_addchain;
8564 }
8565
8566 if (NSEC3REMOVE(nsec3chain->nsec3param.flags)) {
8567 goto next_addchain;
8568 }
8569
8570 dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
8571
8572 if (nsec3chain->delete_nsec) {
8573 delegation = false;
8574 dns_dbiterator_pause(nsec3chain->dbiterator);
8575 CHECK(delete_nsec(db, version, node, name, &nsec_diff));
8576 goto next_addnode;
8577 }
8578 /*
8579 * On the first pass we need to check if the current node
8580 * has not been obscured.
8581 */
8582 delegation = false;
8583 unsecure = false;
8584 if (first) {
8585 dns_fixedname_t ffound;
8586 dns_name_t *found;
8587 found = dns_fixedname_initname(&ffound);
8588 result = dns_db_find(
8589 db, name, version, dns_rdatatype_soa,
8590 DNS_DBFIND_NOWILD, 0, NULL, found, NULL, NULL);
8591 if ((result == DNS_R_DELEGATION ||
8592 result == DNS_R_DNAME) &&
8593 !dns_name_equal(name, found))
8594 {
8595 /*
8596 * Remember the obscuring name so that
8597 * we skip all obscured names.
8598 */
8599 dns_name_copy(found, name);
8600 delegation = true;
8601 goto next_addnode;
8602 }
8603 }
8604
8605 /*
8606 * Check to see if this is a bottom of zone node.
8607 */
8608 result = dns_db_allrdatasets(db, node, version, 0, 0,
8609 &iterator);
8610 if (result == ISC_R_NOTFOUND) {
8611 /* Empty node? */
8612 goto next_addnode;
8613 }
8614 if (result != ISC_R_SUCCESS) {
8615 goto failure;
8616 }
8617
8618 seen_soa = seen_ns = seen_dname = seen_ds = seen_nsec = false;
8619 for (result = dns_rdatasetiter_first(iterator);
8620 result == ISC_R_SUCCESS;
8621 result = dns_rdatasetiter_next(iterator))
8622 {
8623 dns_rdatasetiter_current(iterator, &rdataset);
8624 INSIST(rdataset.type != dns_rdatatype_nsec3);
8625 if (rdataset.type == dns_rdatatype_soa) {
8626 seen_soa = true;
8627 } else if (rdataset.type == dns_rdatatype_ns) {
8628 seen_ns = true;
8629 } else if (rdataset.type == dns_rdatatype_dname) {
8630 seen_dname = true;
8631 } else if (rdataset.type == dns_rdatatype_ds) {
8632 seen_ds = true;
8633 } else if (rdataset.type == dns_rdatatype_nsec) {
8634 seen_nsec = true;
8635 }
8636 dns_rdataset_disassociate(&rdataset);
8637 }
8638 dns_rdatasetiter_destroy(&iterator);
8639 /*
8640 * Is there a NSEC chain than needs to be cleaned up?
8641 */
8642 if (seen_nsec) {
8643 nsec3chain->seen_nsec = true;
8644 }
8645 if (seen_ns && !seen_soa && !seen_ds) {
8646 unsecure = true;
8647 }
8648 if ((seen_ns && !seen_soa) || seen_dname) {
8649 delegation = true;
8650 }
8651
8652 /*
8653 * Process one node.
8654 */
8655 dns_dbiterator_pause(nsec3chain->dbiterator);
8656 result = dns_nsec3_addnsec3(
8657 db, version, name, &nsec3chain->nsec3param,
8658 zone_nsecttl(zone), unsecure, &nsec3_diff);
8659 if (result != ISC_R_SUCCESS) {
8660 dnssec_log(zone, ISC_LOG_ERROR,
8661 "zone_nsec3chain:"
8662 "dns_nsec3_addnsec3 -> %s",
8663 isc_result_totext(result));
8664 goto failure;
8665 }
8666
8667 /*
8668 * Treat each call to dns_nsec3_addnsec3() as if it's cost is
8669 * two signatures. Additionally there will, in general, be
8670 * two signature generated below.
8671 *
8672 * If we are only changing the optout flag the cost is half
8673 * that of the cost of generating a completely new chain.
8674 */
8675 signatures -= 4;
8676
8677 /*
8678 * Go onto next node.
8679 */
8680 next_addnode:
8681 first = false;
8682 dns_db_detachnode(db, &node);
8683 do {
8684 result = dns_dbiterator_next(nsec3chain->dbiterator);
8685
8686 if (result == ISC_R_NOMORE && nsec3chain->delete_nsec) {
8687 dns_dbiterator_pause(nsec3chain->dbiterator);
8688 CHECK(fixup_nsec3param(db, version, nsec3chain,
8689 false, privatetype,
8690 ¶m_diff));
8691 LOCK_ZONE(zone);
8692 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
8693 link);
8694 UNLOCK_ZONE(zone);
8695 ISC_LIST_APPEND(cleanup, nsec3chain, link);
8696 goto next_addchain;
8697 }
8698 if (result == ISC_R_NOMORE) {
8699 dns_dbiterator_pause(nsec3chain->dbiterator);
8700 if (nsec3chain->seen_nsec) {
8701 CHECK(fixup_nsec3param(
8702 db, version, nsec3chain, true,
8703 privatetype, ¶m_diff));
8704 nsec3chain->delete_nsec = true;
8705 goto same_addchain;
8706 }
8707 CHECK(fixup_nsec3param(db, version, nsec3chain,
8708 false, privatetype,
8709 ¶m_diff));
8710 LOCK_ZONE(zone);
8711 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
8712 link);
8713 UNLOCK_ZONE(zone);
8714 ISC_LIST_APPEND(cleanup, nsec3chain, link);
8715 goto next_addchain;
8716 } else if (result != ISC_R_SUCCESS) {
8717 dnssec_log(zone, ISC_LOG_ERROR,
8718 "zone_nsec3chain:"
8719 "dns_dbiterator_next -> %s",
8720 isc_result_totext(result));
8721 goto failure;
8722 } else if (delegation) {
8723 dns_dbiterator_current(nsec3chain->dbiterator,
8724 &node, nextname);
8725 dns_db_detachnode(db, &node);
8726 if (!dns_name_issubdomain(nextname, name)) {
8727 break;
8728 }
8729 } else {
8730 break;
8731 }
8732 } while (1);
8733 continue;
8734
8735 same_addchain:
8736 CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
8737 first = true;
8738 continue;
8739
8740 next_addchain:
8741 dns_dbiterator_pause(nsec3chain->dbiterator);
8742 nsec3chain = nextnsec3chain;
8743 first = true;
8744 if (nsec3chain != NULL) {
8745 nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
8746 }
8747 }
8748
8749 if (nsec3chain != NULL) {
8750 goto skip_removals;
8751 }
8752
8753 /*
8754 * Process removals.
8755 *
8756 * This is a counterpart of the above while loop which takes care of
8757 * removing an NSEC3 chain. It starts with determining whether the
8758 * zone needs to switch from NSEC3 to NSEC; if so, it first builds an
8759 * NSEC chain by iterating over all nodes in the zone database and only
8760 * then goes on to remove NSEC3 records be iterating over all nodes
8761 * again and calling deletematchingnsec3() for each of them; otherwise,
8762 * it starts removing NSEC3 records immediately. Rules for processing
8763 * obscured nodes and interrupting work are the same as for the while
8764 * loop above.
8765 */
8766 LOCK_ZONE(zone);
8767 nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
8768 UNLOCK_ZONE(zone);
8769 first = true;
8770 buildnsecchain = false;
8771 while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
8772 dns_dbiterator_pause(nsec3chain->dbiterator);
8773
8774 LOCK_ZONE(zone);
8775 nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
8776 UNLOCK_ZONE(zone);
8777
8778 if (nsec3chain->db != db) {
8779 goto next_removechain;
8780 }
8781
8782 if (!NSEC3REMOVE(nsec3chain->nsec3param.flags)) {
8783 goto next_removechain;
8784 }
8785
8786 /*
8787 * Work out if we need to build a NSEC chain as a consequence
8788 * of removing this NSEC3 chain.
8789 */
8790 if (first && !updatensec &&
8791 (nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_NONSEC) == 0)
8792 {
8793 result = need_nsec_chain(db, version,
8794 &nsec3chain->nsec3param,
8795 &buildnsecchain);
8796 if (result != ISC_R_SUCCESS) {
8797 dnssec_log(zone, ISC_LOG_ERROR,
8798 "zone_nsec3chain:"
8799 "need_nsec_chain -> %s",
8800 isc_result_totext(result));
8801 goto failure;
8802 }
8803 }
8804
8805 if (first) {
8806 dnssec_log(zone, ISC_LOG_DEBUG(3),
8807 "zone_nsec3chain:buildnsecchain = %u\n",
8808 buildnsecchain);
8809 }
8810
8811 dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
8812 dns_dbiterator_pause(nsec3chain->dbiterator);
8813 delegation = false;
8814
8815 if (!buildnsecchain) {
8816 /*
8817 * Delete the NSEC3PARAM record matching this chain.
8818 */
8819 if (first) {
8820 result = fixup_nsec3param(
8821 db, version, nsec3chain, true,
8822 privatetype, ¶m_diff);
8823 if (result != ISC_R_SUCCESS) {
8824 dnssec_log(zone, ISC_LOG_ERROR,
8825 "zone_nsec3chain:"
8826 "fixup_nsec3param -> %s",
8827 isc_result_totext(result));
8828 goto failure;
8829 }
8830 }
8831
8832 /*
8833 * Delete the NSEC3 records.
8834 */
8835 result = deletematchingnsec3(db, version, node, name,
8836 &nsec3chain->nsec3param,
8837 &nsec3_diff);
8838 if (result != ISC_R_SUCCESS) {
8839 dnssec_log(zone, ISC_LOG_ERROR,
8840 "zone_nsec3chain:"
8841 "deletematchingnsec3 -> %s",
8842 isc_result_totext(result));
8843 goto failure;
8844 }
8845 goto next_removenode;
8846 }
8847
8848 if (first) {
8849 dns_fixedname_t ffound;
8850 dns_name_t *found;
8851 found = dns_fixedname_initname(&ffound);
8852 result = dns_db_find(
8853 db, name, version, dns_rdatatype_soa,
8854 DNS_DBFIND_NOWILD, 0, NULL, found, NULL, NULL);
8855 if ((result == DNS_R_DELEGATION ||
8856 result == DNS_R_DNAME) &&
8857 !dns_name_equal(name, found))
8858 {
8859 /*
8860 * Remember the obscuring name so that
8861 * we skip all obscured names.
8862 */
8863 dns_name_copy(found, name);
8864 delegation = true;
8865 goto next_removenode;
8866 }
8867 }
8868
8869 /*
8870 * Check to see if this is a bottom of zone node.
8871 */
8872 result = dns_db_allrdatasets(db, node, version, 0, 0,
8873 &iterator);
8874 if (result == ISC_R_NOTFOUND) {
8875 /* Empty node? */
8876 goto next_removenode;
8877 }
8878 if (result != ISC_R_SUCCESS) {
8879 goto failure;
8880 }
8881
8882 seen_soa = seen_ns = seen_dname = seen_nsec3 = seen_nsec =
8883 seen_rr = false;
8884 for (result = dns_rdatasetiter_first(iterator);
8885 result == ISC_R_SUCCESS;
8886 result = dns_rdatasetiter_next(iterator))
8887 {
8888 dns_rdatasetiter_current(iterator, &rdataset);
8889 if (rdataset.type == dns_rdatatype_soa) {
8890 seen_soa = true;
8891 } else if (rdataset.type == dns_rdatatype_ns) {
8892 seen_ns = true;
8893 } else if (rdataset.type == dns_rdatatype_dname) {
8894 seen_dname = true;
8895 } else if (rdataset.type == dns_rdatatype_nsec) {
8896 seen_nsec = true;
8897 } else if (rdataset.type == dns_rdatatype_nsec3) {
8898 seen_nsec3 = true;
8899 } else if (rdataset.type != dns_rdatatype_rrsig) {
8900 seen_rr = true;
8901 }
8902 dns_rdataset_disassociate(&rdataset);
8903 }
8904 dns_rdatasetiter_destroy(&iterator);
8905
8906 if (!seen_rr || seen_nsec3 || seen_nsec) {
8907 goto next_removenode;
8908 }
8909 if ((seen_ns && !seen_soa) || seen_dname) {
8910 delegation = true;
8911 }
8912
8913 /*
8914 * Add a NSEC record except at the origin.
8915 */
8916 if (!dns_name_equal(name, dns_db_origin(db))) {
8917 dns_dbiterator_pause(nsec3chain->dbiterator);
8918 CHECK(add_nsec(db, version, name, node,
8919 zone_nsecttl(zone), delegation,
8920 &nsec_diff));
8921 signatures--;
8922 }
8923
8924 next_removenode:
8925 first = false;
8926 dns_db_detachnode(db, &node);
8927 do {
8928 result = dns_dbiterator_next(nsec3chain->dbiterator);
8929 if (result == ISC_R_NOMORE && buildnsecchain) {
8930 /*
8931 * The NSEC chain should now be built.
8932 * We can now remove the NSEC3 chain.
8933 */
8934 updatensec = true;
8935 goto same_removechain;
8936 }
8937 if (result == ISC_R_NOMORE) {
8938 dns_dbiterator_pause(nsec3chain->dbiterator);
8939 LOCK_ZONE(zone);
8940 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
8941 link);
8942 UNLOCK_ZONE(zone);
8943 ISC_LIST_APPEND(cleanup, nsec3chain, link);
8944 result = fixup_nsec3param(
8945 db, version, nsec3chain, false,
8946 privatetype, ¶m_diff);
8947 if (result != ISC_R_SUCCESS) {
8948 dnssec_log(zone, ISC_LOG_ERROR,
8949 "zone_nsec3chain:"
8950 "fixup_nsec3param -> %s",
8951 isc_result_totext(result));
8952 goto failure;
8953 }
8954 goto next_removechain;
8955 } else if (result != ISC_R_SUCCESS) {
8956 dnssec_log(zone, ISC_LOG_ERROR,
8957 "zone_nsec3chain:"
8958 "dns_dbiterator_next -> %s",
8959 isc_result_totext(result));
8960 goto failure;
8961 } else if (delegation) {
8962 dns_dbiterator_current(nsec3chain->dbiterator,
8963 &node, nextname);
8964 dns_db_detachnode(db, &node);
8965 if (!dns_name_issubdomain(nextname, name)) {
8966 break;
8967 }
8968 } else {
8969 break;
8970 }
8971 } while (1);
8972 continue;
8973
8974 same_removechain:
8975 CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
8976 buildnsecchain = false;
8977 first = true;
8978 continue;
8979
8980 next_removechain:
8981 dns_dbiterator_pause(nsec3chain->dbiterator);
8982 nsec3chain = nextnsec3chain;
8983 first = true;
8984 }
8985
8986 skip_removals:
8987 /*
8988 * We may need to update the NSEC/NSEC3 records for the zone apex.
8989 */
8990 if (!ISC_LIST_EMPTY(param_diff.tuples)) {
8991 bool rebuild_nsec = false, rebuild_nsec3 = false;
8992 result = dns_db_getoriginnode(db, &node);
8993 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8994 result = dns_db_allrdatasets(db, node, version, 0, 0,
8995 &iterator);
8996 if (result != ISC_R_SUCCESS) {
8997 dnssec_log(zone, ISC_LOG_ERROR,
8998 "zone_nsec3chain:dns_db_allrdatasets -> %s",
8999 isc_result_totext(result));
9000 goto failure;
9001 }
9002 for (result = dns_rdatasetiter_first(iterator);
9003 result == ISC_R_SUCCESS;
9004 result = dns_rdatasetiter_next(iterator))
9005 {
9006 dns_rdatasetiter_current(iterator, &rdataset);
9007 if (rdataset.type == dns_rdatatype_nsec) {
9008 rebuild_nsec = true;
9009 } else if (rdataset.type == dns_rdatatype_nsec3param) {
9010 rebuild_nsec3 = true;
9011 }
9012 dns_rdataset_disassociate(&rdataset);
9013 }
9014 dns_rdatasetiter_destroy(&iterator);
9015 dns_db_detachnode(db, &node);
9016
9017 if (rebuild_nsec) {
9018 if (nsec3chain != NULL) {
9019 dns_dbiterator_pause(nsec3chain->dbiterator);
9020 }
9021
9022 result = updatesecure(db, version, &zone->origin,
9023 zone_nsecttl(zone), true,
9024 &nsec_diff);
9025 if (result != ISC_R_SUCCESS) {
9026 dnssec_log(zone, ISC_LOG_ERROR,
9027 "zone_nsec3chain:updatesecure -> %s",
9028 isc_result_totext(result));
9029 goto failure;
9030 }
9031 }
9032
9033 if (rebuild_nsec3) {
9034 if (nsec3chain != NULL) {
9035 dns_dbiterator_pause(nsec3chain->dbiterator);
9036 }
9037
9038 result = dns_nsec3_addnsec3s(
9039 db, version, dns_db_origin(db),
9040 zone_nsecttl(zone), false, &nsec3_diff);
9041 if (result != ISC_R_SUCCESS) {
9042 dnssec_log(zone, ISC_LOG_ERROR,
9043 "zone_nsec3chain:"
9044 "dns_nsec3_addnsec3s -> %s",
9045 isc_result_totext(result));
9046 goto failure;
9047 }
9048 }
9049 }
9050
9051 /*
9052 * Add / update signatures for the NSEC3 records.
9053 */
9054 if (nsec3chain != NULL) {
9055 dns_dbiterator_pause(nsec3chain->dbiterator);
9056 }
9057 result = dns__zone_updatesigs(&nsec3_diff, db, version, zone_keys,
9058 nkeys, zone, inception, expire, 0, now,
9059 check_ksk, keyset_kskonly, &zonediff);
9060 if (result != ISC_R_SUCCESS) {
9061 dnssec_log(zone, ISC_LOG_ERROR,
9062 "zone_nsec3chain:dns__zone_updatesigs -> %s",
9063 isc_result_totext(result));
9064 goto failure;
9065 }
9066
9067 /*
9068 * We have changed the NSEC3PARAM or private RRsets
9069 * above so we need to update the signatures.
9070 */
9071 result = dns__zone_updatesigs(¶m_diff, db, version, zone_keys,
9072 nkeys, zone, inception, expire, 0, now,
9073 check_ksk, keyset_kskonly, &zonediff);
9074 if (result != ISC_R_SUCCESS) {
9075 dnssec_log(zone, ISC_LOG_ERROR,
9076 "zone_nsec3chain:dns__zone_updatesigs -> %s",
9077 isc_result_totext(result));
9078 goto failure;
9079 }
9080
9081 if (updatensec) {
9082 result = updatesecure(db, version, &zone->origin,
9083 zone_nsecttl(zone), false, &nsec_diff);
9084 if (result != ISC_R_SUCCESS) {
9085 dnssec_log(zone, ISC_LOG_ERROR,
9086 "zone_nsec3chain:updatesecure -> %s",
9087 isc_result_totext(result));
9088 goto failure;
9089 }
9090 }
9091
9092 result = dns__zone_updatesigs(&nsec_diff, db, version, zone_keys, nkeys,
9093 zone, inception, expire, 0, now,
9094 check_ksk, keyset_kskonly, &zonediff);
9095 if (result != ISC_R_SUCCESS) {
9096 dnssec_log(zone, ISC_LOG_ERROR,
9097 "zone_nsec3chain:dns__zone_updatesigs -> %s",
9098 isc_result_totext(result));
9099 goto failure;
9100 }
9101
9102 /*
9103 * If we made no effective changes to the zone then we can just
9104 * cleanup otherwise we need to increment the serial.
9105 */
9106 if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
9107 /*
9108 * No need to call dns_db_closeversion() here as it is
9109 * called with commit = true below.
9110 */
9111 goto done;
9112 }
9113
9114 result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
9115 &zonediff, zone_keys, nkeys, now, false);
9116 if (result != ISC_R_SUCCESS) {
9117 dnssec_log(zone, ISC_LOG_ERROR,
9118 "zone_nsec3chain:del_sigs -> %s",
9119 isc_result_totext(result));
9120 goto failure;
9121 }
9122
9123 result = update_soa_serial(zone, db, version, zonediff.diff, zone->mctx,
9124 zone->updatemethod);
9125 if (result != ISC_R_SUCCESS) {
9126 dnssec_log(zone, ISC_LOG_ERROR,
9127 "zone_nsec3chain:update_soa_serial -> %s",
9128 isc_result_totext(result));
9129 goto failure;
9130 }
9131
9132 result = add_sigs(db, version, &zone->origin, zone, dns_rdatatype_soa,
9133 zonediff.diff, zone_keys, nkeys, zone->mctx, now,
9134 inception, soaexpire, check_ksk, keyset_kskonly);
9135 if (result != ISC_R_SUCCESS) {
9136 dnssec_log(zone, ISC_LOG_ERROR,
9137 "zone_nsec3chain:add_sigs -> %s",
9138 isc_result_totext(result));
9139 goto failure;
9140 }
9141
9142 /* Write changes to journal file. */
9143 CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_nsec3chain"));
9144
9145 LOCK_ZONE(zone);
9146 zone_needdump(zone, DNS_DUMP_DELAY);
9147 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
9148 UNLOCK_ZONE(zone);
9149
9150 done:
9151 /*
9152 * Pause all iterators so that dns_db_closeversion() can succeed.
9153 */
9154 LOCK_ZONE(zone);
9155 for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain); nsec3chain != NULL;
9156 nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
9157 {
9158 dns_dbiterator_pause(nsec3chain->dbiterator);
9159 }
9160 UNLOCK_ZONE(zone);
9161
9162 /*
9163 * Everything has succeeded. Commit the changes.
9164 * Unconditionally commit as zonediff.offline not checked above.
9165 */
9166 dns_db_closeversion(db, &version, true);
9167
9168 /*
9169 * Everything succeeded so we can clean these up now.
9170 */
9171 nsec3chain = ISC_LIST_HEAD(cleanup);
9172 while (nsec3chain != NULL) {
9173 ISC_LIST_UNLINK(cleanup, nsec3chain, link);
9174 dns_db_detach(&nsec3chain->db);
9175 dns_dbiterator_destroy(&nsec3chain->dbiterator);
9176 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
9177 nsec3chain = ISC_LIST_HEAD(cleanup);
9178 }
9179
9180 LOCK_ZONE(zone);
9181 set_resigntime(zone);
9182 UNLOCK_ZONE(zone);
9183
9184 failure:
9185 if (result != ISC_R_SUCCESS) {
9186 dnssec_log(zone, ISC_LOG_ERROR, "zone_nsec3chain: %s",
9187 isc_result_totext(result));
9188 }
9189
9190 /*
9191 * On error roll back the current nsec3chain.
9192 */
9193 if (result != ISC_R_SUCCESS && nsec3chain != NULL) {
9194 if (nsec3chain->done) {
9195 dns_db_detach(&nsec3chain->db);
9196 dns_dbiterator_destroy(&nsec3chain->dbiterator);
9197 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
9198 } else {
9199 result = dns_dbiterator_first(nsec3chain->dbiterator);
9200 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9201 dns_dbiterator_pause(nsec3chain->dbiterator);
9202 nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
9203 }
9204 }
9205
9206 /*
9207 * Rollback the cleanup list.
9208 */
9209 nsec3chain = ISC_LIST_TAIL(cleanup);
9210 while (nsec3chain != NULL) {
9211 ISC_LIST_UNLINK(cleanup, nsec3chain, link);
9212 if (nsec3chain->done) {
9213 dns_db_detach(&nsec3chain->db);
9214 dns_dbiterator_destroy(&nsec3chain->dbiterator);
9215 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
9216 } else {
9217 LOCK_ZONE(zone);
9218 ISC_LIST_PREPEND(zone->nsec3chain, nsec3chain, link);
9219 UNLOCK_ZONE(zone);
9220 result = dns_dbiterator_first(nsec3chain->dbiterator);
9221 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9222 dns_dbiterator_pause(nsec3chain->dbiterator);
9223 nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
9224 }
9225 nsec3chain = ISC_LIST_TAIL(cleanup);
9226 }
9227
9228 LOCK_ZONE(zone);
9229 for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain); nsec3chain != NULL;
9230 nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
9231 {
9232 dns_dbiterator_pause(nsec3chain->dbiterator);
9233 }
9234 UNLOCK_ZONE(zone);
9235
9236 dns_diff_clear(¶m_diff);
9237 dns_diff_clear(&nsec3_diff);
9238 dns_diff_clear(&nsec_diff);
9239 dns_diff_clear(&_sig_diff);
9240
9241 if (iterator != NULL) {
9242 dns_rdatasetiter_destroy(&iterator);
9243 }
9244
9245 for (i = 0; i < nkeys; i++) {
9246 dst_key_free(&zone_keys[i]);
9247 }
9248
9249 if (node != NULL) {
9250 dns_db_detachnode(db, &node);
9251 }
9252 if (version != NULL) {
9253 dns_db_closeversion(db, &version, false);
9254 dns_db_detach(&db);
9255 } else if (db != NULL) {
9256 dns_db_detach(&db);
9257 }
9258
9259 LOCK_ZONE(zone);
9260 if (ISC_LIST_HEAD(zone->nsec3chain) != NULL) {
9261 isc_interval_t interval;
9262 if (zone->update_disabled || result != ISC_R_SUCCESS) {
9263 isc_interval_set(&interval, 60, 0); /* 1 minute */
9264 } else {
9265 isc_interval_set(&interval, 0, 10000000); /* 10 ms */
9266 }
9267 isc_time_nowplusinterval(&zone->nsec3chaintime, &interval);
9268 } else {
9269 isc_time_settoepoch(&zone->nsec3chaintime);
9270 }
9271 UNLOCK_ZONE(zone);
9272
9273 INSIST(version == NULL);
9274 }
9275
9276 /*%
9277 * Delete all RRSIG records with the given algorithm and keyid.
9278 * Remove the NSEC record and RRSIGs if nkeys is zero.
9279 * If all remaining RRsets are signed with the given algorithm
9280 * set *has_algp to true.
9281 */
9282 static isc_result_t
9283 del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
9284 dns_dbnode_t *node, unsigned int nkeys, dns_secalg_t algorithm,
9285 uint16_t keyid, bool *has_algp, dns_diff_t *diff) {
9286 dns_rdata_rrsig_t rrsig;
9287 dns_rdataset_t rdataset;
9288 dns_rdatasetiter_t *iterator = NULL;
9289 isc_result_t result;
9290 bool alg_missed = false;
9291 bool alg_found = false;
9292
9293 char namebuf[DNS_NAME_FORMATSIZE];
9294 dns_name_format(name, namebuf, sizeof(namebuf));
9295
9296 result = dns_db_allrdatasets(db, node, version, 0, 0, &iterator);
9297 if (result != ISC_R_SUCCESS) {
9298 if (result == ISC_R_NOTFOUND) {
9299 result = ISC_R_SUCCESS;
9300 }
9301 return (result);
9302 }
9303
9304 dns_rdataset_init(&rdataset);
9305 for (result = dns_rdatasetiter_first(iterator); result == ISC_R_SUCCESS;
9306 result = dns_rdatasetiter_next(iterator))
9307 {
9308 bool has_alg = false;
9309 dns_rdatasetiter_current(iterator, &rdataset);
9310 if (nkeys == 0 && rdataset.type == dns_rdatatype_nsec) {
9311 for (result = dns_rdataset_first(&rdataset);
9312 result == ISC_R_SUCCESS;
9313 result = dns_rdataset_next(&rdataset))
9314 {
9315 dns_rdata_t rdata = DNS_RDATA_INIT;
9316 dns_rdataset_current(&rdataset, &rdata);
9317 CHECK(update_one_rr(db, version, diff,
9318 DNS_DIFFOP_DEL, name,
9319 rdataset.ttl, &rdata));
9320 }
9321 if (result != ISC_R_NOMORE) {
9322 goto failure;
9323 }
9324 dns_rdataset_disassociate(&rdataset);
9325 continue;
9326 }
9327 if (rdataset.type != dns_rdatatype_rrsig) {
9328 dns_rdataset_disassociate(&rdataset);
9329 continue;
9330 }
9331 for (result = dns_rdataset_first(&rdataset);
9332 result == ISC_R_SUCCESS;
9333 result = dns_rdataset_next(&rdataset))
9334 {
9335 dns_rdata_t rdata = DNS_RDATA_INIT;
9336 dns_rdataset_current(&rdataset, &rdata);
9337 CHECK(dns_rdata_tostruct(&rdata, &rrsig, NULL));
9338 if (nkeys != 0 && (rrsig.algorithm != algorithm ||
9339 rrsig.keyid != keyid))
9340 {
9341 if (rrsig.algorithm == algorithm) {
9342 has_alg = true;
9343 }
9344 continue;
9345 }
9346 CHECK(update_one_rr(db, version, diff,
9347 DNS_DIFFOP_DELRESIGN, name,
9348 rdataset.ttl, &rdata));
9349 }
9350 dns_rdataset_disassociate(&rdataset);
9351 if (result != ISC_R_NOMORE) {
9352 break;
9353 }
9354
9355 /*
9356 * After deleting, if there's still a signature for
9357 * 'algorithm', set alg_found; if not, set alg_missed.
9358 */
9359 if (has_alg) {
9360 alg_found = true;
9361 } else {
9362 alg_missed = true;
9363 }
9364 }
9365 if (result == ISC_R_NOMORE) {
9366 result = ISC_R_SUCCESS;
9367 }
9368
9369 /*
9370 * Set `has_algp` if the algorithm was found in every RRset:
9371 * i.e., found in at least one, and not missing from any.
9372 */
9373 *has_algp = (alg_found && !alg_missed);
9374 failure:
9375 if (dns_rdataset_isassociated(&rdataset)) {
9376 dns_rdataset_disassociate(&rdataset);
9377 }
9378 dns_rdatasetiter_destroy(&iterator);
9379 return (result);
9380 }
9381
9382 /*
9383 * Prevent the zone entering a inconsistent state where
9384 * NSEC only DNSKEYs are present with NSEC3 chains.
9385 */
9386 bool
9387 dns_zone_check_dnskey_nsec3(dns_zone_t *zone, dns_db_t *db,
9388 dns_dbversion_t *ver, dns_diff_t *diff,
9389 dst_key_t **keys, unsigned int numkeys) {
9390 uint8_t alg;
9391 dns_rdatatype_t privatetype;
9392 ;
9393 bool nseconly = false, nsec3 = false;
9394 isc_result_t result;
9395
9396 REQUIRE(DNS_ZONE_VALID(zone));
9397 REQUIRE(db != NULL);
9398
9399 privatetype = dns_zone_getprivatetype(zone);
9400
9401 /* Scan the tuples for an NSEC-only DNSKEY */
9402 if (diff != NULL) {
9403 for (dns_difftuple_t *tuple = ISC_LIST_HEAD(diff->tuples);
9404 tuple != NULL; tuple = ISC_LIST_NEXT(tuple, link))
9405 {
9406 if (nseconly && nsec3) {
9407 break;
9408 }
9409
9410 if (tuple->op != DNS_DIFFOP_ADD) {
9411 continue;
9412 }
9413
9414 if (tuple->rdata.type == dns_rdatatype_nsec3param) {
9415 nsec3 = true;
9416 }
9417
9418 if (tuple->rdata.type != dns_rdatatype_dnskey) {
9419 continue;
9420 }
9421
9422 alg = tuple->rdata.data[3];
9423 if (alg == DNS_KEYALG_RSAMD5 || alg == DNS_KEYALG_DH ||
9424 alg == DNS_KEYALG_DSA || alg == DNS_KEYALG_RSASHA1)
9425 {
9426 nseconly = true;
9427 }
9428 }
9429 }
9430 /* Scan the zone keys for an NSEC-only DNSKEY */
9431 if (keys != NULL && !nseconly) {
9432 for (unsigned int i = 0; i < numkeys; i++) {
9433 alg = dst_key_alg(keys[i]);
9434 if (alg == DNS_KEYALG_RSAMD5 || alg == DNS_KEYALG_DH ||
9435 alg == DNS_KEYALG_DSA || alg == DNS_KEYALG_RSASHA1)
9436 {
9437 nseconly = true;
9438 break;
9439 }
9440 }
9441 }
9442
9443 /* Check DB for NSEC-only DNSKEY */
9444 if (!nseconly) {
9445 result = dns_nsec_nseconly(db, ver, diff, &nseconly);
9446 /*
9447 * Adding an NSEC3PARAM record can proceed without a
9448 * DNSKEY (it will trigger a delayed change), so we can
9449 * ignore ISC_R_NOTFOUND here.
9450 */
9451 if (result == ISC_R_NOTFOUND) {
9452 result = ISC_R_SUCCESS;
9453 }
9454 CHECK(result);
9455 }
9456
9457 /* Check existing DB for NSEC3 */
9458 if (!nsec3) {
9459 CHECK(dns_nsec3_activex(db, ver, false, privatetype, &nsec3));
9460 }
9461
9462 /* Check kasp for NSEC3PARAM settings */
9463 if (!nsec3) {
9464 dns_kasp_t *kasp = dns_zone_getkasp(zone);
9465 if (kasp != NULL) {
9466 nsec3 = dns_kasp_nsec3(kasp);
9467 }
9468 }
9469
9470 /* Refuse to allow NSEC3 with NSEC-only keys */
9471 if (nseconly && nsec3) {
9472 goto failure;
9473 }
9474
9475 return (true);
9476
9477 failure:
9478 return (false);
9479 }
9480
9481 /*
9482 * Incrementally sign the zone using the keys requested.
9483 * Builds the NSEC chain if required.
9484 */
9485 static void
9486 zone_sign(dns_zone_t *zone) {
9487 const char *me = "zone_sign";
9488 dns_db_t *db = NULL;
9489 dns_dbnode_t *node = NULL;
9490 dns_dbversion_t *version = NULL;
9491 dns_diff_t _sig_diff;
9492 dns_diff_t post_diff;
9493 dns__zonediff_t zonediff;
9494 dns_fixedname_t fixed;
9495 dns_fixedname_t nextfixed;
9496 dns_kasp_t *kasp;
9497 dns_name_t *name, *nextname;
9498 dns_rdataset_t rdataset;
9499 dns_signing_t *signing, *nextsigning;
9500 dns_signinglist_t cleanup;
9501 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
9502 int32_t signatures;
9503 bool check_ksk, keyset_kskonly, is_ksk, is_zsk;
9504 bool with_ksk, with_zsk;
9505 bool commit = false;
9506 bool is_bottom_of_zone;
9507 bool build_nsec = false;
9508 bool build_nsec3 = false;
9509 bool use_kasp = false;
9510 bool first;
9511 isc_result_t result;
9512 isc_stdtime_t now, inception, soaexpire, expire;
9513 uint32_t jitter, sigvalidityinterval, expiryinterval;
9514 unsigned int i, j;
9515 unsigned int nkeys = 0;
9516 uint32_t nodes;
9517
9518 ENTER;
9519
9520 dns_rdataset_init(&rdataset);
9521 name = dns_fixedname_initname(&fixed);
9522 nextname = dns_fixedname_initname(&nextfixed);
9523 dns_diff_init(zone->mctx, &_sig_diff);
9524 dns_diff_init(zone->mctx, &post_diff);
9525 zonediff_init(&zonediff, &_sig_diff);
9526 ISC_LIST_INIT(cleanup);
9527
9528 /*
9529 * Updates are disabled. Pause for 1 minute.
9530 */
9531 if (zone->update_disabled) {
9532 result = ISC_R_FAILURE;
9533 goto cleanup;
9534 }
9535
9536 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9537 if (zone->db != NULL) {
9538 dns_db_attach(zone->db, &db);
9539 }
9540 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9541 if (db == NULL) {
9542 result = ISC_R_FAILURE;
9543 goto cleanup;
9544 }
9545
9546 result = dns_db_newversion(db, &version);
9547 if (result != ISC_R_SUCCESS) {
9548 dnssec_log(zone, ISC_LOG_ERROR,
9549 "zone_sign:dns_db_newversion -> %s",
9550 isc_result_totext(result));
9551 goto cleanup;
9552 }
9553
9554 isc_stdtime_get(&now);
9555
9556 result = dns__zone_findkeys(zone, db, version, now, zone->mctx,
9557 DNS_MAXZONEKEYS, zone_keys, &nkeys);
9558 if (result != ISC_R_SUCCESS) {
9559 dnssec_log(zone, ISC_LOG_ERROR,
9560 "zone_sign:dns__zone_findkeys -> %s",
9561 isc_result_totext(result));
9562 goto cleanup;
9563 }
9564
9565 kasp = dns_zone_getkasp(zone);
9566 sigvalidityinterval = dns_zone_getsigvalidityinterval(zone);
9567 inception = now - 3600; /* Allow for clock skew. */
9568 soaexpire = now + sigvalidityinterval;
9569 expiryinterval = dns_zone_getsigresigninginterval(zone);
9570 if (expiryinterval > sigvalidityinterval) {
9571 expiryinterval = sigvalidityinterval;
9572 } else {
9573 expiryinterval = sigvalidityinterval - expiryinterval;
9574 }
9575
9576 /*
9577 * Spread out signatures over time if they happen to be
9578 * clumped. We don't do this for each add_sigs() call as
9579 * we still want some clustering to occur.
9580 */
9581 if (sigvalidityinterval >= 3600U) {
9582 if (sigvalidityinterval > 7200U) {
9583 jitter = isc_random_uniform(expiryinterval);
9584 } else {
9585 jitter = isc_random_uniform(1200);
9586 }
9587 expire = soaexpire - jitter - 1;
9588 } else {
9589 expire = soaexpire - 1;
9590 }
9591
9592 /*
9593 * We keep pulling nodes off each iterator in turn until
9594 * we have no more nodes to pull off or we reach the limits
9595 * for this quantum.
9596 */
9597 nodes = zone->nodes;
9598 signatures = zone->signatures;
9599 signing = ISC_LIST_HEAD(zone->signing);
9600 first = true;
9601
9602 if (dns_zone_getkasp(zone) != NULL) {
9603 check_ksk = false;
9604 keyset_kskonly = true;
9605 use_kasp = true;
9606 } else {
9607 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
9608 keyset_kskonly = DNS_ZONE_OPTION(zone,
9609 DNS_ZONEOPT_DNSKEYKSKONLY);
9610 }
9611 dnssec_log(zone, ISC_LOG_DEBUG(3), "zone_sign:use kasp -> %s",
9612 use_kasp ? "yes" : "no");
9613
9614 /* Determine which type of chain to build */
9615 CHECK(dns_private_chains(db, version, zone->privatetype, &build_nsec,
9616 &build_nsec3));
9617 if (!build_nsec && !build_nsec3) {
9618 if (use_kasp) {
9619 build_nsec3 = dns_kasp_nsec3(kasp);
9620 if (!dns_zone_check_dnskey_nsec3(
9621 zone, db, version, NULL,
9622 (dst_key_t **)&zone_keys, nkeys))
9623 {
9624 dnssec_log(zone, ISC_LOG_INFO,
9625 "wait building NSEC3 chain until "
9626 "NSEC only DNSKEYs are removed");
9627 build_nsec3 = false;
9628 }
9629 build_nsec = !build_nsec3;
9630 } else {
9631 /* If neither chain is found, default to NSEC */
9632 build_nsec = true;
9633 }
9634 }
9635
9636 while (signing != NULL && nodes-- > 0 && signatures > 0) {
9637 bool has_alg = false;
9638
9639 dns_dbiterator_pause(signing->dbiterator);
9640 nextsigning = ISC_LIST_NEXT(signing, link);
9641
9642 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9643 if (signing->done || signing->db != zone->db) {
9644 /*
9645 * The zone has been reloaded. We will have to
9646 * created new signings as part of the reload
9647 * process so we can destroy this one.
9648 */
9649 ISC_LIST_UNLINK(zone->signing, signing, link);
9650 ISC_LIST_APPEND(cleanup, signing, link);
9651 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9652 goto next_signing;
9653 }
9654 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9655
9656 if (signing->db != db) {
9657 goto next_signing;
9658 }
9659
9660 is_bottom_of_zone = false;
9661
9662 if (first && signing->deleteit) {
9663 /*
9664 * Remove the key we are deleting from consideration.
9665 */
9666 for (i = 0, j = 0; i < nkeys; i++) {
9667 /*
9668 * Find the key we want to remove.
9669 */
9670 if (ALG(zone_keys[i]) == signing->algorithm &&
9671 dst_key_id(zone_keys[i]) == signing->keyid)
9672 {
9673 dst_key_free(&zone_keys[i]);
9674 continue;
9675 }
9676 zone_keys[j] = zone_keys[i];
9677 j++;
9678 }
9679 for (i = j; i < nkeys; i++) {
9680 zone_keys[i] = NULL;
9681 }
9682 nkeys = j;
9683 }
9684
9685 dns_dbiterator_current(signing->dbiterator, &node, name);
9686
9687 if (signing->deleteit) {
9688 dns_dbiterator_pause(signing->dbiterator);
9689 CHECK(del_sig(db, version, name, node, nkeys,
9690 signing->algorithm, signing->keyid,
9691 &has_alg, zonediff.diff));
9692 }
9693
9694 /*
9695 * On the first pass we need to check if the current node
9696 * has not been obscured.
9697 */
9698 if (first) {
9699 dns_fixedname_t ffound;
9700 dns_name_t *found;
9701 found = dns_fixedname_initname(&ffound);
9702 result = dns_db_find(
9703 db, name, version, dns_rdatatype_soa,
9704 DNS_DBFIND_NOWILD, 0, NULL, found, NULL, NULL);
9705 if ((result == DNS_R_DELEGATION ||
9706 result == DNS_R_DNAME) &&
9707 !dns_name_equal(name, found))
9708 {
9709 /*
9710 * Remember the obscuring name so that
9711 * we skip all obscured names.
9712 */
9713 dns_name_copy(found, name);
9714 is_bottom_of_zone = true;
9715 goto next_node;
9716 }
9717 }
9718
9719 /*
9720 * Process one node.
9721 */
9722 with_ksk = false;
9723 with_zsk = false;
9724 dns_dbiterator_pause(signing->dbiterator);
9725
9726 CHECK(check_if_bottom_of_zone(db, node, version,
9727 &is_bottom_of_zone));
9728
9729 for (i = 0; !has_alg && i < nkeys; i++) {
9730 bool both = false;
9731
9732 /*
9733 * Find the keys we want to sign with.
9734 */
9735 if (!dst_key_isprivate(zone_keys[i])) {
9736 continue;
9737 }
9738 if (dst_key_inactive(zone_keys[i])) {
9739 continue;
9740 }
9741
9742 /*
9743 * When adding look for the specific key.
9744 */
9745 if (!signing->deleteit &&
9746 (dst_key_alg(zone_keys[i]) != signing->algorithm ||
9747 dst_key_id(zone_keys[i]) != signing->keyid))
9748 {
9749 continue;
9750 }
9751
9752 /*
9753 * When deleting make sure we are properly signed
9754 * with the algorithm that was being removed.
9755 */
9756 if (signing->deleteit &&
9757 ALG(zone_keys[i]) != signing->algorithm)
9758 {
9759 continue;
9760 }
9761
9762 /*
9763 * Do we do KSK processing?
9764 */
9765 if (check_ksk && !REVOKE(zone_keys[i])) {
9766 bool have_ksk, have_nonksk;
9767 if (KSK(zone_keys[i])) {
9768 have_ksk = true;
9769 have_nonksk = false;
9770 } else {
9771 have_ksk = false;
9772 have_nonksk = true;
9773 }
9774 for (j = 0; j < nkeys; j++) {
9775 if (j == i || (ALG(zone_keys[i]) !=
9776 ALG(zone_keys[j])))
9777 {
9778 continue;
9779 }
9780 /*
9781 * Don't consider inactive keys, however
9782 * the key may be temporary offline, so
9783 * do consider KSKs which private key
9784 * files are unavailable.
9785 */
9786 if (dst_key_inactive(zone_keys[j])) {
9787 continue;
9788 }
9789 if (REVOKE(zone_keys[j])) {
9790 continue;
9791 }
9792 if (KSK(zone_keys[j])) {
9793 have_ksk = true;
9794 } else if (dst_key_isprivate(
9795 zone_keys[j]))
9796 {
9797 have_nonksk = true;
9798 }
9799 both = have_ksk && have_nonksk;
9800 if (both) {
9801 break;
9802 }
9803 }
9804 }
9805 if (use_kasp) {
9806 /*
9807 * A dnssec-policy is found. Check what
9808 * RRsets this key can sign.
9809 */
9810 isc_result_t kresult;
9811 is_ksk = false;
9812 kresult = dst_key_getbool(
9813 zone_keys[i], DST_BOOL_KSK, &is_ksk);
9814 if (kresult != ISC_R_SUCCESS) {
9815 if (KSK(zone_keys[i])) {
9816 is_ksk = true;
9817 }
9818 }
9819
9820 is_zsk = false;
9821 kresult = dst_key_getbool(
9822 zone_keys[i], DST_BOOL_ZSK, &is_zsk);
9823 if (kresult != ISC_R_SUCCESS) {
9824 if (!KSK(zone_keys[i])) {
9825 is_zsk = true;
9826 }
9827 }
9828 /* Treat as if we have both KSK and ZSK. */
9829 both = true;
9830 } else if (both || REVOKE(zone_keys[i])) {
9831 is_ksk = KSK(zone_keys[i]);
9832 is_zsk = !KSK(zone_keys[i]);
9833 } else {
9834 is_ksk = false;
9835 is_zsk = true;
9836 }
9837
9838 /*
9839 * If deleting signatures, we need to ensure that
9840 * the RRset is still signed at least once by a
9841 * KSK and a ZSK.
9842 */
9843 if (signing->deleteit && is_zsk && with_zsk) {
9844 continue;
9845 }
9846
9847 if (signing->deleteit && is_ksk && with_ksk) {
9848 continue;
9849 }
9850
9851 CHECK(sign_a_node(
9852 db, zone, name, node, version, build_nsec3,
9853 build_nsec, zone_keys[i], now, inception,
9854 expire, zone_nsecttl(zone), is_ksk, is_zsk,
9855 (both && keyset_kskonly), is_bottom_of_zone,
9856 zonediff.diff, &signatures, zone->mctx));
9857 /*
9858 * If we are adding we are done. Look for other keys
9859 * of the same algorithm if deleting.
9860 */
9861 if (!signing->deleteit) {
9862 break;
9863 }
9864 if (is_zsk) {
9865 with_zsk = true;
9866 }
9867 if (is_ksk) {
9868 with_ksk = true;
9869 }
9870 }
9871
9872 /*
9873 * Go onto next node.
9874 */
9875 next_node:
9876 first = false;
9877 dns_db_detachnode(db, &node);
9878 do {
9879 result = dns_dbiterator_next(signing->dbiterator);
9880 if (result == ISC_R_NOMORE) {
9881 ISC_LIST_UNLINK(zone->signing, signing, link);
9882 ISC_LIST_APPEND(cleanup, signing, link);
9883 dns_dbiterator_pause(signing->dbiterator);
9884 if (nkeys != 0 && build_nsec) {
9885 /*
9886 * We have finished regenerating the
9887 * zone with a zone signing key.
9888 * The NSEC chain is now complete and
9889 * there is a full set of signatures
9890 * for the zone. We can now clear the
9891 * OPT bit from the NSEC record.
9892 */
9893 result = updatesecure(
9894 db, version, &zone->origin,
9895 zone_nsecttl(zone), false,
9896 &post_diff);
9897 if (result != ISC_R_SUCCESS) {
9898 dnssec_log(zone, ISC_LOG_ERROR,
9899 "updatesecure -> %s",
9900 isc_result_totext(
9901 result));
9902 goto cleanup;
9903 }
9904 }
9905 result = updatesignwithkey(
9906 zone, signing, version, build_nsec3,
9907 zone_nsecttl(zone), &post_diff);
9908 if (result != ISC_R_SUCCESS) {
9909 dnssec_log(zone, ISC_LOG_ERROR,
9910 "updatesignwithkey -> %s",
9911 isc_result_totext(result));
9912 goto cleanup;
9913 }
9914 build_nsec = false;
9915 goto next_signing;
9916 } else if (result != ISC_R_SUCCESS) {
9917 dnssec_log(zone, ISC_LOG_ERROR,
9918 "zone_sign:"
9919 "dns_dbiterator_next -> %s",
9920 isc_result_totext(result));
9921 goto cleanup;
9922 } else if (is_bottom_of_zone) {
9923 dns_dbiterator_current(signing->dbiterator,
9924 &node, nextname);
9925 dns_db_detachnode(db, &node);
9926 if (!dns_name_issubdomain(nextname, name)) {
9927 break;
9928 }
9929 } else {
9930 break;
9931 }
9932 } while (1);
9933 continue;
9934
9935 next_signing:
9936 dns_dbiterator_pause(signing->dbiterator);
9937 signing = nextsigning;
9938 first = true;
9939 }
9940
9941 if (ISC_LIST_HEAD(post_diff.tuples) != NULL) {
9942 result = dns__zone_updatesigs(&post_diff, db, version,
9943 zone_keys, nkeys, zone, inception,
9944 expire, 0, now, check_ksk,
9945 keyset_kskonly, &zonediff);
9946 if (result != ISC_R_SUCCESS) {
9947 dnssec_log(zone, ISC_LOG_ERROR,
9948 "zone_sign:dns__zone_updatesigs -> %s",
9949 isc_result_totext(result));
9950 goto cleanup;
9951 }
9952 }
9953
9954 /*
9955 * Have we changed anything?
9956 */
9957 if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
9958 if (zonediff.offline) {
9959 commit = true;
9960 }
9961 result = ISC_R_SUCCESS;
9962 goto pauseall;
9963 }
9964
9965 commit = true;
9966
9967 result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
9968 &zonediff, zone_keys, nkeys, now, false);
9969 if (result != ISC_R_SUCCESS) {
9970 dnssec_log(zone, ISC_LOG_ERROR, "zone_sign:del_sigs -> %s",
9971 isc_result_totext(result));
9972 goto cleanup;
9973 }
9974
9975 result = update_soa_serial(zone, db, version, zonediff.diff, zone->mctx,
9976 zone->updatemethod);
9977 if (result != ISC_R_SUCCESS) {
9978 dnssec_log(zone, ISC_LOG_ERROR,
9979 "zone_sign:update_soa_serial -> %s",
9980 isc_result_totext(result));
9981 goto cleanup;
9982 }
9983
9984 /*
9985 * Generate maximum life time signatures so that the above loop
9986 * termination is sensible.
9987 */
9988 result = add_sigs(db, version, &zone->origin, zone, dns_rdatatype_soa,
9989 zonediff.diff, zone_keys, nkeys, zone->mctx, now,
9990 inception, soaexpire, check_ksk, keyset_kskonly);
9991 if (result != ISC_R_SUCCESS) {
9992 dnssec_log(zone, ISC_LOG_ERROR, "zone_sign:add_sigs -> %s",
9993 isc_result_totext(result));
9994 goto cleanup;
9995 }
9996
9997 /*
9998 * Write changes to journal file.
9999 */
10000 CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_sign"));
10001
10002 pauseall:
10003 /*
10004 * Pause all iterators so that dns_db_closeversion() can succeed.
10005 */
10006 for (signing = ISC_LIST_HEAD(zone->signing); signing != NULL;
10007 signing = ISC_LIST_NEXT(signing, link))
10008 {
10009 dns_dbiterator_pause(signing->dbiterator);
10010 }
10011
10012 for (signing = ISC_LIST_HEAD(cleanup); signing != NULL;
10013 signing = ISC_LIST_NEXT(signing, link))
10014 {
10015 dns_dbiterator_pause(signing->dbiterator);
10016 }
10017
10018 /*
10019 * Everything has succeeded. Commit the changes.
10020 */
10021 dns_db_closeversion(db, &version, commit);
10022
10023 /*
10024 * Everything succeeded so we can clean these up now.
10025 */
10026 signing = ISC_LIST_HEAD(cleanup);
10027 while (signing != NULL) {
10028 ISC_LIST_UNLINK(cleanup, signing, link);
10029 dns_db_detach(&signing->db);
10030 dns_dbiterator_destroy(&signing->dbiterator);
10031 isc_mem_put(zone->mctx, signing, sizeof *signing);
10032 signing = ISC_LIST_HEAD(cleanup);
10033 }
10034
10035 LOCK_ZONE(zone);
10036 set_resigntime(zone);
10037 if (commit) {
10038 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
10039 zone_needdump(zone, DNS_DUMP_DELAY);
10040 }
10041 UNLOCK_ZONE(zone);
10042
10043 failure:
10044 if (result != ISC_R_SUCCESS) {
10045 dnssec_log(zone, ISC_LOG_ERROR, "zone_sign: failed: %s",
10046 isc_result_totext(result));
10047 }
10048
10049 cleanup:
10050 /*
10051 * Pause all dbiterators.
10052 */
10053 for (signing = ISC_LIST_HEAD(zone->signing); signing != NULL;
10054 signing = ISC_LIST_NEXT(signing, link))
10055 {
10056 dns_dbiterator_pause(signing->dbiterator);
10057 }
10058
10059 /*
10060 * Rollback the cleanup list.
10061 */
10062 signing = ISC_LIST_HEAD(cleanup);
10063 while (signing != NULL) {
10064 ISC_LIST_UNLINK(cleanup, signing, link);
10065 ISC_LIST_PREPEND(zone->signing, signing, link);
10066 dns_dbiterator_first(signing->dbiterator);
10067 dns_dbiterator_pause(signing->dbiterator);
10068 signing = ISC_LIST_HEAD(cleanup);
10069 }
10070
10071 dns_diff_clear(&_sig_diff);
10072
10073 for (i = 0; i < nkeys; i++) {
10074 dst_key_free(&zone_keys[i]);
10075 }
10076
10077 if (node != NULL) {
10078 dns_db_detachnode(db, &node);
10079 }
10080
10081 if (version != NULL) {
10082 dns_db_closeversion(db, &version, false);
10083 dns_db_detach(&db);
10084 } else if (db != NULL) {
10085 dns_db_detach(&db);
10086 }
10087
10088 LOCK_ZONE(zone);
10089 if (ISC_LIST_HEAD(zone->signing) != NULL) {
10090 isc_interval_t interval;
10091 if (zone->update_disabled || result != ISC_R_SUCCESS) {
10092 isc_interval_set(&interval, 60, 0); /* 1 minute */
10093 } else {
10094 isc_interval_set(&interval, 0, 10000000); /* 10 ms */
10095 }
10096 isc_time_nowplusinterval(&zone->signingtime, &interval);
10097 } else {
10098 isc_time_settoepoch(&zone->signingtime);
10099 }
10100 UNLOCK_ZONE(zone);
10101
10102 INSIST(version == NULL);
10103 }
10104
10105 static isc_result_t
10106 normalize_key(dns_rdata_t *rr, dns_rdata_t *target, unsigned char *data,
10107 int size) {
10108 dns_rdata_dnskey_t dnskey;
10109 dns_rdata_keydata_t keydata;
10110 isc_buffer_t buf;
10111 isc_result_t result;
10112
10113 dns_rdata_reset(target);
10114 isc_buffer_init(&buf, data, size);
10115
10116 switch (rr->type) {
10117 case dns_rdatatype_dnskey:
10118 result = dns_rdata_tostruct(rr, &dnskey, NULL);
10119 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10120 dnskey.flags &= ~DNS_KEYFLAG_REVOKE;
10121 dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
10122 &dnskey, &buf);
10123 break;
10124 case dns_rdatatype_keydata:
10125 result = dns_rdata_tostruct(rr, &keydata, NULL);
10126 if (result == ISC_R_UNEXPECTEDEND) {
10127 return (result);
10128 }
10129 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10130 dns_keydata_todnskey(&keydata, &dnskey, NULL);
10131 dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
10132 &dnskey, &buf);
10133 break;
10134 default:
10135 UNREACHABLE();
10136 }
10137 return (ISC_R_SUCCESS);
10138 }
10139
10140 /*
10141 * 'rdset' contains either a DNSKEY rdataset from the zone apex, or
10142 * a KEYDATA rdataset from the key zone.
10143 *
10144 * 'rr' contains either a DNSKEY record, or a KEYDATA record
10145 *
10146 * After normalizing keys to the same format (DNSKEY, with revoke bit
10147 * cleared), return true if a key that matches 'rr' is found in
10148 * 'rdset', or false if not.
10149 */
10150
10151 static bool
10152 matchkey(dns_rdataset_t *rdset, dns_rdata_t *rr) {
10153 unsigned char data1[4096], data2[4096];
10154 dns_rdata_t rdata, rdata1, rdata2;
10155 isc_result_t result;
10156
10157 dns_rdata_init(&rdata);
10158 dns_rdata_init(&rdata1);
10159 dns_rdata_init(&rdata2);
10160
10161 result = normalize_key(rr, &rdata1, data1, sizeof(data1));
10162 if (result != ISC_R_SUCCESS) {
10163 return (false);
10164 }
10165
10166 for (result = dns_rdataset_first(rdset); result == ISC_R_SUCCESS;
10167 result = dns_rdataset_next(rdset))
10168 {
10169 dns_rdata_reset(&rdata);
10170 dns_rdataset_current(rdset, &rdata);
10171 result = normalize_key(&rdata, &rdata2, data2, sizeof(data2));
10172 if (result != ISC_R_SUCCESS) {
10173 continue;
10174 }
10175 if (dns_rdata_compare(&rdata1, &rdata2) == 0) {
10176 return (true);
10177 }
10178 }
10179
10180 return (false);
10181 }
10182
10183 /*
10184 * Calculate the refresh interval for a keydata zone, per
10185 * RFC5011: MAX(1 hr,
10186 * MIN(15 days,
10187 * 1/2 * OrigTTL,
10188 * 1/2 * RRSigExpirationInterval))
10189 * or for retries: MAX(1 hr,
10190 * MIN(1 day,
10191 * 1/10 * OrigTTL,
10192 * 1/10 * RRSigExpirationInterval))
10193 */
10194 static isc_stdtime_t
10195 refresh_time(dns_keyfetch_t *kfetch, bool retry) {
10196 isc_result_t result;
10197 uint32_t t;
10198 dns_rdataset_t *rdset;
10199 dns_rdata_t sigrr = DNS_RDATA_INIT;
10200 dns_rdata_sig_t sig;
10201 isc_stdtime_t now;
10202
10203 isc_stdtime_get(&now);
10204
10205 if (dns_rdataset_isassociated(&kfetch->dnskeysigset)) {
10206 rdset = &kfetch->dnskeysigset;
10207 } else {
10208 return (now + dns_zone_mkey_hour);
10209 }
10210
10211 result = dns_rdataset_first(rdset);
10212 if (result != ISC_R_SUCCESS) {
10213 return (now + dns_zone_mkey_hour);
10214 }
10215
10216 dns_rdataset_current(rdset, &sigrr);
10217 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
10218 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10219
10220 if (!retry) {
10221 t = sig.originalttl / 2;
10222
10223 if (isc_serial_gt(sig.timeexpire, now)) {
10224 uint32_t exp = (sig.timeexpire - now) / 2;
10225 if (t > exp) {
10226 t = exp;
10227 }
10228 }
10229
10230 if (t > (15 * dns_zone_mkey_day)) {
10231 t = (15 * dns_zone_mkey_day);
10232 }
10233
10234 if (t < dns_zone_mkey_hour) {
10235 t = dns_zone_mkey_hour;
10236 }
10237 } else {
10238 t = sig.originalttl / 10;
10239
10240 if (isc_serial_gt(sig.timeexpire, now)) {
10241 uint32_t exp = (sig.timeexpire - now) / 10;
10242 if (t > exp) {
10243 t = exp;
10244 }
10245 }
10246
10247 if (t > dns_zone_mkey_day) {
10248 t = dns_zone_mkey_day;
10249 }
10250
10251 if (t < dns_zone_mkey_hour) {
10252 t = dns_zone_mkey_hour;
10253 }
10254 }
10255
10256 return (now + t);
10257 }
10258
10259 /*
10260 * This routine is called when no changes are needed in a KEYDATA
10261 * record except to simply update the refresh timer. Caller should
10262 * hold zone lock.
10263 */
10264 static isc_result_t
10265 minimal_update(dns_keyfetch_t *kfetch, dns_dbversion_t *ver, dns_diff_t *diff) {
10266 isc_result_t result;
10267 isc_buffer_t keyb;
10268 unsigned char key_buf[4096];
10269 dns_rdata_t rdata = DNS_RDATA_INIT;
10270 dns_rdata_keydata_t keydata;
10271 dns_name_t *name;
10272 dns_zone_t *zone = kfetch->zone;
10273 isc_stdtime_t now;
10274
10275 name = dns_fixedname_name(&kfetch->name);
10276 isc_stdtime_get(&now);
10277
10278 for (result = dns_rdataset_first(&kfetch->keydataset);
10279 result == ISC_R_SUCCESS;
10280 result = dns_rdataset_next(&kfetch->keydataset))
10281 {
10282 dns_rdata_reset(&rdata);
10283 dns_rdataset_current(&kfetch->keydataset, &rdata);
10284
10285 /* Delete old version */
10286 CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_DEL, name,
10287 0, &rdata));
10288
10289 /* Update refresh timer */
10290 result = dns_rdata_tostruct(&rdata, &keydata, NULL);
10291 if (result == ISC_R_UNEXPECTEDEND) {
10292 continue;
10293 }
10294 if (result != ISC_R_SUCCESS) {
10295 goto failure;
10296 }
10297 keydata.refresh = refresh_time(kfetch, true);
10298 set_refreshkeytimer(zone, &keydata, now, false);
10299
10300 dns_rdata_reset(&rdata);
10301 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10302 CHECK(dns_rdata_fromstruct(&rdata, zone->rdclass,
10303 dns_rdatatype_keydata, &keydata,
10304 &keyb));
10305
10306 /* Insert updated version */
10307 CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_ADD, name,
10308 0, &rdata));
10309 }
10310 result = ISC_R_SUCCESS;
10311 failure:
10312 return (result);
10313 }
10314
10315 /*
10316 * Verify that DNSKEY set is signed by the key specified in 'keydata'.
10317 */
10318 static bool
10319 revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) {
10320 isc_result_t result;
10321 dns_name_t *keyname;
10322 isc_mem_t *mctx;
10323 dns_rdata_t sigrr = DNS_RDATA_INIT;
10324 dns_rdata_t rr = DNS_RDATA_INIT;
10325 dns_rdata_rrsig_t sig;
10326 dns_rdata_dnskey_t dnskey;
10327 dst_key_t *dstkey = NULL;
10328 unsigned char key_buf[4096];
10329 isc_buffer_t keyb;
10330 bool answer = false;
10331
10332 REQUIRE(kfetch != NULL && keydata != NULL);
10333 REQUIRE(dns_rdataset_isassociated(&kfetch->dnskeysigset));
10334
10335 keyname = dns_fixedname_name(&kfetch->name);
10336 mctx = kfetch->zone->view->mctx;
10337
10338 /* Generate a key from keydata */
10339 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10340 dns_keydata_todnskey(keydata, &dnskey, NULL);
10341 dns_rdata_fromstruct(&rr, keydata->common.rdclass, dns_rdatatype_dnskey,
10342 &dnskey, &keyb);
10343 result = dns_dnssec_keyfromrdata(keyname, &rr, mctx, &dstkey);
10344 if (result != ISC_R_SUCCESS) {
10345 return (false);
10346 }
10347
10348 /* See if that key generated any of the signatures */
10349 for (result = dns_rdataset_first(&kfetch->dnskeysigset);
10350 result == ISC_R_SUCCESS;
10351 result = dns_rdataset_next(&kfetch->dnskeysigset))
10352 {
10353 dns_fixedname_t fixed;
10354 dns_fixedname_init(&fixed);
10355
10356 dns_rdata_reset(&sigrr);
10357 dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
10358 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
10359 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10360
10361 if (dst_key_alg(dstkey) == sig.algorithm &&
10362 dst_key_rid(dstkey) == sig.keyid)
10363 {
10364 result = dns_dnssec_verify(
10365 keyname, &kfetch->dnskeyset, dstkey, false, 0,
10366 mctx, &sigrr, dns_fixedname_name(&fixed));
10367
10368 dnssec_log(kfetch->zone, ISC_LOG_DEBUG(3),
10369 "Confirm revoked DNSKEY is self-signed: %s",
10370 isc_result_totext(result));
10371
10372 if (result == ISC_R_SUCCESS) {
10373 answer = true;
10374 break;
10375 }
10376 }
10377 }
10378
10379 dst_key_free(&dstkey);
10380 return (answer);
10381 }
10382
10383 /*
10384 * A DNSKEY set has been fetched from the zone apex of a zone whose trust
10385 * anchors are being managed; scan the keyset, and update the key zone and the
10386 * local trust anchors according to RFC5011.
10387 */
10388 static void
10389 keyfetch_done(isc_task_t *task, isc_event_t *event) {
10390 isc_result_t result, eresult;
10391 dns_fetchevent_t *devent;
10392 dns_keyfetch_t *kfetch;
10393 dns_zone_t *zone;
10394 isc_mem_t *mctx = NULL;
10395 dns_keytable_t *secroots = NULL;
10396 dns_dbversion_t *ver = NULL;
10397 dns_diff_t diff;
10398 bool alldone = false;
10399 bool commit = false;
10400 dns_name_t *keyname = NULL;
10401 dns_rdata_t sigrr = DNS_RDATA_INIT;
10402 dns_rdata_t dnskeyrr = DNS_RDATA_INIT;
10403 dns_rdata_t keydatarr = DNS_RDATA_INIT;
10404 dns_rdata_rrsig_t sig;
10405 dns_rdata_dnskey_t dnskey;
10406 dns_rdata_keydata_t keydata;
10407 bool initializing;
10408 char namebuf[DNS_NAME_FORMATSIZE];
10409 unsigned char key_buf[4096];
10410 isc_buffer_t keyb;
10411 dst_key_t *dstkey = NULL;
10412 isc_stdtime_t now;
10413 int pending = 0;
10414 bool secure = false, initial = false;
10415 bool free_needed;
10416 dns_keynode_t *keynode = NULL;
10417 dns_rdataset_t *dnskeys = NULL, *dnskeysigs = NULL;
10418 dns_rdataset_t *keydataset = NULL, dsset;
10419
10420 UNUSED(task);
10421 INSIST(event != NULL && event->ev_type == DNS_EVENT_FETCHDONE);
10422 INSIST(event->ev_arg != NULL);
10423
10424 kfetch = event->ev_arg;
10425 zone = kfetch->zone;
10426 mctx = kfetch->mctx;
10427 keyname = dns_fixedname_name(&kfetch->name);
10428 dnskeys = &kfetch->dnskeyset;
10429 dnskeysigs = &kfetch->dnskeysigset;
10430 keydataset = &kfetch->keydataset;
10431
10432 devent = (dns_fetchevent_t *)event;
10433 eresult = devent->result;
10434
10435 /* Free resources which are not of interest */
10436 if (devent->node != NULL) {
10437 dns_db_detachnode(devent->db, &devent->node);
10438 }
10439 if (devent->db != NULL) {
10440 dns_db_detach(&devent->db);
10441 }
10442 isc_event_free(&event);
10443 dns_resolver_destroyfetch(&kfetch->fetch);
10444
10445 LOCK_ZONE(zone);
10446 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || zone->view == NULL) {
10447 goto cleanup;
10448 }
10449
10450 isc_stdtime_get(&now);
10451 dns_name_format(keyname, namebuf, sizeof(namebuf));
10452
10453 result = dns_view_getsecroots(zone->view, &secroots);
10454 INSIST(result == ISC_R_SUCCESS);
10455
10456 dns_diff_init(mctx, &diff);
10457
10458 CHECK(dns_db_newversion(kfetch->db, &ver));
10459
10460 zone->refreshkeycount--;
10461 alldone = (zone->refreshkeycount == 0);
10462
10463 if (alldone) {
10464 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
10465 }
10466
10467 dnssec_log(zone, ISC_LOG_DEBUG(3),
10468 "Returned from key fetch in keyfetch_done() for '%s': %s",
10469 namebuf, isc_result_totext(eresult));
10470
10471 /* Fetch failed */
10472 if (eresult != ISC_R_SUCCESS || !dns_rdataset_isassociated(dnskeys)) {
10473 dnssec_log(zone, ISC_LOG_WARNING,
10474 "Unable to fetch DNSKEY set '%s': %s", namebuf,
10475 isc_result_totext(eresult));
10476 CHECK(minimal_update(kfetch, ver, &diff));
10477 goto done;
10478 }
10479
10480 /* No RRSIGs found */
10481 if (!dns_rdataset_isassociated(dnskeysigs)) {
10482 dnssec_log(zone, ISC_LOG_WARNING,
10483 "No DNSKEY RRSIGs found for '%s': %s", namebuf,
10484 isc_result_totext(eresult));
10485 CHECK(minimal_update(kfetch, ver, &diff));
10486 goto done;
10487 }
10488
10489 /*
10490 * Clear any cached trust level, as we need to run validation
10491 * over again; trusted keys might have changed.
10492 */
10493 dnskeys->trust = dnskeysigs->trust = dns_trust_none;
10494
10495 /* Look up the trust anchor */
10496 result = dns_keytable_find(secroots, keyname, &keynode);
10497 if (result != ISC_R_SUCCESS) {
10498 goto anchors_done;
10499 }
10500
10501 /*
10502 * If the keynode has a DS trust anchor, use it for verification.
10503 */
10504 dns_rdataset_init(&dsset);
10505 if (dns_keynode_dsset(keynode, &dsset)) {
10506 for (result = dns_rdataset_first(dnskeysigs);
10507 result == ISC_R_SUCCESS;
10508 result = dns_rdataset_next(dnskeysigs))
10509 {
10510 isc_result_t tresult;
10511 dns_rdata_t keyrdata = DNS_RDATA_INIT;
10512
10513 dns_rdata_reset(&sigrr);
10514 dns_rdataset_current(dnskeysigs, &sigrr);
10515 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
10516 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10517
10518 for (tresult = dns_rdataset_first(&dsset);
10519 tresult == ISC_R_SUCCESS;
10520 tresult = dns_rdataset_next(&dsset))
10521 {
10522 dns_rdata_t dsrdata = DNS_RDATA_INIT;
10523 dns_rdata_ds_t ds;
10524
10525 dns_rdata_reset(&dsrdata);
10526 dns_rdataset_current(&dsset, &dsrdata);
10527 tresult = dns_rdata_tostruct(&dsrdata, &ds,
10528 NULL);
10529 RUNTIME_CHECK(tresult == ISC_R_SUCCESS);
10530
10531 if (ds.key_tag != sig.keyid ||
10532 ds.algorithm != sig.algorithm)
10533 {
10534 continue;
10535 }
10536
10537 result = dns_dnssec_matchdskey(
10538 keyname, &dsrdata, dnskeys, &keyrdata);
10539 if (result == ISC_R_SUCCESS) {
10540 break;
10541 }
10542 }
10543
10544 if (tresult == ISC_R_NOMORE) {
10545 continue;
10546 }
10547
10548 result = dns_dnssec_keyfromrdata(keyname, &keyrdata,
10549 mctx, &dstkey);
10550 if (result != ISC_R_SUCCESS) {
10551 continue;
10552 }
10553
10554 result = dns_dnssec_verify(keyname, dnskeys, dstkey,
10555 false, 0, mctx, &sigrr,
10556 NULL);
10557 dst_key_free(&dstkey);
10558
10559 dnssec_log(zone, ISC_LOG_DEBUG(3),
10560 "Verifying DNSKEY set for zone "
10561 "'%s' using DS %d/%d: %s",
10562 namebuf, sig.keyid, sig.algorithm,
10563 isc_result_totext(result));
10564
10565 if (result == ISC_R_SUCCESS) {
10566 dnskeys->trust = dns_trust_secure;
10567 dnskeysigs->trust = dns_trust_secure;
10568 initial = dns_keynode_initial(keynode);
10569 dns_keynode_trust(keynode);
10570 secure = true;
10571 break;
10572 }
10573 }
10574 dns_rdataset_disassociate(&dsset);
10575 }
10576
10577 anchors_done:
10578 if (keynode != NULL) {
10579 dns_keytable_detachkeynode(secroots, &keynode);
10580 }
10581
10582 /*
10583 * If we were not able to verify the answer using the current
10584 * trusted keys then all we can do is look at any revoked keys.
10585 */
10586 if (!secure) {
10587 dnssec_log(zone, ISC_LOG_INFO,
10588 "DNSKEY set for zone '%s' could not be verified "
10589 "with current keys",
10590 namebuf);
10591 }
10592
10593 /*
10594 * First scan keydataset to find keys that are not in dnskeyset
10595 * - Missing keys which are not scheduled for removal,
10596 * log a warning
10597 * - Missing keys which are scheduled for removal and
10598 * the remove hold-down timer has completed should
10599 * be removed from the key zone
10600 * - Missing keys whose acceptance timers have not yet
10601 * completed, log a warning and reset the acceptance
10602 * timer to 30 days in the future
10603 * - All keys not being removed have their refresh timers
10604 * updated
10605 */
10606 initializing = true;
10607 for (result = dns_rdataset_first(keydataset); result == ISC_R_SUCCESS;
10608 result = dns_rdataset_next(keydataset))
10609 {
10610 dns_keytag_t keytag;
10611
10612 dns_rdata_reset(&keydatarr);
10613 dns_rdataset_current(keydataset, &keydatarr);
10614 result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
10615 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10616
10617 dns_keydata_todnskey(&keydata, &dnskey, NULL);
10618 result = compute_tag(keyname, &dnskey, mctx, &keytag);
10619 if (result != ISC_R_SUCCESS) {
10620 /*
10621 * Skip if we cannot compute the key tag.
10622 * This may happen if the algorithm is unsupported
10623 */
10624 dns_zone_log(zone, ISC_LOG_ERROR,
10625 "Cannot compute tag for key in zone %s: "
10626 "%s "
10627 "(skipping)",
10628 namebuf, isc_result_totext(result));
10629 continue;
10630 }
10631 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10632
10633 /*
10634 * If any keydata record has a nonzero add holddown, then
10635 * there was a pre-existing trust anchor for this domain;
10636 * that means we are *not* initializing it and shouldn't
10637 * automatically trust all the keys we find at the zone apex.
10638 */
10639 initializing = initializing && (keydata.addhd == 0);
10640
10641 if (!matchkey(dnskeys, &keydatarr)) {
10642 bool deletekey = false;
10643
10644 if (!secure) {
10645 if (keydata.removehd != 0 &&
10646 keydata.removehd <= now)
10647 {
10648 deletekey = true;
10649 }
10650 } else if (keydata.addhd == 0) {
10651 deletekey = true;
10652 } else if (keydata.addhd > now) {
10653 dnssec_log(zone, ISC_LOG_INFO,
10654 "Pending key %d for zone %s "
10655 "unexpectedly missing from DNSKEY "
10656 "RRset: restarting 30-day "
10657 "acceptance timer",
10658 keytag, namebuf);
10659 if (keydata.addhd < now + dns_zone_mkey_month) {
10660 keydata.addhd = now +
10661 dns_zone_mkey_month;
10662 }
10663 keydata.refresh = refresh_time(kfetch, false);
10664 } else if (keydata.removehd == 0) {
10665 dnssec_log(zone, ISC_LOG_INFO,
10666 "Active key %d for zone %s "
10667 "unexpectedly missing from DNSKEY "
10668 "RRset",
10669 keytag, namebuf);
10670 keydata.refresh = now + dns_zone_mkey_hour;
10671 } else if (keydata.removehd <= now) {
10672 deletekey = true;
10673 dnssec_log(
10674 zone, ISC_LOG_INFO,
10675 "Revoked key %d for zone %s no longer "
10676 "present in DNSKEY RRset: deleting "
10677 "from managed keys database",
10678 keytag, namebuf);
10679 } else {
10680 keydata.refresh = refresh_time(kfetch, false);
10681 }
10682
10683 if (secure || deletekey) {
10684 /* Delete old version */
10685 CHECK(update_one_rr(kfetch->db, ver, &diff,
10686 DNS_DIFFOP_DEL, keyname, 0,
10687 &keydatarr));
10688 }
10689
10690 if (!secure || deletekey) {
10691 continue;
10692 }
10693
10694 dns_rdata_reset(&keydatarr);
10695 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10696 dns_rdata_fromstruct(&keydatarr, zone->rdclass,
10697 dns_rdatatype_keydata, &keydata,
10698 &keyb);
10699
10700 /* Insert updated version */
10701 CHECK(update_one_rr(kfetch->db, ver, &diff,
10702 DNS_DIFFOP_ADD, keyname, 0,
10703 &keydatarr));
10704
10705 set_refreshkeytimer(zone, &keydata, now, false);
10706 }
10707 }
10708
10709 /*
10710 * Next scan dnskeyset:
10711 * - If new keys are found (i.e., lacking a match in keydataset)
10712 * add them to the key zone and set the acceptance timer
10713 * to 30 days in the future (or to immediately if we've
10714 * determined that we're initializing the zone for the
10715 * first time)
10716 * - Previously-known keys that have been revoked
10717 * must be scheduled for removal from the key zone (or,
10718 * if they hadn't been accepted as trust anchors yet
10719 * anyway, removed at once)
10720 * - Previously-known unrevoked keys whose acceptance timers
10721 * have completed are promoted to trust anchors
10722 * - All keys not being removed have their refresh
10723 * timers updated
10724 */
10725 for (result = dns_rdataset_first(dnskeys); result == ISC_R_SUCCESS;
10726 result = dns_rdataset_next(dnskeys))
10727 {
10728 bool revoked = false;
10729 bool newkey = false;
10730 bool updatekey = false;
10731 bool deletekey = false;
10732 bool trustkey = false;
10733 dns_keytag_t keytag;
10734
10735 dns_rdata_reset(&dnskeyrr);
10736 dns_rdataset_current(dnskeys, &dnskeyrr);
10737 result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
10738 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10739
10740 /* Skip ZSK's */
10741 if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0) {
10742 continue;
10743 }
10744
10745 result = compute_tag(keyname, &dnskey, mctx, &keytag);
10746 if (result != ISC_R_SUCCESS) {
10747 /*
10748 * Skip if we cannot compute the key tag.
10749 * This may happen if the algorithm is unsupported
10750 */
10751 dns_zone_log(zone, ISC_LOG_ERROR,
10752 "Cannot compute tag for key in zone %s: "
10753 "%s "
10754 "(skipping)",
10755 namebuf, isc_result_totext(result));
10756 continue;
10757 }
10758 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10759
10760 revoked = ((dnskey.flags & DNS_KEYFLAG_REVOKE) != 0);
10761
10762 if (matchkey(keydataset, &dnskeyrr)) {
10763 dns_rdata_reset(&keydatarr);
10764 dns_rdataset_current(keydataset, &keydatarr);
10765 result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
10766 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10767
10768 if (revoked && revocable(kfetch, &keydata)) {
10769 if (keydata.addhd > now) {
10770 /*
10771 * Key wasn't trusted yet, and now
10772 * it's been revoked? Just remove it
10773 */
10774 deletekey = true;
10775 dnssec_log(zone, ISC_LOG_INFO,
10776 "Pending key %d for "
10777 "zone %s is now revoked: "
10778 "deleting from the "
10779 "managed keys database",
10780 keytag, namebuf);
10781 } else if (keydata.removehd == 0) {
10782 /*
10783 * Remove key from secroots.
10784 */
10785 dns_view_untrust(zone->view, keyname,
10786 &dnskey);
10787
10788 /* If initializing, delete now */
10789 if (keydata.addhd == 0) {
10790 deletekey = true;
10791 } else {
10792 keydata.removehd =
10793 now +
10794 dns_zone_mkey_month;
10795 keydata.flags |=
10796 DNS_KEYFLAG_REVOKE;
10797 }
10798
10799 dnssec_log(zone, ISC_LOG_INFO,
10800 "Trusted key %d for "
10801 "zone %s is now revoked",
10802 keytag, namebuf);
10803 } else if (keydata.removehd < now) {
10804 /* Scheduled for removal */
10805 deletekey = true;
10806
10807 dnssec_log(zone, ISC_LOG_INFO,
10808 "Revoked key %d for "
10809 "zone %s removal timer "
10810 "complete: deleting from "
10811 "the managed keys database",
10812 keytag, namebuf);
10813 }
10814 } else if (revoked && keydata.removehd == 0) {
10815 dnssec_log(zone, ISC_LOG_WARNING,
10816 "Active key %d for zone "
10817 "%s is revoked but "
10818 "did not self-sign; "
10819 "ignoring",
10820 keytag, namebuf);
10821 continue;
10822 } else if (secure) {
10823 if (keydata.removehd != 0) {
10824 /*
10825 * Key isn't revoked--but it
10826 * seems it used to be.
10827 * Remove it now and add it
10828 * back as if it were a fresh key,
10829 * with a 30-day acceptance timer.
10830 */
10831 deletekey = true;
10832 newkey = true;
10833 keydata.removehd = 0;
10834 keydata.addhd = now +
10835 dns_zone_mkey_month;
10836
10837 dnssec_log(zone, ISC_LOG_INFO,
10838 "Revoked key %d for "
10839 "zone %s has returned: "
10840 "starting 30-day "
10841 "acceptance timer",
10842 keytag, namebuf);
10843 } else if (keydata.addhd > now) {
10844 pending++;
10845 } else if (keydata.addhd == 0) {
10846 keydata.addhd = now;
10847 }
10848
10849 if (keydata.addhd <= now) {
10850 trustkey = true;
10851 dnssec_log(zone, ISC_LOG_INFO,
10852 "Key %d for zone %s "
10853 "is now trusted (%s)",
10854 keytag, namebuf,
10855 initial ? "initializing key "
10856 "verified"
10857 : "acceptance timer "
10858 "complete");
10859 }
10860 } else if (keydata.addhd > now) {
10861 /*
10862 * Not secure, and key is pending:
10863 * reset the acceptance timer
10864 */
10865 pending++;
10866 keydata.addhd = now + dns_zone_mkey_month;
10867 dnssec_log(zone, ISC_LOG_INFO,
10868 "Pending key %d "
10869 "for zone %s was "
10870 "not validated: restarting "
10871 "30-day acceptance timer",
10872 keytag, namebuf);
10873 }
10874
10875 if (!deletekey && !newkey) {
10876 updatekey = true;
10877 }
10878 } else if (secure) {
10879 /*
10880 * Key wasn't in the key zone but it's
10881 * revoked now anyway, so just skip it
10882 */
10883 if (revoked) {
10884 continue;
10885 }
10886
10887 /* Key wasn't in the key zone: add it */
10888 newkey = true;
10889
10890 if (initializing) {
10891 dnssec_log(zone, ISC_LOG_WARNING,
10892 "Initializing automatic trust "
10893 "anchor management for zone '%s'; "
10894 "DNSKEY ID %d is now trusted, "
10895 "waiving the normal 30-day "
10896 "waiting period.",
10897 namebuf, keytag);
10898 trustkey = true;
10899 } else {
10900 dnssec_log(zone, ISC_LOG_INFO,
10901 "New key %d observed "
10902 "for zone '%s': "
10903 "starting 30-day "
10904 "acceptance timer",
10905 keytag, namebuf);
10906 }
10907 } else {
10908 /*
10909 * No previously known key, and the key is not
10910 * secure, so skip it.
10911 */
10912 continue;
10913 }
10914
10915 /* Delete old version */
10916 if (deletekey || !newkey) {
10917 CHECK(update_one_rr(kfetch->db, ver, &diff,
10918 DNS_DIFFOP_DEL, keyname, 0,
10919 &keydatarr));
10920 }
10921
10922 if (updatekey) {
10923 /* Set refresh timer */
10924 keydata.refresh = refresh_time(kfetch, false);
10925 dns_rdata_reset(&keydatarr);
10926 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10927 dns_rdata_fromstruct(&keydatarr, zone->rdclass,
10928 dns_rdatatype_keydata, &keydata,
10929 &keyb);
10930
10931 /* Insert updated version */
10932 CHECK(update_one_rr(kfetch->db, ver, &diff,
10933 DNS_DIFFOP_ADD, keyname, 0,
10934 &keydatarr));
10935 } else if (newkey) {
10936 /* Convert DNSKEY to KEYDATA */
10937 result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
10938 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10939 dns_keydata_fromdnskey(&keydata, &dnskey, 0, 0, 0,
10940 NULL);
10941 keydata.addhd = initializing
10942 ? now
10943 : now + dns_zone_mkey_month;
10944 keydata.refresh = refresh_time(kfetch, false);
10945 dns_rdata_reset(&keydatarr);
10946 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10947 dns_rdata_fromstruct(&keydatarr, zone->rdclass,
10948 dns_rdatatype_keydata, &keydata,
10949 &keyb);
10950
10951 /* Insert into key zone */
10952 CHECK(update_one_rr(kfetch->db, ver, &diff,
10953 DNS_DIFFOP_ADD, keyname, 0,
10954 &keydatarr));
10955 }
10956
10957 if (trustkey) {
10958 /* Trust this key. */
10959 result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
10960 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10961 trust_key(zone, keyname, &dnskey, false);
10962 }
10963
10964 if (secure && !deletekey) {
10965 INSIST(newkey || updatekey);
10966 set_refreshkeytimer(zone, &keydata, now, false);
10967 }
10968 }
10969
10970 /*
10971 * RFC5011 says, "A trust point that has all of its trust anchors
10972 * revoked is considered deleted and is treated as if the trust
10973 * point was never configured." But if someone revoked their
10974 * active key before the standby was trusted, that would mean the
10975 * zone would suddenly be nonsecured. We avoid this by checking to
10976 * see if there's pending keydata. If so, we put a null key in
10977 * the security roots; then all queries to the zone will fail.
10978 */
10979 if (pending != 0) {
10980 fail_secure(zone, keyname);
10981 }
10982
10983 done:
10984 if (!ISC_LIST_EMPTY(diff.tuples)) {
10985 /* Write changes to journal file. */
10986 CHECK(update_soa_serial(zone, kfetch->db, ver, &diff, mctx,
10987 zone->updatemethod));
10988 CHECK(zone_journal(zone, &diff, NULL, "keyfetch_done"));
10989 commit = true;
10990
10991 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
10992 zone_needdump(zone, 30);
10993 } else if (result == ISC_R_NOMORE) {
10994 /*
10995 * If "updatekey" was true for all keys found in the DNSKEY
10996 * response and the previous update of those keys happened
10997 * during the same second (only possible if a key refresh was
10998 * externally triggered), it may happen that all relevant
10999 * update_one_rr() calls will return ISC_R_SUCCESS, but
11000 * diff.tuples will remain empty. Reset result to
11001 * ISC_R_SUCCESS to prevent a bogus warning from being logged.
11002 */
11003 result = ISC_R_SUCCESS;
11004 }
11005
11006 failure:
11007 if (result != ISC_R_SUCCESS) {
11008 dnssec_log(zone, ISC_LOG_ERROR,
11009 "error during managed-keys processing (%s): "
11010 "DNSSEC validation may be at risk",
11011 isc_result_totext(result));
11012 }
11013 dns_diff_clear(&diff);
11014 if (ver != NULL) {
11015 dns_db_closeversion(kfetch->db, &ver, commit);
11016 }
11017
11018 cleanup:
11019 dns_db_detach(&kfetch->db);
11020
11021 /* The zone must be managed */
11022 INSIST(kfetch->zone->task != NULL);
11023 isc_refcount_decrement(&zone->irefs);
11024
11025 if (dns_rdataset_isassociated(keydataset)) {
11026 dns_rdataset_disassociate(keydataset);
11027 }
11028 if (dns_rdataset_isassociated(dnskeys)) {
11029 dns_rdataset_disassociate(dnskeys);
11030 }
11031 if (dns_rdataset_isassociated(dnskeysigs)) {
11032 dns_rdataset_disassociate(dnskeysigs);
11033 }
11034
11035 dns_name_free(keyname, mctx);
11036 isc_mem_putanddetach(&kfetch->mctx, kfetch, sizeof(dns_keyfetch_t));
11037
11038 if (secroots != NULL) {
11039 dns_keytable_detach(&secroots);
11040 }
11041
11042 free_needed = exit_check(zone);
11043 UNLOCK_ZONE(zone);
11044
11045 if (free_needed) {
11046 zone_free(zone);
11047 }
11048
11049 INSIST(ver == NULL);
11050 }
11051
11052 static void
11053 retry_keyfetch(dns_keyfetch_t *kfetch, dns_name_t *kname) {
11054 isc_time_t timenow, timethen;
11055 dns_zone_t *zone = kfetch->zone;
11056 bool free_needed;
11057 char namebuf[DNS_NAME_FORMATSIZE];
11058
11059 dns_name_format(kname, namebuf, sizeof(namebuf));
11060 dnssec_log(zone, ISC_LOG_WARNING,
11061 "Failed to create fetch for %s DNSKEY update", namebuf);
11062
11063 /*
11064 * Error during a key fetch; cancel and retry in an hour.
11065 */
11066 LOCK_ZONE(zone);
11067 zone->refreshkeycount--;
11068 isc_refcount_decrement(&zone->irefs);
11069 dns_db_detach(&kfetch->db);
11070 dns_rdataset_disassociate(&kfetch->keydataset);
11071 dns_name_free(kname, zone->mctx);
11072 isc_mem_putanddetach(&kfetch->mctx, kfetch, sizeof(*kfetch));
11073
11074 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
11075 /* Don't really retry if we are exiting */
11076 char timebuf[80];
11077
11078 TIME_NOW(&timenow);
11079 DNS_ZONE_TIME_ADD(&timenow, dns_zone_mkey_hour, &timethen);
11080 zone->refreshkeytime = timethen;
11081 zone_settimer(zone, &timenow);
11082
11083 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
11084 dnssec_log(zone, ISC_LOG_DEBUG(1), "retry key refresh: %s",
11085 timebuf);
11086 }
11087
11088 free_needed = exit_check(zone);
11089 UNLOCK_ZONE(zone);
11090
11091 if (free_needed) {
11092 zone_free(zone);
11093 }
11094 }
11095
11096 static void
11097 do_keyfetch(isc_task_t *task, isc_event_t *event) {
11098 isc_result_t result;
11099 dns_keyfetch_t *kfetch = (dns_keyfetch_t *)event->ev_arg;
11100 dns_name_t *kname = dns_fixedname_name(&kfetch->name);
11101 dns_zone_t *zone = kfetch->zone;
11102
11103 UNUSED(task);
11104
11105 isc_event_free(&event);
11106
11107 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
11108 retry_keyfetch(kfetch, kname);
11109 return;
11110 }
11111
11112 /*
11113 * Use of DNS_FETCHOPT_NOCACHED is essential here. If it is not
11114 * set and the cache still holds a non-expired, validated version
11115 * of the RRset being queried for by the time the response is
11116 * received, the cached RRset will be passed to keyfetch_done()
11117 * instead of the one received in the response as the latter will
11118 * have a lower trust level due to not being validated until
11119 * keyfetch_done() is called.
11120 */
11121 result = dns_resolver_createfetch(
11122 zone->view->resolver, kname, dns_rdatatype_dnskey, NULL, NULL,
11123 NULL, NULL, 0,
11124 DNS_FETCHOPT_NOVALIDATE | DNS_FETCHOPT_UNSHARED |
11125 DNS_FETCHOPT_NOCACHED,
11126 0, NULL, zone->task, keyfetch_done, kfetch, &kfetch->dnskeyset,
11127 &kfetch->dnskeysigset, &kfetch->fetch);
11128
11129 if (result != ISC_R_SUCCESS) {
11130 retry_keyfetch(kfetch, kname);
11131 }
11132 }
11133
11134 /*
11135 * Refresh the data in the key zone. Initiate a fetch to look up
11136 * DNSKEY records at the trust anchor name.
11137 */
11138 static void
11139 zone_refreshkeys(dns_zone_t *zone) {
11140 const char me[] = "zone_refreshkeys";
11141 isc_result_t result;
11142 dns_rriterator_t rrit;
11143 dns_db_t *db = NULL;
11144 dns_dbversion_t *ver = NULL;
11145 dns_diff_t diff;
11146 dns_rdata_t rdata = DNS_RDATA_INIT;
11147 dns_rdata_keydata_t kd;
11148 isc_stdtime_t now;
11149 bool commit = false;
11150 bool fetching = false;
11151 bool timerset = false;
11152
11153 ENTER;
11154 REQUIRE(zone->db != NULL);
11155
11156 isc_stdtime_get(&now);
11157
11158 LOCK_ZONE(zone);
11159 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
11160 isc_time_settoepoch(&zone->refreshkeytime);
11161 UNLOCK_ZONE(zone);
11162 return;
11163 }
11164
11165 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11166 dns_db_attach(zone->db, &db);
11167 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11168
11169 dns_diff_init(zone->mctx, &diff);
11170
11171 CHECK(dns_db_newversion(db, &ver));
11172
11173 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESHING);
11174
11175 dns_rriterator_init(&rrit, db, ver, 0);
11176 for (result = dns_rriterator_first(&rrit); result == ISC_R_SUCCESS;
11177 result = dns_rriterator_nextrrset(&rrit))
11178 {
11179 isc_stdtime_t timer = 0xffffffff;
11180 dns_name_t *name = NULL, *kname = NULL;
11181 dns_rdataset_t *kdset = NULL;
11182 uint32_t ttl;
11183
11184 dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL);
11185 if (kdset == NULL || kdset->type != dns_rdatatype_keydata ||
11186 !dns_rdataset_isassociated(kdset))
11187 {
11188 continue;
11189 }
11190
11191 /*
11192 * Scan the stored keys looking for ones that need
11193 * removal or refreshing
11194 */
11195 for (result = dns_rdataset_first(kdset);
11196 result == ISC_R_SUCCESS; result = dns_rdataset_next(kdset))
11197 {
11198 dns_rdata_reset(&rdata);
11199 dns_rdataset_current(kdset, &rdata);
11200 result = dns_rdata_tostruct(&rdata, &kd, NULL);
11201 RUNTIME_CHECK(result == ISC_R_SUCCESS);
11202
11203 /* Removal timer expired? */
11204 if (kd.removehd != 0 && kd.removehd < now) {
11205 dns_rriterator_pause(&rrit);
11206 CHECK(update_one_rr(db, ver, &diff,
11207 DNS_DIFFOP_DEL, name, ttl,
11208 &rdata));
11209 continue;
11210 }
11211
11212 /* Acceptance timer expired? */
11213 if (kd.addhd <= now) {
11214 timer = kd.addhd;
11215 }
11216
11217 /* Or do we just need to refresh the keyset? */
11218 if (timer > kd.refresh) {
11219 timer = kd.refresh;
11220 }
11221
11222 dns_rriterator_pause(&rrit);
11223 set_refreshkeytimer(zone, &kd, now, false);
11224 timerset = true;
11225 }
11226
11227 if (timer > now) {
11228 continue;
11229 }
11230
11231 dns_rriterator_pause(&rrit);
11232
11233 #ifdef ENABLE_AFL
11234 if (!dns_fuzzing_resolver) {
11235 #endif /* ifdef ENABLE_AFL */
11236 dns_keyfetch_t *kfetch = NULL;
11237 isc_event_t *e;
11238
11239 kfetch = isc_mem_get(zone->mctx,
11240 sizeof(dns_keyfetch_t));
11241 *kfetch = (dns_keyfetch_t){ .zone = zone };
11242 isc_mem_attach(zone->mctx, &kfetch->mctx);
11243
11244 zone->refreshkeycount++;
11245 isc_refcount_increment0(&zone->irefs);
11246 kname = dns_fixedname_initname(&kfetch->name);
11247 dns_name_dup(name, zone->mctx, kname);
11248 dns_rdataset_init(&kfetch->dnskeyset);
11249 dns_rdataset_init(&kfetch->dnskeysigset);
11250 dns_rdataset_init(&kfetch->keydataset);
11251 dns_rdataset_clone(kdset, &kfetch->keydataset);
11252 dns_db_attach(db, &kfetch->db);
11253
11254 if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
11255 char namebuf[DNS_NAME_FORMATSIZE];
11256 dns_name_format(kname, namebuf,
11257 sizeof(namebuf));
11258 dnssec_log(zone, ISC_LOG_DEBUG(3),
11259 "Creating key fetch in "
11260 "zone_refreshkeys() for '%s'",
11261 namebuf);
11262 }
11263
11264 e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE,
11265 do_keyfetch, kfetch,
11266 sizeof(isc_event_t));
11267 isc_task_send(zone->task, &e);
11268 fetching = true;
11269 #ifdef ENABLE_AFL
11270 }
11271 #endif /* ifdef ENABLE_AFL */
11272 }
11273 if (!ISC_LIST_EMPTY(diff.tuples)) {
11274 CHECK(update_soa_serial(zone, db, ver, &diff, zone->mctx,
11275 zone->updatemethod));
11276 CHECK(zone_journal(zone, &diff, NULL, "zone_refreshkeys"));
11277 commit = true;
11278 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
11279 zone_needdump(zone, 30);
11280 }
11281
11282 failure:
11283 if (!timerset) {
11284 isc_time_settoepoch(&zone->refreshkeytime);
11285 }
11286
11287 if (!fetching) {
11288 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
11289 }
11290
11291 dns_diff_clear(&diff);
11292 if (ver != NULL) {
11293 dns_rriterator_destroy(&rrit);
11294 dns_db_closeversion(db, &ver, commit);
11295 }
11296 dns_db_detach(&db);
11297
11298 UNLOCK_ZONE(zone);
11299
11300 INSIST(ver == NULL);
11301 }
11302
11303 static void
11304 zone_maintenance(dns_zone_t *zone) {
11305 const char me[] = "zone_maintenance";
11306 isc_time_t now;
11307 isc_result_t result;
11308 bool load_pending, exiting, dumping, viewok, notify;
11309 bool refreshkeys, sign, resign, rekey, chain, warn_expire;
11310
11311 REQUIRE(DNS_ZONE_VALID(zone));
11312 ENTER;
11313
11314 /*
11315 * Are we pending load/reload, exiting, or unconfigured
11316 * (e.g. because of a syntax failure in the config file)?
11317 * If so, don't attempt maintenance.
11318 */
11319 LOCK_ZONE(zone);
11320 load_pending = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING);
11321 exiting = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING);
11322 viewok = (zone->view != NULL && zone->view->adb != NULL);
11323 UNLOCK_ZONE(zone);
11324
11325 if (load_pending || exiting || !viewok) {
11326 return;
11327 }
11328
11329 TIME_NOW(&now);
11330
11331 /*
11332 * Expire check.
11333 */
11334 switch (zone->type) {
11335 case dns_zone_redirect:
11336 if (zone->primaries == NULL) {
11337 break;
11338 }
11339 FALLTHROUGH;
11340 case dns_zone_secondary:
11341 case dns_zone_mirror:
11342 case dns_zone_stub:
11343 LOCK_ZONE(zone);
11344 if (isc_time_compare(&now, &zone->expiretime) >= 0 &&
11345 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
11346 {
11347 zone_expire(zone);
11348 zone->refreshtime = now;
11349 }
11350 UNLOCK_ZONE(zone);
11351 break;
11352 default:
11353 break;
11354 }
11355
11356 /*
11357 * Up to date check.
11358 */
11359 switch (zone->type) {
11360 case dns_zone_redirect:
11361 if (zone->primaries == NULL) {
11362 break;
11363 }
11364 FALLTHROUGH;
11365 case dns_zone_secondary:
11366 case dns_zone_mirror:
11367 case dns_zone_stub:
11368 LOCK_ZONE(zone);
11369 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
11370 isc_time_compare(&now, &zone->refreshtime) >= 0)
11371 {
11372 zone_refresh(zone);
11373 }
11374 UNLOCK_ZONE(zone);
11375 break;
11376 default:
11377 break;
11378 }
11379
11380 /*
11381 * Secondaries send notifies before backing up to disk,
11382 * primaries after.
11383 */
11384 LOCK_ZONE(zone);
11385 notify = (zone->type == dns_zone_secondary ||
11386 zone->type == dns_zone_mirror) &&
11387 (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
11388 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY)) &&
11389 isc_time_compare(&now, &zone->notifytime) >= 0;
11390 UNLOCK_ZONE(zone);
11391
11392 if (notify) {
11393 zone_notify(zone, &now);
11394 }
11395
11396 /*
11397 * Do we need to consolidate the backing store?
11398 */
11399 switch (zone->type) {
11400 case dns_zone_primary:
11401 case dns_zone_secondary:
11402 case dns_zone_mirror:
11403 case dns_zone_key:
11404 case dns_zone_redirect:
11405 case dns_zone_stub:
11406 LOCK_ZONE(zone);
11407 if (zone->masterfile != NULL &&
11408 isc_time_compare(&now, &zone->dumptime) >= 0 &&
11409 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
11410 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP))
11411 {
11412 dumping = was_dumping(zone);
11413 } else {
11414 dumping = true;
11415 }
11416 UNLOCK_ZONE(zone);
11417 if (!dumping) {
11418 result = zone_dump(zone, true); /* task locked */
11419 if (result != ISC_R_SUCCESS) {
11420 dns_zone_log(zone, ISC_LOG_WARNING,
11421 "dump failed: %s",
11422 isc_result_totext(result));
11423 }
11424 }
11425 break;
11426 default:
11427 break;
11428 }
11429
11430 /*
11431 * Primary/redirect zones send notifies now, if needed
11432 */
11433 switch (zone->type) {
11434 case dns_zone_primary:
11435 case dns_zone_redirect:
11436 LOCK_ZONE(zone);
11437 notify = (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
11438 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY)) &&
11439 isc_time_compare(&now, &zone->notifytime) >= 0;
11440 UNLOCK_ZONE(zone);
11441 if (notify) {
11442 zone_notify(zone, &now);
11443 }
11444 default:
11445 break;
11446 }
11447
11448 /*
11449 * Do we need to refresh keys?
11450 */
11451 switch (zone->type) {
11452 case dns_zone_key:
11453 LOCK_ZONE(zone);
11454 refreshkeys = isc_time_compare(&now, &zone->refreshkeytime) >=
11455 0 &&
11456 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
11457 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING);
11458 UNLOCK_ZONE(zone);
11459 if (refreshkeys) {
11460 zone_refreshkeys(zone);
11461 }
11462 break;
11463 case dns_zone_primary:
11464 LOCK_ZONE(zone);
11465 rekey = (!isc_time_isepoch(&zone->refreshkeytime) &&
11466 isc_time_compare(&now, &zone->refreshkeytime) >= 0 &&
11467 zone->rss_event == NULL);
11468 UNLOCK_ZONE(zone);
11469 if (rekey) {
11470 zone_rekey(zone);
11471 }
11472 default:
11473 break;
11474 }
11475
11476 switch (zone->type) {
11477 case dns_zone_primary:
11478 case dns_zone_redirect:
11479 case dns_zone_secondary:
11480 /*
11481 * Do we need to sign/resign some RRsets?
11482 */
11483 LOCK_ZONE(zone);
11484 if (zone->rss_event != NULL) {
11485 UNLOCK_ZONE(zone);
11486 break;
11487 }
11488 sign = !isc_time_isepoch(&zone->signingtime) &&
11489 isc_time_compare(&now, &zone->signingtime) >= 0;
11490 resign = !isc_time_isepoch(&zone->resigntime) &&
11491 isc_time_compare(&now, &zone->resigntime) >= 0;
11492 chain = !isc_time_isepoch(&zone->nsec3chaintime) &&
11493 isc_time_compare(&now, &zone->nsec3chaintime) >= 0;
11494 warn_expire = !isc_time_isepoch(&zone->keywarntime) &&
11495 isc_time_compare(&now, &zone->keywarntime) >= 0;
11496 UNLOCK_ZONE(zone);
11497
11498 if (sign) {
11499 zone_sign(zone);
11500 } else if (resign) {
11501 zone_resigninc(zone);
11502 } else if (chain) {
11503 zone_nsec3chain(zone);
11504 }
11505
11506 /*
11507 * Do we need to issue a key expiry warning?
11508 */
11509 if (warn_expire) {
11510 set_key_expiry_warning(zone, zone->key_expiry,
11511 isc_time_seconds(&now));
11512 }
11513 break;
11514
11515 default:
11516 break;
11517 }
11518 LOCK_ZONE(zone);
11519 zone_settimer(zone, &now);
11520 UNLOCK_ZONE(zone);
11521 }
11522
11523 void
11524 dns_zone_markdirty(dns_zone_t *zone) {
11525 uint32_t serial;
11526 isc_result_t result = ISC_R_SUCCESS;
11527 dns_zone_t *secure = NULL;
11528
11529 /*
11530 * Obtaining a lock on the zone->secure (see zone_send_secureserial)
11531 * could result in a deadlock due to a LOR so we will spin if we
11532 * can't obtain the both locks.
11533 */
11534 again:
11535 LOCK_ZONE(zone);
11536 if (zone->type == dns_zone_primary) {
11537 if (inline_raw(zone)) {
11538 unsigned int soacount;
11539 secure = zone->secure;
11540 INSIST(secure != zone);
11541 TRYLOCK_ZONE(result, secure);
11542 if (result != ISC_R_SUCCESS) {
11543 UNLOCK_ZONE(zone);
11544 secure = NULL;
11545 isc_thread_yield();
11546 goto again;
11547 }
11548
11549 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11550 if (zone->db != NULL) {
11551 result = zone_get_from_db(
11552 zone, zone->db, NULL, &soacount, NULL,
11553 &serial, NULL, NULL, NULL, NULL, NULL);
11554 } else {
11555 result = DNS_R_NOTLOADED;
11556 }
11557 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11558 if (result == ISC_R_SUCCESS && soacount > 0U) {
11559 zone_send_secureserial(zone, serial);
11560 }
11561 }
11562
11563 /* XXXMPA make separate call back */
11564 if (result == ISC_R_SUCCESS) {
11565 set_resigntime(zone);
11566 if (zone->task != NULL) {
11567 isc_time_t now;
11568 TIME_NOW(&now);
11569 zone_settimer(zone, &now);
11570 }
11571 }
11572 }
11573 if (secure != NULL) {
11574 UNLOCK_ZONE(secure);
11575 }
11576 zone_needdump(zone, DNS_DUMP_DELAY);
11577 UNLOCK_ZONE(zone);
11578 }
11579
11580 void
11581 dns_zone_expire(dns_zone_t *zone) {
11582 REQUIRE(DNS_ZONE_VALID(zone));
11583
11584 LOCK_ZONE(zone);
11585 zone_expire(zone);
11586 UNLOCK_ZONE(zone);
11587 }
11588
11589 static void
11590 zone_expire(dns_zone_t *zone) {
11591 dns_db_t *db = NULL;
11592
11593 /*
11594 * 'zone' locked by caller.
11595 */
11596
11597 REQUIRE(LOCKED_ZONE(zone));
11598
11599 dns_zone_log(zone, ISC_LOG_WARNING, "expired");
11600
11601 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXPIRED);
11602 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
11603 zone->retry = DNS_ZONE_DEFAULTRETRY;
11604 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
11605
11606 /*
11607 * An RPZ zone has expired; before unloading it, we must
11608 * first remove it from the RPZ summary database. The
11609 * easiest way to do this is "update" it with an empty
11610 * database so that the update callback synchronizes
11611 * the diff automatically.
11612 */
11613 if (zone->rpzs != NULL && zone->rpz_num != DNS_RPZ_INVALID_NUM) {
11614 isc_result_t result;
11615 dns_rpz_zone_t *rpz = zone->rpzs->zones[zone->rpz_num];
11616
11617 CHECK(dns_db_create(zone->mctx, "rbt", &zone->origin,
11618 dns_dbtype_zone, zone->rdclass, 0, NULL,
11619 &db));
11620 CHECK(dns_rpz_dbupdate_callback(db, rpz));
11621 dns_zone_log(zone, ISC_LOG_WARNING,
11622 "response-policy zone expired; "
11623 "policies unloaded");
11624 }
11625
11626 failure:
11627 if (db != NULL) {
11628 dns_db_detach(&db);
11629 }
11630
11631 zone_unload(zone);
11632 }
11633
11634 static void
11635 zone_refresh(dns_zone_t *zone) {
11636 isc_interval_t i;
11637 uint32_t oldflags;
11638 unsigned int j;
11639 isc_result_t result;
11640
11641 REQUIRE(DNS_ZONE_VALID(zone));
11642 REQUIRE(LOCKED_ZONE(zone));
11643
11644 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
11645 return;
11646 }
11647
11648 /*
11649 * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation
11650 * in progress at a time.
11651 */
11652
11653 oldflags = atomic_load(&zone->flags);
11654 if (zone->primariescnt == 0) {
11655 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOPRIMARIES);
11656 if ((oldflags & DNS_ZONEFLG_NOPRIMARIES) == 0) {
11657 dns_zone_log(zone, ISC_LOG_ERROR,
11658 "cannot refresh: no primaries");
11659 }
11660 return;
11661 }
11662 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
11663 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
11664 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
11665 if ((oldflags & (DNS_ZONEFLG_REFRESH | DNS_ZONEFLG_LOADING)) != 0) {
11666 return;
11667 }
11668
11669 /*
11670 * Set the next refresh time as if refresh check has failed.
11671 * Setting this to the retry time will do that. XXXMLG
11672 * If we are successful it will be reset using zone->refresh.
11673 */
11674 isc_interval_set(&i, zone->retry - isc_random_uniform(zone->retry / 4),
11675 0);
11676 result = isc_time_nowplusinterval(&zone->refreshtime, &i);
11677 if (result != ISC_R_SUCCESS) {
11678 dns_zone_log(zone, ISC_LOG_WARNING,
11679 "isc_time_nowplusinterval() failed: %s",
11680 isc_result_totext(result));
11681 }
11682
11683 /*
11684 * When lacking user-specified timer values from the SOA,
11685 * do exponential backoff of the retry time up to a
11686 * maximum of six hours.
11687 */
11688 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS)) {
11689 zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
11690 }
11691
11692 zone->curprimary = 0;
11693 for (j = 0; j < zone->primariescnt; j++) {
11694 zone->primariesok[j] = false;
11695 }
11696 /* initiate soa query */
11697 queue_soa_query(zone);
11698 }
11699
11700 void
11701 dns_zone_refresh(dns_zone_t *zone) {
11702 LOCK_ZONE(zone);
11703 zone_refresh(zone);
11704 UNLOCK_ZONE(zone);
11705 }
11706
11707 static isc_result_t
11708 zone_journal_rollforward(dns_zone_t *zone, dns_db_t *db, bool *needdump,
11709 bool *fixjournal) {
11710 dns_journal_t *journal = NULL;
11711 unsigned int options;
11712 isc_result_t result;
11713
11714 if (zone->type == dns_zone_primary &&
11715 (inline_secure(zone) ||
11716 (zone->update_acl != NULL || zone->ssutable != NULL)))
11717 {
11718 options = DNS_JOURNALOPT_RESIGN;
11719 } else {
11720 options = 0;
11721 }
11722
11723 result = dns_journal_open(zone->mctx, zone->journal, DNS_JOURNAL_READ,
11724 &journal);
11725 if (result == ISC_R_NOTFOUND) {
11726 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(3),
11727 "no journal file, but that's OK ");
11728 return (ISC_R_SUCCESS);
11729 } else if (result != ISC_R_SUCCESS) {
11730 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
11731 "journal open failed: %s",
11732 isc_result_totext(result));
11733 return (result);
11734 }
11735
11736 if (dns_journal_empty(journal)) {
11737 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
11738 "journal empty");
11739 dns_journal_destroy(&journal);
11740 return (ISC_R_SUCCESS);
11741 }
11742
11743 result = dns_journal_rollforward(journal, db, options);
11744 switch (result) {
11745 case ISC_R_SUCCESS:
11746 *needdump = true;
11747 FALLTHROUGH;
11748 case DNS_R_UPTODATE:
11749 if (dns_journal_recovered(journal)) {
11750 *fixjournal = true;
11751 dns_zone_logc(
11752 zone, DNS_LOGCATEGORY_ZONELOAD,
11753 ISC_LOG_DEBUG(1),
11754 "journal rollforward completed successfully "
11755 "using old journal format: %s",
11756 isc_result_totext(result));
11757 } else {
11758 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
11759 ISC_LOG_DEBUG(1),
11760 "journal rollforward completed "
11761 "successfully: %s",
11762 isc_result_totext(result));
11763 }
11764
11765 dns_journal_destroy(&journal);
11766 return (ISC_R_SUCCESS);
11767 case ISC_R_NOTFOUND:
11768 case ISC_R_RANGE:
11769 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
11770 "journal rollforward failed: journal out of sync "
11771 "with zone");
11772 dns_journal_destroy(&journal);
11773 return (result);
11774 default:
11775 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
11776 "journal rollforward failed: %s",
11777 isc_result_totext(result));
11778 dns_journal_destroy(&journal);
11779 return (result);
11780 }
11781 }
11782
11783 static void
11784 zone_journal_compact(dns_zone_t *zone, dns_db_t *db, uint32_t serial) {
11785 isc_result_t result;
11786 int32_t journalsize;
11787 dns_dbversion_t *ver = NULL;
11788 uint64_t dbsize;
11789 uint32_t options = 0;
11790
11791 INSIST(LOCKED_ZONE(zone));
11792 if (inline_raw(zone)) {
11793 INSIST(LOCKED_ZONE(zone->secure));
11794 }
11795
11796 journalsize = zone->journalsize;
11797 if (journalsize == -1) {
11798 journalsize = DNS_JOURNAL_SIZE_MAX;
11799 dns_db_currentversion(db, &ver);
11800 result = dns_db_getsize(db, ver, NULL, &dbsize);
11801 dns_db_closeversion(db, &ver, false);
11802 if (result != ISC_R_SUCCESS) {
11803 dns_zone_log(zone, ISC_LOG_ERROR,
11804 "zone_journal_compact: "
11805 "could not get zone size: %s",
11806 isc_result_totext(result));
11807 } else if (dbsize < DNS_JOURNAL_SIZE_MAX / 2) {
11808 journalsize = (int32_t)dbsize * 2;
11809 }
11810 }
11811 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FIXJOURNAL)) {
11812 options |= DNS_JOURNAL_COMPACTALL;
11813 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FIXJOURNAL);
11814 zone_debuglog(zone, "zone_journal_compact", 1,
11815 "repair full journal");
11816 } else {
11817 zone_debuglog(zone, "zone_journal_compact", 1,
11818 "target journal size %d", journalsize);
11819 }
11820 result = dns_journal_compact(zone->mctx, zone->journal, serial, options,
11821 journalsize);
11822 switch (result) {
11823 case ISC_R_SUCCESS:
11824 case ISC_R_NOSPACE:
11825 case ISC_R_NOTFOUND:
11826 dns_zone_log(zone, ISC_LOG_DEBUG(3), "dns_journal_compact: %s",
11827 isc_result_totext(result));
11828 break;
11829 default:
11830 dns_zone_log(zone, ISC_LOG_ERROR,
11831 "dns_journal_compact failed: %s",
11832 isc_result_totext(result));
11833 break;
11834 }
11835 }
11836
11837 isc_result_t
11838 dns_zone_flush(dns_zone_t *zone) {
11839 isc_result_t result = ISC_R_SUCCESS;
11840 bool dumping;
11841
11842 REQUIRE(DNS_ZONE_VALID(zone));
11843
11844 LOCK_ZONE(zone);
11845 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FLUSH);
11846 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
11847 zone->masterfile != NULL)
11848 {
11849 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
11850 result = ISC_R_ALREADYRUNNING;
11851 dumping = was_dumping(zone);
11852 } else {
11853 dumping = true;
11854 }
11855 UNLOCK_ZONE(zone);
11856 if (!dumping) {
11857 result = zone_dump(zone, true); /* Unknown task. */
11858 }
11859 return (result);
11860 }
11861
11862 isc_result_t
11863 dns_zone_dump(dns_zone_t *zone) {
11864 isc_result_t result = ISC_R_ALREADYRUNNING;
11865 bool dumping;
11866
11867 REQUIRE(DNS_ZONE_VALID(zone));
11868
11869 LOCK_ZONE(zone);
11870 dumping = was_dumping(zone);
11871 UNLOCK_ZONE(zone);
11872 if (!dumping) {
11873 result = zone_dump(zone, false); /* Unknown task. */
11874 }
11875 return (result);
11876 }
11877
11878 static void
11879 zone_needdump(dns_zone_t *zone, unsigned int delay) {
11880 const char me[] = "zone_needdump";
11881 isc_time_t dumptime;
11882 isc_time_t now;
11883
11884 /*
11885 * 'zone' locked by caller
11886 */
11887
11888 REQUIRE(DNS_ZONE_VALID(zone));
11889 REQUIRE(LOCKED_ZONE(zone));
11890 ENTER;
11891
11892 /*
11893 * Do we have a place to dump to and are we loaded?
11894 */
11895 if (zone->masterfile == NULL ||
11896 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
11897 {
11898 return;
11899 }
11900
11901 TIME_NOW(&now);
11902 /* add some noise */
11903 DNS_ZONE_JITTER_ADD(&now, delay, &dumptime);
11904
11905 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
11906 if (isc_time_isepoch(&zone->dumptime) ||
11907 isc_time_compare(&zone->dumptime, &dumptime) > 0)
11908 {
11909 zone->dumptime = dumptime;
11910 }
11911 if (zone->task != NULL) {
11912 zone_settimer(zone, &now);
11913 }
11914 }
11915
11916 static void
11917 dump_done(void *arg, isc_result_t result) {
11918 const char me[] = "dump_done";
11919 dns_zone_t *zone = arg;
11920 dns_zone_t *secure = NULL;
11921 dns_db_t *db;
11922 dns_dbversion_t *version;
11923 bool again = false;
11924 bool compact = false;
11925 uint32_t serial;
11926 isc_result_t tresult;
11927
11928 REQUIRE(DNS_ZONE_VALID(zone));
11929
11930 ENTER;
11931
11932 if (result == ISC_R_SUCCESS && zone->journal != NULL) {
11933 /*
11934 * We don't own these, zone->dctx must stay valid.
11935 */
11936 db = dns_dumpctx_db(zone->dctx);
11937 version = dns_dumpctx_version(zone->dctx);
11938 tresult = dns_db_getsoaserial(db, version, &serial);
11939
11940 /*
11941 * Handle lock order inversion.
11942 */
11943 again:
11944 LOCK_ZONE(zone);
11945 if (inline_raw(zone)) {
11946 secure = zone->secure;
11947 INSIST(secure != zone);
11948 TRYLOCK_ZONE(result, secure);
11949 if (result != ISC_R_SUCCESS) {
11950 UNLOCK_ZONE(zone);
11951 secure = NULL;
11952 isc_thread_yield();
11953 goto again;
11954 }
11955 }
11956
11957 /*
11958 * If there is a secure version of this zone
11959 * use its serial if it is less than ours.
11960 */
11961 if (tresult == ISC_R_SUCCESS && secure != NULL) {
11962 uint32_t sserial;
11963 isc_result_t mresult;
11964
11965 ZONEDB_LOCK(&secure->dblock, isc_rwlocktype_read);
11966 if (secure->db != NULL) {
11967 mresult = dns_db_getsoaserial(zone->secure->db,
11968 NULL, &sserial);
11969 if (mresult == ISC_R_SUCCESS &&
11970 isc_serial_lt(sserial, serial))
11971 {
11972 serial = sserial;
11973 }
11974 }
11975 ZONEDB_UNLOCK(&secure->dblock, isc_rwlocktype_read);
11976 }
11977 if (tresult == ISC_R_SUCCESS && zone->xfr == NULL) {
11978 dns_db_t *zdb = NULL;
11979 if (dns_zone_getdb(zone, &zdb) == ISC_R_SUCCESS) {
11980 zone_journal_compact(zone, zdb, serial);
11981 dns_db_detach(&zdb);
11982 }
11983 } else if (tresult == ISC_R_SUCCESS) {
11984 compact = true;
11985 zone->compact_serial = serial;
11986 }
11987 if (secure != NULL) {
11988 UNLOCK_ZONE(secure);
11989 }
11990 UNLOCK_ZONE(zone);
11991 }
11992
11993 LOCK_ZONE(zone);
11994 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
11995 if (compact) {
11996 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
11997 }
11998 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN)) {
11999 /*
12000 * If DNS_ZONEFLG_SHUTDOWN is set, all external references to
12001 * the zone are gone, which means it is in the process of being
12002 * cleaned up, so do not reschedule dumping.
12003 *
12004 * Detach from the raw version of the zone in case this
12005 * operation has been deferred in zone_shutdown().
12006 */
12007 if (zone->raw != NULL) {
12008 dns_zone_detach(&zone->raw);
12009 }
12010 if (result == ISC_R_SUCCESS) {
12011 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
12012 }
12013 } else if (result != ISC_R_SUCCESS && result != ISC_R_CANCELED) {
12014 /*
12015 * Try again in a short while.
12016 */
12017 zone_needdump(zone, DNS_DUMP_DELAY);
12018 } else if (result == ISC_R_SUCCESS &&
12019 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
12020 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
12021 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
12022 {
12023 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
12024 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
12025 isc_time_settoepoch(&zone->dumptime);
12026 again = true;
12027 } else if (result == ISC_R_SUCCESS) {
12028 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
12029 }
12030
12031 if (zone->dctx != NULL) {
12032 dns_dumpctx_detach(&zone->dctx);
12033 }
12034 zonemgr_putio(&zone->writeio);
12035 UNLOCK_ZONE(zone);
12036 if (again) {
12037 (void)zone_dump(zone, false);
12038 }
12039 dns_zone_idetach(&zone);
12040 }
12041
12042 static isc_result_t
12043 zone_dump(dns_zone_t *zone, bool compact) {
12044 const char me[] = "zone_dump";
12045 isc_result_t result;
12046 dns_dbversion_t *version = NULL;
12047 bool again;
12048 dns_db_t *db = NULL;
12049 char *masterfile = NULL;
12050 dns_masterformat_t masterformat = dns_masterformat_none;
12051
12052 /*
12053 * 'compact' MUST only be set if we are task locked.
12054 */
12055
12056 REQUIRE(DNS_ZONE_VALID(zone));
12057 ENTER;
12058
12059 redo:
12060 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
12061 if (zone->db != NULL) {
12062 dns_db_attach(zone->db, &db);
12063 }
12064 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12065 LOCK_ZONE(zone);
12066 if (zone->masterfile != NULL) {
12067 masterfile = isc_mem_strdup(zone->mctx, zone->masterfile);
12068 masterformat = zone->masterformat;
12069 }
12070 UNLOCK_ZONE(zone);
12071 if (db == NULL) {
12072 result = DNS_R_NOTLOADED;
12073 goto fail;
12074 }
12075 if (masterfile == NULL) {
12076 result = DNS_R_NOMASTERFILE;
12077 goto fail;
12078 }
12079
12080 if (compact && zone->type != dns_zone_stub) {
12081 dns_zone_t *dummy = NULL;
12082 LOCK_ZONE(zone);
12083 zone_iattach(zone, &dummy);
12084 result = zonemgr_getio(zone->zmgr, false, zone->task,
12085 zone_gotwritehandle, zone,
12086 &zone->writeio);
12087 if (result != ISC_R_SUCCESS) {
12088 zone_idetach(&dummy);
12089 } else {
12090 result = DNS_R_CONTINUE;
12091 }
12092 UNLOCK_ZONE(zone);
12093 } else {
12094 const dns_master_style_t *output_style;
12095
12096 dns_masterrawheader_t rawdata;
12097 dns_db_currentversion(db, &version);
12098 dns_master_initrawheader(&rawdata);
12099 if (inline_secure(zone)) {
12100 get_raw_serial(zone->raw, &rawdata);
12101 }
12102 if (zone->type == dns_zone_key) {
12103 output_style = &dns_master_style_keyzone;
12104 } else {
12105 output_style = &dns_master_style_default;
12106 }
12107 result = dns_master_dump(zone->mctx, db, version, output_style,
12108 masterfile, masterformat, &rawdata);
12109 dns_db_closeversion(db, &version, false);
12110 }
12111 fail:
12112 if (db != NULL) {
12113 dns_db_detach(&db);
12114 }
12115 if (masterfile != NULL) {
12116 isc_mem_free(zone->mctx, masterfile);
12117 }
12118 masterfile = NULL;
12119
12120 if (result == DNS_R_CONTINUE) {
12121 return (ISC_R_SUCCESS); /* XXXMPA */
12122 }
12123
12124 again = false;
12125 LOCK_ZONE(zone);
12126 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
12127 if (result != ISC_R_SUCCESS) {
12128 /*
12129 * Try again in a short while.
12130 */
12131 zone_needdump(zone, DNS_DUMP_DELAY);
12132 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
12133 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
12134 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
12135 {
12136 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
12137 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
12138 isc_time_settoepoch(&zone->dumptime);
12139 again = true;
12140 } else {
12141 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
12142 }
12143 UNLOCK_ZONE(zone);
12144 if (again) {
12145 goto redo;
12146 }
12147
12148 return (result);
12149 }
12150
12151 static isc_result_t
12152 dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style,
12153 dns_masterformat_t format, const uint32_t rawversion) {
12154 isc_result_t result;
12155 dns_dbversion_t *version = NULL;
12156 dns_db_t *db = NULL;
12157 dns_masterrawheader_t rawdata;
12158
12159 REQUIRE(DNS_ZONE_VALID(zone));
12160
12161 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
12162 if (zone->db != NULL) {
12163 dns_db_attach(zone->db, &db);
12164 }
12165 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12166 if (db == NULL) {
12167 return (DNS_R_NOTLOADED);
12168 }
12169
12170 dns_db_currentversion(db, &version);
12171 dns_master_initrawheader(&rawdata);
12172 if (rawversion == 0) {
12173 rawdata.flags |= DNS_MASTERRAW_COMPAT;
12174 } else if (inline_secure(zone)) {
12175 get_raw_serial(zone->raw, &rawdata);
12176 } else if (zone->sourceserialset) {
12177 rawdata.flags = DNS_MASTERRAW_SOURCESERIALSET;
12178 rawdata.sourceserial = zone->sourceserial;
12179 }
12180 result = dns_master_dumptostream(zone->mctx, db, version, style, format,
12181 &rawdata, fd);
12182 dns_db_closeversion(db, &version, false);
12183 dns_db_detach(&db);
12184 return (result);
12185 }
12186
12187 isc_result_t
12188 dns_zone_dumptostream(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
12189 const dns_master_style_t *style,
12190 const uint32_t rawversion) {
12191 return (dumptostream(zone, fd, style, format, rawversion));
12192 }
12193
12194 void
12195 dns_zone_unload(dns_zone_t *zone) {
12196 REQUIRE(DNS_ZONE_VALID(zone));
12197
12198 LOCK_ZONE(zone);
12199 zone_unload(zone);
12200 UNLOCK_ZONE(zone);
12201 }
12202
12203 static void
12204 notify_cancel(dns_zone_t *zone) {
12205 dns_notify_t *notify;
12206
12207 /*
12208 * 'zone' locked by caller.
12209 */
12210
12211 REQUIRE(LOCKED_ZONE(zone));
12212
12213 for (notify = ISC_LIST_HEAD(zone->notifies); notify != NULL;
12214 notify = ISC_LIST_NEXT(notify, link))
12215 {
12216 if (notify->find != NULL) {
12217 dns_adb_cancelfind(notify->find);
12218 }
12219 if (notify->request != NULL) {
12220 dns_request_cancel(notify->request);
12221 }
12222 }
12223 }
12224
12225 static void
12226 checkds_cancel(dns_zone_t *zone) {
12227 dns_checkds_t *checkds;
12228
12229 /*
12230 * 'zone' locked by caller.
12231 */
12232
12233 REQUIRE(LOCKED_ZONE(zone));
12234
12235 for (checkds = ISC_LIST_HEAD(zone->checkds_requests); checkds != NULL;
12236 checkds = ISC_LIST_NEXT(checkds, link))
12237 {
12238 if (checkds->request != NULL) {
12239 dns_request_cancel(checkds->request);
12240 }
12241 }
12242 }
12243
12244 static void
12245 forward_cancel(dns_zone_t *zone) {
12246 dns_forward_t *forward;
12247
12248 /*
12249 * 'zone' locked by caller.
12250 */
12251
12252 REQUIRE(LOCKED_ZONE(zone));
12253
12254 for (forward = ISC_LIST_HEAD(zone->forwards); forward != NULL;
12255 forward = ISC_LIST_NEXT(forward, link))
12256 {
12257 if (forward->request != NULL) {
12258 dns_request_cancel(forward->request);
12259 }
12260 }
12261 }
12262
12263 static void
12264 zone_unload(dns_zone_t *zone) {
12265 /*
12266 * 'zone' locked by caller.
12267 */
12268
12269 REQUIRE(LOCKED_ZONE(zone));
12270
12271 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
12272 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
12273 {
12274 if (zone->writeio != NULL) {
12275 zonemgr_cancelio(zone->writeio);
12276 }
12277
12278 if (zone->dctx != NULL) {
12279 dns_dumpctx_cancel(zone->dctx);
12280 }
12281 }
12282 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
12283 zone_detachdb(zone);
12284 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
12285 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
12286 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
12287
12288 if (zone->type == dns_zone_mirror) {
12289 dns_zone_log(zone, ISC_LOG_INFO,
12290 "mirror zone is no longer in use; "
12291 "reverting to normal recursion");
12292 }
12293 }
12294
12295 void
12296 dns_zone_setminrefreshtime(dns_zone_t *zone, uint32_t val) {
12297 REQUIRE(DNS_ZONE_VALID(zone));
12298 REQUIRE(val > 0);
12299
12300 zone->minrefresh = val;
12301 }
12302
12303 void
12304 dns_zone_setmaxrefreshtime(dns_zone_t *zone, uint32_t val) {
12305 REQUIRE(DNS_ZONE_VALID(zone));
12306 REQUIRE(val > 0);
12307
12308 zone->maxrefresh = val;
12309 }
12310
12311 void
12312 dns_zone_setminretrytime(dns_zone_t *zone, uint32_t val) {
12313 REQUIRE(DNS_ZONE_VALID(zone));
12314 REQUIRE(val > 0);
12315
12316 zone->minretry = val;
12317 }
12318
12319 void
12320 dns_zone_setmaxretrytime(dns_zone_t *zone, uint32_t val) {
12321 REQUIRE(DNS_ZONE_VALID(zone));
12322 REQUIRE(val > 0);
12323
12324 zone->maxretry = val;
12325 }
12326
12327 uint32_t
12328 dns_zone_getmaxrecords(dns_zone_t *zone) {
12329 REQUIRE(DNS_ZONE_VALID(zone));
12330
12331 return (zone->maxrecords);
12332 }
12333
12334 void
12335 dns_zone_setmaxrecords(dns_zone_t *zone, uint32_t val) {
12336 REQUIRE(DNS_ZONE_VALID(zone));
12337
12338 zone->maxrecords = val;
12339 }
12340
12341 static bool
12342 notify_isqueued(dns_zone_t *zone, unsigned int flags, dns_name_t *name,
12343 isc_sockaddr_t *addr, dns_tsigkey_t *key,
12344 dns_transport_t *transport) {
12345 dns_notify_t *notify;
12346 dns_zonemgr_t *zmgr;
12347 isc_result_t result;
12348
12349 for (notify = ISC_LIST_HEAD(zone->notifies); notify != NULL;
12350 notify = ISC_LIST_NEXT(notify, link))
12351 {
12352 if (notify->request != NULL) {
12353 continue;
12354 }
12355 if (name != NULL && dns_name_dynamic(¬ify->ns) &&
12356 dns_name_equal(name, ¬ify->ns))
12357 {
12358 goto requeue;
12359 }
12360 if (addr != NULL && isc_sockaddr_equal(addr, ¬ify->dst) &&
12361 notify->key == key && notify->transport == transport)
12362 {
12363 goto requeue;
12364 }
12365 }
12366 return (false);
12367
12368 requeue:
12369 /*
12370 * If we are enqueued on the startup ratelimiter and this is
12371 * not a startup notify, re-enqueue on the normal notify
12372 * ratelimiter.
12373 */
12374 if (notify->event != NULL && (flags & DNS_NOTIFY_STARTUP) == 0 &&
12375 (notify->flags & DNS_NOTIFY_STARTUP) != 0)
12376 {
12377 zmgr = notify->zone->zmgr;
12378 result = isc_ratelimiter_dequeue(zmgr->startupnotifyrl,
12379 notify->event);
12380 if (result != ISC_R_SUCCESS) {
12381 return (true);
12382 }
12383
12384 notify->flags &= ~DNS_NOTIFY_STARTUP;
12385 result = isc_ratelimiter_enqueue(notify->zone->zmgr->notifyrl,
12386 notify->zone->task,
12387 ¬ify->event);
12388 if (result != ISC_R_SUCCESS) {
12389 isc_event_free(¬ify->event);
12390 return (false);
12391 }
12392 }
12393
12394 return (true);
12395 }
12396
12397 static bool
12398 notify_isself(dns_zone_t *zone, isc_sockaddr_t *dst) {
12399 dns_tsigkey_t *key = NULL;
12400 isc_sockaddr_t src;
12401 isc_sockaddr_t any;
12402 bool isself;
12403 isc_netaddr_t dstaddr;
12404 isc_result_t result;
12405
12406 if (zone->view == NULL || zone->isself == NULL) {
12407 return (false);
12408 }
12409
12410 switch (isc_sockaddr_pf(dst)) {
12411 case PF_INET:
12412 src = zone->notifysrc4;
12413 isc_sockaddr_any(&any);
12414 break;
12415 case PF_INET6:
12416 src = zone->notifysrc6;
12417 isc_sockaddr_any6(&any);
12418 break;
12419 default:
12420 return (false);
12421 }
12422
12423 /*
12424 * When sending from any the kernel will assign a source address
12425 * that matches the destination address.
12426 */
12427 if (isc_sockaddr_eqaddr(&any, &src)) {
12428 src = *dst;
12429 }
12430
12431 isc_netaddr_fromsockaddr(&dstaddr, dst);
12432 result = dns_view_getpeertsig(zone->view, &dstaddr, &key);
12433 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
12434 return (false);
12435 }
12436 isself = (zone->isself)(zone->view, key, &src, dst, zone->rdclass,
12437 zone->isselfarg);
12438 if (key != NULL) {
12439 dns_tsigkey_detach(&key);
12440 }
12441 return (isself);
12442 }
12443
12444 static void
12445 notify_destroy(dns_notify_t *notify, bool locked) {
12446 isc_mem_t *mctx;
12447
12448 REQUIRE(DNS_NOTIFY_VALID(notify));
12449
12450 if (notify->zone != NULL) {
12451 if (!locked) {
12452 LOCK_ZONE(notify->zone);
12453 }
12454 REQUIRE(LOCKED_ZONE(notify->zone));
12455 if (ISC_LINK_LINKED(notify, link)) {
12456 ISC_LIST_UNLINK(notify->zone->notifies, notify, link);
12457 }
12458 if (!locked) {
12459 UNLOCK_ZONE(notify->zone);
12460 }
12461 if (locked) {
12462 zone_idetach(¬ify->zone);
12463 } else {
12464 dns_zone_idetach(¬ify->zone);
12465 }
12466 }
12467 if (notify->find != NULL) {
12468 dns_adb_destroyfind(¬ify->find);
12469 }
12470 if (notify->request != NULL) {
12471 dns_request_destroy(¬ify->request);
12472 }
12473 if (dns_name_dynamic(¬ify->ns)) {
12474 dns_name_free(¬ify->ns, notify->mctx);
12475 }
12476 if (notify->key != NULL) {
12477 dns_tsigkey_detach(¬ify->key);
12478 }
12479 if (notify->transport != NULL) {
12480 dns_transport_detach(¬ify->transport);
12481 }
12482 mctx = notify->mctx;
12483 isc_mem_put(notify->mctx, notify, sizeof(*notify));
12484 isc_mem_detach(&mctx);
12485 }
12486
12487 static isc_result_t
12488 notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
12489 dns_notify_t *notify;
12490
12491 REQUIRE(notifyp != NULL && *notifyp == NULL);
12492
12493 notify = isc_mem_get(mctx, sizeof(*notify));
12494 *notify = (dns_notify_t){
12495 .flags = flags,
12496 };
12497
12498 isc_mem_attach(mctx, ¬ify->mctx);
12499 isc_sockaddr_any(¬ify->dst);
12500 dns_name_init(¬ify->ns, NULL);
12501 ISC_LINK_INIT(notify, link);
12502 notify->magic = NOTIFY_MAGIC;
12503 *notifyp = notify;
12504 return (ISC_R_SUCCESS);
12505 }
12506
12507 /*
12508 * XXXAG should check for DNS_ZONEFLG_EXITING
12509 */
12510 static void
12511 process_adb_event(isc_task_t *task, isc_event_t *ev) {
12512 dns_notify_t *notify;
12513 isc_eventtype_t result;
12514
12515 UNUSED(task);
12516
12517 notify = ev->ev_arg;
12518 REQUIRE(DNS_NOTIFY_VALID(notify));
12519 INSIST(task == notify->zone->task);
12520 result = ev->ev_type;
12521 isc_event_free(&ev);
12522 if (result == DNS_EVENT_ADBMOREADDRESSES) {
12523 dns_adb_destroyfind(¬ify->find);
12524 notify_find_address(notify);
12525 return;
12526 }
12527 if (result == DNS_EVENT_ADBNOMOREADDRESSES) {
12528 LOCK_ZONE(notify->zone);
12529 notify_send(notify);
12530 UNLOCK_ZONE(notify->zone);
12531 }
12532 notify_destroy(notify, false);
12533 }
12534
12535 static void
12536 notify_find_address(dns_notify_t *notify) {
12537 isc_result_t result;
12538 unsigned int options;
12539
12540 REQUIRE(DNS_NOTIFY_VALID(notify));
12541 options = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_INET | DNS_ADBFIND_INET6 |
12542 DNS_ADBFIND_RETURNLAME;
12543
12544 if (notify->zone->view->adb == NULL) {
12545 goto destroy;
12546 }
12547
12548 result = dns_adb_createfind(
12549 notify->zone->view->adb, notify->zone->task, process_adb_event,
12550 notify, ¬ify->ns, dns_rootname, 0, options, 0, NULL,
12551 notify->zone->view->dstport, 0, NULL, ¬ify->find);
12552
12553 /* Something failed? */
12554 if (result != ISC_R_SUCCESS) {
12555 goto destroy;
12556 }
12557
12558 /* More addresses pending? */
12559 if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0) {
12560 return;
12561 }
12562
12563 /* We have as many addresses as we can get. */
12564 LOCK_ZONE(notify->zone);
12565 notify_send(notify);
12566 UNLOCK_ZONE(notify->zone);
12567
12568 destroy:
12569 notify_destroy(notify, false);
12570 }
12571
12572 static isc_result_t
12573 notify_send_queue(dns_notify_t *notify, bool startup) {
12574 isc_event_t *e;
12575 isc_result_t result;
12576
12577 INSIST(notify->event == NULL);
12578 e = isc_event_allocate(notify->mctx, NULL, DNS_EVENT_NOTIFYSENDTOADDR,
12579 notify_send_toaddr, notify, sizeof(isc_event_t));
12580 if (startup) {
12581 notify->event = e;
12582 }
12583 e->ev_arg = notify;
12584 e->ev_sender = NULL;
12585 result = isc_ratelimiter_enqueue(
12586 startup ? notify->zone->zmgr->startupnotifyrl
12587 : notify->zone->zmgr->notifyrl,
12588 notify->zone->task, &e);
12589 if (result != ISC_R_SUCCESS) {
12590 isc_event_free(&e);
12591 notify->event = NULL;
12592 }
12593 return (result);
12594 }
12595
12596 static void
12597 notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
12598 dns_notify_t *notify;
12599 isc_result_t result;
12600 dns_message_t *message = NULL;
12601 isc_netaddr_t dstip;
12602 dns_tsigkey_t *key = NULL;
12603 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
12604 isc_sockaddr_t src;
12605 unsigned int options, timeout;
12606 bool have_notifysource = false;
12607
12608 notify = event->ev_arg;
12609 REQUIRE(DNS_NOTIFY_VALID(notify));
12610
12611 UNUSED(task);
12612
12613 LOCK_ZONE(notify->zone);
12614
12615 notify->event = NULL;
12616
12617 if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0) {
12618 result = ISC_R_CANCELED;
12619 goto cleanup;
12620 }
12621
12622 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
12623 DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) ||
12624 notify->zone->view->requestmgr == NULL || notify->zone->db == NULL)
12625 {
12626 result = ISC_R_CANCELED;
12627 goto cleanup;
12628 }
12629
12630 /*
12631 * The raw IPv4 address should also exist. Don't send to the
12632 * mapped form.
12633 */
12634 if (isc_sockaddr_pf(¬ify->dst) == PF_INET6 &&
12635 IN6_IS_ADDR_V4MAPPED(¬ify->dst.type.sin6.sin6_addr))
12636 {
12637 isc_sockaddr_format(¬ify->dst, addrbuf, sizeof(addrbuf));
12638 notify_log(notify->zone, ISC_LOG_DEBUG(3),
12639 "notify: ignoring IPv6 mapped IPV4 address: %s",
12640 addrbuf);
12641 result = ISC_R_CANCELED;
12642 goto cleanup;
12643 }
12644
12645 result = notify_createmessage(notify->zone, notify->flags, &message);
12646 if (result != ISC_R_SUCCESS) {
12647 goto cleanup;
12648 }
12649
12650 isc_sockaddr_format(¬ify->dst, addrbuf, sizeof(addrbuf));
12651 if (notify->key != NULL) {
12652 /* Transfer ownership of key */
12653 key = notify->key;
12654 notify->key = NULL;
12655 } else {
12656 isc_netaddr_fromsockaddr(&dstip, ¬ify->dst);
12657 result = dns_view_getpeertsig(notify->zone->view, &dstip, &key);
12658 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
12659 notify_log(notify->zone, ISC_LOG_ERROR,
12660 "NOTIFY to %s not sent. "
12661 "Peer TSIG key lookup failure.",
12662 addrbuf);
12663 goto cleanup_message;
12664 }
12665 }
12666
12667 if (key != NULL) {
12668 char namebuf[DNS_NAME_FORMATSIZE];
12669
12670 dns_name_format(&key->name, namebuf, sizeof(namebuf));
12671 notify_log(notify->zone, ISC_LOG_DEBUG(3),
12672 "sending notify to %s : TSIG (%s)", addrbuf,
12673 namebuf);
12674 } else {
12675 notify_log(notify->zone, ISC_LOG_DEBUG(3),
12676 "sending notify to %s", addrbuf);
12677 }
12678 options = 0;
12679 if (notify->zone->view->peers != NULL) {
12680 dns_peer_t *peer = NULL;
12681 bool usetcp = false;
12682 result = dns_peerlist_peerbyaddr(notify->zone->view->peers,
12683 &dstip, &peer);
12684 if (result == ISC_R_SUCCESS) {
12685 result = dns_peer_getnotifysource(peer, &src);
12686 if (result == ISC_R_SUCCESS) {
12687 have_notifysource = true;
12688 }
12689 result = dns_peer_getforcetcp(peer, &usetcp);
12690 if (result == ISC_R_SUCCESS && usetcp) {
12691 options |= DNS_FETCHOPT_TCP;
12692 }
12693 }
12694 }
12695 switch (isc_sockaddr_pf(¬ify->dst)) {
12696 case PF_INET:
12697 if (!have_notifysource) {
12698 src = notify->zone->notifysrc4;
12699 }
12700 break;
12701 case PF_INET6:
12702 if (!have_notifysource) {
12703 src = notify->zone->notifysrc6;
12704 }
12705 break;
12706 default:
12707 result = ISC_R_NOTIMPLEMENTED;
12708 goto cleanup_key;
12709 }
12710 timeout = 5;
12711 if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY)) {
12712 timeout = 30;
12713 }
12714 result = dns_request_create(
12715 notify->zone->view->requestmgr, message, &src, ¬ify->dst,
12716 options, key, timeout * 3 + 1, timeout, 2, notify->zone->task,
12717 notify_done, notify, ¬ify->request);
12718 if (result == ISC_R_SUCCESS) {
12719 if (isc_sockaddr_pf(¬ify->dst) == AF_INET) {
12720 inc_stats(notify->zone,
12721 dns_zonestatscounter_notifyoutv4);
12722 } else {
12723 inc_stats(notify->zone,
12724 dns_zonestatscounter_notifyoutv6);
12725 }
12726 }
12727
12728 cleanup_key:
12729 if (key != NULL) {
12730 dns_tsigkey_detach(&key);
12731 }
12732 cleanup_message:
12733 dns_message_detach(&message);
12734 cleanup:
12735 UNLOCK_ZONE(notify->zone);
12736 isc_event_free(&event);
12737 if (result != ISC_R_SUCCESS) {
12738 notify_destroy(notify, false);
12739 }
12740 }
12741
12742 static void
12743 notify_send(dns_notify_t *notify) {
12744 dns_adbaddrinfo_t *ai;
12745 isc_sockaddr_t dst;
12746 isc_result_t result;
12747 dns_notify_t *newnotify = NULL;
12748 unsigned int flags;
12749 bool startup;
12750
12751 /*
12752 * Zone lock held by caller.
12753 */
12754 REQUIRE(DNS_NOTIFY_VALID(notify));
12755 REQUIRE(LOCKED_ZONE(notify->zone));
12756
12757 if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING)) {
12758 return;
12759 }
12760
12761 for (ai = ISC_LIST_HEAD(notify->find->list); ai != NULL;
12762 ai = ISC_LIST_NEXT(ai, publink))
12763 {
12764 dst = ai->sockaddr;
12765 if (notify_isqueued(notify->zone, notify->flags, NULL, &dst,
12766 NULL, NULL))
12767 {
12768 continue;
12769 }
12770 if (notify_isself(notify->zone, &dst)) {
12771 continue;
12772 }
12773 newnotify = NULL;
12774 flags = notify->flags & DNS_NOTIFY_NOSOA;
12775 result = notify_create(notify->mctx, flags, &newnotify);
12776 if (result != ISC_R_SUCCESS) {
12777 goto cleanup;
12778 }
12779 zone_iattach(notify->zone, &newnotify->zone);
12780 ISC_LIST_APPEND(newnotify->zone->notifies, newnotify, link);
12781 newnotify->dst = dst;
12782 startup = ((notify->flags & DNS_NOTIFY_STARTUP) != 0);
12783 result = notify_send_queue(newnotify, startup);
12784 if (result != ISC_R_SUCCESS) {
12785 goto cleanup;
12786 }
12787 newnotify = NULL;
12788 }
12789
12790 cleanup:
12791 if (newnotify != NULL) {
12792 notify_destroy(newnotify, true);
12793 }
12794 }
12795
12796 void
12797 dns_zone_notify(dns_zone_t *zone) {
12798 isc_time_t now;
12799
12800 REQUIRE(DNS_ZONE_VALID(zone));
12801
12802 LOCK_ZONE(zone);
12803 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
12804
12805 TIME_NOW(&now);
12806 zone_settimer(zone, &now);
12807 UNLOCK_ZONE(zone);
12808 }
12809
12810 static void
12811 zone_notify(dns_zone_t *zone, isc_time_t *now) {
12812 dns_dbnode_t *node = NULL;
12813 dns_db_t *zonedb = NULL;
12814 dns_dbversion_t *version = NULL;
12815 dns_name_t *origin = NULL;
12816 dns_name_t primary;
12817 dns_rdata_ns_t ns;
12818 dns_rdata_soa_t soa;
12819 uint32_t serial;
12820 dns_rdata_t rdata = DNS_RDATA_INIT;
12821 dns_rdataset_t nsrdset;
12822 dns_rdataset_t soardset;
12823 isc_result_t result;
12824 unsigned int i;
12825 isc_sockaddr_t dst;
12826 bool isqueued;
12827 dns_notifytype_t notifytype;
12828 unsigned int flags = 0;
12829 bool loggednotify = false;
12830 bool startup;
12831
12832 REQUIRE(DNS_ZONE_VALID(zone));
12833
12834 LOCK_ZONE(zone);
12835 startup = !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
12836 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
12837 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY);
12838 notifytype = zone->notifytype;
12839 DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime);
12840 UNLOCK_ZONE(zone);
12841
12842 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
12843 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
12844 {
12845 return;
12846 }
12847
12848 if (notifytype == dns_notifytype_no) {
12849 return;
12850 }
12851
12852 if (notifytype == dns_notifytype_masteronly &&
12853 zone->type != dns_zone_primary)
12854 {
12855 return;
12856 }
12857
12858 origin = &zone->origin;
12859
12860 /*
12861 * If the zone is dialup we are done as we don't want to send
12862 * the current soa so as to force a refresh query.
12863 */
12864 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY)) {
12865 flags |= DNS_NOTIFY_NOSOA;
12866 }
12867
12868 /*
12869 * Record that this was a notify due to starting up.
12870 */
12871 if (startup) {
12872 flags |= DNS_NOTIFY_STARTUP;
12873 }
12874
12875 /*
12876 * Get SOA RRset.
12877 */
12878 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
12879 if (zone->db != NULL) {
12880 dns_db_attach(zone->db, &zonedb);
12881 }
12882 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12883 if (zonedb == NULL) {
12884 return;
12885 }
12886 dns_db_currentversion(zonedb, &version);
12887 result = dns_db_findnode(zonedb, origin, false, &node);
12888 if (result != ISC_R_SUCCESS) {
12889 goto cleanup1;
12890 }
12891
12892 dns_rdataset_init(&soardset);
12893 result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
12894 dns_rdatatype_none, 0, &soardset, NULL);
12895 if (result != ISC_R_SUCCESS) {
12896 goto cleanup2;
12897 }
12898
12899 /*
12900 * Find serial and primary server's name.
12901 */
12902 dns_name_init(&primary, NULL);
12903 result = dns_rdataset_first(&soardset);
12904 if (result != ISC_R_SUCCESS) {
12905 goto cleanup3;
12906 }
12907 dns_rdataset_current(&soardset, &rdata);
12908 result = dns_rdata_tostruct(&rdata, &soa, NULL);
12909 RUNTIME_CHECK(result == ISC_R_SUCCESS);
12910 dns_rdata_reset(&rdata);
12911 dns_name_dup(&soa.origin, zone->mctx, &primary);
12912 serial = soa.serial;
12913 dns_rdataset_disassociate(&soardset);
12914
12915 /*
12916 * Enqueue notify requests for 'also-notify' servers.
12917 */
12918 LOCK_ZONE(zone);
12919 for (i = 0; i < zone->notifycnt; i++) {
12920 dns_tsigkey_t *key = NULL;
12921 dns_transport_t *transport = NULL;
12922 dns_notify_t *notify = NULL;
12923 dns_view_t *view = dns_zone_getview(zone);
12924
12925 if ((zone->notifykeynames != NULL) &&
12926 (zone->notifykeynames[i] != NULL))
12927 {
12928 dns_name_t *keyname = zone->notifykeynames[i];
12929 (void)dns_view_gettsig(view, keyname, &key);
12930 }
12931
12932 if ((zone->notifytlsnames != NULL) &&
12933 (zone->notifytlsnames[i] != NULL))
12934 {
12935 dns_name_t *tlsname = zone->notifytlsnames[i];
12936 (void)dns_view_gettransport(view, DNS_TRANSPORT_TLS,
12937 tlsname, &transport);
12938
12939 dns_zone_logc(
12940 zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
12941 "got TLS configuration for zone transfer");
12942 }
12943
12944 /* TODO: glue the transport to the notify */
12945
12946 dst = zone->notify[i];
12947 if (notify_isqueued(zone, flags, NULL, &dst, key, transport)) {
12948 if (key != NULL) {
12949 dns_tsigkey_detach(&key);
12950 }
12951 if (transport != NULL) {
12952 dns_transport_detach(&transport);
12953 }
12954 continue;
12955 }
12956
12957 result = notify_create(zone->mctx, flags, ¬ify);
12958 if (result != ISC_R_SUCCESS) {
12959 if (key != NULL) {
12960 dns_tsigkey_detach(&key);
12961 }
12962 if (transport != NULL) {
12963 dns_transport_detach(&transport);
12964 }
12965 continue;
12966 }
12967
12968 zone_iattach(zone, ¬ify->zone);
12969 notify->dst = dst;
12970
12971 INSIST(notify->key == NULL);
12972
12973 if (key != NULL) {
12974 notify->key = key;
12975 key = NULL;
12976 }
12977
12978 INSIST(notify->transport == NULL);
12979 if (transport != NULL) {
12980 notify->transport = transport;
12981 transport = NULL;
12982 }
12983
12984 ISC_LIST_APPEND(zone->notifies, notify, link);
12985 result = notify_send_queue(notify, startup);
12986 if (result != ISC_R_SUCCESS) {
12987 notify_destroy(notify, true);
12988 }
12989 if (!loggednotify) {
12990 notify_log(zone, ISC_LOG_INFO,
12991 "sending notifies (serial %u)", serial);
12992 loggednotify = true;
12993 }
12994 }
12995 UNLOCK_ZONE(zone);
12996
12997 if (notifytype == dns_notifytype_explicit) {
12998 goto cleanup3;
12999 }
13000
13001 /*
13002 * Process NS RRset to generate notifies.
13003 */
13004
13005 dns_rdataset_init(&nsrdset);
13006 result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_ns,
13007 dns_rdatatype_none, 0, &nsrdset, NULL);
13008 if (result != ISC_R_SUCCESS) {
13009 goto cleanup3;
13010 }
13011
13012 result = dns_rdataset_first(&nsrdset);
13013 while (result == ISC_R_SUCCESS) {
13014 dns_notify_t *notify = NULL;
13015
13016 dns_rdataset_current(&nsrdset, &rdata);
13017 result = dns_rdata_tostruct(&rdata, &ns, NULL);
13018 RUNTIME_CHECK(result == ISC_R_SUCCESS);
13019 dns_rdata_reset(&rdata);
13020 /*
13021 * Don't notify the primary server unless explicitly
13022 * configured to do so.
13023 */
13024 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOTIFYTOSOA) &&
13025 dns_name_compare(&primary, &ns.name) == 0)
13026 {
13027 result = dns_rdataset_next(&nsrdset);
13028 continue;
13029 }
13030
13031 if (!loggednotify) {
13032 notify_log(zone, ISC_LOG_INFO,
13033 "sending notifies (serial %u)", serial);
13034 loggednotify = true;
13035 }
13036
13037 LOCK_ZONE(zone);
13038 isqueued = notify_isqueued(zone, flags, &ns.name, NULL, NULL,
13039 NULL);
13040 UNLOCK_ZONE(zone);
13041 if (isqueued) {
13042 result = dns_rdataset_next(&nsrdset);
13043 continue;
13044 }
13045 result = notify_create(zone->mctx, flags, ¬ify);
13046 if (result != ISC_R_SUCCESS) {
13047 continue;
13048 }
13049 dns_zone_iattach(zone, ¬ify->zone);
13050 dns_name_dup(&ns.name, zone->mctx, ¬ify->ns);
13051 LOCK_ZONE(zone);
13052 ISC_LIST_APPEND(zone->notifies, notify, link);
13053 UNLOCK_ZONE(zone);
13054 notify_find_address(notify);
13055 result = dns_rdataset_next(&nsrdset);
13056 }
13057 dns_rdataset_disassociate(&nsrdset);
13058
13059 cleanup3:
13060 if (dns_name_dynamic(&primary)) {
13061 dns_name_free(&primary, zone->mctx);
13062 }
13063 cleanup2:
13064 dns_db_detachnode(zonedb, &node);
13065 cleanup1:
13066 dns_db_closeversion(zonedb, &version, false);
13067 dns_db_detach(&zonedb);
13068 }
13069
13070 /***
13071 *** Private
13072 ***/
13073 static isc_result_t
13074 create_query(dns_zone_t *zone, dns_rdatatype_t rdtype, dns_name_t *name,
13075 dns_message_t **messagep) {
13076 dns_message_t *message = NULL;
13077 dns_name_t *qname = NULL;
13078 dns_rdataset_t *qrdataset = NULL;
13079 isc_result_t result;
13080
13081 dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER, &message);
13082
13083 message->opcode = dns_opcode_query;
13084 message->rdclass = zone->rdclass;
13085
13086 result = dns_message_gettempname(message, &qname);
13087 if (result != ISC_R_SUCCESS) {
13088 goto cleanup;
13089 }
13090
13091 result = dns_message_gettemprdataset(message, &qrdataset);
13092 if (result != ISC_R_SUCCESS) {
13093 goto cleanup;
13094 }
13095
13096 /*
13097 * Make question.
13098 */
13099 dns_name_clone(name, qname);
13100 dns_rdataset_makequestion(qrdataset, zone->rdclass, rdtype);
13101 ISC_LIST_APPEND(qname->list, qrdataset, link);
13102 dns_message_addname(message, qname, DNS_SECTION_QUESTION);
13103
13104 *messagep = message;
13105 return (ISC_R_SUCCESS);
13106
13107 cleanup:
13108 if (qname != NULL) {
13109 dns_message_puttempname(message, &qname);
13110 }
13111 if (qrdataset != NULL) {
13112 dns_message_puttemprdataset(message, &qrdataset);
13113 }
13114 dns_message_detach(&message);
13115 return (result);
13116 }
13117
13118 static isc_result_t
13119 add_opt(dns_message_t *message, uint16_t udpsize, bool reqnsid,
13120 bool reqexpire) {
13121 isc_result_t result;
13122 dns_rdataset_t *rdataset = NULL;
13123 dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS];
13124 int count = 0;
13125
13126 /* Set EDNS options if applicable. */
13127 if (reqnsid) {
13128 INSIST(count < DNS_EDNSOPTIONS);
13129 ednsopts[count].code = DNS_OPT_NSID;
13130 ednsopts[count].length = 0;
13131 ednsopts[count].value = NULL;
13132 count++;
13133 }
13134 if (reqexpire) {
13135 INSIST(count < DNS_EDNSOPTIONS);
13136 ednsopts[count].code = DNS_OPT_EXPIRE;
13137 ednsopts[count].length = 0;
13138 ednsopts[count].value = NULL;
13139 count++;
13140 }
13141 result = dns_message_buildopt(message, &rdataset, 0, udpsize, 0,
13142 ednsopts, count);
13143 if (result != ISC_R_SUCCESS) {
13144 return (result);
13145 }
13146
13147 return (dns_message_setopt(message, rdataset));
13148 }
13149
13150 /*
13151 * Called when stub zone update is finished.
13152 * Update zone refresh, retry, expire values accordingly with
13153 * SOA received from primary, sync database to file, restart
13154 * zone management timer.
13155 */
13156 static void
13157 stub_finish_zone_update(dns_stub_t *stub, isc_time_t now) {
13158 uint32_t refresh, retry, expire;
13159 isc_result_t result;
13160 isc_interval_t i;
13161 unsigned int soacount;
13162 dns_zone_t *zone = stub->zone;
13163
13164 /*
13165 * Tidy up.
13166 */
13167 dns_db_closeversion(stub->db, &stub->version, true);
13168 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
13169 if (zone->db == NULL) {
13170 zone_attachdb(zone, stub->db);
13171 }
13172 result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL, NULL,
13173 &refresh, &retry, &expire, NULL, NULL);
13174 if (result == ISC_R_SUCCESS && soacount > 0U) {
13175 zone->refresh = RANGE(refresh, zone->minrefresh,
13176 zone->maxrefresh);
13177 zone->retry = RANGE(retry, zone->minretry, zone->maxretry);
13178 zone->expire = RANGE(expire, zone->refresh + zone->retry,
13179 DNS_MAX_EXPIRE);
13180 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
13181 }
13182 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
13183 dns_db_detach(&stub->db);
13184
13185 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
13186 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
13187 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
13188 isc_interval_set(&i, zone->expire, 0);
13189 DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
13190
13191 if (zone->masterfile != NULL) {
13192 zone_needdump(zone, 0);
13193 }
13194
13195 zone_settimer(zone, &now);
13196 }
13197
13198 /*
13199 * Process answers for A and AAAA queries when
13200 * resolving nameserver addresses for which glue
13201 * was missing in a previous answer for a NS query.
13202 */
13203 static void
13204 stub_glue_response_cb(isc_task_t *task, isc_event_t *event) {
13205 const char me[] = "stub_glue_response_cb";
13206 dns_requestevent_t *revent = (dns_requestevent_t *)event;
13207 dns_stub_t *stub = NULL;
13208 dns_message_t *msg = NULL;
13209 dns_zone_t *zone = NULL;
13210 char primary[ISC_SOCKADDR_FORMATSIZE];
13211 char source[ISC_SOCKADDR_FORMATSIZE];
13212 uint32_t addr_count, cnamecnt;
13213 isc_result_t result;
13214 isc_time_t now;
13215 struct stub_glue_request *request;
13216 struct stub_cb_args *cb_args;
13217 dns_rdataset_t *addr_rdataset = NULL;
13218 dns_dbnode_t *node = NULL;
13219
13220 UNUSED(task);
13221
13222 request = revent->ev_arg;
13223 cb_args = request->args;
13224 stub = cb_args->stub;
13225 INSIST(DNS_STUB_VALID(stub));
13226
13227 zone = stub->zone;
13228
13229 ENTER;
13230
13231 TIME_NOW(&now);
13232
13233 LOCK_ZONE(zone);
13234
13235 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
13236 zone_debuglog(zone, me, 1, "exiting");
13237 goto cleanup;
13238 }
13239
13240 isc_sockaddr_format(&zone->primaryaddr, primary, sizeof(primary));
13241 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
13242
13243 if (revent->result != ISC_R_SUCCESS) {
13244 dns_zonemgr_unreachableadd(zone->zmgr, &zone->primaryaddr,
13245 &zone->sourceaddr, &now);
13246 dns_zone_log(zone, ISC_LOG_INFO,
13247 "could not refresh stub from primary %s"
13248 " (source %s): %s",
13249 primary, source,
13250 isc_result_totext(revent->result));
13251 goto cleanup;
13252 }
13253
13254 dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
13255 result = dns_request_getresponse(revent->request, msg, 0);
13256 if (result != ISC_R_SUCCESS) {
13257 dns_zone_log(zone, ISC_LOG_INFO,
13258 "refreshing stub: unable to parse response (%s)",
13259 isc_result_totext(result));
13260 goto cleanup;
13261 }
13262
13263 /*
13264 * Unexpected opcode.
13265 */
13266 if (msg->opcode != dns_opcode_query) {
13267 char opcode[128];
13268 isc_buffer_t rb;
13269
13270 isc_buffer_init(&rb, opcode, sizeof(opcode));
13271 (void)dns_opcode_totext(msg->opcode, &rb);
13272
13273 dns_zone_log(zone, ISC_LOG_INFO,
13274 "refreshing stub: "
13275 "unexpected opcode (%.*s) from %s (source %s)",
13276 (int)rb.used, opcode, primary, source);
13277 goto cleanup;
13278 }
13279
13280 /*
13281 * Unexpected rcode.
13282 */
13283 if (msg->rcode != dns_rcode_noerror) {
13284 char rcode[128];
13285 isc_buffer_t rb;
13286
13287 isc_buffer_init(&rb, rcode, sizeof(rcode));
13288 (void)dns_rcode_totext(msg->rcode, &rb);
13289
13290 dns_zone_log(zone, ISC_LOG_INFO,
13291 "refreshing stub: "
13292 "unexpected rcode (%.*s) from %s (source %s)",
13293 (int)rb.used, rcode, primary, source);
13294 goto cleanup;
13295 }
13296
13297 /*
13298 * We need complete messages.
13299 */
13300 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
13301 if (dns_request_usedtcp(revent->request)) {
13302 dns_zone_log(zone, ISC_LOG_INFO,
13303 "refreshing stub: truncated TCP "
13304 "response from primary %s (source %s)",
13305 primary, source);
13306 }
13307 goto cleanup;
13308 }
13309
13310 /*
13311 * If non-auth log.
13312 */
13313 if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
13314 dns_zone_log(zone, ISC_LOG_INFO,
13315 "refreshing stub: "
13316 "non-authoritative answer from "
13317 "primary %s (source %s)",
13318 primary, source);
13319 goto cleanup;
13320 }
13321
13322 /*
13323 * Sanity checks.
13324 */
13325 cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
13326 addr_count = message_count(msg, DNS_SECTION_ANSWER,
13327 request->ipv4 ? dns_rdatatype_a
13328 : dns_rdatatype_aaaa);
13329
13330 if (cnamecnt != 0) {
13331 dns_zone_log(zone, ISC_LOG_INFO,
13332 "refreshing stub: unexpected CNAME response "
13333 "from primary %s (source %s)",
13334 primary, source);
13335 goto cleanup;
13336 }
13337
13338 if (addr_count == 0) {
13339 dns_zone_log(zone, ISC_LOG_INFO,
13340 "refreshing stub: no %s records in response "
13341 "from primary %s (source %s)",
13342 request->ipv4 ? "A" : "AAAA", primary, source);
13343 goto cleanup;
13344 }
13345 /*
13346 * Extract A or AAAA RRset from message.
13347 */
13348 result = dns_message_findname(msg, DNS_SECTION_ANSWER, &request->name,
13349 request->ipv4 ? dns_rdatatype_a
13350 : dns_rdatatype_aaaa,
13351 dns_rdatatype_none, NULL, &addr_rdataset);
13352 if (result != ISC_R_SUCCESS) {
13353 if (result != DNS_R_NXDOMAIN && result != DNS_R_NXRRSET) {
13354 char namebuf[DNS_NAME_FORMATSIZE];
13355 dns_name_format(&request->name, namebuf,
13356 sizeof(namebuf));
13357 dns_zone_log(
13358 zone, ISC_LOG_INFO,
13359 "refreshing stub: dns_message_findname(%s/%s) "
13360 "failed (%s)",
13361 namebuf, request->ipv4 ? "A" : "AAAA",
13362 isc_result_totext(result));
13363 }
13364 goto cleanup;
13365 }
13366
13367 result = dns_db_findnode(stub->db, &request->name, true, &node);
13368 if (result != ISC_R_SUCCESS) {
13369 dns_zone_log(zone, ISC_LOG_INFO,
13370 "refreshing stub: "
13371 "dns_db_findnode() failed: %s",
13372 isc_result_totext(result));
13373 goto cleanup;
13374 }
13375
13376 result = dns_db_addrdataset(stub->db, node, stub->version, 0,
13377 addr_rdataset, 0, NULL);
13378 if (result != ISC_R_SUCCESS) {
13379 dns_zone_log(zone, ISC_LOG_INFO,
13380 "refreshing stub: "
13381 "dns_db_addrdataset() failed: %s",
13382 isc_result_totext(result));
13383 }
13384 dns_db_detachnode(stub->db, &node);
13385
13386 cleanup:
13387 if (msg != NULL) {
13388 dns_message_detach(&msg);
13389 }
13390 isc_event_free(&event);
13391 dns_name_free(&request->name, zone->mctx);
13392 dns_request_destroy(&request->request);
13393 isc_mem_put(zone->mctx, request, sizeof(*request));
13394
13395 /* If last request, release all related resources */
13396 if (atomic_fetch_sub_release(&stub->pending_requests, 1) == 1) {
13397 isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
13398 stub_finish_zone_update(stub, now);
13399 UNLOCK_ZONE(zone);
13400 stub->magic = 0;
13401 dns_zone_idetach(&stub->zone);
13402 INSIST(stub->db == NULL);
13403 INSIST(stub->version == NULL);
13404 isc_mem_put(stub->mctx, stub, sizeof(*stub));
13405 } else {
13406 UNLOCK_ZONE(zone);
13407 }
13408 }
13409
13410 /*
13411 * Create and send an A or AAAA query to the primary
13412 * server of the stub zone given.
13413 */
13414 static isc_result_t
13415 stub_request_nameserver_address(struct stub_cb_args *args, bool ipv4,
13416 const dns_name_t *name) {
13417 dns_message_t *message = NULL;
13418 dns_zone_t *zone;
13419 isc_result_t result;
13420 struct stub_glue_request *request;
13421
13422 zone = args->stub->zone;
13423 request = isc_mem_get(zone->mctx, sizeof(*request));
13424 request->request = NULL;
13425 request->args = args;
13426 request->name = (dns_name_t)DNS_NAME_INITEMPTY;
13427 request->ipv4 = ipv4;
13428 dns_name_dup(name, zone->mctx, &request->name);
13429
13430 result = create_query(zone, ipv4 ? dns_rdatatype_a : dns_rdatatype_aaaa,
13431 &request->name, &message);
13432 INSIST(result == ISC_R_SUCCESS);
13433
13434 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
13435 result = add_opt(message, args->udpsize, args->reqnsid, false);
13436 if (result != ISC_R_SUCCESS) {
13437 zone_debuglog(zone, "stub_send_query", 1,
13438 "unable to add opt record: %s",
13439 isc_result_totext(result));
13440 goto fail;
13441 }
13442 }
13443
13444 atomic_fetch_add_release(&args->stub->pending_requests, 1);
13445
13446 result = dns_request_create(
13447 zone->view->requestmgr, message, &zone->sourceaddr,
13448 &zone->primaryaddr, DNS_REQUESTOPT_TCP, args->tsig_key,
13449 args->timeout * 3, args->timeout, 2, zone->task,
13450 stub_glue_response_cb, request, &request->request);
13451
13452 if (result != ISC_R_SUCCESS) {
13453 uint_fast32_t pr;
13454 pr = atomic_fetch_sub_release(&args->stub->pending_requests, 1);
13455 INSIST(pr > 1);
13456 zone_debuglog(zone, "stub_send_query", 1,
13457 "dns_request_create() failed: %s",
13458 isc_result_totext(result));
13459 goto fail;
13460 }
13461
13462 dns_message_detach(&message);
13463
13464 return (ISC_R_SUCCESS);
13465
13466 fail:
13467 dns_name_free(&request->name, zone->mctx);
13468 isc_mem_put(zone->mctx, request, sizeof(*request));
13469
13470 if (message != NULL) {
13471 dns_message_detach(&message);
13472 }
13473
13474 return (result);
13475 }
13476
13477 static isc_result_t
13478 save_nsrrset(dns_message_t *message, dns_name_t *name,
13479 struct stub_cb_args *cb_args, dns_db_t *db,
13480 dns_dbversion_t *version) {
13481 dns_rdataset_t *nsrdataset = NULL;
13482 dns_rdataset_t *rdataset = NULL;
13483 dns_dbnode_t *node = NULL;
13484 dns_rdata_ns_t ns;
13485 isc_result_t result;
13486 dns_rdata_t rdata = DNS_RDATA_INIT;
13487 bool has_glue = false;
13488 dns_name_t *ns_name;
13489 /*
13490 * List of NS entries in answer, keep names that will be used
13491 * to resolve missing A/AAAA glue for each entry.
13492 */
13493 dns_namelist_t ns_list;
13494 ISC_LIST_INIT(ns_list);
13495
13496 /*
13497 * Extract NS RRset from message.
13498 */
13499 result = dns_message_findname(message, DNS_SECTION_ANSWER, name,
13500 dns_rdatatype_ns, dns_rdatatype_none,
13501 NULL, &nsrdataset);
13502 if (result != ISC_R_SUCCESS) {
13503 goto done;
13504 }
13505
13506 /*
13507 * Add NS rdataset.
13508 */
13509 result = dns_db_findnode(db, name, true, &node);
13510 if (result != ISC_R_SUCCESS) {
13511 goto done;
13512 }
13513 result = dns_db_addrdataset(db, node, version, 0, nsrdataset, 0, NULL);
13514 dns_db_detachnode(db, &node);
13515 if (result != ISC_R_SUCCESS) {
13516 goto done;
13517 }
13518 /*
13519 * Add glue rdatasets.
13520 */
13521 for (result = dns_rdataset_first(nsrdataset); result == ISC_R_SUCCESS;
13522 result = dns_rdataset_next(nsrdataset))
13523 {
13524 dns_rdataset_current(nsrdataset, &rdata);
13525 result = dns_rdata_tostruct(&rdata, &ns, NULL);
13526 RUNTIME_CHECK(result == ISC_R_SUCCESS);
13527 dns_rdata_reset(&rdata);
13528
13529 if (!dns_name_issubdomain(&ns.name, name)) {
13530 continue;
13531 }
13532 rdataset = NULL;
13533 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
13534 &ns.name, dns_rdatatype_aaaa,
13535 dns_rdatatype_none, NULL,
13536 &rdataset);
13537 if (result == ISC_R_SUCCESS) {
13538 has_glue = true;
13539 result = dns_db_findnode(db, &ns.name, true, &node);
13540 if (result != ISC_R_SUCCESS) {
13541 goto done;
13542 }
13543 result = dns_db_addrdataset(db, node, version, 0,
13544 rdataset, 0, NULL);
13545 dns_db_detachnode(db, &node);
13546 if (result != ISC_R_SUCCESS) {
13547 goto done;
13548 }
13549 }
13550
13551 rdataset = NULL;
13552 result = dns_message_findname(
13553 message, DNS_SECTION_ADDITIONAL, &ns.name,
13554 dns_rdatatype_a, dns_rdatatype_none, NULL, &rdataset);
13555 if (result == ISC_R_SUCCESS) {
13556 has_glue = true;
13557 result = dns_db_findnode(db, &ns.name, true, &node);
13558 if (result != ISC_R_SUCCESS) {
13559 goto done;
13560 }
13561 result = dns_db_addrdataset(db, node, version, 0,
13562 rdataset, 0, NULL);
13563 dns_db_detachnode(db, &node);
13564 if (result != ISC_R_SUCCESS) {
13565 goto done;
13566 }
13567 }
13568
13569 /*
13570 * If no glue is found so far, we add the name to the list to
13571 * resolve the A/AAAA glue later. If any glue is found in any
13572 * iteration step, this list will be discarded and only the glue
13573 * provided in this message will be used.
13574 */
13575 if (!has_glue && dns_name_issubdomain(&ns.name, name)) {
13576 dns_name_t *tmp_name;
13577 tmp_name = isc_mem_get(cb_args->stub->mctx,
13578 sizeof(*tmp_name));
13579 dns_name_init(tmp_name, NULL);
13580 dns_name_dup(&ns.name, cb_args->stub->mctx, tmp_name);
13581 ISC_LIST_APPEND(ns_list, tmp_name, link);
13582 }
13583 }
13584
13585 if (result != ISC_R_NOMORE) {
13586 goto done;
13587 }
13588
13589 /*
13590 * If no glue records were found, we attempt to resolve A/AAAA
13591 * for each NS entry found in the answer.
13592 */
13593 if (!has_glue) {
13594 for (ns_name = ISC_LIST_HEAD(ns_list); ns_name != NULL;
13595 ns_name = ISC_LIST_NEXT(ns_name, link))
13596 {
13597 /*
13598 * Resolve NS IPv4 address/A.
13599 */
13600 result = stub_request_nameserver_address(cb_args, true,
13601 ns_name);
13602 if (result != ISC_R_SUCCESS) {
13603 goto done;
13604 }
13605 /*
13606 * Resolve NS IPv6 address/AAAA.
13607 */
13608 result = stub_request_nameserver_address(cb_args, false,
13609 ns_name);
13610 if (result != ISC_R_SUCCESS) {
13611 goto done;
13612 }
13613 }
13614 }
13615
13616 result = ISC_R_SUCCESS;
13617
13618 done:
13619 while ((ns_name = ISC_LIST_HEAD(ns_list)) != NULL) {
13620 ISC_LIST_UNLINK(ns_list, ns_name, link);
13621 dns_name_free(ns_name, cb_args->stub->mctx);
13622 isc_mem_put(cb_args->stub->mctx, ns_name, sizeof(*ns_name));
13623 }
13624 return (result);
13625 }
13626
13627 static void
13628 stub_callback(isc_task_t *task, isc_event_t *event) {
13629 const char me[] = "stub_callback";
13630 dns_requestevent_t *revent = (dns_requestevent_t *)event;
13631 dns_stub_t *stub = NULL;
13632 dns_message_t *msg = NULL;
13633 dns_zone_t *zone = NULL;
13634 char primary[ISC_SOCKADDR_FORMATSIZE];
13635 char source[ISC_SOCKADDR_FORMATSIZE];
13636 uint32_t nscnt, cnamecnt;
13637 isc_result_t result;
13638 isc_time_t now;
13639 bool exiting = false;
13640 unsigned int j;
13641 struct stub_cb_args *cb_args;
13642
13643 cb_args = revent->ev_arg;
13644 stub = cb_args->stub;
13645 INSIST(DNS_STUB_VALID(stub));
13646
13647 UNUSED(task);
13648
13649 zone = stub->zone;
13650
13651 ENTER;
13652
13653 TIME_NOW(&now);
13654
13655 LOCK_ZONE(zone);
13656
13657 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
13658 goto exiting;
13659 }
13660
13661 isc_sockaddr_format(&zone->primaryaddr, primary, sizeof(primary));
13662 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
13663
13664 switch (revent->result) {
13665 case ISC_R_SUCCESS:
13666 break;
13667 case ISC_R_SHUTTINGDOWN:
13668 goto exiting;
13669 case ISC_R_TIMEDOUT:
13670 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
13671 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
13672 dns_zone_log(zone, ISC_LOG_DEBUG(1),
13673 "refreshing stub: timeout retrying "
13674 "without EDNS primary %s (source %s)",
13675 primary, source);
13676 goto same_primary;
13677 }
13678 FALLTHROUGH;
13679 default:
13680 dns_zonemgr_unreachableadd(zone->zmgr, &zone->primaryaddr,
13681 &zone->sourceaddr, &now);
13682 dns_zone_log(zone, ISC_LOG_INFO,
13683 "could not refresh stub from primary "
13684 "%s (source %s): %s",
13685 primary, source,
13686 isc_result_totext(revent->result));
13687 goto next_primary;
13688 }
13689
13690 dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
13691
13692 result = dns_request_getresponse(revent->request, msg, 0);
13693 if (result != ISC_R_SUCCESS) {
13694 goto next_primary;
13695 }
13696
13697 /*
13698 * Unexpected opcode.
13699 */
13700 if (msg->opcode != dns_opcode_query) {
13701 char opcode[128];
13702 isc_buffer_t rb;
13703
13704 isc_buffer_init(&rb, opcode, sizeof(opcode));
13705 (void)dns_opcode_totext(msg->opcode, &rb);
13706
13707 dns_zone_log(zone, ISC_LOG_INFO,
13708 "refreshing stub: "
13709 "unexpected opcode (%.*s) from %s (source %s)",
13710 (int)rb.used, opcode, primary, source);
13711 goto next_primary;
13712 }
13713
13714 /*
13715 * Unexpected rcode.
13716 */
13717 if (msg->rcode != dns_rcode_noerror) {
13718 char rcode[128];
13719 isc_buffer_t rb;
13720
13721 isc_buffer_init(&rb, rcode, sizeof(rcode));
13722 (void)dns_rcode_totext(msg->rcode, &rb);
13723
13724 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
13725 (msg->rcode == dns_rcode_servfail ||
13726 msg->rcode == dns_rcode_notimp ||
13727 (msg->rcode == dns_rcode_formerr && msg->opt == NULL)))
13728 {
13729 dns_zone_log(zone, ISC_LOG_DEBUG(1),
13730 "refreshing stub: rcode (%.*s) retrying "
13731 "without EDNS primary %s (source %s)",
13732 (int)rb.used, rcode, primary, source);
13733 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
13734 goto same_primary;
13735 }
13736
13737 dns_zone_log(zone, ISC_LOG_INFO,
13738 "refreshing stub: "
13739 "unexpected rcode (%.*s) from %s (source %s)",
13740 (int)rb.used, rcode, primary, source);
13741 goto next_primary;
13742 }
13743
13744 /*
13745 * We need complete messages.
13746 */
13747 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
13748 if (dns_request_usedtcp(revent->request)) {
13749 dns_zone_log(zone, ISC_LOG_INFO,
13750 "refreshing stub: truncated TCP "
13751 "response from primary %s (source %s)",
13752 primary, source);
13753 goto next_primary;
13754 }
13755 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
13756 goto same_primary;
13757 }
13758
13759 /*
13760 * If non-auth log and next primary.
13761 */
13762 if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
13763 dns_zone_log(zone, ISC_LOG_INFO,
13764 "refreshing stub: "
13765 "non-authoritative answer from "
13766 "primary %s (source %s)",
13767 primary, source);
13768 goto next_primary;
13769 }
13770
13771 /*
13772 * Sanity checks.
13773 */
13774 cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
13775 nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns);
13776
13777 if (cnamecnt != 0) {
13778 dns_zone_log(zone, ISC_LOG_INFO,
13779 "refreshing stub: unexpected CNAME response "
13780 "from primary %s (source %s)",
13781 primary, source);
13782 goto next_primary;
13783 }
13784
13785 if (nscnt == 0) {
13786 dns_zone_log(zone, ISC_LOG_INFO,
13787 "refreshing stub: no NS records in response "
13788 "from primary %s (source %s)",
13789 primary, source);
13790 goto next_primary;
13791 }
13792
13793 atomic_fetch_add(&stub->pending_requests, 1);
13794
13795 /*
13796 * Save answer.
13797 */
13798 result = save_nsrrset(msg, &zone->origin, cb_args, stub->db,
13799 stub->version);
13800 if (result != ISC_R_SUCCESS) {
13801 dns_zone_log(zone, ISC_LOG_INFO,
13802 "refreshing stub: unable to save NS records "
13803 "from primary %s (source %s)",
13804 primary, source);
13805 goto next_primary;
13806 }
13807
13808 dns_message_detach(&msg);
13809 isc_event_free(&event);
13810 dns_request_destroy(&zone->request);
13811
13812 /*
13813 * Check to see if there are no outstanding requests and
13814 * finish off if that is so.
13815 */
13816 if (atomic_fetch_sub(&stub->pending_requests, 1) == 1) {
13817 isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
13818 stub_finish_zone_update(stub, now);
13819 goto free_stub;
13820 }
13821
13822 UNLOCK_ZONE(zone);
13823 return;
13824
13825 exiting:
13826 zone_debuglog(zone, me, 1, "exiting");
13827 exiting = true;
13828
13829 next_primary:
13830 isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
13831 if (stub->version != NULL) {
13832 dns_db_closeversion(stub->db, &stub->version, false);
13833 }
13834 if (stub->db != NULL) {
13835 dns_db_detach(&stub->db);
13836 }
13837 if (msg != NULL) {
13838 dns_message_detach(&msg);
13839 }
13840 isc_event_free(&event);
13841 dns_request_destroy(&zone->request);
13842 /*
13843 * Skip to next failed / untried primary.
13844 */
13845 do {
13846 zone->curprimary++;
13847 } while (zone->curprimary < zone->primariescnt &&
13848 zone->primariesok[zone->curprimary]);
13849 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
13850 if (exiting || zone->curprimary >= zone->primariescnt) {
13851 bool done = true;
13852 if (!exiting &&
13853 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
13854 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
13855 {
13856 /*
13857 * Did we get a good answer from all the primaries?
13858 */
13859 for (j = 0; j < zone->primariescnt; j++) {
13860 if (!zone->primariesok[j]) {
13861 {
13862 done = false;
13863 break;
13864 }
13865 }
13866 }
13867 } else {
13868 done = true;
13869 }
13870 if (!done) {
13871 zone->curprimary = 0;
13872 /*
13873 * Find the next failed primary.
13874 */
13875 while (zone->curprimary < zone->primariescnt &&
13876 zone->primariesok[zone->curprimary])
13877 {
13878 zone->curprimary++;
13879 }
13880 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
13881 } else {
13882 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
13883
13884 zone_settimer(zone, &now);
13885 goto free_stub;
13886 }
13887 }
13888 queue_soa_query(zone);
13889 goto free_stub;
13890
13891 same_primary:
13892 isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
13893 if (msg != NULL) {
13894 dns_message_detach(&msg);
13895 }
13896 isc_event_free(&event);
13897 dns_request_destroy(&zone->request);
13898 ns_query(zone, NULL, stub);
13899 UNLOCK_ZONE(zone);
13900 goto done;
13901
13902 free_stub:
13903 UNLOCK_ZONE(zone);
13904 stub->magic = 0;
13905 dns_zone_idetach(&stub->zone);
13906 INSIST(stub->db == NULL);
13907 INSIST(stub->version == NULL);
13908 isc_mem_put(stub->mctx, stub, sizeof(*stub));
13909
13910 done:
13911 INSIST(event == NULL);
13912 return;
13913 }
13914
13915 /*
13916 * Get the EDNS EXPIRE option from the response and if it exists trim
13917 * expire to be not more than it.
13918 */
13919 static void
13920 get_edns_expire(dns_zone_t *zone, dns_message_t *message, uint32_t *expirep) {
13921 isc_result_t result;
13922 uint32_t expire;
13923 dns_rdata_t rdata = DNS_RDATA_INIT;
13924 isc_buffer_t optbuf;
13925 uint16_t optcode;
13926 uint16_t optlen;
13927
13928 REQUIRE(expirep != NULL);
13929 REQUIRE(message != NULL);
13930
13931 if (message->opt == NULL) {
13932 return;
13933 }
13934
13935 result = dns_rdataset_first(message->opt);
13936 if (result == ISC_R_SUCCESS) {
13937 dns_rdataset_current(message->opt, &rdata);
13938 isc_buffer_init(&optbuf, rdata.data, rdata.length);
13939 isc_buffer_add(&optbuf, rdata.length);
13940 while (isc_buffer_remaininglength(&optbuf) >= 4) {
13941 optcode = isc_buffer_getuint16(&optbuf);
13942 optlen = isc_buffer_getuint16(&optbuf);
13943 /*
13944 * A EDNS EXPIRE response has a length of 4.
13945 */
13946 if (optcode != DNS_OPT_EXPIRE || optlen != 4) {
13947 isc_buffer_forward(&optbuf, optlen);
13948 continue;
13949 }
13950 expire = isc_buffer_getuint32(&optbuf);
13951 dns_zone_log(zone, ISC_LOG_DEBUG(1),
13952 "got EDNS EXPIRE of %u", expire);
13953 /*
13954 * Trim *expirep?
13955 */
13956 if (expire < *expirep) {
13957 *expirep = expire;
13958 }
13959 break;
13960 }
13961 }
13962 }
13963
13964 /*
13965 * Set the file modification time zone->expire seconds before expiretime.
13966 */
13967 static void
13968 setmodtime(dns_zone_t *zone, isc_time_t *expiretime) {
13969 isc_result_t result;
13970 isc_time_t when;
13971 isc_interval_t i;
13972
13973 isc_interval_set(&i, zone->expire, 0);
13974 result = isc_time_subtract(expiretime, &i, &when);
13975 if (result != ISC_R_SUCCESS) {
13976 return;
13977 }
13978
13979 result = ISC_R_FAILURE;
13980 if (zone->journal != NULL) {
13981 result = isc_file_settime(zone->journal, &when);
13982 }
13983 if (result == ISC_R_SUCCESS &&
13984 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
13985 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
13986 {
13987 result = isc_file_settime(zone->masterfile, &when);
13988 } else if (result != ISC_R_SUCCESS) {
13989 result = isc_file_settime(zone->masterfile, &when);
13990 }
13991
13992 /*
13993 * Someone removed the file from underneath us!
13994 */
13995 if (result == ISC_R_FILENOTFOUND) {
13996 zone_needdump(zone, DNS_DUMP_DELAY);
13997 } else if (result != ISC_R_SUCCESS) {
13998 dns_zone_log(zone, ISC_LOG_ERROR,
13999 "refresh: could not set "
14000 "file modification time of '%s': %s",
14001 zone->masterfile, isc_result_totext(result));
14002 }
14003 }
14004
14005 /*
14006 * An SOA query has finished (successfully or not).
14007 */
14008 static void
14009 refresh_callback(isc_task_t *task, isc_event_t *event) {
14010 const char me[] = "refresh_callback";
14011 dns_requestevent_t *revent = (dns_requestevent_t *)event;
14012 dns_zone_t *zone;
14013 dns_message_t *msg = NULL;
14014 uint32_t soacnt, cnamecnt, soacount, nscount;
14015 isc_time_t now;
14016 char primary[ISC_SOCKADDR_FORMATSIZE];
14017 char source[ISC_SOCKADDR_FORMATSIZE];
14018 dns_rdataset_t *rdataset = NULL;
14019 dns_rdata_t rdata = DNS_RDATA_INIT;
14020 dns_rdata_soa_t soa;
14021 isc_result_t result;
14022 uint32_t serial, oldserial = 0;
14023 unsigned int j;
14024 bool do_queue_xfrin = false;
14025
14026 zone = revent->ev_arg;
14027 INSIST(DNS_ZONE_VALID(zone));
14028
14029 UNUSED(task);
14030
14031 ENTER;
14032
14033 TIME_NOW(&now);
14034
14035 LOCK_ZONE(zone);
14036
14037 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
14038 goto exiting;
14039 }
14040
14041 /*
14042 * If timeout, log and try the next primary
14043 */
14044 isc_sockaddr_format(&zone->primaryaddr, primary, sizeof(primary));
14045 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
14046
14047 switch (revent->result) {
14048 case ISC_R_SUCCESS:
14049 break;
14050 case ISC_R_SHUTTINGDOWN:
14051 goto exiting;
14052 case ISC_R_TIMEDOUT:
14053 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
14054 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
14055 dns_zone_log(zone, ISC_LOG_DEBUG(1),
14056 "refresh: timeout retrying without EDNS "
14057 "primary %s (source %s)",
14058 primary, source);
14059 goto same_primary;
14060 } else if (!dns_request_usedtcp(revent->request)) {
14061 dns_zone_log(zone, ISC_LOG_INFO,
14062 "refresh: retry limit for "
14063 "primary %s exceeded (source %s)",
14064 primary, source);
14065 /* Try with secondary with TCP. */
14066 if ((zone->type == dns_zone_secondary ||
14067 zone->type == dns_zone_mirror ||
14068 zone->type == dns_zone_redirect) &&
14069 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH))
14070 {
14071 if (!dns_zonemgr_unreachable(
14072 zone->zmgr, &zone->primaryaddr,
14073 &zone->sourceaddr, &now))
14074 {
14075 DNS_ZONE_SETFLAG(
14076 zone,
14077 DNS_ZONEFLG_SOABEFOREAXFR);
14078 goto tcp_transfer;
14079 }
14080 dns_zone_log(zone, ISC_LOG_DEBUG(1),
14081 "refresh: skipped tcp fallback "
14082 "as primary %s (source %s) is "
14083 "unreachable (cached)",
14084 primary, source);
14085 }
14086 goto next_primary;
14087 }
14088 FALLTHROUGH;
14089 default:
14090 dns_zone_log(zone, ISC_LOG_INFO,
14091 "refresh: failure trying primary "
14092 "%s (source %s): %s",
14093 primary, source,
14094 isc_result_totext(revent->result));
14095 goto next_primary;
14096 }
14097
14098 dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
14099 result = dns_request_getresponse(revent->request, msg, 0);
14100 if (result != ISC_R_SUCCESS) {
14101 dns_zone_log(zone, ISC_LOG_INFO,
14102 "refresh: failure trying primary "
14103 "%s (source %s): %s",
14104 primary, source, isc_result_totext(result));
14105 goto next_primary;
14106 }
14107
14108 /*
14109 * Unexpected opcode.
14110 */
14111 if (msg->opcode != dns_opcode_query) {
14112 char opcode[128];
14113 isc_buffer_t rb;
14114
14115 isc_buffer_init(&rb, opcode, sizeof(opcode));
14116 (void)dns_opcode_totext(msg->opcode, &rb);
14117
14118 dns_zone_log(zone, ISC_LOG_INFO,
14119 "refresh: "
14120 "unexpected opcode (%.*s) from %s (source %s)",
14121 (int)rb.used, opcode, primary, source);
14122 goto next_primary;
14123 }
14124
14125 /*
14126 * Unexpected rcode.
14127 */
14128 if (msg->rcode != dns_rcode_noerror) {
14129 char rcode[128];
14130 isc_buffer_t rb;
14131
14132 isc_buffer_init(&rb, rcode, sizeof(rcode));
14133 (void)dns_rcode_totext(msg->rcode, &rb);
14134
14135 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
14136 (msg->rcode == dns_rcode_servfail ||
14137 msg->rcode == dns_rcode_notimp ||
14138 (msg->rcode == dns_rcode_formerr && msg->opt == NULL)))
14139 {
14140 dns_zone_log(zone, ISC_LOG_DEBUG(1),
14141 "refresh: rcode (%.*s) retrying without "
14142 "EDNS primary %s (source %s)",
14143 (int)rb.used, rcode, primary, source);
14144 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
14145 goto same_primary;
14146 }
14147 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
14148 msg->rcode == dns_rcode_badvers)
14149 {
14150 dns_zone_log(zone, ISC_LOG_DEBUG(1),
14151 "refresh: rcode (%.*s) retrying without "
14152 "EDNS EXPIRE OPTION primary %s "
14153 "(source %s)",
14154 (int)rb.used, rcode, primary, source);
14155 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
14156 goto same_primary;
14157 }
14158 dns_zone_log(zone, ISC_LOG_INFO,
14159 "refresh: unexpected rcode (%.*s) from "
14160 "primary %s (source %s)",
14161 (int)rb.used, rcode, primary, source);
14162 /*
14163 * Perhaps AXFR/IXFR is allowed even if SOA queries aren't.
14164 */
14165 if (msg->rcode == dns_rcode_refused &&
14166 (zone->type == dns_zone_secondary ||
14167 zone->type == dns_zone_mirror ||
14168 zone->type == dns_zone_redirect))
14169 {
14170 goto tcp_transfer;
14171 }
14172 goto next_primary;
14173 }
14174
14175 /*
14176 * If truncated punt to zone transfer which will query again.
14177 */
14178 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
14179 if (zone->type == dns_zone_secondary ||
14180 zone->type == dns_zone_mirror ||
14181 zone->type == dns_zone_redirect)
14182 {
14183 dns_zone_log(zone, ISC_LOG_INFO,
14184 "refresh: truncated UDP answer, "
14185 "initiating TCP zone xfer "
14186 "for primary %s (source %s)",
14187 primary, source);
14188 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
14189 goto tcp_transfer;
14190 } else {
14191 INSIST(zone->type == dns_zone_stub);
14192 if (dns_request_usedtcp(revent->request)) {
14193 dns_zone_log(zone, ISC_LOG_INFO,
14194 "refresh: truncated TCP response "
14195 "from primary %s (source %s)",
14196 primary, source);
14197 goto next_primary;
14198 }
14199 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
14200 goto same_primary;
14201 }
14202 }
14203
14204 /*
14205 * If non-auth, log and try the next primary
14206 */
14207 if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
14208 dns_zone_log(zone, ISC_LOG_INFO,
14209 "refresh: non-authoritative answer from "
14210 "primary %s (source %s)",
14211 primary, source);
14212 goto next_primary;
14213 }
14214
14215 cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
14216 soacnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_soa);
14217 nscount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_ns);
14218 soacount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_soa);
14219
14220 /*
14221 * There should not be a CNAME record at top of zone.
14222 */
14223 if (cnamecnt != 0) {
14224 dns_zone_log(zone, ISC_LOG_INFO,
14225 "refresh: CNAME at top of zone "
14226 "in primary %s (source %s)",
14227 primary, source);
14228 goto next_primary;
14229 }
14230
14231 /*
14232 * If referral, log and try the next primary;
14233 */
14234 if (soacnt == 0 && soacount == 0 && nscount != 0) {
14235 dns_zone_log(zone, ISC_LOG_INFO,
14236 "refresh: referral response "
14237 "from primary %s (source %s)",
14238 primary, source);
14239 goto next_primary;
14240 }
14241
14242 /*
14243 * If nodata, log and try the next primary;
14244 */
14245 if (soacnt == 0 && (nscount == 0 || soacount != 0)) {
14246 dns_zone_log(zone, ISC_LOG_INFO,
14247 "refresh: NODATA response "
14248 "from primary %s (source %s)",
14249 primary, source);
14250 goto next_primary;
14251 }
14252
14253 /*
14254 * Only one soa at top of zone.
14255 */
14256 if (soacnt != 1) {
14257 dns_zone_log(zone, ISC_LOG_INFO,
14258 "refresh: answer SOA count (%d) != 1 "
14259 "from primary %s (source %s)",
14260 soacnt, primary, source);
14261 goto next_primary;
14262 }
14263
14264 /*
14265 * Extract serial
14266 */
14267 rdataset = NULL;
14268 result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin,
14269 dns_rdatatype_soa, dns_rdatatype_none,
14270 NULL, &rdataset);
14271 if (result != ISC_R_SUCCESS) {
14272 dns_zone_log(zone, ISC_LOG_INFO,
14273 "refresh: unable to get SOA record "
14274 "from primary %s (source %s)",
14275 primary, source);
14276 goto next_primary;
14277 }
14278
14279 result = dns_rdataset_first(rdataset);
14280 if (result != ISC_R_SUCCESS) {
14281 dns_zone_log(zone, ISC_LOG_INFO,
14282 "refresh: dns_rdataset_first() failed");
14283 goto next_primary;
14284 }
14285
14286 dns_rdataset_current(rdataset, &rdata);
14287 result = dns_rdata_tostruct(&rdata, &soa, NULL);
14288 RUNTIME_CHECK(result == ISC_R_SUCCESS);
14289
14290 serial = soa.serial;
14291 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
14292 unsigned int dbsoacount;
14293 result = zone_get_from_db(zone, zone->db, NULL, &dbsoacount,
14294 NULL, &oldserial, NULL, NULL, NULL,
14295 NULL, NULL);
14296 RUNTIME_CHECK(result == ISC_R_SUCCESS);
14297 RUNTIME_CHECK(dbsoacount > 0U);
14298 zone_debuglog(zone, me, 1, "serial: new %u, old %u", serial,
14299 oldserial);
14300 } else {
14301 zone_debuglog(zone, me, 1, "serial: new %u, old not loaded",
14302 serial);
14303 }
14304
14305 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
14306 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
14307 isc_serial_gt(serial, oldserial))
14308 {
14309 if (dns_zonemgr_unreachable(zone->zmgr, &zone->primaryaddr,
14310 &zone->sourceaddr, &now))
14311 {
14312 dns_zone_log(zone, ISC_LOG_INFO,
14313 "refresh: skipping %s as primary %s "
14314 "(source %s) is unreachable (cached)",
14315 (zone->type == dns_zone_secondary ||
14316 zone->type == dns_zone_mirror ||
14317 zone->type == dns_zone_redirect)
14318 ? "zone transfer"
14319 : "NS query",
14320 primary, source);
14321 goto next_primary;
14322 }
14323 tcp_transfer:
14324 isc_event_free(&event);
14325 dns_request_destroy(&zone->request);
14326 if (zone->type == dns_zone_secondary ||
14327 zone->type == dns_zone_mirror ||
14328 zone->type == dns_zone_redirect)
14329 {
14330 do_queue_xfrin = true;
14331 } else {
14332 INSIST(zone->type == dns_zone_stub);
14333 ns_query(zone, rdataset, NULL);
14334 }
14335 if (msg != NULL) {
14336 dns_message_detach(&msg);
14337 }
14338 } else if (isc_serial_eq(soa.serial, oldserial)) {
14339 isc_time_t expiretime;
14340 uint32_t expire;
14341
14342 /*
14343 * Compute the new expire time based on this response.
14344 */
14345 expire = zone->expire;
14346 get_edns_expire(zone, msg, &expire);
14347 DNS_ZONE_TIME_ADD(&now, expire, &expiretime);
14348
14349 /*
14350 * Has the expire time improved?
14351 */
14352 if (isc_time_compare(&expiretime, &zone->expiretime) > 0) {
14353 zone->expiretime = expiretime;
14354 if (zone->masterfile != NULL) {
14355 setmodtime(zone, &expiretime);
14356 }
14357 }
14358
14359 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
14360 zone->primariesok[zone->curprimary] = true;
14361 goto next_primary;
14362 } else {
14363 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER)) {
14364 dns_zone_log(zone, ISC_LOG_INFO,
14365 "serial number (%u) "
14366 "received from primary %s < ours (%u)",
14367 soa.serial, primary, oldserial);
14368 } else {
14369 zone_debuglog(zone, me, 1, "ahead");
14370 }
14371 zone->primariesok[zone->curprimary] = true;
14372 goto next_primary;
14373 }
14374 if (msg != NULL) {
14375 dns_message_detach(&msg);
14376 }
14377 goto detach;
14378
14379 next_primary:
14380 if (msg != NULL) {
14381 dns_message_detach(&msg);
14382 }
14383 isc_event_free(&event);
14384 dns_request_destroy(&zone->request);
14385 /*
14386 * Skip to next failed / untried primary.
14387 */
14388 do {
14389 zone->curprimary++;
14390 } while (zone->curprimary < zone->primariescnt &&
14391 zone->primariesok[zone->curprimary]);
14392 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
14393 if (zone->curprimary >= zone->primariescnt) {
14394 bool done = true;
14395 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
14396 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
14397 {
14398 /*
14399 * Did we get a good answer from all the primaries?
14400 */
14401 for (j = 0; j < zone->primariescnt; j++) {
14402 if (!zone->primariesok[j]) {
14403 {
14404 done = false;
14405 break;
14406 }
14407 }
14408 }
14409 } else {
14410 done = true;
14411 }
14412 if (!done) {
14413 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
14414 zone->curprimary = 0;
14415 /*
14416 * Find the next failed primary.
14417 */
14418 while (zone->curprimary < zone->primariescnt &&
14419 zone->primariesok[zone->curprimary])
14420 {
14421 zone->curprimary++;
14422 }
14423 goto requeue;
14424 }
14425 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
14426 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
14427 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
14428 zone->refreshtime = now;
14429 }
14430 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
14431 zone_settimer(zone, &now);
14432 goto detach;
14433 }
14434
14435 requeue:
14436 queue_soa_query(zone);
14437 goto detach;
14438
14439 exiting:
14440 isc_event_free(&event);
14441 dns_request_destroy(&zone->request);
14442 goto detach;
14443
14444 same_primary:
14445 if (msg != NULL) {
14446 dns_message_detach(&msg);
14447 }
14448 isc_event_free(&event);
14449 dns_request_destroy(&zone->request);
14450 queue_soa_query(zone);
14451
14452 detach:
14453 UNLOCK_ZONE(zone);
14454 if (do_queue_xfrin) {
14455 queue_xfrin(zone);
14456 }
14457 dns_zone_idetach(&zone);
14458 return;
14459 }
14460
14461 static void
14462 queue_soa_query(dns_zone_t *zone) {
14463 const char me[] = "queue_soa_query";
14464 isc_event_t *e;
14465 dns_zone_t *dummy = NULL;
14466 isc_result_t result;
14467
14468 ENTER;
14469 /*
14470 * Locked by caller
14471 */
14472 REQUIRE(LOCKED_ZONE(zone));
14473
14474 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
14475 cancel_refresh(zone);
14476 return;
14477 }
14478
14479 e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE, soa_query,
14480 zone, sizeof(isc_event_t));
14481
14482 /*
14483 * Attach so that we won't clean up
14484 * until the event is delivered.
14485 */
14486 zone_iattach(zone, &dummy);
14487
14488 e->ev_arg = zone;
14489 e->ev_sender = NULL;
14490 result = isc_ratelimiter_enqueue(zone->zmgr->refreshrl, zone->task, &e);
14491 if (result != ISC_R_SUCCESS) {
14492 zone_idetach(&dummy);
14493 isc_event_free(&e);
14494 cancel_refresh(zone);
14495 }
14496 }
14497
14498 static void
14499 soa_query(isc_task_t *task, isc_event_t *event) {
14500 const char me[] = "soa_query";
14501 isc_result_t result = ISC_R_FAILURE;
14502 dns_message_t *message = NULL;
14503 dns_zone_t *zone = event->ev_arg;
14504 dns_zone_t *dummy = NULL;
14505 isc_netaddr_t primaryip;
14506 dns_tsigkey_t *key = NULL;
14507 dns_transport_t *transport = NULL;
14508 uint32_t options;
14509 bool cancel = true;
14510 int timeout;
14511 bool have_xfrsource = false, reqnsid, reqexpire;
14512 uint16_t udpsize = SEND_BUFFER_SIZE;
14513 bool do_queue_xfrin = false;
14514
14515 REQUIRE(DNS_ZONE_VALID(zone));
14516
14517 UNUSED(task);
14518
14519 ENTER;
14520
14521 LOCK_ZONE(zone);
14522 if (((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) ||
14523 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
14524 zone->view->requestmgr == NULL)
14525 {
14526 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
14527 cancel = false;
14528 }
14529 goto cleanup;
14530 }
14531
14532 again:
14533 INSIST(zone->primariescnt > 0);
14534 INSIST(zone->curprimary < zone->primariescnt);
14535
14536 zone->primaryaddr = zone->primaries[zone->curprimary];
14537
14538 isc_netaddr_fromsockaddr(&primaryip, &zone->primaryaddr);
14539 /*
14540 * First, look for a tsig key in the primaries statement, then
14541 * try for a server key.
14542 */
14543 if ((zone->primarykeynames != NULL) &&
14544 (zone->primarykeynames[zone->curprimary] != NULL))
14545 {
14546 dns_view_t *view = dns_zone_getview(zone);
14547 dns_name_t *keyname = zone->primarykeynames[zone->curprimary];
14548 result = dns_view_gettsig(view, keyname, &key);
14549 if (result != ISC_R_SUCCESS) {
14550 char namebuf[DNS_NAME_FORMATSIZE];
14551 dns_name_format(keyname, namebuf, sizeof(namebuf));
14552 dns_zone_log(zone, ISC_LOG_ERROR,
14553 "unable to find key: %s", namebuf);
14554 goto skip_primary;
14555 }
14556 }
14557 if (key == NULL) {
14558 result = dns_view_getpeertsig(zone->view, &primaryip, &key);
14559 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
14560 char addrbuf[ISC_NETADDR_FORMATSIZE];
14561 isc_netaddr_format(&primaryip, addrbuf,
14562 sizeof(addrbuf));
14563 dns_zone_log(zone, ISC_LOG_ERROR,
14564 "unable to find TSIG key for %s", addrbuf);
14565 goto skip_primary;
14566 }
14567 }
14568
14569 if ((zone->primarytlsnames != NULL) &&
14570 (zone->primarytlsnames[zone->curprimary] != NULL))
14571 {
14572 dns_view_t *view = dns_zone_getview(zone);
14573 dns_name_t *tlsname = zone->primarytlsnames[zone->curprimary];
14574 result = dns_view_gettransport(view, DNS_TRANSPORT_TLS, tlsname,
14575 &transport);
14576 if (result != ISC_R_SUCCESS) {
14577 char namebuf[DNS_NAME_FORMATSIZE];
14578 dns_name_format(tlsname, namebuf, sizeof(namebuf));
14579 dns_zone_log(zone, ISC_LOG_ERROR,
14580 "unable to find TLS configuration: %s",
14581 namebuf);
14582 goto skip_primary;
14583 }
14584 }
14585
14586 options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ? DNS_REQUESTOPT_TCP
14587 : 0;
14588 reqnsid = zone->view->requestnsid;
14589 reqexpire = zone->requestexpire;
14590 if (zone->view->peers != NULL) {
14591 dns_peer_t *peer = NULL;
14592 bool edns, usetcp;
14593 result = dns_peerlist_peerbyaddr(zone->view->peers, &primaryip,
14594 &peer);
14595 if (result == ISC_R_SUCCESS) {
14596 result = dns_peer_getsupportedns(peer, &edns);
14597 if (result == ISC_R_SUCCESS && !edns) {
14598 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
14599 }
14600 result = dns_peer_gettransfersource(peer,
14601 &zone->sourceaddr);
14602 if (result == ISC_R_SUCCESS) {
14603 have_xfrsource = true;
14604 }
14605 if (zone->view->resolver != NULL) {
14606 udpsize = dns_resolver_getudpsize(
14607 zone->view->resolver);
14608 }
14609 (void)dns_peer_getudpsize(peer, &udpsize);
14610 (void)dns_peer_getrequestnsid(peer, &reqnsid);
14611 (void)dns_peer_getrequestexpire(peer, &reqexpire);
14612 result = dns_peer_getforcetcp(peer, &usetcp);
14613 if (result == ISC_R_SUCCESS && usetcp) {
14614 options |= DNS_REQUESTOPT_TCP;
14615 }
14616 }
14617 }
14618
14619 switch (isc_sockaddr_pf(&zone->primaryaddr)) {
14620 case PF_INET:
14621 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
14622 if (isc_sockaddr_equal(&zone->altxfrsource4,
14623 &zone->xfrsource4))
14624 {
14625 goto skip_primary;
14626 }
14627 zone->sourceaddr = zone->altxfrsource4;
14628 } else if (!have_xfrsource) {
14629 zone->sourceaddr = zone->xfrsource4;
14630 }
14631 break;
14632 case PF_INET6:
14633 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
14634 if (isc_sockaddr_equal(&zone->altxfrsource6,
14635 &zone->xfrsource6))
14636 {
14637 goto skip_primary;
14638 }
14639 zone->sourceaddr = zone->altxfrsource6;
14640 } else if (!have_xfrsource) {
14641 zone->sourceaddr = zone->xfrsource6;
14642 }
14643 break;
14644 default:
14645 result = ISC_R_NOTIMPLEMENTED;
14646 goto cleanup;
14647 }
14648
14649 /*
14650 * FIXME(OS): This is a bit hackish, but it enforces the SOA query to go
14651 * through the XFR channel instead of doing dns_request that doesn't
14652 * have DoT support yet.
14653 */
14654 if (transport != NULL) {
14655 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
14656 do_queue_xfrin = true;
14657 cancel = false;
14658 result = ISC_R_SUCCESS;
14659 goto cleanup;
14660 }
14661
14662 result = create_query(zone, dns_rdatatype_soa, &zone->origin, &message);
14663 if (result != ISC_R_SUCCESS) {
14664 goto cleanup;
14665 }
14666
14667 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
14668 result = add_opt(message, udpsize, reqnsid, reqexpire);
14669 if (result != ISC_R_SUCCESS) {
14670 zone_debuglog(zone, me, 1,
14671 "unable to add opt record: %s",
14672 isc_result_totext(result));
14673 }
14674 }
14675
14676 zone_iattach(zone, &dummy);
14677 timeout = 5;
14678 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH)) {
14679 timeout = 30;
14680 }
14681 result = dns_request_create(
14682 zone->view->requestmgr, message, &zone->sourceaddr,
14683 &zone->primaryaddr, options, key, timeout * 3 + 1, timeout, 2,
14684 zone->task, refresh_callback, zone, &zone->request);
14685 if (result != ISC_R_SUCCESS) {
14686 zone_idetach(&dummy);
14687 zone_debuglog(zone, me, 1, "dns_request_create() failed: %s",
14688 isc_result_totext(result));
14689 goto skip_primary;
14690 } else {
14691 if (isc_sockaddr_pf(&zone->primaryaddr) == PF_INET) {
14692 inc_stats(zone, dns_zonestatscounter_soaoutv4);
14693 } else {
14694 inc_stats(zone, dns_zonestatscounter_soaoutv6);
14695 }
14696 }
14697 cancel = false;
14698 cleanup:
14699 if (transport != NULL) {
14700 dns_transport_detach(&transport);
14701 }
14702 if (key != NULL) {
14703 dns_tsigkey_detach(&key);
14704 }
14705 if (result != ISC_R_SUCCESS) {
14706 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
14707 }
14708 if (message != NULL) {
14709 dns_message_detach(&message);
14710 }
14711 if (cancel) {
14712 cancel_refresh(zone);
14713 }
14714 isc_event_free(&event);
14715 UNLOCK_ZONE(zone);
14716 if (do_queue_xfrin) {
14717 queue_xfrin(zone);
14718 }
14719 dns_zone_idetach(&zone);
14720 return;
14721
14722 skip_primary:
14723 if (transport != NULL) {
14724 dns_transport_detach(&transport);
14725 }
14726 if (key != NULL) {
14727 dns_tsigkey_detach(&key);
14728 }
14729 if (message != NULL) {
14730 dns_message_detach(&message);
14731 }
14732 /*
14733 * Skip to next failed / untried primary.
14734 */
14735 do {
14736 zone->curprimary++;
14737 } while (zone->curprimary < zone->primariescnt &&
14738 zone->primariesok[zone->curprimary]);
14739 if (zone->curprimary < zone->primariescnt) {
14740 goto again;
14741 }
14742 zone->curprimary = 0;
14743 goto cleanup;
14744 }
14745
14746 static void
14747 ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
14748 const char me[] = "ns_query";
14749 isc_result_t result;
14750 dns_message_t *message = NULL;
14751 isc_netaddr_t primaryip;
14752 dns_tsigkey_t *key = NULL;
14753 dns_dbnode_t *node = NULL;
14754 int timeout;
14755 bool have_xfrsource = false;
14756 bool reqnsid;
14757 uint16_t udpsize = SEND_BUFFER_SIZE;
14758 struct stub_cb_args *cb_args;
14759
14760 REQUIRE(DNS_ZONE_VALID(zone));
14761 REQUIRE(LOCKED_ZONE(zone));
14762 REQUIRE((soardataset != NULL && stub == NULL) ||
14763 (soardataset == NULL && stub != NULL));
14764 REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
14765
14766 ENTER;
14767
14768 if (stub == NULL) {
14769 stub = isc_mem_get(zone->mctx, sizeof(*stub));
14770 stub->magic = STUB_MAGIC;
14771 stub->mctx = zone->mctx;
14772 stub->zone = NULL;
14773 stub->db = NULL;
14774 stub->version = NULL;
14775 atomic_init(&stub->pending_requests, 0);
14776
14777 /*
14778 * Attach so that the zone won't disappear from under us.
14779 */
14780 zone_iattach(zone, &stub->zone);
14781
14782 /*
14783 * If a db exists we will update it, otherwise we create a
14784 * new one and attach it to the zone once we have the NS
14785 * RRset and glue.
14786 */
14787 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
14788 if (zone->db != NULL) {
14789 dns_db_attach(zone->db, &stub->db);
14790 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
14791 } else {
14792 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
14793
14794 INSIST(zone->db_argc >= 1);
14795 result = dns_db_create(zone->mctx, zone->db_argv[0],
14796 &zone->origin, dns_dbtype_stub,
14797 zone->rdclass, zone->db_argc - 1,
14798 zone->db_argv + 1, &stub->db);
14799 if (result != ISC_R_SUCCESS) {
14800 dns_zone_log(zone, ISC_LOG_ERROR,
14801 "refreshing stub: "
14802 "could not create "
14803 "database: %s",
14804 isc_result_totext(result));
14805 goto cleanup;
14806 }
14807 dns_db_settask(stub->db, zone->task);
14808 }
14809
14810 result = dns_db_newversion(stub->db, &stub->version);
14811 if (result != ISC_R_SUCCESS) {
14812 dns_zone_log(zone, ISC_LOG_INFO,
14813 "refreshing stub: "
14814 "dns_db_newversion() failed: %s",
14815 isc_result_totext(result));
14816 goto cleanup;
14817 }
14818
14819 /*
14820 * Update SOA record.
14821 */
14822 result = dns_db_findnode(stub->db, &zone->origin, true, &node);
14823 if (result != ISC_R_SUCCESS) {
14824 dns_zone_log(zone, ISC_LOG_INFO,
14825 "refreshing stub: "
14826 "dns_db_findnode() failed: %s",
14827 isc_result_totext(result));
14828 goto cleanup;
14829 }
14830
14831 result = dns_db_addrdataset(stub->db, node, stub->version, 0,
14832 soardataset, 0, NULL);
14833 dns_db_detachnode(stub->db, &node);
14834 if (result != ISC_R_SUCCESS) {
14835 dns_zone_log(zone, ISC_LOG_INFO,
14836 "refreshing stub: "
14837 "dns_db_addrdataset() failed: %s",
14838 isc_result_totext(result));
14839 goto cleanup;
14840 }
14841 }
14842
14843 /*
14844 * XXX Optimisation: Create message when zone is setup and reuse.
14845 */
14846 result = create_query(zone, dns_rdatatype_ns, &zone->origin, &message);
14847 INSIST(result == ISC_R_SUCCESS);
14848
14849 INSIST(zone->primariescnt > 0);
14850 INSIST(zone->curprimary < zone->primariescnt);
14851 zone->primaryaddr = zone->primaries[zone->curprimary];
14852
14853 isc_netaddr_fromsockaddr(&primaryip, &zone->primaryaddr);
14854 /*
14855 * First, look for a tsig key in the primaries statement, then
14856 * try for a server key.
14857 */
14858 if ((zone->primarykeynames != NULL) &&
14859 (zone->primarykeynames[zone->curprimary] != NULL))
14860 {
14861 dns_view_t *view = dns_zone_getview(zone);
14862 dns_name_t *keyname = zone->primarykeynames[zone->curprimary];
14863 result = dns_view_gettsig(view, keyname, &key);
14864 if (result != ISC_R_SUCCESS) {
14865 char namebuf[DNS_NAME_FORMATSIZE];
14866 dns_name_format(keyname, namebuf, sizeof(namebuf));
14867 dns_zone_log(zone, ISC_LOG_ERROR,
14868 "unable to find key: %s", namebuf);
14869 }
14870 }
14871 if (key == NULL) {
14872 (void)dns_view_getpeertsig(zone->view, &primaryip, &key);
14873 }
14874
14875 /* FIXME(OS): Do we need the transport here too? Most probably yes */
14876
14877 reqnsid = zone->view->requestnsid;
14878 if (zone->view->peers != NULL) {
14879 dns_peer_t *peer = NULL;
14880 bool edns;
14881 result = dns_peerlist_peerbyaddr(zone->view->peers, &primaryip,
14882 &peer);
14883 if (result == ISC_R_SUCCESS) {
14884 result = dns_peer_getsupportedns(peer, &edns);
14885 if (result == ISC_R_SUCCESS && !edns) {
14886 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
14887 }
14888 result = dns_peer_gettransfersource(peer,
14889 &zone->sourceaddr);
14890 if (result == ISC_R_SUCCESS) {
14891 have_xfrsource = true;
14892 }
14893 if (zone->view->resolver != NULL) {
14894 udpsize = dns_resolver_getudpsize(
14895 zone->view->resolver);
14896 }
14897 (void)dns_peer_getudpsize(peer, &udpsize);
14898 (void)dns_peer_getrequestnsid(peer, &reqnsid);
14899 }
14900 }
14901 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
14902 result = add_opt(message, udpsize, reqnsid, false);
14903 if (result != ISC_R_SUCCESS) {
14904 zone_debuglog(zone, me, 1,
14905 "unable to add opt record: %s",
14906 isc_result_totext(result));
14907 }
14908 }
14909
14910 /*
14911 * Always use TCP so that we shouldn't truncate in additional section.
14912 */
14913 switch (isc_sockaddr_pf(&zone->primaryaddr)) {
14914 case PF_INET:
14915 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
14916 zone->sourceaddr = zone->altxfrsource4;
14917 } else if (!have_xfrsource) {
14918 zone->sourceaddr = zone->xfrsource4;
14919 }
14920 break;
14921 case PF_INET6:
14922 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
14923 zone->sourceaddr = zone->altxfrsource6;
14924 } else if (!have_xfrsource) {
14925 zone->sourceaddr = zone->xfrsource6;
14926 }
14927 break;
14928 default:
14929 result = ISC_R_NOTIMPLEMENTED;
14930 POST(result);
14931 goto cleanup;
14932 }
14933 timeout = 5;
14934 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH)) {
14935 timeout = 30;
14936 }
14937
14938 /*
14939 * Save request parameters so we can reuse them later on
14940 * for resolving missing glue A/AAAA records.
14941 */
14942 cb_args = isc_mem_get(zone->mctx, sizeof(*cb_args));
14943 cb_args->stub = stub;
14944 cb_args->tsig_key = key;
14945 cb_args->udpsize = udpsize;
14946 cb_args->timeout = timeout;
14947 cb_args->reqnsid = reqnsid;
14948
14949 result = dns_request_create(
14950 zone->view->requestmgr, message, &zone->sourceaddr,
14951 &zone->primaryaddr, DNS_REQUESTOPT_TCP, key, timeout * 3 + 1,
14952 timeout, 2, zone->task, stub_callback, cb_args, &zone->request);
14953 if (result != ISC_R_SUCCESS) {
14954 zone_debuglog(zone, me, 1, "dns_request_create() failed: %s",
14955 isc_result_totext(result));
14956 goto cleanup;
14957 }
14958 dns_message_detach(&message);
14959 goto unlock;
14960
14961 cleanup:
14962 cancel_refresh(zone);
14963 stub->magic = 0;
14964 if (stub->version != NULL) {
14965 dns_db_closeversion(stub->db, &stub->version, false);
14966 }
14967 if (stub->db != NULL) {
14968 dns_db_detach(&stub->db);
14969 }
14970 if (stub->zone != NULL) {
14971 zone_idetach(&stub->zone);
14972 }
14973 isc_mem_put(stub->mctx, stub, sizeof(*stub));
14974 if (message != NULL) {
14975 dns_message_detach(&message);
14976 }
14977 unlock:
14978 if (key != NULL) {
14979 dns_tsigkey_detach(&key);
14980 }
14981 return;
14982 }
14983
14984 /*
14985 * Shut the zone down.
14986 */
14987 static void
14988 zone_shutdown(isc_task_t *task, isc_event_t *event) {
14989 dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
14990 bool free_needed, linked = false;
14991 dns_zone_t *raw = NULL, *secure = NULL;
14992 dns_view_t *view = NULL, *prev_view = NULL;
14993
14994 UNUSED(task);
14995 REQUIRE(DNS_ZONE_VALID(zone));
14996 INSIST(event->ev_type == DNS_EVENT_ZONECONTROL);
14997 INSIST(isc_refcount_current(&zone->erefs) == 0);
14998
14999 zone_debuglog(zone, "zone_shutdown", 3, "shutting down");
15000
15001 /*
15002 * If we were waiting for xfrin quota, step out of
15003 * the queue.
15004 * If there's no zone manager, we can't be waiting for the
15005 * xfrin quota
15006 */
15007 if (zone->zmgr != NULL) {
15008 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
15009 if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
15010 ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone,
15011 statelink);
15012 linked = true;
15013 zone->statelist = NULL;
15014 }
15015 if (zone->statelist == &zone->zmgr->xfrin_in_progress) {
15016 ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone,
15017 statelink);
15018 zone->statelist = NULL;
15019 zmgr_resume_xfrs(zone->zmgr, false);
15020 }
15021 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
15022 }
15023
15024 /*
15025 * In task context, no locking required. See zone_xfrdone().
15026 */
15027 if (zone->xfr != NULL) {
15028 /* The final detach will happen in zone_xfrdone() */
15029 dns_xfrin_shutdown(zone->xfr);
15030 }
15031
15032 /* Safe to release the zone now */
15033 if (zone->zmgr != NULL) {
15034 dns_zonemgr_releasezone(zone->zmgr, zone);
15035 }
15036
15037 LOCK_ZONE(zone);
15038 INSIST(zone != zone->raw);
15039
15040 /*
15041 * Detach the views early, we don't need them anymore. However, we need
15042 * to detach them outside of the zone lock to break the lock loop
15043 * between view, adb and zone locks.
15044 */
15045 view = zone->view;
15046 zone->view = NULL;
15047 prev_view = zone->prev_view;
15048 zone->prev_view = NULL;
15049
15050 if (linked) {
15051 isc_refcount_decrement(&zone->irefs);
15052 }
15053 if (zone->request != NULL) {
15054 dns_request_cancel(zone->request);
15055 }
15056
15057 if (zone->readio != NULL) {
15058 zonemgr_cancelio(zone->readio);
15059 }
15060
15061 if (zone->lctx != NULL) {
15062 dns_loadctx_cancel(zone->lctx);
15063 }
15064
15065 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
15066 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
15067 {
15068 if (zone->writeio != NULL) {
15069 zonemgr_cancelio(zone->writeio);
15070 }
15071
15072 if (zone->dctx != NULL) {
15073 dns_dumpctx_cancel(zone->dctx);
15074 }
15075 }
15076
15077 checkds_cancel(zone);
15078
15079 notify_cancel(zone);
15080
15081 forward_cancel(zone);
15082
15083 if (zone->timer != NULL) {
15084 isc_timer_destroy(&zone->timer);
15085 isc_refcount_decrement(&zone->irefs);
15086 }
15087
15088 /*
15089 * We have now canceled everything set the flag to allow exit_check()
15090 * to succeed. We must not unlock between setting this flag and
15091 * calling exit_check().
15092 */
15093 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN);
15094 free_needed = exit_check(zone);
15095 /*
15096 * If a dump is in progress for the secure zone, defer detaching from
15097 * the raw zone as it may prevent the unsigned serial number from being
15098 * stored in the raw-format dump of the secure zone. In this scenario,
15099 * dump_done() takes care of cleaning up the zone->raw reference.
15100 */
15101 if (inline_secure(zone) && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
15102 raw = zone->raw;
15103 zone->raw = NULL;
15104 }
15105 if (inline_raw(zone)) {
15106 secure = zone->secure;
15107 zone->secure = NULL;
15108 }
15109 UNLOCK_ZONE(zone);
15110
15111 if (view != NULL) {
15112 dns_view_weakdetach(&view);
15113 }
15114 if (prev_view != NULL) {
15115 dns_view_weakdetach(&prev_view);
15116 }
15117
15118 if (raw != NULL) {
15119 dns_zone_detach(&raw);
15120 }
15121 if (secure != NULL) {
15122 dns_zone_idetach(&secure);
15123 }
15124 if (free_needed) {
15125 zone_free(zone);
15126 }
15127 }
15128
15129 static void
15130 zone_timer(isc_task_t *task, isc_event_t *event) {
15131 const char me[] = "zone_timer";
15132 dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
15133
15134 UNUSED(task);
15135 REQUIRE(DNS_ZONE_VALID(zone));
15136
15137 ENTER;
15138
15139 zone_maintenance(zone);
15140
15141 isc_event_free(&event);
15142 }
15143
15144 static void
15145 zone_settimer(dns_zone_t *zone, isc_time_t *now) {
15146 const char me[] = "zone_settimer";
15147 isc_time_t next;
15148 isc_result_t result;
15149
15150 REQUIRE(DNS_ZONE_VALID(zone));
15151 REQUIRE(LOCKED_ZONE(zone));
15152 ENTER;
15153
15154 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
15155 return;
15156 }
15157
15158 isc_time_settoepoch(&next);
15159
15160 switch (zone->type) {
15161 case dns_zone_redirect:
15162 if (zone->primaries != NULL) {
15163 goto treat_as_secondary;
15164 }
15165 FALLTHROUGH;
15166 case dns_zone_primary:
15167 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
15168 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))
15169 {
15170 next = zone->notifytime;
15171 }
15172 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
15173 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
15174 {
15175 INSIST(!isc_time_isepoch(&zone->dumptime));
15176 if (isc_time_isepoch(&next) ||
15177 isc_time_compare(&zone->dumptime, &next) < 0)
15178 {
15179 next = zone->dumptime;
15180 }
15181 }
15182 if (zone->type == dns_zone_redirect) {
15183 break;
15184 }
15185 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING) &&
15186 !isc_time_isepoch(&zone->refreshkeytime))
15187 {
15188 if (isc_time_isepoch(&next) ||
15189 isc_time_compare(&zone->refreshkeytime, &next) < 0)
15190 {
15191 next = zone->refreshkeytime;
15192 }
15193 }
15194 if (!isc_time_isepoch(&zone->resigntime)) {
15195 if (isc_time_isepoch(&next) ||
15196 isc_time_compare(&zone->resigntime, &next) < 0)
15197 {
15198 next = zone->resigntime;
15199 }
15200 }
15201 if (!isc_time_isepoch(&zone->keywarntime)) {
15202 if (isc_time_isepoch(&next) ||
15203 isc_time_compare(&zone->keywarntime, &next) < 0)
15204 {
15205 next = zone->keywarntime;
15206 }
15207 }
15208 if (!isc_time_isepoch(&zone->signingtime)) {
15209 if (isc_time_isepoch(&next) ||
15210 isc_time_compare(&zone->signingtime, &next) < 0)
15211 {
15212 next = zone->signingtime;
15213 }
15214 }
15215 if (!isc_time_isepoch(&zone->nsec3chaintime)) {
15216 if (isc_time_isepoch(&next) ||
15217 isc_time_compare(&zone->nsec3chaintime, &next) < 0)
15218 {
15219 next = zone->nsec3chaintime;
15220 }
15221 }
15222 break;
15223
15224 case dns_zone_secondary:
15225 case dns_zone_mirror:
15226 treat_as_secondary:
15227 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
15228 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))
15229 {
15230 next = zone->notifytime;
15231 }
15232 FALLTHROUGH;
15233 case dns_zone_stub:
15234 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) &&
15235 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOPRIMARIES) &&
15236 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH) &&
15237 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING) &&
15238 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING) &&
15239 !isc_time_isepoch(&zone->refreshtime) &&
15240 (isc_time_isepoch(&next) ||
15241 isc_time_compare(&zone->refreshtime, &next) < 0))
15242 {
15243 next = zone->refreshtime;
15244 }
15245 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
15246 !isc_time_isepoch(&zone->expiretime))
15247 {
15248 if (isc_time_isepoch(&next) ||
15249 isc_time_compare(&zone->expiretime, &next) < 0)
15250 {
15251 next = zone->expiretime;
15252 }
15253 }
15254 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
15255 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
15256 {
15257 INSIST(!isc_time_isepoch(&zone->dumptime));
15258 if (isc_time_isepoch(&next) ||
15259 isc_time_compare(&zone->dumptime, &next) < 0)
15260 {
15261 next = zone->dumptime;
15262 }
15263 }
15264 break;
15265
15266 case dns_zone_key:
15267 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
15268 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
15269 {
15270 INSIST(!isc_time_isepoch(&zone->dumptime));
15271 if (isc_time_isepoch(&next) ||
15272 isc_time_compare(&zone->dumptime, &next) < 0)
15273 {
15274 next = zone->dumptime;
15275 }
15276 }
15277 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
15278 if (isc_time_isepoch(&next) ||
15279 (!isc_time_isepoch(&zone->refreshkeytime) &&
15280 isc_time_compare(&zone->refreshkeytime, &next) <
15281 0))
15282 {
15283 next = zone->refreshkeytime;
15284 }
15285 }
15286 break;
15287
15288 default:
15289 break;
15290 }
15291
15292 if (isc_time_isepoch(&next)) {
15293 zone_debuglog(zone, me, 10, "settimer inactive");
15294 result = isc_timer_reset(zone->timer, isc_timertype_inactive,
15295 NULL, NULL, true);
15296 if (result != ISC_R_SUCCESS) {
15297 dns_zone_log(zone, ISC_LOG_ERROR,
15298 "could not deactivate zone timer: %s",
15299 isc_result_totext(result));
15300 }
15301 } else {
15302 if (isc_time_compare(&next, now) <= 0) {
15303 next = *now;
15304 }
15305 result = isc_timer_reset(zone->timer, isc_timertype_once, &next,
15306 NULL, true);
15307 if (result != ISC_R_SUCCESS) {
15308 dns_zone_log(zone, ISC_LOG_ERROR,
15309 "could not reset zone timer: %s",
15310 isc_result_totext(result));
15311 }
15312 }
15313 }
15314
15315 static void
15316 cancel_refresh(dns_zone_t *zone) {
15317 const char me[] = "cancel_refresh";
15318 isc_time_t now;
15319
15320 /*
15321 * 'zone' locked by caller.
15322 */
15323
15324 REQUIRE(DNS_ZONE_VALID(zone));
15325 REQUIRE(LOCKED_ZONE(zone));
15326
15327 ENTER;
15328
15329 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
15330 TIME_NOW(&now);
15331 zone_settimer(zone, &now);
15332 }
15333
15334 static isc_result_t
15335 notify_createmessage(dns_zone_t *zone, unsigned int flags,
15336 dns_message_t **messagep) {
15337 dns_db_t *zonedb = NULL;
15338 dns_dbnode_t *node = NULL;
15339 dns_dbversion_t *version = NULL;
15340 dns_message_t *message = NULL;
15341 dns_rdataset_t rdataset;
15342 dns_rdata_t rdata = DNS_RDATA_INIT;
15343
15344 dns_name_t *tempname = NULL;
15345 dns_rdata_t *temprdata = NULL;
15346 dns_rdatalist_t *temprdatalist = NULL;
15347 dns_rdataset_t *temprdataset = NULL;
15348
15349 isc_result_t result;
15350 isc_region_t r;
15351 isc_buffer_t *b = NULL;
15352
15353 REQUIRE(DNS_ZONE_VALID(zone));
15354 REQUIRE(messagep != NULL && *messagep == NULL);
15355
15356 dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER, &message);
15357
15358 message->opcode = dns_opcode_notify;
15359 message->flags |= DNS_MESSAGEFLAG_AA;
15360 message->rdclass = zone->rdclass;
15361
15362 result = dns_message_gettempname(message, &tempname);
15363 if (result != ISC_R_SUCCESS) {
15364 goto cleanup;
15365 }
15366
15367 result = dns_message_gettemprdataset(message, &temprdataset);
15368 if (result != ISC_R_SUCCESS) {
15369 goto cleanup;
15370 }
15371
15372 /*
15373 * Make question.
15374 */
15375 dns_name_clone(&zone->origin, tempname);
15376 dns_rdataset_makequestion(temprdataset, zone->rdclass,
15377 dns_rdatatype_soa);
15378 ISC_LIST_APPEND(tempname->list, temprdataset, link);
15379 dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
15380 tempname = NULL;
15381 temprdataset = NULL;
15382
15383 if ((flags & DNS_NOTIFY_NOSOA) != 0) {
15384 goto done;
15385 }
15386
15387 result = dns_message_gettempname(message, &tempname);
15388 if (result != ISC_R_SUCCESS) {
15389 goto soa_cleanup;
15390 }
15391 result = dns_message_gettemprdata(message, &temprdata);
15392 if (result != ISC_R_SUCCESS) {
15393 goto soa_cleanup;
15394 }
15395 result = dns_message_gettemprdataset(message, &temprdataset);
15396 if (result != ISC_R_SUCCESS) {
15397 goto soa_cleanup;
15398 }
15399 result = dns_message_gettemprdatalist(message, &temprdatalist);
15400 if (result != ISC_R_SUCCESS) {
15401 goto soa_cleanup;
15402 }
15403
15404 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
15405 INSIST(zone->db != NULL); /* XXXJT: is this assumption correct? */
15406 dns_db_attach(zone->db, &zonedb);
15407 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
15408
15409 dns_name_clone(&zone->origin, tempname);
15410 dns_db_currentversion(zonedb, &version);
15411 result = dns_db_findnode(zonedb, tempname, false, &node);
15412 if (result != ISC_R_SUCCESS) {
15413 goto soa_cleanup;
15414 }
15415
15416 dns_rdataset_init(&rdataset);
15417 result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
15418 dns_rdatatype_none, 0, &rdataset, NULL);
15419 if (result != ISC_R_SUCCESS) {
15420 goto soa_cleanup;
15421 }
15422 result = dns_rdataset_first(&rdataset);
15423 if (result != ISC_R_SUCCESS) {
15424 goto soa_cleanup;
15425 }
15426 dns_rdataset_current(&rdataset, &rdata);
15427 dns_rdata_toregion(&rdata, &r);
15428 isc_buffer_allocate(zone->mctx, &b, r.length);
15429 isc_buffer_putmem(b, r.base, r.length);
15430 isc_buffer_usedregion(b, &r);
15431 dns_rdata_init(temprdata);
15432 dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r);
15433 dns_message_takebuffer(message, &b);
15434 result = dns_rdataset_next(&rdataset);
15435 dns_rdataset_disassociate(&rdataset);
15436 if (result != ISC_R_NOMORE) {
15437 goto soa_cleanup;
15438 }
15439 temprdatalist->rdclass = rdata.rdclass;
15440 temprdatalist->type = rdata.type;
15441 temprdatalist->ttl = rdataset.ttl;
15442 ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link);
15443
15444 result = dns_rdatalist_tordataset(temprdatalist, temprdataset);
15445 if (result != ISC_R_SUCCESS) {
15446 goto soa_cleanup;
15447 }
15448
15449 ISC_LIST_APPEND(tempname->list, temprdataset, link);
15450 dns_message_addname(message, tempname, DNS_SECTION_ANSWER);
15451 temprdatalist = NULL;
15452 temprdataset = NULL;
15453 temprdata = NULL;
15454 tempname = NULL;
15455
15456 soa_cleanup:
15457 if (node != NULL) {
15458 dns_db_detachnode(zonedb, &node);
15459 }
15460 if (version != NULL) {
15461 dns_db_closeversion(zonedb, &version, false);
15462 }
15463 if (zonedb != NULL) {
15464 dns_db_detach(&zonedb);
15465 }
15466 if (tempname != NULL) {
15467 dns_message_puttempname(message, &tempname);
15468 }
15469 if (temprdata != NULL) {
15470 dns_message_puttemprdata(message, &temprdata);
15471 }
15472 if (temprdataset != NULL) {
15473 dns_message_puttemprdataset(message, &temprdataset);
15474 }
15475 if (temprdatalist != NULL) {
15476 dns_message_puttemprdatalist(message, &temprdatalist);
15477 }
15478
15479 done:
15480 *messagep = message;
15481 return (ISC_R_SUCCESS);
15482
15483 cleanup:
15484 if (tempname != NULL) {
15485 dns_message_puttempname(message, &tempname);
15486 }
15487 if (temprdataset != NULL) {
15488 dns_message_puttemprdataset(message, &temprdataset);
15489 }
15490 dns_message_detach(&message);
15491 return (result);
15492 }
15493
15494 isc_result_t
15495 dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
15496 isc_sockaddr_t *to, dns_message_t *msg) {
15497 unsigned int i;
15498 dns_rdata_soa_t soa;
15499 dns_rdataset_t *rdataset = NULL;
15500 dns_rdata_t rdata = DNS_RDATA_INIT;
15501 isc_result_t result;
15502 char fromtext[ISC_SOCKADDR_FORMATSIZE];
15503 int match = 0;
15504 isc_netaddr_t netaddr;
15505 uint32_t serial = 0;
15506 bool have_serial = false;
15507 dns_tsigkey_t *tsigkey;
15508 const dns_name_t *tsig;
15509
15510 REQUIRE(DNS_ZONE_VALID(zone));
15511
15512 /*
15513 * If type != T_SOA return DNS_R_NOTIMP. We don't yet support
15514 * ROLLOVER.
15515 *
15516 * SOA: RFC1996
15517 * Check that 'from' is a valid notify source, (zone->primaries).
15518 * Return DNS_R_REFUSED if not.
15519 *
15520 * If the notify message contains a serial number check it
15521 * against the zones serial and return if <= current serial
15522 *
15523 * If a refresh check is progress, if so just record the
15524 * fact we received a NOTIFY and from where and return.
15525 * We will perform a new refresh check when the current one
15526 * completes. Return ISC_R_SUCCESS.
15527 *
15528 * Otherwise initiate a refresh check using 'from' as the
15529 * first address to check. Return ISC_R_SUCCESS.
15530 */
15531
15532 isc_sockaddr_format(from, fromtext, sizeof(fromtext));
15533
15534 /*
15535 * Notify messages are processed by the raw zone.
15536 */
15537 LOCK_ZONE(zone);
15538 INSIST(zone != zone->raw);
15539 if (inline_secure(zone)) {
15540 result = dns_zone_notifyreceive(zone->raw, from, to, msg);
15541 UNLOCK_ZONE(zone);
15542 return (result);
15543 }
15544 /*
15545 * We only handle NOTIFY (SOA) at the present.
15546 */
15547 if (isc_sockaddr_pf(from) == PF_INET) {
15548 inc_stats(zone, dns_zonestatscounter_notifyinv4);
15549 } else {
15550 inc_stats(zone, dns_zonestatscounter_notifyinv6);
15551 }
15552 if (msg->counts[DNS_SECTION_QUESTION] == 0 ||
15553 dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin,
15554 dns_rdatatype_soa, dns_rdatatype_none, NULL,
15555 NULL) != ISC_R_SUCCESS)
15556 {
15557 UNLOCK_ZONE(zone);
15558 if (msg->counts[DNS_SECTION_QUESTION] == 0) {
15559 dns_zone_log(zone, ISC_LOG_NOTICE,
15560 "NOTIFY with no "
15561 "question section from: %s",
15562 fromtext);
15563 return (DNS_R_FORMERR);
15564 }
15565 dns_zone_log(zone, ISC_LOG_NOTICE,
15566 "NOTIFY zone does not match");
15567 return (DNS_R_NOTIMP);
15568 }
15569
15570 /*
15571 * If we are a primary zone just succeed.
15572 */
15573 if (zone->type == dns_zone_primary) {
15574 UNLOCK_ZONE(zone);
15575 return (ISC_R_SUCCESS);
15576 }
15577
15578 isc_netaddr_fromsockaddr(&netaddr, from);
15579 for (i = 0; i < zone->primariescnt; i++) {
15580 if (isc_sockaddr_eqaddr(from, &zone->primaries[i])) {
15581 break;
15582 }
15583 if (zone->view->aclenv->match_mapped &&
15584 IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) &&
15585 isc_sockaddr_pf(&zone->primaries[i]) == AF_INET)
15586 {
15587 isc_netaddr_t na1, na2;
15588 isc_netaddr_fromv4mapped(&na1, &netaddr);
15589 isc_netaddr_fromsockaddr(&na2, &zone->primaries[i]);
15590 if (isc_netaddr_equal(&na1, &na2)) {
15591 break;
15592 }
15593 }
15594 }
15595
15596 /*
15597 * Accept notify requests from non primaries if they are on
15598 * 'zone->notify_acl'.
15599 */
15600 tsigkey = dns_message_gettsigkey(msg);
15601 tsig = dns_tsigkey_identity(tsigkey);
15602 if (i >= zone->primariescnt && zone->notify_acl != NULL &&
15603 (dns_acl_match(&netaddr, tsig, zone->notify_acl, zone->view->aclenv,
15604 &match, NULL) == ISC_R_SUCCESS) &&
15605 match > 0)
15606 {
15607 /* Accept notify. */
15608 } else if (i >= zone->primariescnt) {
15609 UNLOCK_ZONE(zone);
15610 dns_zone_log(zone, ISC_LOG_INFO,
15611 "refused notify from non-primary: %s", fromtext);
15612 inc_stats(zone, dns_zonestatscounter_notifyrej);
15613 return (DNS_R_REFUSED);
15614 }
15615
15616 /*
15617 * If the zone is loaded and there are answers check the serial
15618 * to see if we need to do a refresh. Do not worry about this
15619 * check if we are a dialup zone as we use the notify request
15620 * to trigger a refresh check.
15621 */
15622 if (msg->counts[DNS_SECTION_ANSWER] > 0 &&
15623 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
15624 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH))
15625 {
15626 result = dns_message_findname(
15627 msg, DNS_SECTION_ANSWER, &zone->origin,
15628 dns_rdatatype_soa, dns_rdatatype_none, NULL, &rdataset);
15629 if (result == ISC_R_SUCCESS) {
15630 result = dns_rdataset_first(rdataset);
15631 }
15632 if (result == ISC_R_SUCCESS) {
15633 uint32_t oldserial;
15634 unsigned int soacount;
15635
15636 dns_rdataset_current(rdataset, &rdata);
15637 result = dns_rdata_tostruct(&rdata, &soa, NULL);
15638 RUNTIME_CHECK(result == ISC_R_SUCCESS);
15639 serial = soa.serial;
15640 have_serial = true;
15641 /*
15642 * The following should safely be performed without DB
15643 * lock and succeed in this context.
15644 */
15645 result = zone_get_from_db(zone, zone->db, NULL,
15646 &soacount, NULL, &oldserial,
15647 NULL, NULL, NULL, NULL, NULL);
15648 RUNTIME_CHECK(result == ISC_R_SUCCESS);
15649 RUNTIME_CHECK(soacount > 0U);
15650 if (isc_serial_le(serial, oldserial)) {
15651 dns_zone_log(zone, ISC_LOG_INFO,
15652 "notify from %s: "
15653 "zone is up to date",
15654 fromtext);
15655 UNLOCK_ZONE(zone);
15656 return (ISC_R_SUCCESS);
15657 }
15658 }
15659 }
15660
15661 /*
15662 * If we got this far and there was a refresh in progress just
15663 * let it complete. Record where we got the notify from so we
15664 * can perform a refresh check when the current one completes
15665 */
15666 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
15667 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
15668 zone->notifyfrom = *from;
15669 UNLOCK_ZONE(zone);
15670 if (have_serial) {
15671 dns_zone_log(zone, ISC_LOG_INFO,
15672 "notify from %s: serial %u: refresh in "
15673 "progress, refresh check queued",
15674 fromtext, serial);
15675 } else {
15676 dns_zone_log(zone, ISC_LOG_INFO,
15677 "notify from %s: refresh in progress, "
15678 "refresh check queued",
15679 fromtext);
15680 }
15681 return (ISC_R_SUCCESS);
15682 }
15683 if (have_serial) {
15684 dns_zone_log(zone, ISC_LOG_INFO, "notify from %s: serial %u",
15685 fromtext, serial);
15686 } else {
15687 dns_zone_log(zone, ISC_LOG_INFO, "notify from %s: no serial",
15688 fromtext);
15689 }
15690 zone->notifyfrom = *from;
15691 UNLOCK_ZONE(zone);
15692
15693 if (to != NULL) {
15694 dns_zonemgr_unreachabledel(zone->zmgr, from, to);
15695 }
15696 dns_zone_refresh(zone);
15697 return (ISC_R_SUCCESS);
15698 }
15699
15700 void
15701 dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
15702 REQUIRE(DNS_ZONE_VALID(zone));
15703
15704 LOCK_ZONE(zone);
15705 if (zone->notify_acl != NULL) {
15706 dns_acl_detach(&zone->notify_acl);
15707 }
15708 dns_acl_attach(acl, &zone->notify_acl);
15709 UNLOCK_ZONE(zone);
15710 }
15711
15712 void
15713 dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
15714 REQUIRE(DNS_ZONE_VALID(zone));
15715
15716 LOCK_ZONE(zone);
15717 if (zone->query_acl != NULL) {
15718 dns_acl_detach(&zone->query_acl);
15719 }
15720 dns_acl_attach(acl, &zone->query_acl);
15721 UNLOCK_ZONE(zone);
15722 }
15723
15724 void
15725 dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl) {
15726 REQUIRE(DNS_ZONE_VALID(zone));
15727
15728 LOCK_ZONE(zone);
15729 if (zone->queryon_acl != NULL) {
15730 dns_acl_detach(&zone->queryon_acl);
15731 }
15732 dns_acl_attach(acl, &zone->queryon_acl);
15733 UNLOCK_ZONE(zone);
15734 }
15735
15736 void
15737 dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
15738 REQUIRE(DNS_ZONE_VALID(zone));
15739
15740 LOCK_ZONE(zone);
15741 if (zone->update_acl != NULL) {
15742 dns_acl_detach(&zone->update_acl);
15743 }
15744 dns_acl_attach(acl, &zone->update_acl);
15745 UNLOCK_ZONE(zone);
15746 }
15747
15748 void
15749 dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
15750 REQUIRE(DNS_ZONE_VALID(zone));
15751
15752 LOCK_ZONE(zone);
15753 if (zone->forward_acl != NULL) {
15754 dns_acl_detach(&zone->forward_acl);
15755 }
15756 dns_acl_attach(acl, &zone->forward_acl);
15757 UNLOCK_ZONE(zone);
15758 }
15759
15760 void
15761 dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
15762 REQUIRE(DNS_ZONE_VALID(zone));
15763
15764 LOCK_ZONE(zone);
15765 if (zone->xfr_acl != NULL) {
15766 dns_acl_detach(&zone->xfr_acl);
15767 }
15768 dns_acl_attach(acl, &zone->xfr_acl);
15769 UNLOCK_ZONE(zone);
15770 }
15771
15772 dns_acl_t *
15773 dns_zone_getnotifyacl(dns_zone_t *zone) {
15774 REQUIRE(DNS_ZONE_VALID(zone));
15775
15776 return (zone->notify_acl);
15777 }
15778
15779 dns_acl_t *
15780 dns_zone_getqueryacl(dns_zone_t *zone) {
15781 REQUIRE(DNS_ZONE_VALID(zone));
15782
15783 return (zone->query_acl);
15784 }
15785
15786 dns_acl_t *
15787 dns_zone_getqueryonacl(dns_zone_t *zone) {
15788 REQUIRE(DNS_ZONE_VALID(zone));
15789
15790 return (zone->queryon_acl);
15791 }
15792
15793 dns_acl_t *
15794 dns_zone_getupdateacl(dns_zone_t *zone) {
15795 REQUIRE(DNS_ZONE_VALID(zone));
15796
15797 return (zone->update_acl);
15798 }
15799
15800 dns_acl_t *
15801 dns_zone_getforwardacl(dns_zone_t *zone) {
15802 REQUIRE(DNS_ZONE_VALID(zone));
15803
15804 return (zone->forward_acl);
15805 }
15806
15807 dns_acl_t *
15808 dns_zone_getxfracl(dns_zone_t *zone) {
15809 REQUIRE(DNS_ZONE_VALID(zone));
15810
15811 return (zone->xfr_acl);
15812 }
15813
15814 void
15815 dns_zone_clearupdateacl(dns_zone_t *zone) {
15816 REQUIRE(DNS_ZONE_VALID(zone));
15817
15818 LOCK_ZONE(zone);
15819 if (zone->update_acl != NULL) {
15820 dns_acl_detach(&zone->update_acl);
15821 }
15822 UNLOCK_ZONE(zone);
15823 }
15824
15825 void
15826 dns_zone_clearforwardacl(dns_zone_t *zone) {
15827 REQUIRE(DNS_ZONE_VALID(zone));
15828
15829 LOCK_ZONE(zone);
15830 if (zone->forward_acl != NULL) {
15831 dns_acl_detach(&zone->forward_acl);
15832 }
15833 UNLOCK_ZONE(zone);
15834 }
15835
15836 void
15837 dns_zone_clearnotifyacl(dns_zone_t *zone) {
15838 REQUIRE(DNS_ZONE_VALID(zone));
15839
15840 LOCK_ZONE(zone);
15841 if (zone->notify_acl != NULL) {
15842 dns_acl_detach(&zone->notify_acl);
15843 }
15844 UNLOCK_ZONE(zone);
15845 }
15846
15847 void
15848 dns_zone_clearqueryacl(dns_zone_t *zone) {
15849 REQUIRE(DNS_ZONE_VALID(zone));
15850
15851 LOCK_ZONE(zone);
15852 if (zone->query_acl != NULL) {
15853 dns_acl_detach(&zone->query_acl);
15854 }
15855 UNLOCK_ZONE(zone);
15856 }
15857
15858 void
15859 dns_zone_clearqueryonacl(dns_zone_t *zone) {
15860 REQUIRE(DNS_ZONE_VALID(zone));
15861
15862 LOCK_ZONE(zone);
15863 if (zone->queryon_acl != NULL) {
15864 dns_acl_detach(&zone->queryon_acl);
15865 }
15866 UNLOCK_ZONE(zone);
15867 }
15868
15869 void
15870 dns_zone_clearxfracl(dns_zone_t *zone) {
15871 REQUIRE(DNS_ZONE_VALID(zone));
15872
15873 LOCK_ZONE(zone);
15874 if (zone->xfr_acl != NULL) {
15875 dns_acl_detach(&zone->xfr_acl);
15876 }
15877 UNLOCK_ZONE(zone);
15878 }
15879
15880 bool
15881 dns_zone_getupdatedisabled(dns_zone_t *zone) {
15882 REQUIRE(DNS_ZONE_VALID(zone));
15883 return (zone->update_disabled);
15884 }
15885
15886 void
15887 dns_zone_setupdatedisabled(dns_zone_t *zone, bool state) {
15888 REQUIRE(DNS_ZONE_VALID(zone));
15889 zone->update_disabled = state;
15890 }
15891
15892 bool
15893 dns_zone_getzeronosoattl(dns_zone_t *zone) {
15894 REQUIRE(DNS_ZONE_VALID(zone));
15895 return (zone->zero_no_soa_ttl);
15896 }
15897
15898 void
15899 dns_zone_setzeronosoattl(dns_zone_t *zone, bool state) {
15900 REQUIRE(DNS_ZONE_VALID(zone));
15901 zone->zero_no_soa_ttl = state;
15902 }
15903
15904 void
15905 dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
15906 REQUIRE(DNS_ZONE_VALID(zone));
15907
15908 zone->check_names = severity;
15909 }
15910
15911 dns_severity_t
15912 dns_zone_getchecknames(dns_zone_t *zone) {
15913 REQUIRE(DNS_ZONE_VALID(zone));
15914
15915 return (zone->check_names);
15916 }
15917
15918 void
15919 dns_zone_setjournalsize(dns_zone_t *zone, int32_t size) {
15920 REQUIRE(DNS_ZONE_VALID(zone));
15921
15922 zone->journalsize = size;
15923 }
15924
15925 int32_t
15926 dns_zone_getjournalsize(dns_zone_t *zone) {
15927 REQUIRE(DNS_ZONE_VALID(zone));
15928
15929 return (zone->journalsize);
15930 }
15931
15932 static void
15933 zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) {
15934 isc_result_t result = ISC_R_FAILURE;
15935 isc_buffer_t buffer;
15936
15937 REQUIRE(buf != NULL);
15938 REQUIRE(length > 1U);
15939
15940 /*
15941 * Leave space for terminating '\0'.
15942 */
15943 isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
15944 if (zone->type != dns_zone_redirect && zone->type != dns_zone_key) {
15945 if (dns_name_dynamic(&zone->origin)) {
15946 result = dns_name_totext(&zone->origin, true, &buffer);
15947 }
15948 if (result != ISC_R_SUCCESS &&
15949 isc_buffer_availablelength(&buffer) >=
15950 (sizeof("<UNKNOWN>") - 1))
15951 {
15952 isc_buffer_putstr(&buffer, "<UNKNOWN>");
15953 }
15954
15955 if (isc_buffer_availablelength(&buffer) > 0) {
15956 isc_buffer_putstr(&buffer, "/");
15957 }
15958 (void)dns_rdataclass_totext(zone->rdclass, &buffer);
15959 }
15960
15961 if (zone->view != NULL && strcmp(zone->view->name, "_bind") != 0 &&
15962 strcmp(zone->view->name, "_default") != 0 &&
15963 strlen(zone->view->name) < isc_buffer_availablelength(&buffer))
15964 {
15965 isc_buffer_putstr(&buffer, "/");
15966 isc_buffer_putstr(&buffer, zone->view->name);
15967 }
15968 if (inline_secure(zone) && 9U < isc_buffer_availablelength(&buffer)) {
15969 isc_buffer_putstr(&buffer, " (signed)");
15970 }
15971 if (inline_raw(zone) && 11U < isc_buffer_availablelength(&buffer)) {
15972 isc_buffer_putstr(&buffer, " (unsigned)");
15973 }
15974
15975 buf[isc_buffer_usedlength(&buffer)] = '\0';
15976 }
15977
15978 static void
15979 zone_name_tostr(dns_zone_t *zone, char *buf, size_t length) {
15980 isc_result_t result = ISC_R_FAILURE;
15981 isc_buffer_t buffer;
15982
15983 REQUIRE(buf != NULL);
15984 REQUIRE(length > 1U);
15985
15986 /*
15987 * Leave space for terminating '\0'.
15988 */
15989 isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
15990 if (dns_name_dynamic(&zone->origin)) {
15991 result = dns_name_totext(&zone->origin, true, &buffer);
15992 }
15993 if (result != ISC_R_SUCCESS &&
15994 isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
15995 {
15996 isc_buffer_putstr(&buffer, "<UNKNOWN>");
15997 }
15998
15999 buf[isc_buffer_usedlength(&buffer)] = '\0';
16000 }
16001
16002 static void
16003 zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length) {
16004 isc_buffer_t buffer;
16005
16006 REQUIRE(buf != NULL);
16007 REQUIRE(length > 1U);
16008
16009 /*
16010 * Leave space for terminating '\0'.
16011 */
16012 isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
16013 (void)dns_rdataclass_totext(zone->rdclass, &buffer);
16014
16015 buf[isc_buffer_usedlength(&buffer)] = '\0';
16016 }
16017
16018 static void
16019 zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length) {
16020 isc_buffer_t buffer;
16021
16022 REQUIRE(buf != NULL);
16023 REQUIRE(length > 1U);
16024
16025 /*
16026 * Leave space for terminating '\0'.
16027 */
16028 isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
16029
16030 if (zone->view == NULL) {
16031 isc_buffer_putstr(&buffer, "_none");
16032 } else if (strlen(zone->view->name) <
16033 isc_buffer_availablelength(&buffer))
16034 {
16035 isc_buffer_putstr(&buffer, zone->view->name);
16036 } else {
16037 isc_buffer_putstr(&buffer, "_toolong");
16038 }
16039
16040 buf[isc_buffer_usedlength(&buffer)] = '\0';
16041 }
16042
16043 void
16044 dns_zone_name(dns_zone_t *zone, char *buf, size_t length) {
16045 REQUIRE(DNS_ZONE_VALID(zone));
16046 REQUIRE(buf != NULL);
16047
16048 LOCK_ZONE(zone);
16049 zone_namerd_tostr(zone, buf, length);
16050 UNLOCK_ZONE(zone);
16051 }
16052
16053 void
16054 dns_zone_nameonly(dns_zone_t *zone, char *buf, size_t length) {
16055 REQUIRE(DNS_ZONE_VALID(zone));
16056 REQUIRE(buf != NULL);
16057 zone_name_tostr(zone, buf, length);
16058 }
16059
16060 void
16061 dns_zone_logv(dns_zone_t *zone, isc_logcategory_t *category, int level,
16062 const char *prefix, const char *fmt, va_list ap) {
16063 char message[4096];
16064 const char *zstr;
16065
16066 REQUIRE(DNS_ZONE_VALID(zone));
16067
16068 if (!isc_log_wouldlog(dns_lctx, level)) {
16069 return;
16070 }
16071
16072 vsnprintf(message, sizeof(message), fmt, ap);
16073
16074 switch (zone->type) {
16075 case dns_zone_key:
16076 zstr = "managed-keys-zone";
16077 break;
16078 case dns_zone_redirect:
16079 zstr = "redirect-zone";
16080 break;
16081 default:
16082 zstr = "zone ";
16083 }
16084
16085 isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE, level,
16086 "%s%s%s%s: %s", (prefix != NULL ? prefix : ""),
16087 (prefix != NULL ? ": " : ""), zstr, zone->strnamerd,
16088 message);
16089 }
16090
16091 static void
16092 notify_log(dns_zone_t *zone, int level, const char *fmt, ...) {
16093 va_list ap;
16094
16095 va_start(ap, fmt);
16096 dns_zone_logv(zone, DNS_LOGCATEGORY_NOTIFY, level, NULL, fmt, ap);
16097 va_end(ap);
16098 }
16099
16100 void
16101 dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category, int level,
16102 const char *fmt, ...) {
16103 va_list ap;
16104
16105 va_start(ap, fmt);
16106 dns_zone_logv(zone, category, level, NULL, fmt, ap);
16107 va_end(ap);
16108 }
16109
16110 void
16111 dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) {
16112 va_list ap;
16113
16114 va_start(ap, fmt);
16115 dns_zone_logv(zone, DNS_LOGCATEGORY_GENERAL, level, NULL, fmt, ap);
16116 va_end(ap);
16117 }
16118
16119 static void
16120 zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel, const char *fmt,
16121 ...) {
16122 int level = ISC_LOG_DEBUG(debuglevel);
16123 va_list ap;
16124
16125 va_start(ap, fmt);
16126 dns_zone_logv(zone, DNS_LOGCATEGORY_GENERAL, level, me, fmt, ap);
16127 va_end(ap);
16128 }
16129
16130 static void
16131 dnssec_log(dns_zone_t *zone, int level, const char *fmt, ...) {
16132 va_list ap;
16133
16134 va_start(ap, fmt);
16135 dns_zone_logv(zone, DNS_LOGCATEGORY_DNSSEC, level, NULL, fmt, ap);
16136 va_end(ap);
16137 }
16138
16139 static int
16140 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type) {
16141 isc_result_t result;
16142 dns_name_t *name;
16143 dns_rdataset_t *curr;
16144 int count = 0;
16145
16146 result = dns_message_firstname(msg, section);
16147 while (result == ISC_R_SUCCESS) {
16148 name = NULL;
16149 dns_message_currentname(msg, section, &name);
16150
16151 for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
16152 curr = ISC_LIST_PREV(curr, link))
16153 {
16154 if (curr->type == type) {
16155 count++;
16156 }
16157 }
16158 result = dns_message_nextname(msg, section);
16159 }
16160
16161 return (count);
16162 }
16163
16164 void
16165 dns_zone_setmaxxfrin(dns_zone_t *zone, uint32_t maxxfrin) {
16166 REQUIRE(DNS_ZONE_VALID(zone));
16167
16168 zone->maxxfrin = maxxfrin;
16169 }
16170
16171 uint32_t
16172 dns_zone_getmaxxfrin(dns_zone_t *zone) {
16173 REQUIRE(DNS_ZONE_VALID(zone));
16174
16175 return (zone->maxxfrin);
16176 }
16177
16178 void
16179 dns_zone_setmaxxfrout(dns_zone_t *zone, uint32_t maxxfrout) {
16180 REQUIRE(DNS_ZONE_VALID(zone));
16181 zone->maxxfrout = maxxfrout;
16182 }
16183
16184 uint32_t
16185 dns_zone_getmaxxfrout(dns_zone_t *zone) {
16186 REQUIRE(DNS_ZONE_VALID(zone));
16187
16188 return (zone->maxxfrout);
16189 }
16190
16191 dns_zonetype_t
16192 dns_zone_gettype(dns_zone_t *zone) {
16193 REQUIRE(DNS_ZONE_VALID(zone));
16194
16195 return (zone->type);
16196 }
16197
16198 const char *
16199 dns_zonetype_name(dns_zonetype_t type) {
16200 switch (type) {
16201 case dns_zone_none:
16202 return ("none");
16203 case dns_zone_primary:
16204 return ("primary");
16205 case dns_zone_secondary:
16206 return ("secondary");
16207 case dns_zone_mirror:
16208 return ("mirror");
16209 case dns_zone_stub:
16210 return ("stub");
16211 case dns_zone_staticstub:
16212 return ("static-stub");
16213 case dns_zone_key:
16214 return ("key");
16215 case dns_zone_dlz:
16216 return ("dlz");
16217 case dns_zone_redirect:
16218 return ("redirect");
16219 default:
16220 return ("unknown");
16221 }
16222 }
16223
16224 dns_zonetype_t
16225 dns_zone_getredirecttype(dns_zone_t *zone) {
16226 REQUIRE(DNS_ZONE_VALID(zone));
16227 REQUIRE(zone->type == dns_zone_redirect);
16228
16229 return (zone->primaries == NULL ? dns_zone_primary
16230 : dns_zone_secondary);
16231 }
16232
16233 dns_name_t *
16234 dns_zone_getorigin(dns_zone_t *zone) {
16235 REQUIRE(DNS_ZONE_VALID(zone));
16236
16237 return (&zone->origin);
16238 }
16239
16240 void
16241 dns_zone_settask(dns_zone_t *zone, isc_task_t *task) {
16242 REQUIRE(DNS_ZONE_VALID(zone));
16243
16244 LOCK_ZONE(zone);
16245 if (zone->task != NULL) {
16246 isc_task_detach(&zone->task);
16247 }
16248 isc_task_attach(task, &zone->task);
16249 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
16250 if (zone->db != NULL) {
16251 dns_db_settask(zone->db, zone->task);
16252 }
16253 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
16254 UNLOCK_ZONE(zone);
16255 }
16256
16257 void
16258 dns_zone_gettask(dns_zone_t *zone, isc_task_t **target) {
16259 REQUIRE(DNS_ZONE_VALID(zone));
16260 isc_task_attach(zone->task, target);
16261 }
16262
16263 void
16264 dns_zone_setidlein(dns_zone_t *zone, uint32_t idlein) {
16265 REQUIRE(DNS_ZONE_VALID(zone));
16266
16267 if (idlein == 0) {
16268 idlein = DNS_DEFAULT_IDLEIN;
16269 }
16270 zone->idlein = idlein;
16271 }
16272
16273 uint32_t
16274 dns_zone_getidlein(dns_zone_t *zone) {
16275 REQUIRE(DNS_ZONE_VALID(zone));
16276
16277 return (zone->idlein);
16278 }
16279
16280 void
16281 dns_zone_setidleout(dns_zone_t *zone, uint32_t idleout) {
16282 REQUIRE(DNS_ZONE_VALID(zone));
16283
16284 zone->idleout = idleout;
16285 }
16286
16287 uint32_t
16288 dns_zone_getidleout(dns_zone_t *zone) {
16289 REQUIRE(DNS_ZONE_VALID(zone));
16290
16291 return (zone->idleout);
16292 }
16293
16294 static void
16295 notify_done(isc_task_t *task, isc_event_t *event) {
16296 dns_requestevent_t *revent = (dns_requestevent_t *)event;
16297 dns_notify_t *notify;
16298 isc_result_t result;
16299 dns_message_t *message = NULL;
16300 isc_buffer_t buf;
16301 char rcode[128];
16302 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
16303
16304 UNUSED(task);
16305
16306 notify = event->ev_arg;
16307 REQUIRE(DNS_NOTIFY_VALID(notify));
16308 INSIST(task == notify->zone->task);
16309
16310 isc_buffer_init(&buf, rcode, sizeof(rcode));
16311 isc_sockaddr_format(¬ify->dst, addrbuf, sizeof(addrbuf));
16312 dns_message_create(notify->zone->mctx, DNS_MESSAGE_INTENTPARSE,
16313 &message);
16314
16315 if (revent->result != ISC_R_SUCCESS) {
16316 result = revent->result;
16317 goto fail;
16318 }
16319
16320 result = dns_request_getresponse(revent->request, message,
16321 DNS_MESSAGEPARSE_PRESERVEORDER);
16322 if (result != ISC_R_SUCCESS) {
16323 goto fail;
16324 }
16325
16326 result = dns_rcode_totext(message->rcode, &buf);
16327 if (result == ISC_R_SUCCESS) {
16328 notify_log(notify->zone, ISC_LOG_DEBUG(3),
16329 "notify response from %s: %.*s", addrbuf,
16330 (int)buf.used, rcode);
16331 }
16332
16333 goto done;
16334
16335 fail:
16336 notify_log(notify->zone, ISC_LOG_DEBUG(2), "notify to %s failed: %s",
16337 addrbuf, isc_result_totext(result));
16338 if (result == ISC_R_TIMEDOUT) {
16339 notify_log(notify->zone, ISC_LOG_DEBUG(1),
16340 "notify to %s: retries exceeded", addrbuf);
16341 }
16342 done:
16343 notify_destroy(notify, false);
16344 isc_event_free(&event);
16345 dns_message_detach(&message);
16346 }
16347
16348 struct secure_event {
16349 isc_event_t e;
16350 dns_db_t *db;
16351 uint32_t serial;
16352 };
16353
16354 static void
16355 update_log_cb(void *arg, dns_zone_t *zone, int level, const char *message) {
16356 UNUSED(arg);
16357 dns_zone_log(zone, level, "%s", message);
16358 }
16359
16360 static isc_result_t
16361 sync_secure_journal(dns_zone_t *zone, dns_zone_t *raw, dns_journal_t *journal,
16362 uint32_t start, uint32_t end, dns_difftuple_t **soatuplep,
16363 dns_diff_t *diff) {
16364 isc_result_t result;
16365 dns_difftuple_t *tuple = NULL;
16366 dns_diffop_t op = DNS_DIFFOP_ADD;
16367 int n_soa = 0;
16368
16369 REQUIRE(soatuplep != NULL);
16370
16371 if (start == end) {
16372 return (DNS_R_UNCHANGED);
16373 }
16374
16375 CHECK(dns_journal_iter_init(journal, start, end, NULL));
16376 for (result = dns_journal_first_rr(journal); result == ISC_R_SUCCESS;
16377 result = dns_journal_next_rr(journal))
16378 {
16379 dns_name_t *name = NULL;
16380 uint32_t ttl;
16381 dns_rdata_t *rdata = NULL;
16382 dns_journal_current_rr(journal, &name, &ttl, &rdata);
16383
16384 if (rdata->type == dns_rdatatype_soa) {
16385 n_soa++;
16386 if (n_soa == 2) {
16387 /*
16388 * Save the latest raw SOA record.
16389 */
16390 if (*soatuplep != NULL) {
16391 dns_difftuple_free(soatuplep);
16392 }
16393 CHECK(dns_difftuple_create(
16394 diff->mctx, DNS_DIFFOP_ADD, name, ttl,
16395 rdata, soatuplep));
16396 }
16397 if (n_soa == 3) {
16398 n_soa = 1;
16399 }
16400 continue;
16401 }
16402
16403 /* Sanity. */
16404 if (n_soa == 0) {
16405 dns_zone_log(raw, ISC_LOG_ERROR,
16406 "corrupt journal file: '%s'\n",
16407 raw->journal);
16408 return (ISC_R_FAILURE);
16409 }
16410
16411 if (zone->privatetype != 0 && rdata->type == zone->privatetype)
16412 {
16413 continue;
16414 }
16415
16416 if (rdata->type == dns_rdatatype_nsec ||
16417 rdata->type == dns_rdatatype_rrsig ||
16418 rdata->type == dns_rdatatype_nsec3 ||
16419 rdata->type == dns_rdatatype_dnskey ||
16420 rdata->type == dns_rdatatype_nsec3param)
16421 {
16422 continue;
16423 }
16424
16425 op = (n_soa == 1) ? DNS_DIFFOP_DEL : DNS_DIFFOP_ADD;
16426
16427 CHECK(dns_difftuple_create(diff->mctx, op, name, ttl, rdata,
16428 &tuple));
16429 dns_diff_appendminimal(diff, &tuple);
16430 }
16431 if (result == ISC_R_NOMORE) {
16432 result = ISC_R_SUCCESS;
16433 }
16434
16435 failure:
16436 return (result);
16437 }
16438
16439 static isc_result_t
16440 sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb,
16441 dns_dbversion_t *secver, dns_difftuple_t **soatuple,
16442 dns_diff_t *diff) {
16443 isc_result_t result;
16444 dns_db_t *rawdb = NULL;
16445 dns_dbversion_t *rawver = NULL;
16446 dns_difftuple_t *tuple = NULL, *next;
16447 dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
16448 dns_rdata_soa_t oldsoa, newsoa;
16449
16450 REQUIRE(DNS_ZONE_VALID(seczone));
16451 REQUIRE(soatuple != NULL && *soatuple == NULL);
16452
16453 if (!seczone->sourceserialset) {
16454 return (DNS_R_UNCHANGED);
16455 }
16456
16457 dns_db_attach(raw->db, &rawdb);
16458 dns_db_currentversion(rawdb, &rawver);
16459 result = dns_db_diffx(diff, rawdb, rawver, secdb, secver, NULL);
16460 dns_db_closeversion(rawdb, &rawver, false);
16461 dns_db_detach(&rawdb);
16462
16463 if (result != ISC_R_SUCCESS) {
16464 return (result);
16465 }
16466
16467 for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL; tuple = next) {
16468 next = ISC_LIST_NEXT(tuple, link);
16469 if (tuple->rdata.type == dns_rdatatype_nsec ||
16470 tuple->rdata.type == dns_rdatatype_rrsig ||
16471 tuple->rdata.type == dns_rdatatype_dnskey ||
16472 tuple->rdata.type == dns_rdatatype_nsec3 ||
16473 tuple->rdata.type == dns_rdatatype_nsec3param)
16474 {
16475 ISC_LIST_UNLINK(diff->tuples, tuple, link);
16476 dns_difftuple_free(&tuple);
16477 continue;
16478 }
16479 if (tuple->rdata.type == dns_rdatatype_soa) {
16480 if (tuple->op == DNS_DIFFOP_DEL) {
16481 INSIST(oldtuple == NULL);
16482 oldtuple = tuple;
16483 }
16484 if (tuple->op == DNS_DIFFOP_ADD) {
16485 INSIST(newtuple == NULL);
16486 newtuple = tuple;
16487 }
16488 }
16489 }
16490
16491 if (oldtuple != NULL && newtuple != NULL) {
16492 result = dns_rdata_tostruct(&oldtuple->rdata, &oldsoa, NULL);
16493 RUNTIME_CHECK(result == ISC_R_SUCCESS);
16494
16495 result = dns_rdata_tostruct(&newtuple->rdata, &newsoa, NULL);
16496 RUNTIME_CHECK(result == ISC_R_SUCCESS);
16497
16498 /*
16499 * If the SOA records are the same except for the serial
16500 * remove them from the diff.
16501 */
16502 if (oldtuple->ttl == newtuple->ttl &&
16503 oldsoa.refresh == newsoa.refresh &&
16504 oldsoa.retry == newsoa.retry &&
16505 oldsoa.minimum == newsoa.minimum &&
16506 oldsoa.expire == newsoa.expire &&
16507 dns_name_equal(&oldsoa.origin, &newsoa.origin) &&
16508 dns_name_equal(&oldsoa.contact, &newsoa.contact))
16509 {
16510 ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
16511 dns_difftuple_free(&oldtuple);
16512 ISC_LIST_UNLINK(diff->tuples, newtuple, link);
16513 dns_difftuple_free(&newtuple);
16514 }
16515 }
16516
16517 if (ISC_LIST_EMPTY(diff->tuples)) {
16518 return (DNS_R_UNCHANGED);
16519 }
16520
16521 /*
16522 * If there are still SOA records in the diff they can now be removed
16523 * saving the new SOA record.
16524 */
16525 if (oldtuple != NULL) {
16526 ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
16527 dns_difftuple_free(&oldtuple);
16528 }
16529
16530 if (newtuple != NULL) {
16531 ISC_LIST_UNLINK(diff->tuples, newtuple, link);
16532 *soatuple = newtuple;
16533 }
16534
16535 return (ISC_R_SUCCESS);
16536 }
16537
16538 static void
16539 receive_secure_serial(isc_task_t *task, isc_event_t *event) {
16540 static char me[] = "receive_secure_serial";
16541 isc_result_t result = ISC_R_SUCCESS;
16542 dns_journal_t *rjournal = NULL;
16543 dns_journal_t *sjournal = NULL;
16544 uint32_t start, end;
16545 dns_zone_t *zone;
16546 dns_difftuple_t *tuple = NULL, *soatuple = NULL;
16547 dns_update_log_t log = { update_log_cb, NULL };
16548 uint32_t newserial = 0, desired = 0;
16549 isc_time_t timenow;
16550 int level = ISC_LOG_ERROR;
16551
16552 UNUSED(task);
16553
16554 zone = event->ev_arg;
16555 end = ((struct secure_event *)event)->serial;
16556
16557 ENTER;
16558
16559 LOCK_ZONE(zone);
16560
16561 /*
16562 * If we are already processing a receive secure serial event
16563 * for the zone, just queue the new one and exit.
16564 */
16565 if (zone->rss_event != NULL && zone->rss_event != event) {
16566 ISC_LIST_APPEND(zone->rss_events, event, ev_link);
16567 UNLOCK_ZONE(zone);
16568 return;
16569 }
16570
16571 nextevent:
16572 if (zone->rss_event != NULL) {
16573 INSIST(zone->rss_event == event);
16574 UNLOCK_ZONE(zone);
16575 } else {
16576 zone->rss_event = event;
16577 dns_diff_init(zone->mctx, &zone->rss_diff);
16578
16579 /*
16580 * zone->db may be NULL, if the load from disk failed.
16581 */
16582 result = ISC_R_SUCCESS;
16583 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
16584 if (zone->db != NULL) {
16585 dns_db_attach(zone->db, &zone->rss_db);
16586 } else {
16587 result = ISC_R_FAILURE;
16588 }
16589 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
16590
16591 if (result == ISC_R_SUCCESS && zone->raw != NULL) {
16592 dns_zone_attach(zone->raw, &zone->rss_raw);
16593 } else {
16594 result = ISC_R_FAILURE;
16595 }
16596
16597 UNLOCK_ZONE(zone);
16598
16599 CHECK(result);
16600
16601 /*
16602 * We first attempt to sync the raw zone to the secure zone
16603 * by using the raw zone's journal, applying all the deltas
16604 * from the latest source-serial of the secure zone up to
16605 * the current serial number of the raw zone.
16606 *
16607 * If that fails, then we'll fall back to a direct comparison
16608 * between raw and secure zones.
16609 */
16610 CHECK(dns_journal_open(zone->rss_raw->mctx,
16611 zone->rss_raw->journal,
16612 DNS_JOURNAL_WRITE, &rjournal));
16613
16614 result = dns_journal_open(zone->mctx, zone->journal,
16615 DNS_JOURNAL_READ, &sjournal);
16616 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
16617 goto failure;
16618 }
16619
16620 if (!dns_journal_get_sourceserial(rjournal, &start)) {
16621 start = dns_journal_first_serial(rjournal);
16622 dns_journal_set_sourceserial(rjournal, start);
16623 }
16624 if (sjournal != NULL) {
16625 uint32_t serial;
16626 /*
16627 * We read the secure journal first, if that
16628 * exists use its value provided it is greater
16629 * that from the raw journal.
16630 */
16631 if (dns_journal_get_sourceserial(sjournal, &serial)) {
16632 if (isc_serial_gt(serial, start)) {
16633 start = serial;
16634 }
16635 }
16636 dns_journal_destroy(&sjournal);
16637 }
16638
16639 dns_db_currentversion(zone->rss_db, &zone->rss_oldver);
16640 CHECK(dns_db_newversion(zone->rss_db, &zone->rss_newver));
16641
16642 /*
16643 * Try to apply diffs from the raw zone's journal to the secure
16644 * zone. If that fails, we recover by syncing up the databases
16645 * directly.
16646 */
16647 result = sync_secure_journal(zone, zone->rss_raw, rjournal,
16648 start, end, &soatuple,
16649 &zone->rss_diff);
16650 if (result == DNS_R_UNCHANGED) {
16651 goto failure;
16652 } else if (result != ISC_R_SUCCESS) {
16653 CHECK(sync_secure_db(zone, zone->rss_raw, zone->rss_db,
16654 zone->rss_oldver, &soatuple,
16655 &zone->rss_diff));
16656 }
16657
16658 CHECK(dns_diff_apply(&zone->rss_diff, zone->rss_db,
16659 zone->rss_newver));
16660
16661 if (soatuple != NULL) {
16662 uint32_t oldserial;
16663
16664 CHECK(dns_db_createsoatuple(
16665 zone->rss_db, zone->rss_oldver,
16666 zone->rss_diff.mctx, DNS_DIFFOP_DEL, &tuple));
16667 oldserial = dns_soa_getserial(&tuple->rdata);
16668 newserial = desired =
16669 dns_soa_getserial(&soatuple->rdata);
16670 if (!isc_serial_gt(newserial, oldserial)) {
16671 newserial = oldserial + 1;
16672 if (newserial == 0) {
16673 newserial++;
16674 }
16675 dns_soa_setserial(newserial, &soatuple->rdata);
16676 }
16677 CHECK(do_one_tuple(&tuple, zone->rss_db,
16678 zone->rss_newver, &zone->rss_diff));
16679 CHECK(do_one_tuple(&soatuple, zone->rss_db,
16680 zone->rss_newver, &zone->rss_diff));
16681 } else {
16682 CHECK(update_soa_serial(zone, zone->rss_db,
16683 zone->rss_newver,
16684 &zone->rss_diff, zone->mctx,
16685 zone->updatemethod));
16686 }
16687 }
16688 result = dns_update_signaturesinc(
16689 &log, zone, zone->rss_db, zone->rss_oldver, zone->rss_newver,
16690 &zone->rss_diff, zone->sigvalidityinterval, &zone->rss_state);
16691 if (result == DNS_R_CONTINUE) {
16692 if (rjournal != NULL) {
16693 dns_journal_destroy(&rjournal);
16694 }
16695 isc_task_send(task, &event);
16696 return;
16697 }
16698 /*
16699 * If something went wrong while trying to update the secure zone and
16700 * the latter was already signed before, do not apply raw zone deltas
16701 * to it as that would break existing DNSSEC signatures. However, if
16702 * the secure zone was not yet signed (e.g. because no signing keys
16703 * were created for it), commence applying raw zone deltas to it so
16704 * that contents of the raw zone and the secure zone are kept in sync.
16705 */
16706 if (result != ISC_R_SUCCESS && dns_db_issecure(zone->rss_db)) {
16707 goto failure;
16708 }
16709
16710 if (rjournal == NULL) {
16711 CHECK(dns_journal_open(zone->rss_raw->mctx,
16712 zone->rss_raw->journal,
16713 DNS_JOURNAL_WRITE, &rjournal));
16714 }
16715 CHECK(zone_journal(zone, &zone->rss_diff, &end,
16716 "receive_secure_serial"));
16717
16718 dns_journal_set_sourceserial(rjournal, end);
16719 dns_journal_commit(rjournal);
16720
16721 LOCK_ZONE(zone);
16722 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
16723
16724 zone->sourceserial = end;
16725 zone->sourceserialset = true;
16726 zone_needdump(zone, DNS_DUMP_DELAY);
16727
16728 /*
16729 * Set resign time to make sure it is set to the earliest
16730 * signature expiration.
16731 */
16732 set_resigntime(zone);
16733 TIME_NOW(&timenow);
16734 zone_settimer(zone, &timenow);
16735 UNLOCK_ZONE(zone);
16736
16737 dns_db_closeversion(zone->rss_db, &zone->rss_oldver, false);
16738 dns_db_closeversion(zone->rss_db, &zone->rss_newver, true);
16739
16740 if (newserial != 0) {
16741 dns_zone_log(zone, ISC_LOG_INFO, "serial %u (unsigned %u)",
16742 newserial, desired);
16743 }
16744
16745 failure:
16746 isc_event_free(&zone->rss_event);
16747 event = ISC_LIST_HEAD(zone->rss_events);
16748
16749 if (zone->rss_raw != NULL) {
16750 dns_zone_detach(&zone->rss_raw);
16751 }
16752 if (result != ISC_R_SUCCESS) {
16753 LOCK_ZONE(zone);
16754 set_resigntime(zone);
16755 TIME_NOW(&timenow);
16756 zone_settimer(zone, &timenow);
16757 UNLOCK_ZONE(zone);
16758 if (result == DNS_R_UNCHANGED) {
16759 level = ISC_LOG_INFO;
16760 }
16761 dns_zone_log(zone, level, "receive_secure_serial: %s",
16762 isc_result_totext(result));
16763 }
16764 if (tuple != NULL) {
16765 dns_difftuple_free(&tuple);
16766 }
16767 if (soatuple != NULL) {
16768 dns_difftuple_free(&soatuple);
16769 }
16770 if (zone->rss_db != NULL) {
16771 if (zone->rss_oldver != NULL) {
16772 dns_db_closeversion(zone->rss_db, &zone->rss_oldver,
16773 false);
16774 }
16775 if (zone->rss_newver != NULL) {
16776 dns_db_closeversion(zone->rss_db, &zone->rss_newver,
16777 false);
16778 }
16779 dns_db_detach(&zone->rss_db);
16780 }
16781 INSIST(zone->rss_oldver == NULL);
16782 INSIST(zone->rss_newver == NULL);
16783 if (rjournal != NULL) {
16784 dns_journal_destroy(&rjournal);
16785 }
16786 dns_diff_clear(&zone->rss_diff);
16787
16788 if (event != NULL) {
16789 LOCK_ZONE(zone);
16790 isc_refcount_decrement(&zone->irefs);
16791 ISC_LIST_UNLINK(zone->rss_events, event, ev_link);
16792 goto nextevent;
16793 }
16794
16795 event = ISC_LIST_HEAD(zone->rss_post);
16796 while (event != NULL) {
16797 ISC_LIST_UNLINK(zone->rss_post, event, ev_link);
16798 rss_post(zone, event);
16799 event = ISC_LIST_HEAD(zone->rss_post);
16800 }
16801
16802 dns_zone_idetach(&zone);
16803 }
16804
16805 static isc_result_t
16806 zone_send_secureserial(dns_zone_t *zone, uint32_t serial) {
16807 isc_event_t *e;
16808 dns_zone_t *dummy = NULL;
16809
16810 e = isc_event_allocate(zone->secure->mctx, zone,
16811 DNS_EVENT_ZONESECURESERIAL,
16812 receive_secure_serial, zone->secure,
16813 sizeof(struct secure_event));
16814 ((struct secure_event *)e)->serial = serial;
16815 INSIST(LOCKED_ZONE(zone->secure));
16816 zone_iattach(zone->secure, &dummy);
16817 isc_task_send(zone->secure->task, &e);
16818
16819 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
16820 return (ISC_R_SUCCESS);
16821 }
16822
16823 static isc_result_t
16824 checkandaddsoa(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
16825 dns_rdataset_t *rdataset, uint32_t oldserial) {
16826 dns_rdata_soa_t soa;
16827 dns_rdata_t rdata = DNS_RDATA_INIT;
16828 dns_rdatalist_t temprdatalist;
16829 dns_rdataset_t temprdataset;
16830 isc_buffer_t b;
16831 isc_result_t result;
16832 unsigned char buf[DNS_SOA_BUFFERSIZE];
16833 dns_fixedname_t fixed;
16834 dns_name_t *name;
16835
16836 result = dns_rdataset_first(rdataset);
16837 RUNTIME_CHECK(result == ISC_R_SUCCESS);
16838 dns_rdataset_current(rdataset, &rdata);
16839 result = dns_rdata_tostruct(&rdata, &soa, NULL);
16840 RUNTIME_CHECK(result == ISC_R_SUCCESS);
16841
16842 if (isc_serial_gt(soa.serial, oldserial)) {
16843 return (dns_db_addrdataset(db, node, version, 0, rdataset, 0,
16844 NULL));
16845 }
16846 /*
16847 * Always bump the serial.
16848 */
16849 oldserial++;
16850 if (oldserial == 0) {
16851 oldserial++;
16852 }
16853 soa.serial = oldserial;
16854
16855 /*
16856 * Construct a replacement rdataset.
16857 */
16858 dns_rdata_reset(&rdata);
16859 isc_buffer_init(&b, buf, sizeof(buf));
16860 result = dns_rdata_fromstruct(&rdata, rdataset->rdclass,
16861 dns_rdatatype_soa, &soa, &b);
16862 RUNTIME_CHECK(result == ISC_R_SUCCESS);
16863 dns_rdatalist_init(&temprdatalist);
16864 temprdatalist.rdclass = rdata.rdclass;
16865 temprdatalist.type = rdata.type;
16866 temprdatalist.ttl = rdataset->ttl;
16867 ISC_LIST_APPEND(temprdatalist.rdata, &rdata, link);
16868
16869 dns_rdataset_init(&temprdataset);
16870 result = dns_rdatalist_tordataset(&temprdatalist, &temprdataset);
16871 RUNTIME_CHECK(result == ISC_R_SUCCESS);
16872
16873 name = dns_fixedname_initname(&fixed);
16874 result = dns_db_nodefullname(db, node, name);
16875 RUNTIME_CHECK(result == ISC_R_SUCCESS);
16876 dns_rdataset_getownercase(rdataset, name);
16877 dns_rdataset_setownercase(&temprdataset, name);
16878 return (dns_db_addrdataset(db, node, version, 0, &temprdataset, 0,
16879 NULL));
16880 }
16881
16882 /*
16883 * This function should populate an nsec3paramlist_t with the
16884 * nsecparam_t data from a zone.
16885 */
16886 static isc_result_t
16887 save_nsec3param(dns_zone_t *zone, nsec3paramlist_t *nsec3list) {
16888 isc_result_t result;
16889 dns_dbnode_t *node = NULL;
16890 dns_rdataset_t rdataset, prdataset;
16891 dns_dbversion_t *version = NULL;
16892 nsec3param_t *nsec3param = NULL;
16893 nsec3param_t *nsec3p = NULL;
16894 nsec3param_t *next;
16895 dns_db_t *db = NULL;
16896 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
16897
16898 REQUIRE(DNS_ZONE_VALID(zone));
16899 REQUIRE(nsec3list != NULL);
16900 REQUIRE(ISC_LIST_EMPTY(*nsec3list));
16901
16902 dns_rdataset_init(&rdataset);
16903 dns_rdataset_init(&prdataset);
16904
16905 dns_db_attach(zone->db, &db);
16906 CHECK(dns_db_getoriginnode(db, &node));
16907
16908 dns_db_currentversion(db, &version);
16909 result = dns_db_findrdataset(db, node, version,
16910 dns_rdatatype_nsec3param,
16911 dns_rdatatype_none, 0, &rdataset, NULL);
16912
16913 if (result != ISC_R_SUCCESS) {
16914 goto getprivate;
16915 }
16916
16917 /*
16918 * Walk nsec3param rdataset making a list of parameters (note that
16919 * multiple simultaneous nsec3 chains are annoyingly legal -- this
16920 * is why we use an nsec3list, even though we will usually only
16921 * have one).
16922 */
16923 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
16924 result = dns_rdataset_next(&rdataset))
16925 {
16926 dns_rdata_t rdata = DNS_RDATA_INIT;
16927 dns_rdata_t private = DNS_RDATA_INIT;
16928
16929 dns_rdataset_current(&rdataset, &rdata);
16930 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
16931 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
16932 "looping through nsec3param data");
16933 nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
16934 ISC_LINK_INIT(nsec3param, link);
16935
16936 /*
16937 * now transfer the data from the rdata to
16938 * the nsec3param
16939 */
16940 dns_nsec3param_toprivate(&rdata, &private, zone->privatetype,
16941 nsec3param->data,
16942 sizeof(nsec3param->data));
16943 nsec3param->length = private.length;
16944 ISC_LIST_APPEND(*nsec3list, nsec3param, link);
16945 }
16946
16947 getprivate:
16948 result = dns_db_findrdataset(db, node, version, zone->privatetype,
16949 dns_rdatatype_none, 0, &prdataset, NULL);
16950 if (result != ISC_R_SUCCESS) {
16951 goto done;
16952 }
16953
16954 /*
16955 * walk private type records, converting them to nsec3 parameters
16956 * using dns_nsec3param_fromprivate(), do the right thing based on
16957 * CREATE and REMOVE flags
16958 */
16959 for (result = dns_rdataset_first(&prdataset); result == ISC_R_SUCCESS;
16960 result = dns_rdataset_next(&prdataset))
16961 {
16962 dns_rdata_t rdata = DNS_RDATA_INIT;
16963 dns_rdata_t private = DNS_RDATA_INIT;
16964
16965 dns_rdataset_current(&prdataset, &private);
16966 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
16967 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
16968 "looping through nsec3param private data");
16969
16970 /*
16971 * Do we have a valid private record?
16972 */
16973 if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
16974 sizeof(buf)))
16975 {
16976 continue;
16977 }
16978
16979 /*
16980 * Remove any NSEC3PARAM records scheduled to be removed.
16981 */
16982 if (NSEC3REMOVE(rdata.data[1])) {
16983 /*
16984 * Zero out the flags.
16985 */
16986 rdata.data[1] = 0;
16987
16988 for (nsec3p = ISC_LIST_HEAD(*nsec3list); nsec3p != NULL;
16989 nsec3p = next)
16990 {
16991 next = ISC_LIST_NEXT(nsec3p, link);
16992
16993 if (nsec3p->length == rdata.length + 1 &&
16994 memcmp(rdata.data, nsec3p->data + 1,
16995 nsec3p->length - 1) == 0)
16996 {
16997 ISC_LIST_UNLINK(*nsec3list, nsec3p,
16998 link);
16999 isc_mem_put(zone->mctx, nsec3p,
17000 sizeof(nsec3param_t));
17001 }
17002 }
17003 continue;
17004 }
17005
17006 nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
17007 ISC_LINK_INIT(nsec3param, link);
17008
17009 /*
17010 * Copy the remaining private records so the nsec/nsec3
17011 * chain gets created.
17012 */
17013 INSIST(private.length <= sizeof(nsec3param->data));
17014 memmove(nsec3param->data, private.data, private.length);
17015 nsec3param->length = private.length;
17016 ISC_LIST_APPEND(*nsec3list, nsec3param, link);
17017 }
17018
17019 done:
17020 if (result == ISC_R_NOMORE || result == ISC_R_NOTFOUND) {
17021 result = ISC_R_SUCCESS;
17022 }
17023
17024 failure:
17025 if (node != NULL) {
17026 dns_db_detachnode(db, &node);
17027 }
17028 if (version != NULL) {
17029 dns_db_closeversion(db, &version, false);
17030 }
17031 if (db != NULL) {
17032 dns_db_detach(&db);
17033 }
17034 if (dns_rdataset_isassociated(&rdataset)) {
17035 dns_rdataset_disassociate(&rdataset);
17036 }
17037 if (dns_rdataset_isassociated(&prdataset)) {
17038 dns_rdataset_disassociate(&prdataset);
17039 }
17040 return (result);
17041 }
17042
17043 /*
17044 * Populate new zone db with private type records found by save_nsec3param().
17045 */
17046 static isc_result_t
17047 restore_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
17048 nsec3paramlist_t *nsec3list) {
17049 isc_result_t result = ISC_R_SUCCESS;
17050 dns_diff_t diff;
17051 dns_rdata_t rdata;
17052 nsec3param_t *nsec3p = NULL;
17053 nsec3param_t *next;
17054
17055 REQUIRE(DNS_ZONE_VALID(zone));
17056 REQUIRE(!ISC_LIST_EMPTY(*nsec3list));
17057
17058 dns_diff_init(zone->mctx, &diff);
17059
17060 /*
17061 * Loop through the list of private-type records, set the INITIAL
17062 * and CREATE flags, and the add the record to the apex of the tree
17063 * in db.
17064 */
17065 for (nsec3p = ISC_LIST_HEAD(*nsec3list); nsec3p != NULL; nsec3p = next)
17066 {
17067 next = ISC_LIST_NEXT(nsec3p, link);
17068 dns_rdata_init(&rdata);
17069 nsec3p->data[2] = DNS_NSEC3FLAG_CREATE | DNS_NSEC3FLAG_INITIAL;
17070 rdata.length = nsec3p->length;
17071 rdata.data = nsec3p->data;
17072 rdata.type = zone->privatetype;
17073 rdata.rdclass = zone->rdclass;
17074 result = update_one_rr(db, version, &diff, DNS_DIFFOP_ADD,
17075 &zone->origin, 0, &rdata);
17076 if (result != ISC_R_SUCCESS) {
17077 break;
17078 }
17079 }
17080
17081 dns_diff_clear(&diff);
17082 return (result);
17083 }
17084
17085 static isc_result_t
17086 copy_non_dnssec_records(dns_db_t *db, dns_db_t *version, dns_db_t *rawdb,
17087 dns_dbiterator_t *dbiterator, unsigned int *oldserial) {
17088 dns_dbnode_t *rawnode = NULL, *node = NULL;
17089 dns_fixedname_t fixed;
17090 dns_name_t *name = dns_fixedname_initname(&fixed);
17091 dns_rdataset_t rdataset;
17092 dns_rdatasetiter_t *rdsit = NULL;
17093 isc_result_t result;
17094
17095 result = dns_dbiterator_current(dbiterator, &rawnode, name);
17096 if (result != ISC_R_SUCCESS) {
17097 return (ISC_R_SUCCESS);
17098 }
17099
17100 dns_dbiterator_pause(dbiterator);
17101
17102 result = dns_db_findnode(db, name, true, &node);
17103 if (result != ISC_R_SUCCESS) {
17104 goto cleanup;
17105 }
17106
17107 result = dns_db_allrdatasets(rawdb, rawnode, NULL, 0, 0, &rdsit);
17108 if (result != ISC_R_SUCCESS) {
17109 goto cleanup;
17110 }
17111
17112 dns_rdataset_init(&rdataset);
17113
17114 for (result = dns_rdatasetiter_first(rdsit); result == ISC_R_SUCCESS;
17115 result = dns_rdatasetiter_next(rdsit))
17116 {
17117 dns_rdatasetiter_current(rdsit, &rdataset);
17118 if (rdataset.type == dns_rdatatype_nsec ||
17119 rdataset.type == dns_rdatatype_rrsig ||
17120 rdataset.type == dns_rdatatype_nsec3 ||
17121 rdataset.type == dns_rdatatype_dnskey ||
17122 rdataset.type == dns_rdatatype_nsec3param)
17123 {
17124 dns_rdataset_disassociate(&rdataset);
17125 continue;
17126 }
17127 if (rdataset.type == dns_rdatatype_soa && oldserial != NULL) {
17128 result = checkandaddsoa(db, node, version, &rdataset,
17129 *oldserial);
17130 } else {
17131 result = dns_db_addrdataset(db, node, version, 0,
17132 &rdataset, 0, NULL);
17133 }
17134 dns_rdataset_disassociate(&rdataset);
17135 if (result != ISC_R_SUCCESS) {
17136 goto cleanup;
17137 }
17138 }
17139 if (result == ISC_R_NOMORE) {
17140 result = ISC_R_SUCCESS;
17141 }
17142
17143 cleanup:
17144 if (rdsit != NULL) {
17145 dns_rdatasetiter_destroy(&rdsit);
17146 }
17147 if (rawnode) {
17148 dns_db_detachnode(rawdb, &rawnode);
17149 }
17150 if (node) {
17151 dns_db_detachnode(db, &node);
17152 }
17153 return (result);
17154 }
17155
17156 static void
17157 receive_secure_db(isc_task_t *task, isc_event_t *event) {
17158 isc_result_t result;
17159 dns_zone_t *zone;
17160 dns_db_t *rawdb, *db = NULL;
17161 dns_dbiterator_t *dbiterator = NULL;
17162 dns_dbversion_t *version = NULL;
17163 isc_time_t loadtime;
17164 unsigned int oldserial = 0, *oldserialp = NULL;
17165 nsec3paramlist_t nsec3list;
17166 isc_event_t *setnsec3param_event;
17167 dns_zone_t *dummy;
17168
17169 UNUSED(task);
17170
17171 ISC_LIST_INIT(nsec3list);
17172
17173 zone = event->ev_arg;
17174 rawdb = ((struct secure_event *)event)->db;
17175 isc_event_free(&event);
17176
17177 LOCK_ZONE(zone);
17178 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || !inline_secure(zone)) {
17179 result = ISC_R_SHUTTINGDOWN;
17180 goto failure;
17181 }
17182
17183 TIME_NOW(&loadtime);
17184 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
17185 if (zone->db != NULL) {
17186 result = dns_db_getsoaserial(zone->db, NULL, &oldserial);
17187 if (result == ISC_R_SUCCESS) {
17188 oldserialp = &oldserial;
17189 }
17190
17191 /*
17192 * assemble nsec3parameters from the old zone, and set a flag
17193 * if any are found
17194 */
17195 result = save_nsec3param(zone, &nsec3list);
17196 if (result != ISC_R_SUCCESS) {
17197 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17198 goto failure;
17199 }
17200 }
17201 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17202
17203 result = dns_db_create(zone->mctx, zone->db_argv[0], &zone->origin,
17204 dns_dbtype_zone, zone->rdclass,
17205 zone->db_argc - 1, zone->db_argv + 1, &db);
17206 if (result != ISC_R_SUCCESS) {
17207 goto failure;
17208 }
17209
17210 result = dns_db_setgluecachestats(db, zone->gluecachestats);
17211 if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) {
17212 goto failure;
17213 }
17214
17215 result = dns_db_newversion(db, &version);
17216 if (result != ISC_R_SUCCESS) {
17217 goto failure;
17218 }
17219
17220 result = dns_db_createiterator(rawdb, 0, &dbiterator);
17221 if (result != ISC_R_SUCCESS) {
17222 goto failure;
17223 }
17224
17225 for (result = dns_dbiterator_first(dbiterator); result == ISC_R_SUCCESS;
17226 result = dns_dbiterator_next(dbiterator))
17227 {
17228 result = copy_non_dnssec_records(db, version, rawdb, dbiterator,
17229 oldserialp);
17230 if (result != ISC_R_SUCCESS) {
17231 goto failure;
17232 }
17233 }
17234 dns_dbiterator_destroy(&dbiterator);
17235 if (result != ISC_R_NOMORE) {
17236 goto failure;
17237 }
17238
17239 /*
17240 * Call restore_nsec3param() to create private-type records from
17241 * the old nsec3 parameters and insert them into db
17242 */
17243 if (!ISC_LIST_EMPTY(nsec3list)) {
17244 result = restore_nsec3param(zone, db, version, &nsec3list);
17245 if (result != ISC_R_SUCCESS) {
17246 goto failure;
17247 }
17248 }
17249
17250 dns_db_closeversion(db, &version, true);
17251
17252 /*
17253 * Lock hierarchy: zmgr, zone, raw.
17254 */
17255 INSIST(zone != zone->raw);
17256 LOCK_ZONE(zone->raw);
17257 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
17258 result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
17259 zone_needdump(zone, 0); /* XXXMPA */
17260 UNLOCK_ZONE(zone->raw);
17261
17262 /*
17263 * Process any queued NSEC3PARAM change requests.
17264 */
17265 while (!ISC_LIST_EMPTY(zone->setnsec3param_queue)) {
17266 setnsec3param_event = ISC_LIST_HEAD(zone->setnsec3param_queue);
17267 ISC_LIST_UNLINK(zone->setnsec3param_queue, setnsec3param_event,
17268 ev_link);
17269 dummy = NULL;
17270 zone_iattach(zone, &dummy);
17271 isc_task_send(zone->task, &setnsec3param_event);
17272 }
17273
17274 failure:
17275 UNLOCK_ZONE(zone);
17276 if (dbiterator != NULL) {
17277 dns_dbiterator_destroy(&dbiterator);
17278 }
17279 if (result != ISC_R_SUCCESS) {
17280 dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_db: %s",
17281 isc_result_totext(result));
17282 }
17283
17284 while (!ISC_LIST_EMPTY(nsec3list)) {
17285 nsec3param_t *nsec3p;
17286 nsec3p = ISC_LIST_HEAD(nsec3list);
17287 ISC_LIST_UNLINK(nsec3list, nsec3p, link);
17288 isc_mem_put(zone->mctx, nsec3p, sizeof(nsec3param_t));
17289 }
17290 if (db != NULL) {
17291 if (version != NULL) {
17292 dns_db_closeversion(db, &version, false);
17293 }
17294 dns_db_detach(&db);
17295 }
17296 dns_db_detach(&rawdb);
17297 dns_zone_idetach(&zone);
17298
17299 INSIST(version == NULL);
17300 }
17301
17302 static isc_result_t
17303 zone_send_securedb(dns_zone_t *zone, dns_db_t *db) {
17304 isc_event_t *e;
17305 dns_db_t *dummy = NULL;
17306 dns_zone_t *secure = NULL;
17307
17308 e = isc_event_allocate(zone->secure->mctx, zone, DNS_EVENT_ZONESECUREDB,
17309 receive_secure_db, zone->secure,
17310 sizeof(struct secure_event));
17311 dns_db_attach(db, &dummy);
17312 ((struct secure_event *)e)->db = dummy;
17313 INSIST(LOCKED_ZONE(zone->secure));
17314 zone_iattach(zone->secure, &secure);
17315 isc_task_send(zone->secure->task, &e);
17316 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
17317 return (ISC_R_SUCCESS);
17318 }
17319
17320 isc_result_t
17321 dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump) {
17322 isc_result_t result;
17323 dns_zone_t *secure = NULL;
17324
17325 REQUIRE(DNS_ZONE_VALID(zone));
17326 again:
17327 LOCK_ZONE(zone);
17328 if (inline_raw(zone)) {
17329 secure = zone->secure;
17330 INSIST(secure != zone);
17331 TRYLOCK_ZONE(result, secure);
17332 if (result != ISC_R_SUCCESS) {
17333 UNLOCK_ZONE(zone);
17334 secure = NULL;
17335 isc_thread_yield();
17336 goto again;
17337 }
17338 }
17339 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
17340 result = zone_replacedb(zone, db, dump);
17341 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
17342 if (secure != NULL) {
17343 UNLOCK_ZONE(secure);
17344 }
17345 UNLOCK_ZONE(zone);
17346 return (result);
17347 }
17348
17349 static isc_result_t
17350 zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump) {
17351 dns_dbversion_t *ver;
17352 isc_result_t result;
17353 unsigned int soacount = 0;
17354 unsigned int nscount = 0;
17355
17356 /*
17357 * 'zone' and 'zone->db' locked by caller.
17358 */
17359 REQUIRE(DNS_ZONE_VALID(zone));
17360 REQUIRE(LOCKED_ZONE(zone));
17361 if (inline_raw(zone)) {
17362 REQUIRE(LOCKED_ZONE(zone->secure));
17363 }
17364
17365 result = zone_get_from_db(zone, db, &nscount, &soacount, NULL, NULL,
17366 NULL, NULL, NULL, NULL, NULL);
17367 if (result == ISC_R_SUCCESS) {
17368 if (soacount != 1) {
17369 dns_zone_log(zone, ISC_LOG_ERROR, "has %d SOA records",
17370 soacount);
17371 result = DNS_R_BADZONE;
17372 }
17373 if (nscount == 0 && zone->type != dns_zone_key) {
17374 dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records");
17375 result = DNS_R_BADZONE;
17376 }
17377 if (result != ISC_R_SUCCESS) {
17378 return (result);
17379 }
17380 } else {
17381 dns_zone_log(zone, ISC_LOG_ERROR,
17382 "retrieving SOA and NS records failed: %s",
17383 isc_result_totext(result));
17384 return (result);
17385 }
17386
17387 result = check_nsec3param(zone, db);
17388 if (result != ISC_R_SUCCESS) {
17389 return (result);
17390 }
17391
17392 ver = NULL;
17393 dns_db_currentversion(db, &ver);
17394
17395 /*
17396 * The initial version of a secondary zone is always dumped;
17397 * subsequent versions may be journaled instead if this
17398 * is enabled in the configuration.
17399 */
17400 if (zone->db != NULL && zone->journal != NULL &&
17401 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
17402 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER))
17403 {
17404 uint32_t serial, oldserial;
17405
17406 dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
17407
17408 result = dns_db_getsoaserial(db, ver, &serial);
17409 if (result != ISC_R_SUCCESS) {
17410 dns_zone_log(zone, ISC_LOG_ERROR,
17411 "ixfr-from-differences: unable to get "
17412 "new serial");
17413 goto fail;
17414 }
17415
17416 /*
17417 * This is checked in zone_postload() for primary zones.
17418 */
17419 result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL,
17420 &oldserial, NULL, NULL, NULL, NULL,
17421 NULL);
17422 RUNTIME_CHECK(result == ISC_R_SUCCESS);
17423 RUNTIME_CHECK(soacount > 0U);
17424 if ((zone->type == dns_zone_secondary ||
17425 (zone->type == dns_zone_redirect &&
17426 zone->primaries != NULL)) &&
17427 !isc_serial_gt(serial, oldserial))
17428 {
17429 uint32_t serialmin, serialmax;
17430 serialmin = (oldserial + 1) & 0xffffffffU;
17431 serialmax = (oldserial + 0x7fffffffU) & 0xffffffffU;
17432 dns_zone_log(zone, ISC_LOG_ERROR,
17433 "ixfr-from-differences: failed: "
17434 "new serial (%u) out of range [%u - %u]",
17435 serial, serialmin, serialmax);
17436 result = ISC_R_RANGE;
17437 goto fail;
17438 }
17439
17440 result = dns_db_diff(zone->mctx, db, ver, zone->db, NULL,
17441 zone->journal);
17442 if (result != ISC_R_SUCCESS) {
17443 char strbuf[ISC_STRERRORSIZE];
17444 strerror_r(errno, strbuf, sizeof(strbuf));
17445 dns_zone_log(zone, ISC_LOG_ERROR,
17446 "ixfr-from-differences: failed: "
17447 "%s",
17448 strbuf);
17449 goto fallback;
17450 }
17451 if (dump) {
17452 zone_needdump(zone, DNS_DUMP_DELAY);
17453 } else {
17454 zone_journal_compact(zone, zone->db, serial);
17455 }
17456 if (zone->type == dns_zone_primary && inline_raw(zone)) {
17457 zone_send_secureserial(zone, serial);
17458 }
17459 } else {
17460 fallback:
17461 if (dump && zone->masterfile != NULL) {
17462 /*
17463 * If DNS_ZONEFLG_FORCEXFER was set we don't want
17464 * to keep the old masterfile.
17465 */
17466 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) &&
17467 remove(zone->masterfile) < 0 && errno != ENOENT)
17468 {
17469 char strbuf[ISC_STRERRORSIZE];
17470 strerror_r(errno, strbuf, sizeof(strbuf));
17471 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
17472 DNS_LOGMODULE_ZONE,
17473 ISC_LOG_WARNING,
17474 "unable to remove masterfile "
17475 "'%s': '%s'",
17476 zone->masterfile, strbuf);
17477 }
17478 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0) {
17479 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NODELAY);
17480 } else {
17481 zone_needdump(zone, 0);
17482 }
17483 }
17484 if (dump && zone->journal != NULL) {
17485 /*
17486 * The in-memory database just changed, and
17487 * because 'dump' is set, it didn't change by
17488 * being loaded from disk. Also, we have not
17489 * journaled diffs for this change.
17490 * Therefore, the on-disk journal is missing
17491 * the deltas for this change. Since it can
17492 * no longer be used to bring the zone
17493 * up-to-date, it is useless and should be
17494 * removed.
17495 */
17496 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
17497 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
17498 "removing journal file");
17499 if (remove(zone->journal) < 0 && errno != ENOENT) {
17500 char strbuf[ISC_STRERRORSIZE];
17501 strerror_r(errno, strbuf, sizeof(strbuf));
17502 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
17503 DNS_LOGMODULE_ZONE,
17504 ISC_LOG_WARNING,
17505 "unable to remove journal "
17506 "'%s': '%s'",
17507 zone->journal, strbuf);
17508 }
17509 }
17510
17511 if (inline_raw(zone)) {
17512 zone_send_securedb(zone, db);
17513 }
17514 }
17515
17516 dns_db_closeversion(db, &ver, false);
17517
17518 dns_zone_log(zone, ISC_LOG_DEBUG(3), "replacing zone database");
17519
17520 if (zone->db != NULL) {
17521 zone_detachdb(zone);
17522 }
17523 zone_attachdb(zone, db);
17524 dns_db_settask(zone->db, zone->task);
17525 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED | DNS_ZONEFLG_NEEDNOTIFY);
17526 return (ISC_R_SUCCESS);
17527
17528 fail:
17529 dns_db_closeversion(db, &ver, false);
17530 return (result);
17531 }
17532
17533 /* The caller must hold the dblock as a writer. */
17534 static void
17535 zone_attachdb(dns_zone_t *zone, dns_db_t *db) {
17536 REQUIRE(zone->db == NULL && db != NULL);
17537
17538 dns_db_attach(db, &zone->db);
17539 }
17540
17541 /* The caller must hold the dblock as a writer. */
17542 static void
17543 zone_detachdb(dns_zone_t *zone) {
17544 REQUIRE(zone->db != NULL);
17545
17546 dns_zone_rpz_disable_db(zone, zone->db);
17547 dns_zone_catz_disable_db(zone, zone->db);
17548 dns_db_detach(&zone->db);
17549 }
17550
17551 static void
17552 zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
17553 isc_time_t now;
17554 bool again = false;
17555 unsigned int soacount;
17556 unsigned int nscount;
17557 uint32_t serial, refresh, retry, expire, minimum, soattl;
17558 isc_result_t xfrresult = result;
17559 bool free_needed;
17560 dns_zone_t *secure = NULL;
17561
17562 REQUIRE(DNS_ZONE_VALID(zone));
17563
17564 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(1),
17565 "zone transfer finished: %s", isc_result_totext(result));
17566
17567 /*
17568 * Obtaining a lock on the zone->secure (see zone_send_secureserial)
17569 * could result in a deadlock due to a LOR so we will spin if we
17570 * can't obtain both locks.
17571 */
17572 again:
17573 LOCK_ZONE(zone);
17574 if (inline_raw(zone)) {
17575 secure = zone->secure;
17576 INSIST(secure != zone);
17577 TRYLOCK_ZONE(result, secure);
17578 if (result != ISC_R_SUCCESS) {
17579 UNLOCK_ZONE(zone);
17580 secure = NULL;
17581 isc_thread_yield();
17582 goto again;
17583 }
17584 }
17585
17586 INSIST(DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH));
17587 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
17588 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
17589
17590 TIME_NOW(&now);
17591 switch (xfrresult) {
17592 case ISC_R_SUCCESS:
17593 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
17594 FALLTHROUGH;
17595 case DNS_R_UPTODATE:
17596 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FORCEXFER);
17597 /*
17598 * Has the zone expired underneath us?
17599 */
17600 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
17601 if (zone->db == NULL) {
17602 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17603 goto same_primary;
17604 }
17605
17606 /*
17607 * Update the zone structure's data from the actual
17608 * SOA received.
17609 */
17610 nscount = 0;
17611 soacount = 0;
17612 INSIST(zone->db != NULL);
17613 result = zone_get_from_db(zone, zone->db, &nscount, &soacount,
17614 &soattl, &serial, &refresh, &retry,
17615 &expire, &minimum, NULL);
17616 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17617 if (result == ISC_R_SUCCESS) {
17618 if (soacount != 1) {
17619 dns_zone_log(zone, ISC_LOG_ERROR,
17620 "transferred zone "
17621 "has %d SOA records",
17622 soacount);
17623 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
17624 {
17625 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
17626 zone->retry = DNS_ZONE_DEFAULTRETRY;
17627 }
17628 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
17629 zone_unload(zone);
17630 goto next_primary;
17631 }
17632 if (nscount == 0) {
17633 dns_zone_log(zone, ISC_LOG_ERROR,
17634 "transferred zone "
17635 "has no NS records");
17636 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
17637 {
17638 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
17639 zone->retry = DNS_ZONE_DEFAULTRETRY;
17640 }
17641 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
17642 zone_unload(zone);
17643 goto next_primary;
17644 }
17645 zone->refresh = RANGE(refresh, zone->minrefresh,
17646 zone->maxrefresh);
17647 zone->retry = RANGE(retry, zone->minretry,
17648 zone->maxretry);
17649 zone->expire = RANGE(expire,
17650 zone->refresh + zone->retry,
17651 DNS_MAX_EXPIRE);
17652 zone->soattl = soattl;
17653 zone->minimum = minimum;
17654 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
17655 }
17656
17657 /*
17658 * Set our next update/expire times.
17659 */
17660 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
17661 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
17662 zone->refreshtime = now;
17663 DNS_ZONE_TIME_ADD(&now, zone->expire,
17664 &zone->expiretime);
17665 } else {
17666 DNS_ZONE_JITTER_ADD(&now, zone->refresh,
17667 &zone->refreshtime);
17668 DNS_ZONE_TIME_ADD(&now, zone->expire,
17669 &zone->expiretime);
17670 }
17671
17672 /*
17673 * Set loadtime.
17674 */
17675 zone->loadtime = now;
17676
17677 if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS) {
17678 char buf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
17679 if (zone->tsigkey != NULL) {
17680 char namebuf[DNS_NAME_FORMATSIZE];
17681 dns_name_format(&zone->tsigkey->name, namebuf,
17682 sizeof(namebuf));
17683 snprintf(buf, sizeof(buf), ": TSIG '%s'",
17684 namebuf);
17685 } else {
17686 buf[0] = '\0';
17687 }
17688 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
17689 ISC_LOG_INFO, "transferred serial %u%s",
17690 serial, buf);
17691 if (inline_raw(zone)) {
17692 zone_send_secureserial(zone, serial);
17693 }
17694 }
17695
17696 /*
17697 * This is not necessary if we just performed a AXFR
17698 * however it is necessary for an IXFR / UPTODATE and
17699 * won't hurt with an AXFR.
17700 */
17701 if (zone->masterfile != NULL || zone->journal != NULL) {
17702 unsigned int delay = DNS_DUMP_DELAY;
17703
17704 result = ISC_R_FAILURE;
17705 if (zone->journal != NULL) {
17706 result = isc_file_settime(zone->journal, &now);
17707 }
17708 if (result != ISC_R_SUCCESS && zone->masterfile != NULL)
17709 {
17710 result = isc_file_settime(zone->masterfile,
17711 &now);
17712 }
17713
17714 if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NODELAY) != 0) ||
17715 result == ISC_R_FILENOTFOUND)
17716 {
17717 delay = 0;
17718 }
17719
17720 if ((result == ISC_R_SUCCESS ||
17721 result == ISC_R_FILENOTFOUND) &&
17722 zone->masterfile != NULL)
17723 {
17724 zone_needdump(zone, delay);
17725 } else if (result != ISC_R_SUCCESS) {
17726 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
17727 ISC_LOG_ERROR,
17728 "transfer: could not set file "
17729 "modification time of '%s': %s",
17730 zone->masterfile,
17731 isc_result_totext(result));
17732 }
17733 }
17734 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NODELAY);
17735 inc_stats(zone, dns_zonestatscounter_xfrsuccess);
17736 break;
17737
17738 case DNS_R_BADIXFR:
17739 /* Force retry with AXFR. */
17740 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOIXFR);
17741 goto same_primary;
17742
17743 case DNS_R_TOOMANYRECORDS:
17744 case DNS_R_VERIFYFAILURE:
17745 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
17746 inc_stats(zone, dns_zonestatscounter_xfrfail);
17747 break;
17748
17749 default:
17750 next_primary:
17751 /*
17752 * Skip to next failed / untried primary.
17753 */
17754 do {
17755 zone->curprimary++;
17756 } while (zone->curprimary < zone->primariescnt &&
17757 zone->primariesok[zone->curprimary]);
17758 same_primary:
17759 if (zone->curprimary >= zone->primariescnt) {
17760 zone->curprimary = 0;
17761 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
17762 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
17763 {
17764 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
17765 DNS_ZONE_SETFLAG(zone,
17766 DNS_ZONEFLG_USEALTXFRSRC);
17767 while (zone->curprimary < zone->primariescnt &&
17768 zone->primariesok[zone->curprimary])
17769 {
17770 zone->curprimary++;
17771 }
17772 again = true;
17773 } else {
17774 DNS_ZONE_CLRFLAG(zone,
17775 DNS_ZONEFLG_USEALTXFRSRC);
17776 }
17777 } else {
17778 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
17779 again = true;
17780 }
17781 inc_stats(zone, dns_zonestatscounter_xfrfail);
17782 break;
17783 }
17784 zone_settimer(zone, &now);
17785
17786 /*
17787 * If creating the transfer object failed, zone->xfr is NULL.
17788 * Otherwise, we are called as the done callback of a zone
17789 * transfer object that just entered its shutting-down
17790 * state. Since we are no longer responsible for shutting
17791 * it down, we can detach our reference.
17792 */
17793 if (zone->xfr != NULL) {
17794 dns_xfrin_detach(&zone->xfr);
17795 }
17796
17797 if (zone->tsigkey != NULL) {
17798 dns_tsigkey_detach(&zone->tsigkey);
17799 }
17800
17801 if (zone->transport != NULL) {
17802 dns_transport_detach(&zone->transport);
17803 }
17804
17805 /*
17806 * Handle any deferred journal compaction.
17807 */
17808 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDCOMPACT)) {
17809 dns_db_t *db = NULL;
17810 if (dns_zone_getdb(zone, &db) == ISC_R_SUCCESS) {
17811 zone_journal_compact(zone, db, zone->compact_serial);
17812 dns_db_detach(&db);
17813 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
17814 }
17815 }
17816
17817 if (secure != NULL) {
17818 UNLOCK_ZONE(secure);
17819 }
17820 /*
17821 * This transfer finishing freed up a transfer quota slot.
17822 * Let any other zones waiting for quota have it.
17823 */
17824 if (zone->zmgr != NULL &&
17825 zone->statelist == &zone->zmgr->xfrin_in_progress)
17826 {
17827 UNLOCK_ZONE(zone);
17828 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
17829 ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
17830 zone->statelist = NULL;
17831 zmgr_resume_xfrs(zone->zmgr, false);
17832 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
17833 LOCK_ZONE(zone);
17834 }
17835
17836 /*
17837 * Retry with a different server if necessary.
17838 */
17839 if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
17840 queue_soa_query(zone);
17841 }
17842
17843 isc_refcount_decrement(&zone->irefs);
17844 free_needed = exit_check(zone);
17845 UNLOCK_ZONE(zone);
17846 if (free_needed) {
17847 zone_free(zone);
17848 }
17849 }
17850
17851 static void
17852 zone_loaddone(void *arg, isc_result_t result) {
17853 static char me[] = "zone_loaddone";
17854 dns_load_t *load = arg;
17855 dns_zone_t *zone;
17856 isc_result_t tresult;
17857 dns_zone_t *secure = NULL;
17858
17859 REQUIRE(DNS_LOAD_VALID(load));
17860 zone = load->zone;
17861
17862 ENTER;
17863
17864 /*
17865 * If zone loading failed, remove the update db callbacks prior
17866 * to calling the list of callbacks in the zone load structure.
17867 */
17868 if (result != ISC_R_SUCCESS) {
17869 dns_zone_rpz_disable_db(zone, load->db);
17870 dns_zone_catz_disable_db(zone, load->db);
17871 }
17872
17873 tresult = dns_db_endload(load->db, &load->callbacks);
17874 if (tresult != ISC_R_SUCCESS &&
17875 (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
17876 {
17877 result = tresult;
17878 }
17879
17880 /*
17881 * Lock hierarchy: zmgr, zone, raw.
17882 */
17883 again:
17884 LOCK_ZONE(zone);
17885 INSIST(zone != zone->raw);
17886 if (inline_secure(zone)) {
17887 LOCK_ZONE(zone->raw);
17888 } else if (inline_raw(zone)) {
17889 secure = zone->secure;
17890 TRYLOCK_ZONE(tresult, secure);
17891 if (tresult != ISC_R_SUCCESS) {
17892 UNLOCK_ZONE(zone);
17893 secure = NULL;
17894 isc_thread_yield();
17895 goto again;
17896 }
17897 }
17898 (void)zone_postload(zone, load->db, load->loadtime, result);
17899 zonemgr_putio(&zone->readio);
17900 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADING);
17901 zone_idetach(&load->callbacks.zone);
17902 /*
17903 * Leave the zone frozen if the reload fails.
17904 */
17905 if ((result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) &&
17906 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_THAW))
17907 {
17908 zone->update_disabled = false;
17909 }
17910 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_THAW);
17911 if (inline_secure(zone)) {
17912 UNLOCK_ZONE(zone->raw);
17913 } else if (secure != NULL) {
17914 UNLOCK_ZONE(secure);
17915 }
17916 UNLOCK_ZONE(zone);
17917
17918 load->magic = 0;
17919 dns_db_detach(&load->db);
17920 if (load->zone->lctx != NULL) {
17921 dns_loadctx_detach(&load->zone->lctx);
17922 }
17923 dns_zone_idetach(&load->zone);
17924 isc_mem_putanddetach(&load->mctx, load, sizeof(*load));
17925 }
17926
17927 void
17928 dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) {
17929 REQUIRE(DNS_ZONE_VALID(zone));
17930 REQUIRE(table != NULL);
17931 REQUIRE(*table == NULL);
17932
17933 LOCK_ZONE(zone);
17934 if (zone->ssutable != NULL) {
17935 dns_ssutable_attach(zone->ssutable, table);
17936 }
17937 UNLOCK_ZONE(zone);
17938 }
17939
17940 void
17941 dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
17942 REQUIRE(DNS_ZONE_VALID(zone));
17943
17944 LOCK_ZONE(zone);
17945 if (zone->ssutable != NULL) {
17946 dns_ssutable_detach(&zone->ssutable);
17947 }
17948 if (table != NULL) {
17949 dns_ssutable_attach(table, &zone->ssutable);
17950 }
17951 UNLOCK_ZONE(zone);
17952 }
17953
17954 void
17955 dns_zone_setsigvalidityinterval(dns_zone_t *zone, uint32_t interval) {
17956 REQUIRE(DNS_ZONE_VALID(zone));
17957
17958 zone->sigvalidityinterval = interval;
17959 }
17960
17961 uint32_t
17962 dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
17963 REQUIRE(DNS_ZONE_VALID(zone));
17964
17965 return (zone->sigvalidityinterval);
17966 }
17967
17968 void
17969 dns_zone_setkeyvalidityinterval(dns_zone_t *zone, uint32_t interval) {
17970 REQUIRE(DNS_ZONE_VALID(zone));
17971
17972 zone->keyvalidityinterval = interval;
17973 }
17974
17975 uint32_t
17976 dns_zone_getkeyvalidityinterval(dns_zone_t *zone) {
17977 REQUIRE(DNS_ZONE_VALID(zone));
17978
17979 return (zone->keyvalidityinterval);
17980 }
17981
17982 void
17983 dns_zone_setsigresigninginterval(dns_zone_t *zone, uint32_t interval) {
17984 isc_time_t now;
17985
17986 REQUIRE(DNS_ZONE_VALID(zone));
17987
17988 LOCK_ZONE(zone);
17989 zone->sigresigninginterval = interval;
17990 set_resigntime(zone);
17991 if (zone->task != NULL) {
17992 TIME_NOW(&now);
17993 zone_settimer(zone, &now);
17994 }
17995 UNLOCK_ZONE(zone);
17996 }
17997
17998 uint32_t
17999 dns_zone_getsigresigninginterval(dns_zone_t *zone) {
18000 REQUIRE(DNS_ZONE_VALID(zone));
18001
18002 return (zone->sigresigninginterval);
18003 }
18004
18005 static void
18006 queue_xfrin(dns_zone_t *zone) {
18007 const char me[] = "queue_xfrin";
18008 isc_result_t result;
18009 dns_zonemgr_t *zmgr = zone->zmgr;
18010
18011 ENTER;
18012
18013 INSIST(zone->statelist == NULL);
18014
18015 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18016 ISC_LIST_APPEND(zmgr->waiting_for_xfrin, zone, statelink);
18017 isc_refcount_increment0(&zone->irefs);
18018 zone->statelist = &zmgr->waiting_for_xfrin;
18019 result = zmgr_start_xfrin_ifquota(zmgr, zone);
18020 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18021
18022 if (result == ISC_R_QUOTA) {
18023 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
18024 "zone transfer deferred due to quota");
18025 } else if (result != ISC_R_SUCCESS) {
18026 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
18027 "starting zone transfer: %s",
18028 isc_result_totext(result));
18029 }
18030 }
18031
18032 /*
18033 * This event callback is called when a zone has received
18034 * any necessary zone transfer quota. This is the time
18035 * to go ahead and start the transfer.
18036 */
18037 static void
18038 got_transfer_quota(isc_task_t *task, isc_event_t *event) {
18039 isc_result_t result = ISC_R_SUCCESS;
18040 dns_peer_t *peer = NULL;
18041 char primary[ISC_SOCKADDR_FORMATSIZE];
18042 char source[ISC_SOCKADDR_FORMATSIZE];
18043 dns_rdatatype_t xfrtype;
18044 dns_zone_t *zone = event->ev_arg;
18045 isc_netaddr_t primaryip;
18046 isc_sockaddr_t sourceaddr;
18047 isc_sockaddr_t primaryaddr;
18048 isc_time_t now;
18049 const char *soa_before = "";
18050 bool loaded;
18051 isc_tlsctx_cache_t *zmgr_tlsctx_cache = NULL;
18052
18053 UNUSED(task);
18054
18055 INSIST(task == zone->task);
18056
18057 isc_event_free(&event);
18058
18059 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
18060 zone_xfrdone(zone, ISC_R_CANCELED);
18061 return;
18062 }
18063
18064 TIME_NOW(&now);
18065
18066 isc_sockaddr_format(&zone->primaryaddr, primary, sizeof(primary));
18067 if (dns_zonemgr_unreachable(zone->zmgr, &zone->primaryaddr,
18068 &zone->sourceaddr, &now))
18069 {
18070 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
18071 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
18072 "got_transfer_quota: skipping zone transfer as "
18073 "primary %s (source %s) is unreachable (cached)",
18074 primary, source);
18075 zone_xfrdone(zone, ISC_R_CANCELED);
18076 return;
18077 }
18078
18079 isc_netaddr_fromsockaddr(&primaryip, &zone->primaryaddr);
18080 (void)dns_peerlist_peerbyaddr(zone->view->peers, &primaryip, &peer);
18081
18082 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR)) {
18083 soa_before = "SOA before ";
18084 }
18085 /*
18086 * Decide whether we should request IXFR or AXFR.
18087 */
18088 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
18089 loaded = (zone->db != NULL);
18090 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
18091
18092 if (!loaded) {
18093 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(1),
18094 "no database exists yet, requesting AXFR of "
18095 "initial version from %s",
18096 primary);
18097 xfrtype = dns_rdatatype_axfr;
18098 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
18099 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(1),
18100 "forced reload, requesting AXFR of "
18101 "initial version from %s",
18102 primary);
18103 xfrtype = dns_rdatatype_axfr;
18104 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOIXFR)) {
18105 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(1),
18106 "retrying with AXFR from %s due to "
18107 "previous IXFR failure",
18108 primary);
18109 xfrtype = dns_rdatatype_axfr;
18110 LOCK_ZONE(zone);
18111 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOIXFR);
18112 UNLOCK_ZONE(zone);
18113 } else {
18114 bool use_ixfr = true;
18115 if (peer != NULL) {
18116 result = dns_peer_getrequestixfr(peer, &use_ixfr);
18117 }
18118 if (peer == NULL || result != ISC_R_SUCCESS) {
18119 use_ixfr = zone->requestixfr;
18120 }
18121 if (!use_ixfr) {
18122 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
18123 ISC_LOG_DEBUG(1),
18124 "IXFR disabled, "
18125 "requesting %sAXFR from %s",
18126 soa_before, primary);
18127 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR)) {
18128 xfrtype = dns_rdatatype_soa;
18129 } else {
18130 xfrtype = dns_rdatatype_axfr;
18131 }
18132 } else {
18133 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
18134 ISC_LOG_DEBUG(1),
18135 "requesting IXFR from %s", primary);
18136 xfrtype = dns_rdatatype_ixfr;
18137 }
18138 }
18139
18140 /*
18141 * Determine if we should attempt to sign the request with TSIG.
18142 */
18143 result = ISC_R_NOTFOUND;
18144
18145 /*
18146 * First, look for a tsig key in the primaries statement, then
18147 * try for a server key.
18148 */
18149 if ((zone->primarykeynames != NULL) &&
18150 (zone->primarykeynames[zone->curprimary] != NULL))
18151 {
18152 dns_view_t *view = dns_zone_getview(zone);
18153 dns_name_t *keyname = zone->primarykeynames[zone->curprimary];
18154 result = dns_view_gettsig(view, keyname, &zone->tsigkey);
18155 }
18156 if (result != ISC_R_SUCCESS) {
18157 INSIST(zone->tsigkey == NULL);
18158 result = dns_view_getpeertsig(zone->view, &primaryip,
18159 &zone->tsigkey);
18160 }
18161 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
18162 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
18163 "could not get TSIG key for zone transfer: %s",
18164 isc_result_totext(result));
18165 }
18166
18167 /*
18168 * Get the TLS transport for the primary, if configured.
18169 */
18170 if ((zone->primarytlsnames != NULL) &&
18171 (zone->primarytlsnames[zone->curprimary] != NULL))
18172 {
18173 dns_view_t *view = dns_zone_getview(zone);
18174 dns_name_t *tlsname = zone->primarytlsnames[zone->curprimary];
18175 result = dns_view_gettransport(view, DNS_TRANSPORT_TLS, tlsname,
18176 &zone->transport);
18177 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
18178 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
18179 ISC_LOG_ERROR,
18180 "could not get TLS configuration for "
18181 "zone transfer: %s",
18182 isc_result_totext(result));
18183 }
18184 }
18185
18186 LOCK_ZONE(zone);
18187 primaryaddr = zone->primaryaddr;
18188 sourceaddr = zone->sourceaddr;
18189 UNLOCK_ZONE(zone);
18190 INSIST(isc_sockaddr_pf(&primaryaddr) == isc_sockaddr_pf(&sourceaddr));
18191
18192 if (zone->xfr != NULL) {
18193 dns_xfrin_detach(&zone->xfr);
18194 }
18195
18196 zmgr_tlsctx_attach(zone->zmgr, &zmgr_tlsctx_cache);
18197
18198 result = dns_xfrin_create(zone, xfrtype, &primaryaddr, &sourceaddr,
18199 zone->tsigkey, zone->transport,
18200 zmgr_tlsctx_cache, zone->mctx,
18201 zone->zmgr->netmgr, zone_xfrdone, &zone->xfr);
18202
18203 isc_tlsctx_cache_detach(&zmgr_tlsctx_cache);
18204
18205 /*
18206 * Any failure in this function is handled like a failed
18207 * zone transfer. This ensures that we get removed from
18208 * zmgr->xfrin_in_progress.
18209 */
18210 if (result != ISC_R_SUCCESS) {
18211 zone_xfrdone(zone, result);
18212 return;
18213 }
18214
18215 LOCK_ZONE(zone);
18216 if (xfrtype == dns_rdatatype_axfr) {
18217 if (isc_sockaddr_pf(&primaryaddr) == PF_INET) {
18218 inc_stats(zone, dns_zonestatscounter_axfrreqv4);
18219 } else {
18220 inc_stats(zone, dns_zonestatscounter_axfrreqv6);
18221 }
18222 } else if (xfrtype == dns_rdatatype_ixfr) {
18223 if (isc_sockaddr_pf(&primaryaddr) == PF_INET) {
18224 inc_stats(zone, dns_zonestatscounter_ixfrreqv4);
18225 } else {
18226 inc_stats(zone, dns_zonestatscounter_ixfrreqv6);
18227 }
18228 }
18229 UNLOCK_ZONE(zone);
18230 }
18231
18232 /*
18233 * Update forwarding support.
18234 */
18235
18236 static void
18237 forward_destroy(dns_forward_t *forward) {
18238 forward->magic = 0;
18239 if (forward->request != NULL) {
18240 dns_request_destroy(&forward->request);
18241 }
18242 if (forward->msgbuf != NULL) {
18243 isc_buffer_free(&forward->msgbuf);
18244 }
18245 if (forward->zone != NULL) {
18246 LOCK(&forward->zone->lock);
18247 if (ISC_LINK_LINKED(forward, link)) {
18248 ISC_LIST_UNLINK(forward->zone->forwards, forward, link);
18249 }
18250 UNLOCK(&forward->zone->lock);
18251 dns_zone_idetach(&forward->zone);
18252 }
18253 isc_mem_putanddetach(&forward->mctx, forward, sizeof(*forward));
18254 }
18255
18256 static isc_result_t
18257 sendtoprimary(dns_forward_t *forward) {
18258 isc_result_t result;
18259 isc_sockaddr_t src;
18260
18261 LOCK_ZONE(forward->zone);
18262
18263 if (DNS_ZONE_FLAG(forward->zone, DNS_ZONEFLG_EXITING)) {
18264 UNLOCK_ZONE(forward->zone);
18265 return (ISC_R_CANCELED);
18266 }
18267
18268 if (forward->which >= forward->zone->primariescnt) {
18269 UNLOCK_ZONE(forward->zone);
18270 return (ISC_R_NOMORE);
18271 }
18272
18273 forward->addr = forward->zone->primaries[forward->which];
18274 /*
18275 * Always use TCP regardless of whether the original update
18276 * used TCP.
18277 * XXX The timeout may but a bit small if we are far down a
18278 * transfer graph and have to try several primaries.
18279 */
18280 switch (isc_sockaddr_pf(&forward->addr)) {
18281 case PF_INET:
18282 src = forward->zone->xfrsource4;
18283 break;
18284 case PF_INET6:
18285 src = forward->zone->xfrsource6;
18286 break;
18287 default:
18288 result = ISC_R_NOTIMPLEMENTED;
18289 goto unlock;
18290 }
18291 result = dns_request_createraw(forward->zone->view->requestmgr,
18292 forward->msgbuf, &src, &forward->addr,
18293 forward->options, 15 /* XXX */, 0, 0,
18294 forward->zone->task, forward_callback,
18295 forward, &forward->request);
18296 if (result == ISC_R_SUCCESS) {
18297 if (!ISC_LINK_LINKED(forward, link)) {
18298 ISC_LIST_APPEND(forward->zone->forwards, forward, link);
18299 }
18300 }
18301
18302 unlock:
18303 UNLOCK_ZONE(forward->zone);
18304 return (result);
18305 }
18306
18307 static void
18308 forward_callback(isc_task_t *task, isc_event_t *event) {
18309 const char me[] = "forward_callback";
18310 dns_requestevent_t *revent = (dns_requestevent_t *)event;
18311 dns_message_t *msg = NULL;
18312 char primary[ISC_SOCKADDR_FORMATSIZE];
18313 isc_result_t result;
18314 dns_forward_t *forward;
18315 dns_zone_t *zone;
18316
18317 UNUSED(task);
18318
18319 forward = revent->ev_arg;
18320 INSIST(DNS_FORWARD_VALID(forward));
18321 zone = forward->zone;
18322 INSIST(DNS_ZONE_VALID(zone));
18323
18324 ENTER;
18325
18326 isc_sockaddr_format(&forward->addr, primary, sizeof(primary));
18327
18328 if (revent->result != ISC_R_SUCCESS) {
18329 dns_zone_log(zone, ISC_LOG_INFO,
18330 "could not forward dynamic update to %s: %s",
18331 primary, isc_result_totext(revent->result));
18332 goto next_primary;
18333 }
18334
18335 dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
18336
18337 result = dns_request_getresponse(revent->request, msg,
18338 DNS_MESSAGEPARSE_PRESERVEORDER |
18339 DNS_MESSAGEPARSE_CLONEBUFFER);
18340 if (result != ISC_R_SUCCESS) {
18341 goto next_primary;
18342 }
18343
18344 /*
18345 * Unexpected opcode.
18346 */
18347 if (msg->opcode != dns_opcode_update) {
18348 char opcode[128];
18349 isc_buffer_t rb;
18350
18351 isc_buffer_init(&rb, opcode, sizeof(opcode));
18352 (void)dns_opcode_totext(msg->opcode, &rb);
18353
18354 dns_zone_log(zone, ISC_LOG_INFO,
18355 "forwarding dynamic update: "
18356 "unexpected opcode (%.*s) from %s",
18357 (int)rb.used, opcode, primary);
18358 goto next_primary;
18359 }
18360
18361 switch (msg->rcode) {
18362 /*
18363 * Pass these rcodes back to client.
18364 */
18365 case dns_rcode_noerror:
18366 case dns_rcode_yxdomain:
18367 case dns_rcode_yxrrset:
18368 case dns_rcode_nxrrset:
18369 case dns_rcode_refused:
18370 case dns_rcode_nxdomain: {
18371 char rcode[128];
18372 isc_buffer_t rb;
18373
18374 isc_buffer_init(&rb, rcode, sizeof(rcode));
18375 (void)dns_rcode_totext(msg->rcode, &rb);
18376 dns_zone_log(zone, ISC_LOG_INFO,
18377 "forwarded dynamic update: "
18378 "primary %s returned: %.*s",
18379 primary, (int)rb.used, rcode);
18380 break;
18381 }
18382
18383 /* These should not occur if the primaries/zone are valid. */
18384 case dns_rcode_notzone:
18385 case dns_rcode_notauth: {
18386 char rcode[128];
18387 isc_buffer_t rb;
18388
18389 isc_buffer_init(&rb, rcode, sizeof(rcode));
18390 (void)dns_rcode_totext(msg->rcode, &rb);
18391 dns_zone_log(zone, ISC_LOG_WARNING,
18392 "forwarding dynamic update: "
18393 "unexpected response: primary %s returned: %.*s",
18394 primary, (int)rb.used, rcode);
18395 goto next_primary;
18396 }
18397
18398 /* Try another server for these rcodes. */
18399 case dns_rcode_formerr:
18400 case dns_rcode_servfail:
18401 case dns_rcode_notimp:
18402 case dns_rcode_badvers:
18403 default:
18404 goto next_primary;
18405 }
18406
18407 /* call callback */
18408 (forward->callback)(forward->callback_arg, ISC_R_SUCCESS, msg);
18409 msg = NULL;
18410 dns_request_destroy(&forward->request);
18411 forward_destroy(forward);
18412 isc_event_free(&event);
18413 return;
18414
18415 next_primary:
18416 if (msg != NULL) {
18417 dns_message_detach(&msg);
18418 }
18419 isc_event_free(&event);
18420 forward->which++;
18421 dns_request_destroy(&forward->request);
18422 result = sendtoprimary(forward);
18423 if (result != ISC_R_SUCCESS) {
18424 /* call callback */
18425 dns_zone_log(zone, ISC_LOG_DEBUG(3),
18426 "exhausted dynamic update forwarder list");
18427 (forward->callback)(forward->callback_arg, result, NULL);
18428 forward_destroy(forward);
18429 }
18430 }
18431
18432 isc_result_t
18433 dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
18434 dns_updatecallback_t callback, void *callback_arg) {
18435 dns_forward_t *forward;
18436 isc_result_t result;
18437 isc_region_t *mr;
18438
18439 REQUIRE(DNS_ZONE_VALID(zone));
18440 REQUIRE(msg != NULL);
18441 REQUIRE(callback != NULL);
18442
18443 forward = isc_mem_get(zone->mctx, sizeof(*forward));
18444
18445 forward->request = NULL;
18446 forward->zone = NULL;
18447 forward->msgbuf = NULL;
18448 forward->which = 0;
18449 forward->mctx = 0;
18450 forward->callback = callback;
18451 forward->callback_arg = callback_arg;
18452 ISC_LINK_INIT(forward, link);
18453 forward->magic = FORWARD_MAGIC;
18454 forward->options = DNS_REQUESTOPT_TCP;
18455 /*
18456 * If we have a SIG(0) signed message we need to preserve the
18457 * query id as that is included in the SIG(0) computation.
18458 */
18459 if (msg->sig0 != NULL) {
18460 forward->options |= DNS_REQUESTOPT_FIXEDID;
18461 }
18462
18463 mr = dns_message_getrawmessage(msg);
18464 if (mr == NULL) {
18465 result = ISC_R_UNEXPECTEDEND;
18466 goto cleanup;
18467 }
18468
18469 isc_buffer_allocate(zone->mctx, &forward->msgbuf, mr->length);
18470 result = isc_buffer_copyregion(forward->msgbuf, mr);
18471 if (result != ISC_R_SUCCESS) {
18472 goto cleanup;
18473 }
18474
18475 isc_mem_attach(zone->mctx, &forward->mctx);
18476 dns_zone_iattach(zone, &forward->zone);
18477 result = sendtoprimary(forward);
18478
18479 cleanup:
18480 if (result != ISC_R_SUCCESS) {
18481 forward_destroy(forward);
18482 }
18483 return (result);
18484 }
18485
18486 isc_result_t
18487 dns_zone_next(dns_zone_t *zone, dns_zone_t **next) {
18488 REQUIRE(DNS_ZONE_VALID(zone));
18489 REQUIRE(next != NULL && *next == NULL);
18490
18491 *next = ISC_LIST_NEXT(zone, link);
18492 if (*next == NULL) {
18493 return (ISC_R_NOMORE);
18494 } else {
18495 return (ISC_R_SUCCESS);
18496 }
18497 }
18498
18499 isc_result_t
18500 dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) {
18501 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18502 REQUIRE(first != NULL && *first == NULL);
18503
18504 *first = ISC_LIST_HEAD(zmgr->zones);
18505 if (*first == NULL) {
18506 return (ISC_R_NOMORE);
18507 } else {
18508 return (ISC_R_SUCCESS);
18509 }
18510 }
18511
18512 /***
18513 *** Zone manager.
18514 ***/
18515
18516 #define KEYMGMT_OVERCOMMIT 3
18517 #define KEYMGMT_BITS_MIN 2U
18518 #define KEYMGMT_BITS_MAX 32U
18519
18520 /*
18521 * WMM: Static hash functions copied from lib/dns/rbtdb.c. Should be moved to
18522 * lib/isc/hash.c when we refactor the hash table code.
18523 */
18524 #define GOLDEN_RATIO_32 0x61C88647
18525 #define HASHSIZE(bits) (UINT64_C(1) << (bits))
18526
18527 static uint32_t
18528 hash_index(uint32_t val, uint32_t bits) {
18529 return (val * GOLDEN_RATIO_32 >> (32 - bits));
18530 }
18531
18532 static uint32_t
18533 hash_bits_grow(uint32_t bits, uint32_t count) {
18534 uint32_t newbits = bits;
18535 while (count >= HASHSIZE(newbits) && newbits < KEYMGMT_BITS_MAX) {
18536 newbits++;
18537 }
18538 return (newbits);
18539 }
18540
18541 static uint32_t
18542 hash_bits_shrink(uint32_t bits, uint32_t count) {
18543 uint32_t newbits = bits;
18544 while (count <= HASHSIZE(newbits) && newbits > KEYMGMT_BITS_MIN) {
18545 newbits--;
18546 }
18547 return (newbits);
18548 }
18549
18550 static void
18551 zonemgr_keymgmt_init(dns_zonemgr_t *zmgr) {
18552 dns_keymgmt_t *mgmt = isc_mem_get(zmgr->mctx, sizeof(*mgmt));
18553 uint32_t size;
18554
18555 *mgmt = (dns_keymgmt_t){
18556 .bits = KEYMGMT_BITS_MIN,
18557 };
18558 isc_mem_attach(zmgr->mctx, &mgmt->mctx);
18559 isc_rwlock_init(&mgmt->lock, 0, 0);
18560
18561 size = HASHSIZE(mgmt->bits);
18562 mgmt->table = isc_mem_get(mgmt->mctx, sizeof(*mgmt->table) * size);
18563 memset(mgmt->table, 0, size * sizeof(mgmt->table[0]));
18564
18565 atomic_init(&mgmt->count, 0);
18566 mgmt->magic = KEYMGMT_MAGIC;
18567
18568 zmgr->keymgmt = mgmt;
18569 }
18570
18571 static void
18572 zonemgr_keymgmt_destroy(dns_zonemgr_t *zmgr) {
18573 dns_keymgmt_t *mgmt = zmgr->keymgmt;
18574 uint32_t size;
18575
18576 REQUIRE(DNS_KEYMGMT_VALID(mgmt));
18577
18578 size = HASHSIZE(mgmt->bits);
18579
18580 RWLOCK(&mgmt->lock, isc_rwlocktype_write);
18581 INSIST(mgmt->count == 0);
18582 RWUNLOCK(&mgmt->lock, isc_rwlocktype_write);
18583
18584 mgmt->magic = 0;
18585 isc_rwlock_destroy(&mgmt->lock);
18586 isc_mem_put(mgmt->mctx, mgmt->table, size * sizeof(mgmt->table[0]));
18587 isc_mem_putanddetach(&mgmt->mctx, mgmt, sizeof(dns_keymgmt_t));
18588 }
18589
18590 static void
18591 zonemgr_keymgmt_resize(dns_zonemgr_t *zmgr) {
18592 dns_keyfileio_t **newtable;
18593 dns_keymgmt_t *mgmt = zmgr->keymgmt;
18594 uint32_t bits, newbits, count, size, newsize;
18595 bool grow;
18596
18597 REQUIRE(DNS_KEYMGMT_VALID(mgmt));
18598
18599 RWLOCK(&mgmt->lock, isc_rwlocktype_read);
18600 count = atomic_load_relaxed(&mgmt->count);
18601 bits = mgmt->bits;
18602 RWUNLOCK(&mgmt->lock, isc_rwlocktype_read);
18603
18604 size = HASHSIZE(bits);
18605 INSIST(size > 0);
18606
18607 if (count >= (size * KEYMGMT_OVERCOMMIT)) {
18608 grow = true;
18609 } else if (count < (size / 2)) {
18610 grow = false;
18611 } else {
18612 /* No need to resize. */
18613 return;
18614 }
18615
18616 if (grow) {
18617 newbits = hash_bits_grow(bits, count);
18618 } else {
18619 newbits = hash_bits_shrink(bits, count);
18620 }
18621
18622 if (newbits == bits) {
18623 /*
18624 * Bit values may stay the same if maximum or minimum is
18625 * reached.
18626 */
18627 return;
18628 }
18629
18630 newsize = HASHSIZE(newbits);
18631 INSIST(newsize > 0);
18632
18633 RWLOCK(&mgmt->lock, isc_rwlocktype_write);
18634
18635 newtable = isc_mem_get(mgmt->mctx, sizeof(dns_keyfileio_t *) * newsize);
18636 memset(newtable, 0, sizeof(dns_keyfileio_t *) * newsize);
18637
18638 for (unsigned int i = 0; i < size; i++) {
18639 dns_keyfileio_t *kfio, *next;
18640 for (kfio = mgmt->table[i]; kfio != NULL; kfio = next) {
18641 uint32_t hash = hash_index(kfio->hashval, newbits);
18642 next = kfio->next;
18643 kfio->next = newtable[hash];
18644 newtable[hash] = kfio;
18645 }
18646 mgmt->table[i] = NULL;
18647 }
18648
18649 isc_mem_put(mgmt->mctx, mgmt->table, sizeof(*mgmt->table) * size);
18650 mgmt->bits = newbits;
18651 mgmt->table = newtable;
18652
18653 RWUNLOCK(&mgmt->lock, isc_rwlocktype_write);
18654 }
18655
18656 static void
18657 zonemgr_keymgmt_add(dns_zonemgr_t *zmgr, dns_zone_t *zone,
18658 dns_keyfileio_t **added) {
18659 dns_keymgmt_t *mgmt = zmgr->keymgmt;
18660 uint32_t hashval, hash;
18661 dns_keyfileio_t *kfio, *next;
18662
18663 REQUIRE(DNS_KEYMGMT_VALID(mgmt));
18664 REQUIRE(added != NULL && *added == NULL);
18665
18666 RWLOCK(&mgmt->lock, isc_rwlocktype_write);
18667
18668 hashval = dns_name_hash(&zone->origin, false);
18669 hash = hash_index(hashval, mgmt->bits);
18670
18671 for (kfio = mgmt->table[hash]; kfio != NULL; kfio = next) {
18672 next = kfio->next;
18673 if (dns_name_equal(kfio->name, &zone->origin)) {
18674 /* Already in table, increment the counter. */
18675 isc_refcount_increment(&kfio->references);
18676 break;
18677 }
18678 }
18679
18680 if (kfio == NULL) {
18681 /* No entry found, add it. */
18682 kfio = isc_mem_get(mgmt->mctx, sizeof(*kfio));
18683 *kfio = (dns_keyfileio_t){
18684 .hashval = hashval,
18685 .next = mgmt->table[hash],
18686 .magic = KEYFILEIO_MAGIC,
18687 };
18688
18689 isc_refcount_init(&kfio->references, 1);
18690
18691 kfio->name = dns_fixedname_initname(&kfio->fname);
18692 dns_name_copy(&zone->origin, kfio->name);
18693
18694 isc_mutex_init(&kfio->lock);
18695
18696 mgmt->table[hash] = kfio;
18697
18698 atomic_fetch_add_relaxed(&mgmt->count, 1);
18699 }
18700
18701 RWUNLOCK(&mgmt->lock, isc_rwlocktype_write);
18702
18703 *added = kfio;
18704
18705 /*
18706 * Call resize, that function will also check if resize is necessary.
18707 */
18708 zonemgr_keymgmt_resize(zmgr);
18709 }
18710
18711 static void
18712 zonemgr_keymgmt_delete(dns_zonemgr_t *zmgr, dns_zone_t *zone,
18713 dns_keyfileio_t **deleted) {
18714 dns_keymgmt_t *mgmt = zmgr->keymgmt;
18715 uint32_t hashval, hash;
18716 dns_keyfileio_t *kfio, *prev, *next;
18717
18718 REQUIRE(DNS_KEYMGMT_VALID(mgmt));
18719 REQUIRE(deleted != NULL && DNS_KEYFILEIO_VALID(*deleted));
18720
18721 RWLOCK(&mgmt->lock, isc_rwlocktype_write);
18722
18723 hashval = dns_name_hash(&zone->origin, false);
18724 hash = hash_index(hashval, mgmt->bits);
18725
18726 prev = NULL;
18727 for (kfio = mgmt->table[hash]; kfio != NULL; kfio = next) {
18728 next = kfio->next;
18729 if (dns_name_equal(kfio->name, &zone->origin)) {
18730 INSIST(kfio == *deleted);
18731 *deleted = NULL;
18732
18733 if (isc_refcount_decrement(&kfio->references) == 1) {
18734 if (prev == NULL) {
18735 mgmt->table[hash] = kfio->next;
18736 } else {
18737 prev->next = kfio->next;
18738 }
18739
18740 isc_refcount_destroy(&kfio->references);
18741 isc_mutex_destroy(&kfio->lock);
18742 isc_mem_put(mgmt->mctx, kfio, sizeof(*kfio));
18743
18744 atomic_fetch_sub_relaxed(&mgmt->count, 1);
18745 }
18746 break;
18747 }
18748
18749 prev = kfio;
18750 }
18751
18752 RWUNLOCK(&mgmt->lock, isc_rwlocktype_write);
18753
18754 /*
18755 * Call resize, that function will also check if resize is necessary.
18756 */
18757 zonemgr_keymgmt_resize(zmgr);
18758 }
18759
18760 isc_result_t
18761 dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
18762 isc_timermgr_t *timermgr, isc_nm_t *netmgr,
18763 dns_zonemgr_t **zmgrp) {
18764 dns_zonemgr_t *zmgr;
18765 isc_result_t result;
18766
18767 zmgr = isc_mem_get(mctx, sizeof(*zmgr));
18768 zmgr->mctx = NULL;
18769 isc_refcount_init(&zmgr->refs, 1);
18770 isc_mem_attach(mctx, &zmgr->mctx);
18771 zmgr->taskmgr = taskmgr;
18772 zmgr->timermgr = timermgr;
18773 zmgr->netmgr = netmgr;
18774 zmgr->zonetasks = NULL;
18775 zmgr->loadtasks = NULL;
18776 zmgr->mctxpool = NULL;
18777 zmgr->task = NULL;
18778 zmgr->checkdsrl = NULL;
18779 zmgr->notifyrl = NULL;
18780 zmgr->refreshrl = NULL;
18781 zmgr->startupnotifyrl = NULL;
18782 zmgr->startuprefreshrl = NULL;
18783 ISC_LIST_INIT(zmgr->zones);
18784 ISC_LIST_INIT(zmgr->waiting_for_xfrin);
18785 ISC_LIST_INIT(zmgr->xfrin_in_progress);
18786 memset(zmgr->unreachable, 0, sizeof(zmgr->unreachable));
18787 for (size_t i = 0; i < UNREACH_CACHE_SIZE; i++) {
18788 atomic_init(&zmgr->unreachable[i].expire, 0);
18789 }
18790 isc_rwlock_init(&zmgr->rwlock, 0, 0);
18791
18792 zmgr->transfersin = 10;
18793 zmgr->transfersperns = 2;
18794
18795 /* Unreachable lock. */
18796 isc_rwlock_init(&zmgr->urlock, 0, 0);
18797
18798 /* Create a single task for queueing of SOA queries. */
18799 result = isc_task_create(taskmgr, 1, &zmgr->task);
18800 if (result != ISC_R_SUCCESS) {
18801 goto free_urlock;
18802 }
18803
18804 isc_task_setname(zmgr->task, "zmgr", zmgr);
18805 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
18806 &zmgr->checkdsrl);
18807 if (result != ISC_R_SUCCESS) {
18808 goto free_task;
18809 }
18810
18811 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
18812 &zmgr->notifyrl);
18813 if (result != ISC_R_SUCCESS) {
18814 goto free_checkdsrl;
18815 }
18816
18817 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
18818 &zmgr->refreshrl);
18819 if (result != ISC_R_SUCCESS) {
18820 goto free_notifyrl;
18821 }
18822
18823 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
18824 &zmgr->startupnotifyrl);
18825 if (result != ISC_R_SUCCESS) {
18826 goto free_refreshrl;
18827 }
18828
18829 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
18830 &zmgr->startuprefreshrl);
18831 if (result != ISC_R_SUCCESS) {
18832 goto free_startupnotifyrl;
18833 }
18834
18835 /* Key file I/O locks. */
18836 zonemgr_keymgmt_init(zmgr);
18837
18838 /* Default to 20 refresh queries / notifies / checkds per second. */
18839 setrl(zmgr->checkdsrl, &zmgr->checkdsrate, 20);
18840 setrl(zmgr->notifyrl, &zmgr->notifyrate, 20);
18841 setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, 20);
18842 setrl(zmgr->refreshrl, &zmgr->serialqueryrate, 20);
18843 setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, 20);
18844 isc_ratelimiter_setpushpop(zmgr->startupnotifyrl, true);
18845 isc_ratelimiter_setpushpop(zmgr->startuprefreshrl, true);
18846
18847 zmgr->iolimit = 1;
18848 zmgr->ioactive = 0;
18849 ISC_LIST_INIT(zmgr->high);
18850 ISC_LIST_INIT(zmgr->low);
18851
18852 isc_mutex_init(&zmgr->iolock);
18853
18854 zmgr->tlsctx_cache = NULL;
18855 isc_rwlock_init(&zmgr->tlsctx_cache_rwlock, 0, 0);
18856
18857 zmgr->magic = ZONEMGR_MAGIC;
18858
18859 *zmgrp = zmgr;
18860 return (ISC_R_SUCCESS);
18861
18862 #if 0
18863 free_iolock:
18864 isc_mutex_destroy(&zmgr->iolock);
18865 #endif /* if 0 */
18866 free_startupnotifyrl:
18867 isc_ratelimiter_detach(&zmgr->startupnotifyrl);
18868 free_refreshrl:
18869 isc_ratelimiter_detach(&zmgr->refreshrl);
18870 free_notifyrl:
18871 isc_ratelimiter_detach(&zmgr->notifyrl);
18872 free_checkdsrl:
18873 isc_ratelimiter_detach(&zmgr->checkdsrl);
18874 free_task:
18875 isc_task_detach(&zmgr->task);
18876 free_urlock:
18877 isc_rwlock_destroy(&zmgr->urlock);
18878 isc_rwlock_destroy(&zmgr->rwlock);
18879 isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
18880 isc_mem_detach(&mctx);
18881 return (result);
18882 }
18883
18884 isc_result_t
18885 dns_zonemgr_createzone(dns_zonemgr_t *zmgr, dns_zone_t **zonep) {
18886 isc_result_t result;
18887 isc_mem_t *mctx = NULL;
18888 dns_zone_t *zone = NULL;
18889 void *item;
18890
18891 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18892 REQUIRE(zonep != NULL && *zonep == NULL);
18893
18894 if (zmgr->mctxpool == NULL) {
18895 return (ISC_R_FAILURE);
18896 }
18897
18898 item = isc_pool_get(zmgr->mctxpool);
18899 if (item == NULL) {
18900 return (ISC_R_FAILURE);
18901 }
18902
18903 isc_mem_attach((isc_mem_t *)item, &mctx);
18904 result = dns_zone_create(&zone, mctx);
18905 isc_mem_detach(&mctx);
18906
18907 if (result == ISC_R_SUCCESS) {
18908 *zonep = zone;
18909 }
18910
18911 return (result);
18912 }
18913
18914 isc_result_t
18915 dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
18916 isc_result_t result;
18917
18918 REQUIRE(DNS_ZONE_VALID(zone));
18919 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18920
18921 if (zmgr->zonetasks == NULL) {
18922 return (ISC_R_FAILURE);
18923 }
18924
18925 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18926 LOCK_ZONE(zone);
18927 REQUIRE(zone->task == NULL);
18928 REQUIRE(zone->timer == NULL);
18929 REQUIRE(zone->zmgr == NULL);
18930
18931 isc_taskpool_gettask(zmgr->zonetasks, &zone->task);
18932 isc_taskpool_gettask(zmgr->loadtasks, &zone->loadtask);
18933
18934 /*
18935 * Set the task name. The tag will arbitrarily point to one
18936 * of the zones sharing the task (in practice, the one
18937 * to be managed last).
18938 */
18939 isc_task_setname(zone->task, "zone", zone);
18940 isc_task_setname(zone->loadtask, "loadzone", zone);
18941
18942 result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive, NULL,
18943 NULL, zone->task, zone_timer, zone,
18944 &zone->timer);
18945
18946 if (result != ISC_R_SUCCESS) {
18947 goto cleanup_tasks;
18948 }
18949
18950 /*
18951 * The timer "holds" a iref.
18952 */
18953 isc_refcount_increment0(&zone->irefs);
18954
18955 zonemgr_keymgmt_add(zmgr, zone, &zone->kfio);
18956 INSIST(zone->kfio != NULL);
18957
18958 ISC_LIST_APPEND(zmgr->zones, zone, link);
18959 zone->zmgr = zmgr;
18960 isc_refcount_increment(&zmgr->refs);
18961
18962 goto unlock;
18963
18964 cleanup_tasks:
18965 isc_task_detach(&zone->loadtask);
18966 isc_task_detach(&zone->task);
18967
18968 unlock:
18969 UNLOCK_ZONE(zone);
18970 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18971 return (result);
18972 }
18973
18974 void
18975 dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
18976 REQUIRE(DNS_ZONE_VALID(zone));
18977 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18978 REQUIRE(zone->zmgr == zmgr);
18979
18980 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18981 LOCK_ZONE(zone);
18982
18983 ISC_LIST_UNLINK(zmgr->zones, zone, link);
18984
18985 if (zone->kfio != NULL) {
18986 zonemgr_keymgmt_delete(zmgr, zone, &zone->kfio);
18987 ENSURE(zone->kfio == NULL);
18988 }
18989
18990 /* Detach below, outside of the write lock. */
18991 zone->zmgr = NULL;
18992
18993 UNLOCK_ZONE(zone);
18994 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18995
18996 dns_zonemgr_detach(&zmgr);
18997 }
18998
18999 void
19000 dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) {
19001 REQUIRE(DNS_ZONEMGR_VALID(source));
19002 REQUIRE(target != NULL && *target == NULL);
19003
19004 isc_refcount_increment(&source->refs);
19005
19006 *target = source;
19007 }
19008
19009 void
19010 dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
19011 dns_zonemgr_t *zmgr;
19012
19013 REQUIRE(zmgrp != NULL);
19014 zmgr = *zmgrp;
19015 *zmgrp = NULL;
19016 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19017
19018 if (isc_refcount_decrement(&zmgr->refs) == 1) {
19019 zonemgr_free(zmgr);
19020 }
19021 }
19022
19023 isc_result_t
19024 dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
19025 dns_zone_t *p;
19026
19027 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19028
19029 RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
19030 for (p = ISC_LIST_HEAD(zmgr->zones); p != NULL;
19031 p = ISC_LIST_NEXT(p, link))
19032 {
19033 dns_zone_maintenance(p);
19034 }
19035 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
19036
19037 /*
19038 * Recent configuration changes may have increased the
19039 * amount of available transfers quota. Make sure any
19040 * transfers currently blocked on quota get started if
19041 * possible.
19042 */
19043 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
19044 zmgr_resume_xfrs(zmgr, true);
19045 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
19046 return (ISC_R_SUCCESS);
19047 }
19048
19049 void
19050 dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) {
19051 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19052
19053 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
19054 zmgr_resume_xfrs(zmgr, true);
19055 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
19056 }
19057
19058 void
19059 dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
19060 dns_zone_t *zone;
19061
19062 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19063
19064 isc_ratelimiter_shutdown(zmgr->checkdsrl);
19065 isc_ratelimiter_shutdown(zmgr->notifyrl);
19066 isc_ratelimiter_shutdown(zmgr->refreshrl);
19067 isc_ratelimiter_shutdown(zmgr->startupnotifyrl);
19068 isc_ratelimiter_shutdown(zmgr->startuprefreshrl);
19069
19070 if (zmgr->task != NULL) {
19071 isc_task_destroy(&zmgr->task);
19072 }
19073 if (zmgr->zonetasks != NULL) {
19074 isc_taskpool_destroy(&zmgr->zonetasks);
19075 }
19076 if (zmgr->loadtasks != NULL) {
19077 isc_taskpool_destroy(&zmgr->loadtasks);
19078 }
19079 if (zmgr->mctxpool != NULL) {
19080 isc_pool_destroy(&zmgr->mctxpool);
19081 }
19082
19083 RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
19084 for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
19085 zone = ISC_LIST_NEXT(zone, link))
19086 {
19087 LOCK_ZONE(zone);
19088 forward_cancel(zone);
19089 UNLOCK_ZONE(zone);
19090 }
19091 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
19092 }
19093
19094 static isc_result_t
19095 mctxinit(void **target, void *arg) {
19096 isc_mem_t *mctx = NULL;
19097
19098 UNUSED(arg);
19099
19100 REQUIRE(target != NULL && *target == NULL);
19101
19102 isc_mem_create(&mctx);
19103 isc_mem_setname(mctx, "zonemgr-pool");
19104
19105 *target = mctx;
19106 return (ISC_R_SUCCESS);
19107 }
19108
19109 static void
19110 mctxfree(void **target) {
19111 isc_mem_t *mctx = *(isc_mem_t **)target;
19112 isc_mem_detach(&mctx);
19113 *target = NULL;
19114 }
19115
19116 #define ZONES_PER_TASK 100
19117 #define ZONES_PER_MCTX 1000
19118
19119 isc_result_t
19120 dns_zonemgr_setsize(dns_zonemgr_t *zmgr, int num_zones) {
19121 isc_result_t result;
19122 int ntasks = num_zones / ZONES_PER_TASK;
19123 int nmctx = num_zones / ZONES_PER_MCTX;
19124 isc_taskpool_t *pool = NULL;
19125 isc_pool_t *mctxpool = NULL;
19126
19127 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19128
19129 /*
19130 * For anything fewer than 1000 zones we use 10 tasks in
19131 * the task pools. More than that, and we'll scale at one
19132 * task per 100 zones. Similarly, for anything smaller than
19133 * 2000 zones we use 2 memory contexts, then scale at 1:1000.
19134 */
19135 if (ntasks < 10) {
19136 ntasks = 10;
19137 }
19138 if (nmctx < 2) {
19139 nmctx = 2;
19140 }
19141
19142 /* Create or resize the zone task pools. */
19143 if (zmgr->zonetasks == NULL) {
19144 result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx, ntasks,
19145 2, false, &pool);
19146 } else {
19147 result = isc_taskpool_expand(&zmgr->zonetasks, ntasks, false,
19148 &pool);
19149 }
19150
19151 if (result == ISC_R_SUCCESS) {
19152 zmgr->zonetasks = pool;
19153 }
19154
19155 /*
19156 * We always set all tasks in the zone-load task pool to
19157 * privileged. This prevents other tasks in the system from
19158 * running while the server task manager is in privileged
19159 * mode.
19160 */
19161 pool = NULL;
19162 if (zmgr->loadtasks == NULL) {
19163 result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx, ntasks,
19164 UINT_MAX, true, &pool);
19165 } else {
19166 result = isc_taskpool_expand(&zmgr->loadtasks, ntasks, true,
19167 &pool);
19168 }
19169
19170 if (result == ISC_R_SUCCESS) {
19171 zmgr->loadtasks = pool;
19172 }
19173
19174 /* Create or resize the zone memory context pool. */
19175 if (zmgr->mctxpool == NULL) {
19176 result = isc_pool_create(zmgr->mctx, nmctx, mctxfree, mctxinit,
19177 NULL, &mctxpool);
19178 } else {
19179 result = isc_pool_expand(&zmgr->mctxpool, nmctx, &mctxpool);
19180 }
19181
19182 if (result == ISC_R_SUCCESS) {
19183 zmgr->mctxpool = mctxpool;
19184 }
19185
19186 return (result);
19187 }
19188
19189 static void
19190 zonemgr_free(dns_zonemgr_t *zmgr) {
19191 isc_mem_t *mctx;
19192
19193 INSIST(ISC_LIST_EMPTY(zmgr->zones));
19194
19195 zmgr->magic = 0;
19196
19197 isc_refcount_destroy(&zmgr->refs);
19198 isc_mutex_destroy(&zmgr->iolock);
19199 isc_ratelimiter_detach(&zmgr->checkdsrl);
19200 isc_ratelimiter_detach(&zmgr->notifyrl);
19201 isc_ratelimiter_detach(&zmgr->refreshrl);
19202 isc_ratelimiter_detach(&zmgr->startupnotifyrl);
19203 isc_ratelimiter_detach(&zmgr->startuprefreshrl);
19204
19205 isc_rwlock_destroy(&zmgr->urlock);
19206 isc_rwlock_destroy(&zmgr->rwlock);
19207 isc_rwlock_destroy(&zmgr->tlsctx_cache_rwlock);
19208
19209 zonemgr_keymgmt_destroy(zmgr);
19210
19211 mctx = zmgr->mctx;
19212 if (zmgr->tlsctx_cache != NULL) {
19213 isc_tlsctx_cache_detach(&zmgr->tlsctx_cache);
19214 }
19215 isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
19216 isc_mem_detach(&mctx);
19217 }
19218
19219 void
19220 dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, uint32_t value) {
19221 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19222
19223 zmgr->transfersin = value;
19224 }
19225
19226 uint32_t
19227 dns_zonemgr_gettransfersin(dns_zonemgr_t *zmgr) {
19228 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19229
19230 return (zmgr->transfersin);
19231 }
19232
19233 void
19234 dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, uint32_t value) {
19235 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19236
19237 zmgr->transfersperns = value;
19238 }
19239
19240 uint32_t
19241 dns_zonemgr_gettransfersperns(dns_zonemgr_t *zmgr) {
19242 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19243
19244 return (zmgr->transfersperns);
19245 }
19246
19247 isc_taskmgr_t *
19248 dns_zonemgr_gettaskmgr(dns_zonemgr_t *zmgr) {
19249 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19250
19251 return (zmgr->taskmgr);
19252 }
19253
19254 isc_timermgr_t *
19255 dns_zonemgr_gettimermgr(dns_zonemgr_t *zmgr) {
19256 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19257
19258 return (zmgr->timermgr);
19259 }
19260
19261 /*
19262 * Try to start a new incoming zone transfer to fill a quota
19263 * slot that was just vacated.
19264 *
19265 * Requires:
19266 * The zone manager is locked by the caller.
19267 */
19268 static void
19269 zmgr_resume_xfrs(dns_zonemgr_t *zmgr, bool multi) {
19270 dns_zone_t *zone;
19271 dns_zone_t *next;
19272
19273 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin); zone != NULL;
19274 zone = next)
19275 {
19276 isc_result_t result;
19277 next = ISC_LIST_NEXT(zone, statelink);
19278 result = zmgr_start_xfrin_ifquota(zmgr, zone);
19279 if (result == ISC_R_SUCCESS) {
19280 if (multi) {
19281 continue;
19282 }
19283 /*
19284 * We successfully filled the slot. We're done.
19285 */
19286 break;
19287 } else if (result == ISC_R_QUOTA) {
19288 /*
19289 * Not enough quota. This is probably the per-server
19290 * quota, because we usually get called when a unit of
19291 * global quota has just been freed. Try the next
19292 * zone, it may succeed if it uses another primary.
19293 */
19294 continue;
19295 } else {
19296 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
19297 ISC_LOG_DEBUG(1),
19298 "starting zone transfer: %s",
19299 isc_result_totext(result));
19300 break;
19301 }
19302 }
19303 }
19304
19305 /*
19306 * Try to start an incoming zone transfer for 'zone', quota permitting.
19307 *
19308 * Requires:
19309 * The zone manager is locked by the caller.
19310 *
19311 * Returns:
19312 * ISC_R_SUCCESS There was enough quota and we attempted to
19313 * start a transfer. zone_xfrdone() has been or will
19314 * be called.
19315 * ISC_R_QUOTA Not enough quota.
19316 * Others Failure.
19317 */
19318 static isc_result_t
19319 zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
19320 dns_peer_t *peer = NULL;
19321 isc_netaddr_t primaryip;
19322 uint32_t nxfrsin, nxfrsperns;
19323 dns_zone_t *x;
19324 uint32_t maxtransfersin, maxtransfersperns;
19325 isc_event_t *e;
19326
19327 /*
19328 * If we are exiting just pretend we got quota so the zone will
19329 * be cleaned up in the zone's task context.
19330 */
19331 LOCK_ZONE(zone);
19332 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
19333 UNLOCK_ZONE(zone);
19334 goto gotquota;
19335 }
19336
19337 /*
19338 * Find any configured information about the server we'd
19339 * like to transfer this zone from.
19340 */
19341 isc_netaddr_fromsockaddr(&primaryip, &zone->primaryaddr);
19342 (void)dns_peerlist_peerbyaddr(zone->view->peers, &primaryip, &peer);
19343 UNLOCK_ZONE(zone);
19344
19345 /*
19346 * Determine the total maximum number of simultaneous
19347 * transfers allowed, and the maximum for this specific
19348 * primary.
19349 */
19350 maxtransfersin = zmgr->transfersin;
19351 maxtransfersperns = zmgr->transfersperns;
19352 if (peer != NULL) {
19353 (void)dns_peer_gettransfers(peer, &maxtransfersperns);
19354 }
19355
19356 /*
19357 * Count the total number of transfers that are in progress,
19358 * and the number of transfers in progress from this primary.
19359 * We linearly scan a list of all transfers; if this turns
19360 * out to be too slow, we could hash on the primary address.
19361 */
19362 nxfrsin = nxfrsperns = 0;
19363 for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress); x != NULL;
19364 x = ISC_LIST_NEXT(x, statelink))
19365 {
19366 isc_netaddr_t xip;
19367
19368 LOCK_ZONE(x);
19369 isc_netaddr_fromsockaddr(&xip, &x->primaryaddr);
19370 UNLOCK_ZONE(x);
19371
19372 nxfrsin++;
19373 if (isc_netaddr_equal(&xip, &primaryip)) {
19374 nxfrsperns++;
19375 }
19376 }
19377
19378 /* Enforce quota. */
19379 if (nxfrsin >= maxtransfersin) {
19380 return (ISC_R_QUOTA);
19381 }
19382
19383 if (nxfrsperns >= maxtransfersperns) {
19384 return (ISC_R_QUOTA);
19385 }
19386
19387 gotquota:
19388 /*
19389 * We have sufficient quota. Move the zone to the "xfrin_in_progress"
19390 * list and send it an event to let it start the actual transfer in the
19391 * context of its own task.
19392 */
19393 e = isc_event_allocate(zmgr->mctx, zmgr, DNS_EVENT_ZONESTARTXFRIN,
19394 got_transfer_quota, zone, sizeof(isc_event_t));
19395
19396 LOCK_ZONE(zone);
19397 INSIST(zone->statelist == &zmgr->waiting_for_xfrin);
19398 ISC_LIST_UNLINK(zmgr->waiting_for_xfrin, zone, statelink);
19399 ISC_LIST_APPEND(zmgr->xfrin_in_progress, zone, statelink);
19400 zone->statelist = &zmgr->xfrin_in_progress;
19401 isc_task_send(zone->task, &e);
19402 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
19403 "Transfer started.");
19404 UNLOCK_ZONE(zone);
19405
19406 return (ISC_R_SUCCESS);
19407 }
19408
19409 void
19410 dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, uint32_t iolimit) {
19411 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19412 REQUIRE(iolimit > 0);
19413
19414 zmgr->iolimit = iolimit;
19415 }
19416
19417 uint32_t
19418 dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr) {
19419 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19420
19421 return (zmgr->iolimit);
19422 }
19423
19424 /*
19425 * Get permission to request a file handle from the OS.
19426 * An event will be sent to action when one is available.
19427 * There are two queues available (high and low), the high
19428 * queue will be serviced before the low one.
19429 *
19430 * zonemgr_putio() must be called after the event is delivered to
19431 * 'action'.
19432 */
19433
19434 static isc_result_t
19435 zonemgr_getio(dns_zonemgr_t *zmgr, bool high, isc_task_t *task,
19436 isc_taskaction_t action, void *arg, dns_io_t **iop) {
19437 dns_io_t *io;
19438 bool queue;
19439
19440 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19441 REQUIRE(iop != NULL && *iop == NULL);
19442
19443 io = isc_mem_get(zmgr->mctx, sizeof(*io));
19444
19445 io->event = isc_event_allocate(zmgr->mctx, task, DNS_EVENT_IOREADY,
19446 action, arg, sizeof(*io->event));
19447
19448 io->zmgr = zmgr;
19449 io->high = high;
19450 io->task = NULL;
19451 isc_task_attach(task, &io->task);
19452 ISC_LINK_INIT(io, link);
19453 io->magic = IO_MAGIC;
19454
19455 LOCK(&zmgr->iolock);
19456 zmgr->ioactive++;
19457 queue = (zmgr->ioactive > zmgr->iolimit);
19458 if (queue) {
19459 if (io->high) {
19460 ISC_LIST_APPEND(zmgr->high, io, link);
19461 } else {
19462 ISC_LIST_APPEND(zmgr->low, io, link);
19463 }
19464 }
19465 UNLOCK(&zmgr->iolock);
19466 *iop = io;
19467
19468 if (!queue) {
19469 isc_task_send(io->task, &io->event);
19470 }
19471 return (ISC_R_SUCCESS);
19472 }
19473
19474 static void
19475 zonemgr_putio(dns_io_t **iop) {
19476 dns_io_t *io;
19477 dns_io_t *next;
19478 dns_zonemgr_t *zmgr;
19479
19480 REQUIRE(iop != NULL);
19481 io = *iop;
19482 *iop = NULL;
19483 REQUIRE(DNS_IO_VALID(io));
19484
19485 INSIST(!ISC_LINK_LINKED(io, link));
19486 INSIST(io->event == NULL);
19487
19488 zmgr = io->zmgr;
19489 isc_task_detach(&io->task);
19490 io->magic = 0;
19491 isc_mem_put(zmgr->mctx, io, sizeof(*io));
19492
19493 LOCK(&zmgr->iolock);
19494 INSIST(zmgr->ioactive > 0);
19495 zmgr->ioactive--;
19496 next = HEAD(zmgr->high);
19497 if (next == NULL) {
19498 next = HEAD(zmgr->low);
19499 }
19500 if (next != NULL) {
19501 if (next->high) {
19502 ISC_LIST_UNLINK(zmgr->high, next, link);
19503 } else {
19504 ISC_LIST_UNLINK(zmgr->low, next, link);
19505 }
19506 INSIST(next->event != NULL);
19507 }
19508 UNLOCK(&zmgr->iolock);
19509 if (next != NULL) {
19510 isc_task_send(next->task, &next->event);
19511 }
19512 }
19513
19514 static void
19515 zonemgr_cancelio(dns_io_t *io) {
19516 bool send_event = false;
19517
19518 REQUIRE(DNS_IO_VALID(io));
19519
19520 /*
19521 * If we are queued to be run then dequeue.
19522 */
19523 LOCK(&io->zmgr->iolock);
19524 if (ISC_LINK_LINKED(io, link)) {
19525 if (io->high) {
19526 ISC_LIST_UNLINK(io->zmgr->high, io, link);
19527 } else {
19528 ISC_LIST_UNLINK(io->zmgr->low, io, link);
19529 }
19530
19531 send_event = true;
19532 INSIST(io->event != NULL);
19533 }
19534 UNLOCK(&io->zmgr->iolock);
19535 if (send_event) {
19536 io->event->ev_attributes |= ISC_EVENTATTR_CANCELED;
19537 isc_task_send(io->task, &io->event);
19538 }
19539 }
19540
19541 static void
19542 zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
19543 char *buf;
19544 int buflen;
19545 isc_result_t result;
19546
19547 buflen = strlen(path) + strlen(templat) + 2;
19548
19549 buf = isc_mem_get(zone->mctx, buflen);
19550
19551 result = isc_file_template(path, templat, buf, buflen);
19552 if (result != ISC_R_SUCCESS) {
19553 goto cleanup;
19554 }
19555
19556 result = isc_file_renameunique(path, buf);
19557 if (result != ISC_R_SUCCESS) {
19558 goto cleanup;
19559 }
19560
19561 dns_zone_log(zone, ISC_LOG_WARNING,
19562 "unable to load from '%s'; "
19563 "renaming file to '%s' for failure analysis and "
19564 "retransferring.",
19565 path, buf);
19566
19567 cleanup:
19568 isc_mem_put(zone->mctx, buf, buflen);
19569 }
19570
19571 static void
19572 setrl(isc_ratelimiter_t *rl, unsigned int *rate, unsigned int value) {
19573 isc_interval_t interval;
19574 uint32_t s, ns;
19575 uint32_t pertic;
19576 isc_result_t result;
19577
19578 if (value == 0) {
19579 value = 1;
19580 }
19581
19582 if (value == 1) {
19583 s = 1;
19584 ns = 0;
19585 pertic = 1;
19586 } else if (value <= 10) {
19587 s = 0;
19588 ns = 1000000000 / value;
19589 pertic = 1;
19590 } else {
19591 s = 0;
19592 ns = (1000000000 / value) * 10;
19593 pertic = 10;
19594 }
19595
19596 isc_interval_set(&interval, s, ns);
19597
19598 result = isc_ratelimiter_setinterval(rl, &interval);
19599 RUNTIME_CHECK(result == ISC_R_SUCCESS);
19600 isc_ratelimiter_setpertic(rl, pertic);
19601
19602 *rate = value;
19603 }
19604
19605 void
19606 dns_zonemgr_setcheckdsrate(dns_zonemgr_t *zmgr, unsigned int value) {
19607 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19608
19609 setrl(zmgr->checkdsrl, &zmgr->checkdsrate, value);
19610 }
19611
19612 void
19613 dns_zonemgr_setnotifyrate(dns_zonemgr_t *zmgr, unsigned int value) {
19614 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19615
19616 setrl(zmgr->notifyrl, &zmgr->notifyrate, value);
19617 }
19618
19619 void
19620 dns_zonemgr_setstartupnotifyrate(dns_zonemgr_t *zmgr, unsigned int value) {
19621 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19622
19623 setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, value);
19624 }
19625
19626 void
19627 dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) {
19628 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19629
19630 setrl(zmgr->refreshrl, &zmgr->serialqueryrate, value);
19631 /* XXXMPA separate out once we have the code to support this. */
19632 setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, value);
19633 }
19634
19635 unsigned int
19636 dns_zonemgr_getnotifyrate(dns_zonemgr_t *zmgr) {
19637 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19638
19639 return (zmgr->notifyrate);
19640 }
19641
19642 unsigned int
19643 dns_zonemgr_getstartupnotifyrate(dns_zonemgr_t *zmgr) {
19644 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19645
19646 return (zmgr->startupnotifyrate);
19647 }
19648
19649 unsigned int
19650 dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
19651 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19652
19653 return (zmgr->serialqueryrate);
19654 }
19655
19656 bool
19657 dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
19658 isc_sockaddr_t *local, isc_time_t *now) {
19659 unsigned int i;
19660 uint32_t seconds = isc_time_seconds(now);
19661 uint32_t count = 0;
19662
19663 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19664
19665 RWLOCK(&zmgr->urlock, isc_rwlocktype_read);
19666 for (i = 0; i < UNREACH_CACHE_SIZE; i++) {
19667 if (atomic_load(&zmgr->unreachable[i].expire) >= seconds &&
19668 isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
19669 isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
19670 {
19671 atomic_store_relaxed(&zmgr->unreachable[i].last,
19672 seconds);
19673 count = zmgr->unreachable[i].count;
19674 break;
19675 }
19676 }
19677 RWUNLOCK(&zmgr->urlock, isc_rwlocktype_read);
19678 return (i < UNREACH_CACHE_SIZE && count > 1U);
19679 }
19680
19681 void
19682 dns_zonemgr_unreachabledel(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
19683 isc_sockaddr_t *local) {
19684 unsigned int i;
19685 char primary[ISC_SOCKADDR_FORMATSIZE];
19686 char source[ISC_SOCKADDR_FORMATSIZE];
19687
19688 isc_sockaddr_format(remote, primary, sizeof(primary));
19689 isc_sockaddr_format(local, source, sizeof(source));
19690
19691 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19692
19693 RWLOCK(&zmgr->urlock, isc_rwlocktype_read);
19694 for (i = 0; i < UNREACH_CACHE_SIZE; i++) {
19695 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
19696 isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
19697 {
19698 atomic_store_relaxed(&zmgr->unreachable[i].expire, 0);
19699 break;
19700 }
19701 }
19702 RWUNLOCK(&zmgr->urlock, isc_rwlocktype_read);
19703 }
19704
19705 void
19706 dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
19707 isc_sockaddr_t *local, isc_time_t *now) {
19708 uint32_t seconds = isc_time_seconds(now);
19709 uint32_t expire = 0, last = seconds;
19710 unsigned int slot = UNREACH_CACHE_SIZE, oldest = 0;
19711 bool update_entry = true;
19712 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19713
19714 RWLOCK(&zmgr->urlock, isc_rwlocktype_write);
19715 for (unsigned int i = 0; i < UNREACH_CACHE_SIZE; i++) {
19716 /* Existing entry? */
19717 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
19718 isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
19719 {
19720 update_entry = false;
19721 slot = i;
19722 expire = atomic_load_relaxed(
19723 &zmgr->unreachable[i].expire);
19724 break;
19725 }
19726 /* Pick first empty slot? */
19727 if (atomic_load_relaxed(&zmgr->unreachable[i].expire) < seconds)
19728 {
19729 slot = i;
19730 break;
19731 }
19732 /* The worst case, least recently used slot? */
19733 if (atomic_load_relaxed(&zmgr->unreachable[i].last) < last) {
19734 last = atomic_load_relaxed(&zmgr->unreachable[i].last);
19735 oldest = i;
19736 }
19737 }
19738
19739 /* We haven't found any existing or free slots, use the oldest */
19740 if (slot == UNREACH_CACHE_SIZE) {
19741 slot = oldest;
19742 }
19743
19744 if (expire < seconds) {
19745 /* Expired or new entry, reset count to 1 */
19746 zmgr->unreachable[slot].count = 1;
19747 } else {
19748 zmgr->unreachable[slot].count++;
19749 }
19750 atomic_store_relaxed(&zmgr->unreachable[slot].expire,
19751 seconds + UNREACH_HOLD_TIME);
19752 atomic_store_relaxed(&zmgr->unreachable[slot].last, seconds);
19753 if (update_entry) {
19754 zmgr->unreachable[slot].remote = *remote;
19755 zmgr->unreachable[slot].local = *local;
19756 }
19757
19758 RWUNLOCK(&zmgr->urlock, isc_rwlocktype_write);
19759 }
19760
19761 void
19762 dns_zone_forcereload(dns_zone_t *zone) {
19763 REQUIRE(DNS_ZONE_VALID(zone));
19764
19765 if (zone->type == dns_zone_primary ||
19766 (zone->type == dns_zone_redirect && zone->primaries == NULL))
19767 {
19768 return;
19769 }
19770
19771 LOCK_ZONE(zone);
19772 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
19773 UNLOCK_ZONE(zone);
19774 dns_zone_refresh(zone);
19775 }
19776
19777 bool
19778 dns_zone_isforced(dns_zone_t *zone) {
19779 REQUIRE(DNS_ZONE_VALID(zone));
19780
19781 return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER));
19782 }
19783
19784 isc_result_t
19785 dns_zone_setstatistics(dns_zone_t *zone, bool on) {
19786 /*
19787 * This function is obsoleted.
19788 */
19789 UNUSED(zone);
19790 UNUSED(on);
19791 return (ISC_R_NOTIMPLEMENTED);
19792 }
19793
19794 uint64_t *
19795 dns_zone_getstatscounters(dns_zone_t *zone) {
19796 /*
19797 * This function is obsoleted.
19798 */
19799 UNUSED(zone);
19800 return (NULL);
19801 }
19802
19803 void
19804 dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats) {
19805 REQUIRE(DNS_ZONE_VALID(zone));
19806 REQUIRE(zone->stats == NULL);
19807
19808 LOCK_ZONE(zone);
19809 zone->stats = NULL;
19810 isc_stats_attach(stats, &zone->stats);
19811 UNLOCK_ZONE(zone);
19812 }
19813
19814 void
19815 dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats) {
19816 REQUIRE(DNS_ZONE_VALID(zone));
19817
19818 LOCK_ZONE(zone);
19819 if (zone->requeststats_on && stats == NULL) {
19820 zone->requeststats_on = false;
19821 } else if (!zone->requeststats_on && stats != NULL) {
19822 if (zone->requeststats == NULL) {
19823 isc_stats_attach(stats, &zone->requeststats);
19824 }
19825 zone->requeststats_on = true;
19826 }
19827 UNLOCK_ZONE(zone);
19828 }
19829
19830 void
19831 dns_zone_setrcvquerystats(dns_zone_t *zone, dns_stats_t *stats) {
19832 REQUIRE(DNS_ZONE_VALID(zone));
19833
19834 LOCK_ZONE(zone);
19835 if (zone->requeststats_on && stats != NULL) {
19836 if (zone->rcvquerystats == NULL) {
19837 dns_stats_attach(stats, &zone->rcvquerystats);
19838 zone->requeststats_on = true;
19839 }
19840 }
19841 UNLOCK_ZONE(zone);
19842 }
19843
19844 void
19845 dns_zone_setdnssecsignstats(dns_zone_t *zone, dns_stats_t *stats) {
19846 REQUIRE(DNS_ZONE_VALID(zone));
19847
19848 LOCK_ZONE(zone);
19849 if (stats != NULL && zone->dnssecsignstats == NULL) {
19850 dns_stats_attach(stats, &zone->dnssecsignstats);
19851 }
19852 UNLOCK_ZONE(zone);
19853 }
19854
19855 dns_stats_t *
19856 dns_zone_getdnssecsignstats(dns_zone_t *zone) {
19857 REQUIRE(DNS_ZONE_VALID(zone));
19858
19859 return (zone->dnssecsignstats);
19860 }
19861
19862 isc_stats_t *
19863 dns_zone_getrequeststats(dns_zone_t *zone) {
19864 /*
19865 * We don't lock zone for efficiency reason. This is not catastrophic
19866 * because requeststats must always be valid when requeststats_on is
19867 * true.
19868 * Some counters may be incremented while requeststats_on is becoming
19869 * false, or some cannot be incremented just after the statistics are
19870 * installed, but it shouldn't matter much in practice.
19871 */
19872 if (zone->requeststats_on) {
19873 return (zone->requeststats);
19874 } else {
19875 return (NULL);
19876 }
19877 }
19878
19879 /*
19880 * Return the received query stats bucket
19881 * see note from dns_zone_getrequeststats()
19882 */
19883 dns_stats_t *
19884 dns_zone_getrcvquerystats(dns_zone_t *zone) {
19885 if (zone->requeststats_on) {
19886 return (zone->rcvquerystats);
19887 } else {
19888 return (NULL);
19889 }
19890 }
19891
19892 void
19893 dns_zone_dialup(dns_zone_t *zone) {
19894 REQUIRE(DNS_ZONE_VALID(zone));
19895
19896 zone_debuglog(zone, "dns_zone_dialup", 3, "notify = %d, refresh = %d",
19897 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY),
19898 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH));
19899
19900 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY)) {
19901 dns_zone_notify(zone);
19902 }
19903 if (zone->type != dns_zone_primary && zone->primaries != NULL &&
19904 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
19905 {
19906 dns_zone_refresh(zone);
19907 }
19908 }
19909
19910 void
19911 dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
19912 REQUIRE(DNS_ZONE_VALID(zone));
19913
19914 LOCK_ZONE(zone);
19915 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
19916 DNS_ZONEFLG_DIALREFRESH |
19917 DNS_ZONEFLG_NOREFRESH);
19918 switch (dialup) {
19919 case dns_dialuptype_no:
19920 break;
19921 case dns_dialuptype_yes:
19922 DNS_ZONE_SETFLAG(zone, (DNS_ZONEFLG_DIALNOTIFY |
19923 DNS_ZONEFLG_DIALREFRESH |
19924 DNS_ZONEFLG_NOREFRESH));
19925 break;
19926 case dns_dialuptype_notify:
19927 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
19928 break;
19929 case dns_dialuptype_notifypassive:
19930 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
19931 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
19932 break;
19933 case dns_dialuptype_refresh:
19934 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALREFRESH);
19935 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
19936 break;
19937 case dns_dialuptype_passive:
19938 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
19939 break;
19940 default:
19941 UNREACHABLE();
19942 }
19943 UNLOCK_ZONE(zone);
19944 }
19945
19946 isc_result_t
19947 dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory) {
19948 isc_result_t result = ISC_R_SUCCESS;
19949
19950 REQUIRE(DNS_ZONE_VALID(zone));
19951
19952 LOCK_ZONE(zone);
19953 result = dns_zone_setstring(zone, &zone->keydirectory, directory);
19954 UNLOCK_ZONE(zone);
19955
19956 return (result);
19957 }
19958
19959 const char *
19960 dns_zone_getkeydirectory(dns_zone_t *zone) {
19961 REQUIRE(DNS_ZONE_VALID(zone));
19962
19963 return (zone->keydirectory);
19964 }
19965
19966 unsigned int
19967 dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state) {
19968 dns_zone_t *zone;
19969 unsigned int count = 0;
19970
19971 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19972
19973 RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
19974 switch (state) {
19975 case DNS_ZONESTATE_XFERRUNNING:
19976 for (zone = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
19977 zone != NULL; zone = ISC_LIST_NEXT(zone, statelink))
19978 {
19979 count++;
19980 }
19981 break;
19982 case DNS_ZONESTATE_XFERDEFERRED:
19983 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
19984 zone != NULL; zone = ISC_LIST_NEXT(zone, statelink))
19985 {
19986 count++;
19987 }
19988 break;
19989 case DNS_ZONESTATE_SOAQUERY:
19990 for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
19991 zone = ISC_LIST_NEXT(zone, link))
19992 {
19993 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
19994 count++;
19995 }
19996 }
19997 break;
19998 case DNS_ZONESTATE_ANY:
19999 for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
20000 zone = ISC_LIST_NEXT(zone, link))
20001 {
20002 dns_view_t *view = zone->view;
20003 if (view != NULL && strcmp(view->name, "_bind") == 0) {
20004 continue;
20005 }
20006 count++;
20007 }
20008 break;
20009 case DNS_ZONESTATE_AUTOMATIC:
20010 for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
20011 zone = ISC_LIST_NEXT(zone, link))
20012 {
20013 dns_view_t *view = zone->view;
20014 if (view != NULL && strcmp(view->name, "_bind") == 0) {
20015 continue;
20016 }
20017 if (zone->automatic) {
20018 count++;
20019 }
20020 }
20021 break;
20022 default:
20023 UNREACHABLE();
20024 }
20025
20026 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
20027
20028 return (count);
20029 }
20030
20031 void
20032 dns_zone_lock_keyfiles(dns_zone_t *zone) {
20033 REQUIRE(DNS_ZONE_VALID(zone));
20034
20035 if (zone->kasp == NULL) {
20036 /* No need to lock, nothing is writing key files. */
20037 return;
20038 }
20039
20040 REQUIRE(DNS_KEYFILEIO_VALID(zone->kfio));
20041 isc_mutex_lock(&zone->kfio->lock);
20042 }
20043
20044 void
20045 dns_zone_unlock_keyfiles(dns_zone_t *zone) {
20046 REQUIRE(DNS_ZONE_VALID(zone));
20047
20048 if (zone->kasp == NULL) {
20049 /* No need to lock, nothing is writing key files. */
20050 return;
20051 }
20052
20053 REQUIRE(DNS_KEYFILEIO_VALID(zone->kfio));
20054 isc_mutex_unlock(&zone->kfio->lock);
20055 }
20056
20057 isc_result_t
20058 dns_zone_checknames(dns_zone_t *zone, const dns_name_t *name,
20059 dns_rdata_t *rdata) {
20060 bool ok = true;
20061 bool fail = false;
20062 char namebuf[DNS_NAME_FORMATSIZE];
20063 char namebuf2[DNS_NAME_FORMATSIZE];
20064 char typebuf[DNS_RDATATYPE_FORMATSIZE];
20065 int level = ISC_LOG_WARNING;
20066 dns_name_t bad;
20067
20068 REQUIRE(DNS_ZONE_VALID(zone));
20069
20070 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES) &&
20071 rdata->type != dns_rdatatype_nsec3)
20072 {
20073 return (ISC_R_SUCCESS);
20074 }
20075
20076 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL) ||
20077 rdata->type == dns_rdatatype_nsec3)
20078 {
20079 level = ISC_LOG_ERROR;
20080 fail = true;
20081 }
20082
20083 ok = dns_rdata_checkowner(name, rdata->rdclass, rdata->type, true);
20084 if (!ok) {
20085 dns_name_format(name, namebuf, sizeof(namebuf));
20086 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
20087 dns_zone_log(zone, level, "%s/%s: %s", namebuf, typebuf,
20088 isc_result_totext(DNS_R_BADOWNERNAME));
20089 if (fail) {
20090 return (DNS_R_BADOWNERNAME);
20091 }
20092 }
20093
20094 dns_name_init(&bad, NULL);
20095 ok = dns_rdata_checknames(rdata, name, &bad);
20096 if (!ok) {
20097 dns_name_format(name, namebuf, sizeof(namebuf));
20098 dns_name_format(&bad, namebuf2, sizeof(namebuf2));
20099 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
20100 dns_zone_log(zone, level, "%s/%s: %s: %s ", namebuf, typebuf,
20101 namebuf2, isc_result_totext(DNS_R_BADNAME));
20102 if (fail) {
20103 return (DNS_R_BADNAME);
20104 }
20105 }
20106
20107 return (ISC_R_SUCCESS);
20108 }
20109
20110 void
20111 dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx) {
20112 REQUIRE(DNS_ZONE_VALID(zone));
20113 zone->checkmx = checkmx;
20114 }
20115
20116 void
20117 dns_zone_setchecksrv(dns_zone_t *zone, dns_checksrvfunc_t checksrv) {
20118 REQUIRE(DNS_ZONE_VALID(zone));
20119 zone->checksrv = checksrv;
20120 }
20121
20122 void
20123 dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns) {
20124 REQUIRE(DNS_ZONE_VALID(zone));
20125 zone->checkns = checkns;
20126 }
20127
20128 void
20129 dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg) {
20130 REQUIRE(DNS_ZONE_VALID(zone));
20131
20132 LOCK_ZONE(zone);
20133 zone->isself = isself;
20134 zone->isselfarg = arg;
20135 UNLOCK_ZONE(zone);
20136 }
20137
20138 void
20139 dns_zone_setnotifydelay(dns_zone_t *zone, uint32_t delay) {
20140 REQUIRE(DNS_ZONE_VALID(zone));
20141
20142 LOCK_ZONE(zone);
20143 zone->notifydelay = delay;
20144 UNLOCK_ZONE(zone);
20145 }
20146
20147 uint32_t
20148 dns_zone_getnotifydelay(dns_zone_t *zone) {
20149 REQUIRE(DNS_ZONE_VALID(zone));
20150
20151 return (zone->notifydelay);
20152 }
20153
20154 isc_result_t
20155 dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid,
20156 bool deleteit) {
20157 isc_result_t result;
20158 REQUIRE(DNS_ZONE_VALID(zone));
20159
20160 dnssec_log(zone, ISC_LOG_NOTICE,
20161 "dns_zone_signwithkey(algorithm=%u, keyid=%u)", algorithm,
20162 keyid);
20163 LOCK_ZONE(zone);
20164 result = zone_signwithkey(zone, algorithm, keyid, deleteit);
20165 UNLOCK_ZONE(zone);
20166
20167 return (result);
20168 }
20169
20170 /*
20171 * Called when a dynamic update for an NSEC3PARAM record is received.
20172 *
20173 * If set, transform the NSEC3 salt into human-readable form so that it can be
20174 * logged. Then call zone_addnsec3chain(), passing NSEC3PARAM RDATA to it.
20175 */
20176 isc_result_t
20177 dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
20178 isc_result_t result;
20179 char salt[255 * 2 + 1];
20180
20181 REQUIRE(DNS_ZONE_VALID(zone));
20182
20183 result = dns_nsec3param_salttotext(nsec3param, salt, sizeof(salt));
20184 RUNTIME_CHECK(result == ISC_R_SUCCESS);
20185 dnssec_log(zone, ISC_LOG_NOTICE,
20186 "dns_zone_addnsec3chain(hash=%u, iterations=%u, salt=%s)",
20187 nsec3param->hash, nsec3param->iterations, salt);
20188 LOCK_ZONE(zone);
20189 result = zone_addnsec3chain(zone, nsec3param);
20190 UNLOCK_ZONE(zone);
20191
20192 return (result);
20193 }
20194
20195 void
20196 dns_zone_setnodes(dns_zone_t *zone, uint32_t nodes) {
20197 REQUIRE(DNS_ZONE_VALID(zone));
20198
20199 if (nodes == 0) {
20200 nodes = 1;
20201 }
20202 zone->nodes = nodes;
20203 }
20204
20205 void
20206 dns_zone_setsignatures(dns_zone_t *zone, uint32_t signatures) {
20207 REQUIRE(DNS_ZONE_VALID(zone));
20208
20209 /*
20210 * We treat signatures as a signed value so explicitly
20211 * limit its range here.
20212 */
20213 if (signatures > INT32_MAX) {
20214 signatures = INT32_MAX;
20215 } else if (signatures == 0) {
20216 signatures = 1;
20217 }
20218 zone->signatures = signatures;
20219 }
20220
20221 uint32_t
20222 dns_zone_getsignatures(dns_zone_t *zone) {
20223 REQUIRE(DNS_ZONE_VALID(zone));
20224 return (zone->signatures);
20225 }
20226
20227 void
20228 dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type) {
20229 REQUIRE(DNS_ZONE_VALID(zone));
20230 zone->privatetype = type;
20231 }
20232
20233 dns_rdatatype_t
20234 dns_zone_getprivatetype(dns_zone_t *zone) {
20235 REQUIRE(DNS_ZONE_VALID(zone));
20236 return (zone->privatetype);
20237 }
20238
20239 static isc_result_t
20240 zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid,
20241 bool deleteit) {
20242 dns_signing_t *signing;
20243 dns_signing_t *current;
20244 isc_result_t result = ISC_R_SUCCESS;
20245 isc_time_t now;
20246 dns_db_t *db = NULL;
20247
20248 signing = isc_mem_get(zone->mctx, sizeof *signing);
20249
20250 signing->magic = 0;
20251 signing->db = NULL;
20252 signing->dbiterator = NULL;
20253 signing->algorithm = algorithm;
20254 signing->keyid = keyid;
20255 signing->deleteit = deleteit;
20256 signing->done = false;
20257
20258 TIME_NOW(&now);
20259
20260 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
20261 if (zone->db != NULL) {
20262 dns_db_attach(zone->db, &db);
20263 }
20264 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
20265
20266 if (db == NULL) {
20267 result = ISC_R_NOTFOUND;
20268 goto cleanup;
20269 }
20270
20271 dns_db_attach(db, &signing->db);
20272
20273 for (current = ISC_LIST_HEAD(zone->signing); current != NULL;
20274 current = ISC_LIST_NEXT(current, link))
20275 {
20276 if (current->db == signing->db &&
20277 current->algorithm == signing->algorithm &&
20278 current->keyid == signing->keyid)
20279 {
20280 if (current->deleteit != signing->deleteit) {
20281 current->done = true;
20282 } else {
20283 goto cleanup;
20284 }
20285 }
20286 }
20287
20288 result = dns_db_createiterator(signing->db, 0, &signing->dbiterator);
20289
20290 if (result == ISC_R_SUCCESS) {
20291 result = dns_dbiterator_first(signing->dbiterator);
20292 }
20293 if (result == ISC_R_SUCCESS) {
20294 dns_dbiterator_pause(signing->dbiterator);
20295 ISC_LIST_INITANDAPPEND(zone->signing, signing, link);
20296 signing = NULL;
20297 if (isc_time_isepoch(&zone->signingtime)) {
20298 zone->signingtime = now;
20299 if (zone->task != NULL) {
20300 zone_settimer(zone, &now);
20301 }
20302 }
20303 }
20304
20305 cleanup:
20306 if (signing != NULL) {
20307 if (signing->db != NULL) {
20308 dns_db_detach(&signing->db);
20309 }
20310 if (signing->dbiterator != NULL) {
20311 dns_dbiterator_destroy(&signing->dbiterator);
20312 }
20313 isc_mem_put(zone->mctx, signing, sizeof *signing);
20314 }
20315 if (db != NULL) {
20316 dns_db_detach(&db);
20317 }
20318 return (result);
20319 }
20320
20321 /* Called once; *timep should be set to the current time. */
20322 static isc_result_t
20323 next_keyevent(dst_key_t *key, isc_stdtime_t *timep) {
20324 isc_result_t result;
20325 isc_stdtime_t now, then = 0, event;
20326 int i;
20327
20328 now = *timep;
20329
20330 for (i = 0; i <= DST_MAX_TIMES; i++) {
20331 result = dst_key_gettime(key, i, &event);
20332 if (result == ISC_R_SUCCESS && event > now &&
20333 (then == 0 || event < then))
20334 {
20335 then = event;
20336 }
20337 }
20338
20339 if (then != 0) {
20340 *timep = then;
20341 return (ISC_R_SUCCESS);
20342 }
20343
20344 return (ISC_R_NOTFOUND);
20345 }
20346
20347 static isc_result_t
20348 rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
20349 const dns_rdata_t *rdata, bool *flag) {
20350 dns_rdataset_t rdataset;
20351 dns_dbnode_t *node = NULL;
20352 isc_result_t result;
20353
20354 dns_rdataset_init(&rdataset);
20355 if (rdata->type == dns_rdatatype_nsec3) {
20356 CHECK(dns_db_findnsec3node(db, name, false, &node));
20357 } else {
20358 CHECK(dns_db_findnode(db, name, false, &node));
20359 }
20360 result = dns_db_findrdataset(db, node, ver, rdata->type, 0,
20361 (isc_stdtime_t)0, &rdataset, NULL);
20362 if (result == ISC_R_NOTFOUND) {
20363 *flag = false;
20364 result = ISC_R_SUCCESS;
20365 goto failure;
20366 }
20367
20368 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
20369 result = dns_rdataset_next(&rdataset))
20370 {
20371 dns_rdata_t myrdata = DNS_RDATA_INIT;
20372 dns_rdataset_current(&rdataset, &myrdata);
20373 if (!dns_rdata_compare(&myrdata, rdata)) {
20374 break;
20375 }
20376 }
20377 dns_rdataset_disassociate(&rdataset);
20378 if (result == ISC_R_SUCCESS) {
20379 *flag = true;
20380 } else if (result == ISC_R_NOMORE) {
20381 *flag = false;
20382 result = ISC_R_SUCCESS;
20383 }
20384
20385 failure:
20386 if (node != NULL) {
20387 dns_db_detachnode(db, &node);
20388 }
20389 return (result);
20390 }
20391
20392 /*
20393 * Add records to signal the state of signing or of key removal.
20394 */
20395 static isc_result_t
20396 add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
20397 dns_dbversion_t *ver, dns_diff_t *diff, bool sign_all) {
20398 dns_difftuple_t *tuple, *newtuple = NULL;
20399 dns_rdata_dnskey_t dnskey;
20400 dns_rdata_t rdata = DNS_RDATA_INIT;
20401 bool flag;
20402 isc_region_t r;
20403 isc_result_t result = ISC_R_SUCCESS;
20404 uint16_t keyid;
20405 unsigned char buf[5];
20406 dns_name_t *name = dns_db_origin(db);
20407
20408 for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL;
20409 tuple = ISC_LIST_NEXT(tuple, link))
20410 {
20411 if (tuple->rdata.type != dns_rdatatype_dnskey) {
20412 continue;
20413 }
20414
20415 result = dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
20416 RUNTIME_CHECK(result == ISC_R_SUCCESS);
20417 if ((dnskey.flags & (DNS_KEYFLAG_OWNERMASK |
20418 DNS_KEYTYPE_NOAUTH)) != DNS_KEYOWNER_ZONE)
20419 {
20420 continue;
20421 }
20422
20423 dns_rdata_toregion(&tuple->rdata, &r);
20424
20425 keyid = dst_region_computeid(&r);
20426
20427 buf[0] = dnskey.algorithm;
20428 buf[1] = (keyid & 0xff00) >> 8;
20429 buf[2] = (keyid & 0xff);
20430 buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1;
20431 buf[4] = 0;
20432 rdata.data = buf;
20433 rdata.length = sizeof(buf);
20434 rdata.type = privatetype;
20435 rdata.rdclass = tuple->rdata.rdclass;
20436
20437 if (sign_all || tuple->op == DNS_DIFFOP_DEL) {
20438 CHECK(rr_exists(db, ver, name, &rdata, &flag));
20439 if (flag) {
20440 continue;
20441 }
20442
20443 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
20444 name, 0, &rdata, &newtuple));
20445 CHECK(do_one_tuple(&newtuple, db, ver, diff));
20446 INSIST(newtuple == NULL);
20447 }
20448
20449 /*
20450 * Remove any record which says this operation has already
20451 * completed.
20452 */
20453 buf[4] = 1;
20454 CHECK(rr_exists(db, ver, name, &rdata, &flag));
20455 if (flag) {
20456 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL,
20457 name, 0, &rdata, &newtuple));
20458 CHECK(do_one_tuple(&newtuple, db, ver, diff));
20459 INSIST(newtuple == NULL);
20460 }
20461 }
20462 failure:
20463 return (result);
20464 }
20465
20466 /*
20467 * See if dns__zone_updatesigs() will update signature for RRset 'rrtype' at
20468 * the apex, and if not tickle them and cause to sign so that newly activated
20469 * keys are used.
20470 */
20471 static isc_result_t
20472 tickle_apex_rrset(dns_rdatatype_t rrtype, dns_zone_t *zone, dns_db_t *db,
20473 dns_dbversion_t *ver, isc_stdtime_t now, dns_diff_t *diff,
20474 dns__zonediff_t *zonediff, dst_key_t **keys,
20475 unsigned int nkeys, isc_stdtime_t inception,
20476 isc_stdtime_t keyexpire, bool check_ksk,
20477 bool keyset_kskonly) {
20478 dns_difftuple_t *tuple;
20479 isc_result_t result;
20480
20481 for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL;
20482 tuple = ISC_LIST_NEXT(tuple, link))
20483 {
20484 if (tuple->rdata.type == rrtype &&
20485 dns_name_equal(&tuple->name, &zone->origin))
20486 {
20487 break;
20488 }
20489 }
20490
20491 if (tuple == NULL) {
20492 result = del_sigs(zone, db, ver, &zone->origin, rrtype,
20493 zonediff, keys, nkeys, now, false);
20494 if (result != ISC_R_SUCCESS) {
20495 dnssec_log(zone, ISC_LOG_ERROR,
20496 "sign_apex:del_sigs -> %s",
20497 isc_result_totext(result));
20498 return (result);
20499 }
20500 result = add_sigs(db, ver, &zone->origin, zone, rrtype,
20501 zonediff->diff, keys, nkeys, zone->mctx, now,
20502 inception, keyexpire, check_ksk,
20503 keyset_kskonly);
20504 if (result != ISC_R_SUCCESS) {
20505 dnssec_log(zone, ISC_LOG_ERROR,
20506 "sign_apex:add_sigs -> %s",
20507 isc_result_totext(result));
20508 return (result);
20509 }
20510 }
20511
20512 return (ISC_R_SUCCESS);
20513 }
20514
20515 static isc_result_t
20516 sign_apex(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
20517 isc_stdtime_t now, dns_diff_t *diff, dns__zonediff_t *zonediff) {
20518 isc_result_t result;
20519 isc_stdtime_t inception, soaexpire, keyexpire;
20520 bool check_ksk, keyset_kskonly;
20521 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
20522 unsigned int nkeys = 0, i;
20523
20524 result = dns__zone_findkeys(zone, db, ver, now, zone->mctx,
20525 DNS_MAXZONEKEYS, zone_keys, &nkeys);
20526 if (result != ISC_R_SUCCESS) {
20527 dnssec_log(zone, ISC_LOG_ERROR,
20528 "sign_apex:dns__zone_findkeys -> %s",
20529 isc_result_totext(result));
20530 return (result);
20531 }
20532
20533 inception = now - 3600; /* Allow for clock skew. */
20534 soaexpire = now + dns_zone_getsigvalidityinterval(zone);
20535
20536 keyexpire = dns_zone_getkeyvalidityinterval(zone);
20537 if (keyexpire == 0) {
20538 keyexpire = soaexpire - 1;
20539 } else {
20540 keyexpire += now;
20541 }
20542
20543 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
20544 keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
20545
20546 /*
20547 * See if dns__zone_updatesigs() will update DNSKEY/CDS/CDNSKEY
20548 * signature and if not cause them to sign so that newly activated
20549 * keys are used.
20550 */
20551 result = tickle_apex_rrset(dns_rdatatype_dnskey, zone, db, ver, now,
20552 diff, zonediff, zone_keys, nkeys, inception,
20553 keyexpire, check_ksk, keyset_kskonly);
20554 if (result != ISC_R_SUCCESS) {
20555 goto failure;
20556 }
20557 result = tickle_apex_rrset(dns_rdatatype_cds, zone, db, ver, now, diff,
20558 zonediff, zone_keys, nkeys, inception,
20559 keyexpire, check_ksk, keyset_kskonly);
20560 if (result != ISC_R_SUCCESS) {
20561 goto failure;
20562 }
20563 result = tickle_apex_rrset(dns_rdatatype_cdnskey, zone, db, ver, now,
20564 diff, zonediff, zone_keys, nkeys, inception,
20565 keyexpire, check_ksk, keyset_kskonly);
20566 if (result != ISC_R_SUCCESS) {
20567 goto failure;
20568 }
20569
20570 result = dns__zone_updatesigs(diff, db, ver, zone_keys, nkeys, zone,
20571 inception, soaexpire, keyexpire, now,
20572 check_ksk, keyset_kskonly, zonediff);
20573
20574 if (result != ISC_R_SUCCESS) {
20575 dnssec_log(zone, ISC_LOG_ERROR,
20576 "sign_apex:dns__zone_updatesigs -> %s",
20577 isc_result_totext(result));
20578 goto failure;
20579 }
20580
20581 failure:
20582 for (i = 0; i < nkeys; i++) {
20583 dst_key_free(&zone_keys[i]);
20584 }
20585 return (result);
20586 }
20587
20588 static isc_result_t
20589 clean_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
20590 dns_diff_t *diff) {
20591 isc_result_t result;
20592 dns_dbnode_t *node = NULL;
20593 dns_rdataset_t rdataset;
20594
20595 dns_rdataset_init(&rdataset);
20596 CHECK(dns_db_getoriginnode(db, &node));
20597
20598 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
20599 dns_rdatatype_none, 0, &rdataset, NULL);
20600 if (dns_rdataset_isassociated(&rdataset)) {
20601 dns_rdataset_disassociate(&rdataset);
20602 }
20603 if (result != ISC_R_NOTFOUND) {
20604 goto failure;
20605 }
20606
20607 result = dns_nsec3param_deletechains(db, ver, zone, true, diff);
20608
20609 failure:
20610 if (node != NULL) {
20611 dns_db_detachnode(db, &node);
20612 }
20613 return (result);
20614 }
20615
20616 /*
20617 * Given an RRSIG rdataset and an algorithm, determine whether there
20618 * are any signatures using that algorithm.
20619 */
20620 static bool
20621 signed_with_alg(dns_rdataset_t *rdataset, dns_secalg_t alg) {
20622 dns_rdata_t rdata = DNS_RDATA_INIT;
20623 dns_rdata_rrsig_t rrsig;
20624 isc_result_t result;
20625
20626 REQUIRE(rdataset == NULL || rdataset->type == dns_rdatatype_rrsig);
20627 if (rdataset == NULL || !dns_rdataset_isassociated(rdataset)) {
20628 return (false);
20629 }
20630
20631 for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
20632 result = dns_rdataset_next(rdataset))
20633 {
20634 dns_rdataset_current(rdataset, &rdata);
20635 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
20636 RUNTIME_CHECK(result == ISC_R_SUCCESS);
20637 dns_rdata_reset(&rdata);
20638 if (rrsig.algorithm == alg) {
20639 return (true);
20640 }
20641 }
20642
20643 return (false);
20644 }
20645
20646 static isc_result_t
20647 add_chains(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
20648 dns_diff_t *diff) {
20649 dns_name_t *origin;
20650 bool build_nsec3;
20651 isc_result_t result;
20652
20653 origin = dns_db_origin(db);
20654 CHECK(dns_private_chains(db, ver, zone->privatetype, NULL,
20655 &build_nsec3));
20656 if (build_nsec3) {
20657 CHECK(dns_nsec3_addnsec3sx(db, ver, origin, zone_nsecttl(zone),
20658 false, zone->privatetype, diff));
20659 }
20660 CHECK(updatesecure(db, ver, origin, zone_nsecttl(zone), true, diff));
20661
20662 failure:
20663 return (result);
20664 }
20665
20666 static void
20667 dnssec_report(const char *format, ...) {
20668 va_list args;
20669 va_start(args, format);
20670 isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_ZONE,
20671 ISC_LOG_INFO, format, args);
20672 va_end(args);
20673 }
20674
20675 static void
20676 checkds_destroy(dns_checkds_t *checkds, bool locked) {
20677 isc_mem_t *mctx;
20678
20679 REQUIRE(DNS_CHECKDS_VALID(checkds));
20680
20681 dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
20682 "checkds: destroy DS query");
20683
20684 if (checkds->zone != NULL) {
20685 if (!locked) {
20686 LOCK_ZONE(checkds->zone);
20687 }
20688 REQUIRE(LOCKED_ZONE(checkds->zone));
20689 if (ISC_LINK_LINKED(checkds, link)) {
20690 ISC_LIST_UNLINK(checkds->zone->checkds_requests,
20691 checkds, link);
20692 }
20693 if (!locked) {
20694 UNLOCK_ZONE(checkds->zone);
20695 }
20696 if (locked) {
20697 zone_idetach(&checkds->zone);
20698 } else {
20699 dns_zone_idetach(&checkds->zone);
20700 }
20701 }
20702 if (checkds->request != NULL) {
20703 dns_request_destroy(&checkds->request);
20704 }
20705 if (checkds->key != NULL) {
20706 dns_tsigkey_detach(&checkds->key);
20707 }
20708 if (checkds->transport != NULL) {
20709 dns_transport_detach(&checkds->transport);
20710 }
20711 mctx = checkds->mctx;
20712 isc_mem_put(checkds->mctx, checkds, sizeof(*checkds));
20713 isc_mem_detach(&mctx);
20714 }
20715
20716 static isc_result_t
20717 make_dnskey(dst_key_t *key, unsigned char *buf, int bufsize,
20718 dns_rdata_t *target) {
20719 isc_result_t result;
20720 isc_buffer_t b;
20721 isc_region_t r;
20722
20723 isc_buffer_init(&b, buf, bufsize);
20724 result = dst_key_todns(key, &b);
20725 if (result != ISC_R_SUCCESS) {
20726 return (result);
20727 }
20728
20729 dns_rdata_reset(target);
20730 isc_buffer_usedregion(&b, &r);
20731 dns_rdata_fromregion(target, dst_key_class(key), dns_rdatatype_dnskey,
20732 &r);
20733 return (ISC_R_SUCCESS);
20734 }
20735
20736 static bool
20737 do_checkds(dns_zone_t *zone, dst_key_t *key, isc_stdtime_t now,
20738 bool dspublish) {
20739 dns_kasp_t *kasp = dns_zone_getkasp(zone);
20740 const char *dir = dns_zone_getkeydirectory(zone);
20741 isc_result_t result;
20742 uint32_t count = 0;
20743
20744 if (dspublish) {
20745 (void)dst_key_getnum(key, DST_NUM_DSPUBCOUNT, &count);
20746 count += 1;
20747 dst_key_setnum(key, DST_NUM_DSPUBCOUNT, count);
20748 dns_zone_log(zone, ISC_LOG_DEBUG(3),
20749 "checkds: %u DS published "
20750 "for key %u",
20751 count, dst_key_id(key));
20752
20753 if (count != zone->parentalscnt) {
20754 return false;
20755 }
20756 } else {
20757 (void)dst_key_getnum(key, DST_NUM_DSDELCOUNT, &count);
20758 count += 1;
20759 dst_key_setnum(key, DST_NUM_DSDELCOUNT, count);
20760 dns_zone_log(zone, ISC_LOG_DEBUG(3),
20761 "checkds: %u DS withdrawn "
20762 "for key %u",
20763 count, dst_key_id(key));
20764
20765 if (count != zone->parentalscnt) {
20766 return false;
20767 }
20768 }
20769
20770 dns_zone_log(zone, ISC_LOG_DEBUG(3),
20771 "checkds: checkds %s for key "
20772 "%u",
20773 dspublish ? "published" : "withdrawn", dst_key_id(key));
20774
20775 dns_zone_lock_keyfiles(zone);
20776 result = dns_keymgr_checkds_id(kasp, &zone->checkds_ok, dir, now, now,
20777 dspublish, dst_key_id(key),
20778 dst_key_alg(key));
20779 dns_zone_unlock_keyfiles(zone);
20780
20781 if (result != ISC_R_SUCCESS) {
20782 dns_zone_log(zone, ISC_LOG_WARNING,
20783 "checkds: checkds for key %u failed: %s",
20784 dst_key_id(key), isc_result_totext(result));
20785 return false;
20786 }
20787
20788 return true;
20789 }
20790
20791 static isc_result_t
20792 validate_ds(dns_zone_t *zone, dns_message_t *message) {
20793 UNUSED(zone);
20794 UNUSED(message);
20795
20796 /* Get closest trust anchor */
20797
20798 /* Check that trust anchor is (grand)parent of zone. */
20799
20800 /* Find the DNSKEY signing the message. */
20801
20802 /* Check that DNSKEY is in chain of trust. */
20803
20804 /* Validate DS RRset. */
20805
20806 return (ISC_R_SUCCESS);
20807 }
20808
20809 static void
20810 checkds_done(isc_task_t *task, isc_event_t *event) {
20811 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
20812 char rcode[128];
20813 dns_checkds_t *checkds;
20814 dns_zone_t *zone;
20815 dns_db_t *db = NULL;
20816 dns_dbversion_t *version = NULL;
20817 dns_dnsseckey_t *key;
20818 dns_dnsseckeylist_t keys;
20819 dns_kasp_t *kasp = NULL;
20820 dns_message_t *message = NULL;
20821 dns_rdataset_t *ds_rrset = NULL;
20822 dns_requestevent_t *revent = (dns_requestevent_t *)event;
20823 isc_buffer_t buf;
20824 isc_result_t result;
20825 isc_stdtime_t now;
20826 isc_time_t timenow;
20827 bool rekey = false;
20828 bool empty = false;
20829
20830 UNUSED(task);
20831
20832 checkds = event->ev_arg;
20833 REQUIRE(DNS_CHECKDS_VALID(checkds));
20834
20835 zone = checkds->zone;
20836 INSIST(task == zone->task);
20837
20838 ISC_LIST_INIT(keys);
20839
20840 kasp = zone->kasp;
20841 INSIST(kasp != NULL);
20842
20843 isc_buffer_init(&buf, rcode, sizeof(rcode));
20844 isc_sockaddr_format(&checkds->dst, addrbuf, sizeof(addrbuf));
20845
20846 dns_zone_log(zone, ISC_LOG_DEBUG(1), "checkds: DS query to %s: done",
20847 addrbuf);
20848
20849 dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &message);
20850 INSIST(message != NULL);
20851
20852 CHECK(revent->result);
20853 CHECK(dns_request_getresponse(revent->request, message,
20854 DNS_MESSAGEPARSE_PRESERVEORDER));
20855 CHECK(dns_rcode_totext(message->rcode, &buf));
20856
20857 dns_zone_log(zone, ISC_LOG_DEBUG(3),
20858 "checkds: DS response from %s: %.*s", addrbuf,
20859 (int)buf.used, rcode);
20860
20861 /* Validate response. */
20862 CHECK(validate_ds(zone, message));
20863
20864 /* Check RCODE. */
20865 if (message->rcode != dns_rcode_noerror) {
20866 dns_zone_log(zone, ISC_LOG_NOTICE,
20867 "checkds: bad DS response from %s: %.*s", addrbuf,
20868 (int)buf.used, rcode);
20869 goto failure;
20870 }
20871
20872 /* Make sure that either AA or RA bit is set. */
20873 if ((message->flags & DNS_MESSAGEFLAG_AA) == 0 &&
20874 (message->flags & DNS_MESSAGEFLAG_RA) == 0)
20875 {
20876 dns_zone_log(zone, ISC_LOG_NOTICE,
20877 "checkds: bad DS response from %s: expected AA or "
20878 "RA bit set",
20879 addrbuf);
20880 goto failure;
20881 }
20882
20883 /* Lookup DS RRset. */
20884 result = dns_message_firstname(message, DNS_SECTION_ANSWER);
20885 while (result == ISC_R_SUCCESS) {
20886 dns_name_t *name = NULL;
20887 dns_rdataset_t *rdataset;
20888
20889 dns_message_currentname(message, DNS_SECTION_ANSWER, &name);
20890 if (dns_name_compare(&zone->origin, name) != 0) {
20891 goto next;
20892 }
20893
20894 for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL;
20895 rdataset = ISC_LIST_NEXT(rdataset, link))
20896 {
20897 if (rdataset->type != dns_rdatatype_ds) {
20898 goto next;
20899 }
20900
20901 ds_rrset = rdataset;
20902 break;
20903 }
20904
20905 if (ds_rrset != NULL) {
20906 break;
20907 }
20908
20909 next:
20910 result = dns_message_nextname(message, DNS_SECTION_ANSWER);
20911 }
20912
20913 if (ds_rrset == NULL) {
20914 empty = true;
20915 dns_zone_log(zone, ISC_LOG_NOTICE,
20916 "checkds: empty DS response from %s", addrbuf);
20917 }
20918
20919 TIME_NOW(&timenow);
20920 now = isc_time_seconds(&timenow);
20921
20922 CHECK(dns_zone_getdb(zone, &db));
20923 dns_db_currentversion(db, &version);
20924
20925 KASP_LOCK(kasp);
20926 LOCK_ZONE(zone);
20927 for (key = ISC_LIST_HEAD(zone->checkds_ok); key != NULL;
20928 key = ISC_LIST_NEXT(key, link))
20929 {
20930 bool alldone = false, found = false;
20931 bool checkdspub = false, checkdsdel = false, ksk = false;
20932 dst_key_state_t ds_state = DST_KEY_STATE_NA;
20933 isc_stdtime_t published = 0, withdrawn = 0;
20934 isc_result_t ret = ISC_R_SUCCESS;
20935
20936 /* Is this key have the KSK role? */
20937 (void)dst_key_role(key->key, &ksk, NULL);
20938 if (!ksk) {
20939 continue;
20940 }
20941
20942 /* Do we need to check the DS RRset for this key? */
20943 (void)dst_key_getstate(key->key, DST_KEY_DS, &ds_state);
20944 (void)dst_key_gettime(key->key, DST_TIME_DSPUBLISH, &published);
20945 (void)dst_key_gettime(key->key, DST_TIME_DSDELETE, &withdrawn);
20946
20947 if (ds_state == DST_KEY_STATE_RUMOURED && published == 0) {
20948 checkdspub = true;
20949 } else if (ds_state == DST_KEY_STATE_UNRETENTIVE &&
20950 withdrawn == 0)
20951 {
20952 checkdsdel = true;
20953 }
20954 if (!checkdspub && !checkdsdel) {
20955 continue;
20956 }
20957
20958 if (empty) {
20959 goto dswithdrawn;
20960 }
20961
20962 /* Find the appropriate DS record. */
20963 ret = dns_rdataset_first(ds_rrset);
20964 while (ret == ISC_R_SUCCESS) {
20965 dns_rdata_ds_t ds;
20966 dns_rdata_t dnskey = DNS_RDATA_INIT;
20967 dns_rdata_t dsrdata = DNS_RDATA_INIT;
20968 dns_rdata_t rdata = DNS_RDATA_INIT;
20969 isc_result_t r;
20970 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
20971 unsigned char keybuf[DST_KEY_MAXSIZE];
20972
20973 dns_rdataset_current(ds_rrset, &rdata);
20974 r = dns_rdata_tostruct(&rdata, &ds, NULL);
20975 if (r != ISC_R_SUCCESS) {
20976 goto nextds;
20977 }
20978 /* Check key tag and algorithm. */
20979 if (dst_key_id(key->key) != ds.key_tag) {
20980 goto nextds;
20981 }
20982 if (dst_key_alg(key->key) != ds.algorithm) {
20983 goto nextds;
20984 }
20985 /* Derive DS from DNSKEY, see if the rdata is equal. */
20986 make_dnskey(key->key, keybuf, sizeof(keybuf), &dnskey);
20987 r = dns_ds_buildrdata(&zone->origin, &dnskey,
20988 ds.digest_type, dsbuf, &dsrdata);
20989 if (r != ISC_R_SUCCESS) {
20990 goto nextds;
20991 }
20992 if (dns_rdata_compare(&rdata, &dsrdata) == 0) {
20993 found = true;
20994 if (checkdspub) {
20995 /* DS Published. */
20996 alldone = do_checkds(zone, key->key,
20997 now, true);
20998 if (alldone) {
20999 rekey = true;
21000 }
21001 }
21002 }
21003
21004 nextds:
21005 ret = dns_rdataset_next(ds_rrset);
21006 }
21007
21008 dswithdrawn:
21009 /* DS withdrawn. */
21010 if (checkdsdel && !found) {
21011 alldone = do_checkds(zone, key->key, now, false);
21012 if (alldone) {
21013 rekey = true;
21014 }
21015 }
21016 }
21017 UNLOCK_ZONE(zone);
21018 KASP_UNLOCK(kasp);
21019
21020 /* Rekey after checkds. */
21021 if (rekey) {
21022 dns_zone_rekey(zone, false);
21023 }
21024
21025 failure:
21026 if (result != ISC_R_SUCCESS) {
21027 dns_zone_log(zone, ISC_LOG_DEBUG(3),
21028 "checkds: DS request failed: %s",
21029 isc_result_totext(result));
21030 }
21031
21032 if (version != NULL) {
21033 dns_db_closeversion(db, &version, false);
21034 }
21035 if (db != NULL) {
21036 dns_db_detach(&db);
21037 }
21038
21039 while (!ISC_LIST_EMPTY(keys)) {
21040 key = ISC_LIST_HEAD(keys);
21041 ISC_LIST_UNLINK(keys, key, link);
21042 dns_dnsseckey_destroy(dns_zone_getmctx(zone), &key);
21043 }
21044
21045 isc_event_free(&event);
21046 checkds_destroy(checkds, false);
21047 dns_message_detach(&message);
21048 }
21049
21050 static bool
21051 checkds_isqueued(dns_zone_t *zone, isc_sockaddr_t *addr, dns_tsigkey_t *key,
21052 dns_transport_t *transport) {
21053 dns_checkds_t *checkds;
21054
21055 for (checkds = ISC_LIST_HEAD(zone->checkds_requests); checkds != NULL;
21056 checkds = ISC_LIST_NEXT(checkds, link))
21057 {
21058 if (checkds->request != NULL) {
21059 continue;
21060 }
21061 if (addr != NULL && isc_sockaddr_equal(addr, &checkds->dst) &&
21062 checkds->key == key && checkds->transport == transport)
21063 {
21064 return (true);
21065 }
21066 }
21067 return (false);
21068 }
21069
21070 static isc_result_t
21071 checkds_create(isc_mem_t *mctx, unsigned int flags, dns_checkds_t **checkdsp) {
21072 dns_checkds_t *checkds;
21073
21074 REQUIRE(checkdsp != NULL && *checkdsp == NULL);
21075
21076 checkds = isc_mem_get(mctx, sizeof(*checkds));
21077 *checkds = (dns_checkds_t){
21078 .flags = flags,
21079 };
21080
21081 isc_mem_attach(mctx, &checkds->mctx);
21082 isc_sockaddr_any(&checkds->dst);
21083 ISC_LINK_INIT(checkds, link);
21084 checkds->magic = CHECKDS_MAGIC;
21085 *checkdsp = checkds;
21086 return (ISC_R_SUCCESS);
21087 }
21088
21089 static isc_result_t
21090 checkds_createmessage(dns_zone_t *zone, dns_message_t **messagep) {
21091 dns_message_t *message = NULL;
21092
21093 dns_name_t *tempname = NULL;
21094 dns_rdataset_t *temprdataset = NULL;
21095
21096 isc_result_t result;
21097
21098 REQUIRE(DNS_ZONE_VALID(zone));
21099 REQUIRE(messagep != NULL && *messagep == NULL);
21100
21101 dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER, &message);
21102
21103 message->opcode = dns_opcode_query;
21104 message->rdclass = zone->rdclass;
21105 message->flags |= DNS_MESSAGEFLAG_RD;
21106
21107 result = dns_message_gettempname(message, &tempname);
21108 if (result != ISC_R_SUCCESS) {
21109 goto cleanup;
21110 }
21111
21112 result = dns_message_gettemprdataset(message, &temprdataset);
21113 if (result != ISC_R_SUCCESS) {
21114 goto cleanup;
21115 }
21116
21117 /*
21118 * Make question.
21119 */
21120 dns_name_init(tempname, NULL);
21121 dns_name_clone(&zone->origin, tempname);
21122 dns_rdataset_makequestion(temprdataset, zone->rdclass,
21123 dns_rdatatype_ds);
21124 ISC_LIST_APPEND(tempname->list, temprdataset, link);
21125 dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
21126 tempname = NULL;
21127 temprdataset = NULL;
21128
21129 *messagep = message;
21130 return (ISC_R_SUCCESS);
21131
21132 cleanup:
21133 if (tempname != NULL) {
21134 dns_message_puttempname(message, &tempname);
21135 }
21136 if (temprdataset != NULL) {
21137 dns_message_puttemprdataset(message, &temprdataset);
21138 }
21139 dns_message_detach(&message);
21140 return (result);
21141 }
21142
21143 static void
21144 checkds_send_toaddr(isc_task_t *task, isc_event_t *event) {
21145 dns_checkds_t *checkds;
21146 isc_result_t result;
21147 dns_message_t *message = NULL;
21148 isc_netaddr_t dstip;
21149 dns_tsigkey_t *key = NULL;
21150 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
21151 isc_sockaddr_t src;
21152 unsigned int options, timeout;
21153 bool have_checkdssource = false;
21154
21155 checkds = event->ev_arg;
21156 REQUIRE(DNS_CHECKDS_VALID(checkds));
21157
21158 UNUSED(task);
21159
21160 LOCK_ZONE(checkds->zone);
21161
21162 checkds->event = NULL;
21163
21164 if (DNS_ZONE_FLAG(checkds->zone, DNS_ZONEFLG_LOADED) == 0) {
21165 result = ISC_R_CANCELED;
21166 goto cleanup;
21167 }
21168
21169 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
21170 DNS_ZONE_FLAG(checkds->zone, DNS_ZONEFLG_EXITING) ||
21171 checkds->zone->view->requestmgr == NULL ||
21172 checkds->zone->db == NULL)
21173 {
21174 result = ISC_R_CANCELED;
21175 goto cleanup;
21176 }
21177
21178 /*
21179 * The raw IPv4 address should also exist. Don't send to the
21180 * mapped form.
21181 */
21182 if (isc_sockaddr_pf(&checkds->dst) == PF_INET6 &&
21183 IN6_IS_ADDR_V4MAPPED(&checkds->dst.type.sin6.sin6_addr))
21184 {
21185 isc_sockaddr_format(&checkds->dst, addrbuf, sizeof(addrbuf));
21186 dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
21187 "checkds: ignoring IPv6 mapped IPV4 address: %s",
21188 addrbuf);
21189 result = ISC_R_CANCELED;
21190 goto cleanup;
21191 }
21192
21193 result = checkds_createmessage(checkds->zone, &message);
21194 if (result != ISC_R_SUCCESS) {
21195 goto cleanup;
21196 }
21197
21198 isc_sockaddr_format(&checkds->dst, addrbuf, sizeof(addrbuf));
21199 if (checkds->key != NULL) {
21200 /* Transfer ownership of key */
21201 key = checkds->key;
21202 checkds->key = NULL;
21203 } else {
21204 isc_netaddr_fromsockaddr(&dstip, &checkds->dst);
21205 result = dns_view_getpeertsig(checkds->zone->view, &dstip,
21206 &key);
21207 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
21208 dns_zone_log(checkds->zone, ISC_LOG_ERROR,
21209 "checkds: DS query to %s not sent. "
21210 "Peer TSIG key lookup failure.",
21211 addrbuf);
21212 goto cleanup_message;
21213 }
21214 }
21215
21216 if (key != NULL) {
21217 char namebuf[DNS_NAME_FORMATSIZE];
21218
21219 dns_name_format(&key->name, namebuf, sizeof(namebuf));
21220 dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
21221 "checkds: sending DS query to %s : TSIG (%s)",
21222 addrbuf, namebuf);
21223 } else {
21224 dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
21225 "checkds: sending DS query to %s", addrbuf);
21226 }
21227 options = 0;
21228 if (checkds->zone->view->peers != NULL) {
21229 dns_peer_t *peer = NULL;
21230 bool usetcp = false;
21231 result = dns_peerlist_peerbyaddr(checkds->zone->view->peers,
21232 &dstip, &peer);
21233 if (result == ISC_R_SUCCESS) {
21234 result = dns_peer_getquerysource(peer, &src);
21235 if (result == ISC_R_SUCCESS) {
21236 have_checkdssource = true;
21237 }
21238 result = dns_peer_getforcetcp(peer, &usetcp);
21239 if (result == ISC_R_SUCCESS && usetcp) {
21240 options |= DNS_FETCHOPT_TCP;
21241 }
21242 }
21243 }
21244 switch (isc_sockaddr_pf(&checkds->dst)) {
21245 case PF_INET:
21246 if (!have_checkdssource) {
21247 src = checkds->zone->parentalsrc4;
21248 }
21249 break;
21250 case PF_INET6:
21251 if (!have_checkdssource) {
21252 src = checkds->zone->parentalsrc6;
21253 }
21254 break;
21255 default:
21256 result = ISC_R_NOTIMPLEMENTED;
21257 goto cleanup_key;
21258 }
21259
21260 dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
21261 "checkds: create request for DS query to %s", addrbuf);
21262
21263 timeout = 5;
21264 options |= DNS_REQUESTOPT_TCP;
21265 result = dns_request_create(
21266 checkds->zone->view->requestmgr, message, &src, &checkds->dst,
21267 options, key, timeout * 3 + 1, timeout, 2, checkds->zone->task,
21268 checkds_done, checkds, &checkds->request);
21269 if (result != ISC_R_SUCCESS) {
21270 dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
21271 "checkds: dns_request_create() to %s failed: %s",
21272 addrbuf, isc_result_totext(result));
21273 }
21274
21275 cleanup_key:
21276 if (key != NULL) {
21277 dns_tsigkey_detach(&key);
21278 }
21279 cleanup_message:
21280 dns_message_detach(&message);
21281 cleanup:
21282 UNLOCK_ZONE(checkds->zone);
21283 isc_event_free(&event);
21284 if (result != ISC_R_SUCCESS) {
21285 checkds_destroy(checkds, false);
21286 }
21287 }
21288
21289 static isc_result_t
21290 checkds_send_queue(dns_checkds_t *checkds) {
21291 isc_event_t *e;
21292 isc_result_t result;
21293
21294 INSIST(checkds->event == NULL);
21295 e = isc_event_allocate(checkds->mctx, NULL, DNS_EVENT_CHECKDSSENDTOADDR,
21296 checkds_send_toaddr, checkds,
21297 sizeof(isc_event_t));
21298 e->ev_arg = checkds;
21299 e->ev_sender = NULL;
21300 result = isc_ratelimiter_enqueue(checkds->zone->zmgr->checkdsrl,
21301 checkds->zone->task, &e);
21302 if (result != ISC_R_SUCCESS) {
21303 isc_event_free(&e);
21304 checkds->event = NULL;
21305 }
21306 return (result);
21307 }
21308
21309 static void
21310 checkds_send(dns_zone_t *zone) {
21311 dns_view_t *view = dns_zone_getview(zone);
21312 isc_result_t result;
21313 unsigned int flags = 0;
21314
21315 /*
21316 * Zone lock held by caller.
21317 */
21318 REQUIRE(LOCKED_ZONE(zone));
21319
21320 dns_zone_log(zone, ISC_LOG_DEBUG(3),
21321 "checkds: start sending DS queries to %u parentals",
21322 zone->parentalscnt);
21323
21324 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
21325 dns_zone_log(zone, ISC_LOG_DEBUG(3),
21326 "checkds: abort, named exiting");
21327 return;
21328 }
21329
21330 for (unsigned int i = 0; i < zone->parentalscnt; i++) {
21331 dns_tsigkey_t *key = NULL;
21332 dns_transport_t *transport = NULL;
21333 isc_sockaddr_t dst;
21334 dns_checkds_t *checkds = NULL;
21335
21336 if ((zone->parentalkeynames != NULL) &&
21337 (zone->parentalkeynames[i] != NULL))
21338 {
21339 dns_name_t *keyname = zone->parentalkeynames[i];
21340 (void)dns_view_gettsig(view, keyname, &key);
21341 }
21342
21343 if ((zone->parentaltlsnames != NULL) &&
21344 (zone->parentaltlsnames[i] != NULL))
21345 {
21346 dns_name_t *tlsname = zone->parentaltlsnames[i];
21347 (void)dns_view_gettransport(view, DNS_TRANSPORT_TLS,
21348 tlsname, &transport);
21349 dns_zone_logc(
21350 zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
21351 "got TLS configuration for zone transfer");
21352 }
21353
21354 dst = zone->parentals[i];
21355
21356 /* TODO: glue the transport to the checkds request */
21357
21358 if (checkds_isqueued(zone, &dst, key, transport)) {
21359 dns_zone_log(zone, ISC_LOG_DEBUG(3),
21360 "checkds: DS query to parent "
21361 "%d is queued",
21362 i);
21363 if (key != NULL) {
21364 dns_tsigkey_detach(&key);
21365 }
21366 if (transport != NULL) {
21367 dns_transport_detach(&transport);
21368 }
21369 continue;
21370 }
21371
21372 dns_zone_log(zone, ISC_LOG_DEBUG(3),
21373 "checkds: create DS query for "
21374 "parent %d",
21375 i);
21376
21377 result = checkds_create(zone->mctx, flags, &checkds);
21378 if (result != ISC_R_SUCCESS) {
21379 dns_zone_log(zone, ISC_LOG_DEBUG(3),
21380 "checkds: create DS query for "
21381 "parent %d failed",
21382 i);
21383 continue;
21384 }
21385 zone_iattach(zone, &checkds->zone);
21386 checkds->dst = dst;
21387
21388 INSIST(checkds->key == NULL);
21389 if (key != NULL) {
21390 checkds->key = key;
21391 key = NULL;
21392 }
21393
21394 INSIST(checkds->transport == NULL);
21395 if (transport != NULL) {
21396 checkds->transport = transport;
21397 transport = NULL;
21398 }
21399
21400 ISC_LIST_APPEND(zone->checkds_requests, checkds, link);
21401 result = checkds_send_queue(checkds);
21402 if (result != ISC_R_SUCCESS) {
21403 dns_zone_log(zone, ISC_LOG_DEBUG(3),
21404 "checkds: send DS query to "
21405 "parent %d failed",
21406 i);
21407 checkds_destroy(checkds, true);
21408 }
21409 }
21410 }
21411
21412 static void
21413 zone_checkds(dns_zone_t *zone) {
21414 bool cdscheck = false;
21415
21416 for (dns_dnsseckey_t *key = ISC_LIST_HEAD(zone->checkds_ok);
21417 key != NULL; key = ISC_LIST_NEXT(key, link))
21418 {
21419 dst_key_state_t ds_state = DST_KEY_STATE_NA;
21420 bool ksk = false;
21421 isc_stdtime_t published = 0, withdrawn = 0;
21422
21423 /* Is this key have the KSK role? */
21424 (void)dst_key_role(key->key, &ksk, NULL);
21425 if (!ksk) {
21426 continue;
21427 }
21428
21429 /* Do we need to check the DS RRset? */
21430 (void)dst_key_getstate(key->key, DST_KEY_DS, &ds_state);
21431 (void)dst_key_gettime(key->key, DST_TIME_DSPUBLISH, &published);
21432 (void)dst_key_gettime(key->key, DST_TIME_DSDELETE, &withdrawn);
21433
21434 if (ds_state == DST_KEY_STATE_RUMOURED && published == 0) {
21435 dst_key_setnum(key->key, DST_NUM_DSPUBCOUNT, 0);
21436 cdscheck = true;
21437 } else if (ds_state == DST_KEY_STATE_UNRETENTIVE &&
21438 withdrawn == 0)
21439 {
21440 dst_key_setnum(key->key, DST_NUM_DSDELCOUNT, 0);
21441 cdscheck = true;
21442 }
21443 }
21444
21445 if (cdscheck) {
21446 /* Request the DS RRset. */
21447 LOCK_ZONE(zone);
21448 checkds_send(zone);
21449 UNLOCK_ZONE(zone);
21450 }
21451 }
21452
21453 static void
21454 zone_rekey(dns_zone_t *zone) {
21455 isc_result_t result;
21456 dns_db_t *db = NULL;
21457 dns_dbnode_t *node = NULL;
21458 dns_dbversion_t *ver = NULL;
21459 dns_rdataset_t cdsset, soaset, soasigs, keyset, keysigs, cdnskeyset;
21460 dns_dnsseckeylist_t dnskeys, keys, rmkeys;
21461 dns_dnsseckey_t *key = NULL;
21462 dns_diff_t diff, _sig_diff;
21463 dns_kasp_t *kasp;
21464 dns__zonediff_t zonediff;
21465 bool commit = false, newactive = false;
21466 bool newalg = false;
21467 bool fullsign;
21468 dns_ttl_t ttl = 3600;
21469 const char *dir = NULL;
21470 isc_mem_t *mctx = NULL;
21471 isc_stdtime_t now, nexttime = 0;
21472 isc_time_t timenow;
21473 isc_interval_t ival;
21474 char timebuf[80];
21475
21476 REQUIRE(DNS_ZONE_VALID(zone));
21477
21478 ISC_LIST_INIT(dnskeys);
21479 ISC_LIST_INIT(keys);
21480 ISC_LIST_INIT(rmkeys);
21481 dns_rdataset_init(&soaset);
21482 dns_rdataset_init(&soasigs);
21483 dns_rdataset_init(&keyset);
21484 dns_rdataset_init(&keysigs);
21485 dns_rdataset_init(&cdsset);
21486 dns_rdataset_init(&cdnskeyset);
21487 dir = dns_zone_getkeydirectory(zone);
21488 mctx = zone->mctx;
21489 dns_diff_init(mctx, &diff);
21490 dns_diff_init(mctx, &_sig_diff);
21491 zonediff_init(&zonediff, &_sig_diff);
21492
21493 CHECK(dns_zone_getdb(zone, &db));
21494 CHECK(dns_db_newversion(db, &ver));
21495 CHECK(dns_db_getoriginnode(db, &node));
21496
21497 TIME_NOW(&timenow);
21498 now = isc_time_seconds(&timenow);
21499
21500 kasp = dns_zone_getkasp(zone);
21501
21502 dnssec_log(zone, ISC_LOG_INFO, "reconfiguring zone keys");
21503
21504 /* Get the SOA record's TTL */
21505 CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_soa,
21506 dns_rdatatype_none, 0, &soaset, &soasigs));
21507 ttl = soaset.ttl;
21508 dns_rdataset_disassociate(&soaset);
21509
21510 /* Get the DNSKEY rdataset */
21511 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
21512 dns_rdatatype_none, 0, &keyset, &keysigs);
21513 if (result == ISC_R_SUCCESS) {
21514 ttl = keyset.ttl;
21515
21516 dns_zone_lock_keyfiles(zone);
21517
21518 result = dns_dnssec_keylistfromrdataset(
21519 &zone->origin, dir, mctx, &keyset, &keysigs, &soasigs,
21520 false, false, &dnskeys);
21521
21522 dns_zone_unlock_keyfiles(zone);
21523
21524 if (result != ISC_R_SUCCESS) {
21525 goto failure;
21526 }
21527 } else if (result != ISC_R_NOTFOUND) {
21528 goto failure;
21529 }
21530
21531 /* Get the CDS rdataset */
21532 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_cds,
21533 dns_rdatatype_none, 0, &cdsset, NULL);
21534 if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdsset)) {
21535 dns_rdataset_disassociate(&cdsset);
21536 }
21537
21538 /* Get the CDNSKEY rdataset */
21539 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_cdnskey,
21540 dns_rdatatype_none, 0, &cdnskeyset, NULL);
21541 if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdnskeyset)) {
21542 dns_rdataset_disassociate(&cdnskeyset);
21543 }
21544
21545 /*
21546 * True when called from "rndc sign". Indicates the zone should be
21547 * fully signed now.
21548 */
21549 fullsign = DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_FULLSIGN);
21550
21551 KASP_LOCK(kasp);
21552
21553 dns_zone_lock_keyfiles(zone);
21554 result = dns_dnssec_findmatchingkeys(&zone->origin, dir, now, mctx,
21555 &keys);
21556 dns_zone_unlock_keyfiles(zone);
21557
21558 if (result != ISC_R_SUCCESS) {
21559 dnssec_log(zone, ISC_LOG_DEBUG(1),
21560 "zone_rekey:dns_dnssec_findmatchingkeys failed: %s",
21561 isc_result_totext(result));
21562 }
21563
21564 if (kasp != NULL) {
21565 /*
21566 * Check DS at parental agents. Clear ongoing checks.
21567 */
21568 LOCK_ZONE(zone);
21569 checkds_cancel(zone);
21570 clear_keylist(&zone->checkds_ok, zone->mctx);
21571 ISC_LIST_INIT(zone->checkds_ok);
21572 UNLOCK_ZONE(zone);
21573
21574 result = dns_zone_getdnsseckeys(zone, db, ver, now,
21575 &zone->checkds_ok);
21576
21577 if (result == ISC_R_SUCCESS) {
21578 zone_checkds(zone);
21579 } else {
21580 dnssec_log(zone,
21581 (result == ISC_R_NOTFOUND) ? ISC_LOG_DEBUG(1)
21582 : ISC_LOG_ERROR,
21583 "zone_rekey:dns_zone_getdnsseckeys failed: "
21584 "%s",
21585 isc_result_totext(result));
21586 }
21587
21588 if (result == ISC_R_SUCCESS || result == ISC_R_NOTFOUND) {
21589 dns_zone_lock_keyfiles(zone);
21590 result = dns_keymgr_run(&zone->origin, zone->rdclass,
21591 dir, mctx, &keys, &dnskeys,
21592 kasp, now, &nexttime);
21593 dns_zone_unlock_keyfiles(zone);
21594
21595 if (result != ISC_R_SUCCESS) {
21596 dnssec_log(zone, ISC_LOG_ERROR,
21597 "zone_rekey:dns_dnssec_keymgr "
21598 "failed: %s",
21599 isc_result_totext(result));
21600 KASP_UNLOCK(kasp);
21601 goto failure;
21602 }
21603 }
21604 }
21605
21606 KASP_UNLOCK(kasp);
21607
21608 if (result == ISC_R_SUCCESS) {
21609 bool cdsdel = false;
21610 bool cdnskeydel = false;
21611 bool sane_diff, sane_dnskey;
21612 isc_stdtime_t when;
21613
21614 /*
21615 * Publish CDS/CDNSKEY DELETE records if the zone is
21616 * transitioning from secure to insecure.
21617 */
21618 if (kasp != NULL) {
21619 if (strcmp(dns_kasp_getname(kasp), "insecure") == 0) {
21620 cdsdel = true;
21621 cdnskeydel = true;
21622 }
21623 } else {
21624 /* Check if there is a CDS DELETE record. */
21625 if (dns_rdataset_isassociated(&cdsset)) {
21626 for (result = dns_rdataset_first(&cdsset);
21627 result == ISC_R_SUCCESS;
21628 result = dns_rdataset_next(&cdsset))
21629 {
21630 dns_rdata_t crdata = DNS_RDATA_INIT;
21631 dns_rdataset_current(&cdsset, &crdata);
21632 /*
21633 * CDS deletion record has this form
21634 * "0 0 0 00" which is 5 zero octets.
21635 */
21636 if (crdata.length == 5U &&
21637 memcmp(crdata.data,
21638 (unsigned char[5]){ 0, 0, 0,
21639 0, 0 },
21640 5) == 0)
21641 {
21642 cdsdel = true;
21643 break;
21644 }
21645 }
21646 }
21647
21648 /* Check if there is a CDNSKEY DELETE record. */
21649 if (dns_rdataset_isassociated(&cdnskeyset)) {
21650 for (result = dns_rdataset_first(&cdnskeyset);
21651 result == ISC_R_SUCCESS;
21652 result = dns_rdataset_next(&cdnskeyset))
21653 {
21654 dns_rdata_t crdata = DNS_RDATA_INIT;
21655 dns_rdataset_current(&cdnskeyset,
21656 &crdata);
21657 /*
21658 * CDNSKEY deletion record has this form
21659 * "0 3 0 AA==" which is 2 zero octets,
21660 * a 3, and 2 zero octets.
21661 */
21662 if (crdata.length == 5U &&
21663 memcmp(crdata.data,
21664 (unsigned char[5]){ 0, 0, 3,
21665 0, 0 },
21666 5) == 0)
21667 {
21668 cdnskeydel = true;
21669 break;
21670 }
21671 }
21672 }
21673 }
21674
21675 /*
21676 * Only update DNSKEY TTL if we have a policy.
21677 */
21678 if (kasp != NULL) {
21679 ttl = dns_kasp_dnskeyttl(kasp);
21680 }
21681
21682 result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys,
21683 &zone->origin, ttl, &diff, mctx,
21684 dnssec_report);
21685 /*
21686 * Keys couldn't be updated for some reason;
21687 * try again later.
21688 */
21689 if (result != ISC_R_SUCCESS) {
21690 dnssec_log(zone, ISC_LOG_ERROR,
21691 "zone_rekey:couldn't update zone keys: %s",
21692 isc_result_totext(result));
21693 goto failure;
21694 }
21695
21696 /*
21697 * Update CDS / CDNSKEY records.
21698 */
21699 result = dns_dnssec_syncupdate(&dnskeys, &rmkeys, &cdsset,
21700 &cdnskeyset, now, ttl, &diff,
21701 mctx);
21702 if (result != ISC_R_SUCCESS) {
21703 dnssec_log(zone, ISC_LOG_ERROR,
21704 "zone_rekey:couldn't update CDS/CDNSKEY: %s",
21705 isc_result_totext(result));
21706 goto failure;
21707 }
21708
21709 if (cdsdel || cdnskeydel) {
21710 /*
21711 * Only publish CDS/CDNSKEY DELETE records if there is
21712 * a KSK that can be used to verify the RRset. This
21713 * means there must be a key with the KSK role that is
21714 * published and is used for signing.
21715 */
21716 bool allow = false;
21717 for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
21718 key = ISC_LIST_NEXT(key, link))
21719 {
21720 dst_key_t *dstk = key->key;
21721
21722 if (dst_key_is_published(dstk, now, &when) &&
21723 dst_key_is_signing(dstk, DST_BOOL_KSK, now,
21724 &when))
21725 {
21726 allow = true;
21727 break;
21728 }
21729 }
21730 if (cdsdel) {
21731 cdsdel = allow;
21732 }
21733 if (cdnskeydel) {
21734 cdnskeydel = allow;
21735 }
21736 }
21737 result = dns_dnssec_syncdelete(
21738 &cdsset, &cdnskeyset, &zone->origin, zone->rdclass, ttl,
21739 &diff, mctx, cdsdel, cdnskeydel);
21740 if (result != ISC_R_SUCCESS) {
21741 dnssec_log(zone, ISC_LOG_ERROR,
21742 "zone_rekey:couldn't update CDS/CDNSKEY "
21743 "DELETE records: %s",
21744 isc_result_totext(result));
21745 goto failure;
21746 }
21747
21748 /*
21749 * See if any pre-existing keys have newly become active;
21750 * also, see if any new key is for a new algorithm, as in that
21751 * event, we need to sign the zone fully. (If there's a new
21752 * key, but it's for an already-existing algorithm, then
21753 * the zone signing can be handled incrementally.)
21754 */
21755 for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
21756 key = ISC_LIST_NEXT(key, link))
21757 {
21758 if (!key->first_sign) {
21759 continue;
21760 }
21761
21762 newactive = true;
21763
21764 if (!dns_rdataset_isassociated(&keysigs)) {
21765 newalg = true;
21766 break;
21767 }
21768
21769 if (signed_with_alg(&keysigs, dst_key_alg(key->key))) {
21770 /*
21771 * This isn't a new algorithm; clear
21772 * first_sign so we won't sign the
21773 * whole zone with this key later.
21774 */
21775 key->first_sign = false;
21776 } else {
21777 newalg = true;
21778 break;
21779 }
21780 }
21781
21782 /*
21783 * A sane diff is one that is not empty, and that does not
21784 * introduce a zone with NSEC only DNSKEYs along with NSEC3
21785 * chains.
21786 */
21787 sane_dnskey = dns_zone_check_dnskey_nsec3(zone, db, ver, &diff,
21788 NULL, 0);
21789 sane_diff = !ISC_LIST_EMPTY(diff.tuples) && sane_dnskey;
21790 if (!sane_dnskey) {
21791 dnssec_log(zone, ISC_LOG_ERROR,
21792 "NSEC only DNSKEYs and NSEC3 chains not "
21793 "allowed");
21794 }
21795
21796 if (newactive || fullsign || sane_diff) {
21797 CHECK(dns_diff_apply(&diff, db, ver));
21798 CHECK(clean_nsec3param(zone, db, ver, &diff));
21799 CHECK(add_signing_records(db, zone->privatetype, ver,
21800 &diff, (newalg || fullsign)));
21801 CHECK(update_soa_serial(zone, db, ver, &diff, mctx,
21802 zone->updatemethod));
21803 CHECK(add_chains(zone, db, ver, &diff));
21804 CHECK(sign_apex(zone, db, ver, now, &diff, &zonediff));
21805 CHECK(zone_journal(zone, zonediff.diff, NULL,
21806 "zone_rekey"));
21807 commit = true;
21808 }
21809 }
21810
21811 dns_db_closeversion(db, &ver, true);
21812
21813 LOCK_ZONE(zone);
21814
21815 if (commit) {
21816 dns_difftuple_t *tuple;
21817 dns_stats_t *dnssecsignstats =
21818 dns_zone_getdnssecsignstats(zone);
21819
21820 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
21821
21822 zone_needdump(zone, DNS_DUMP_DELAY);
21823
21824 zone_settimer(zone, &timenow);
21825
21826 /* Remove any signatures from removed keys. */
21827 if (!ISC_LIST_EMPTY(rmkeys)) {
21828 for (key = ISC_LIST_HEAD(rmkeys); key != NULL;
21829 key = ISC_LIST_NEXT(key, link))
21830 {
21831 result = zone_signwithkey(
21832 zone, dst_key_alg(key->key),
21833 dst_key_id(key->key), true);
21834 if (result != ISC_R_SUCCESS) {
21835 dnssec_log(zone, ISC_LOG_ERROR,
21836 "zone_signwithkey failed: "
21837 "%s",
21838 isc_result_totext(result));
21839 }
21840
21841 /* Clear DNSSEC sign statistics. */
21842 if (dnssecsignstats != NULL) {
21843 dns_dnssecsignstats_clear(
21844 dnssecsignstats,
21845 dst_key_id(key->key),
21846 dst_key_alg(key->key));
21847 /*
21848 * Also clear the dnssec-sign
21849 * statistics of the revoked key id.
21850 */
21851 dns_dnssecsignstats_clear(
21852 dnssecsignstats,
21853 dst_key_rid(key->key),
21854 dst_key_alg(key->key));
21855 }
21856 }
21857 }
21858
21859 if (fullsign) {
21860 /*
21861 * "rndc sign" was called, so we now sign the zone
21862 * with all active keys, whether they're new or not.
21863 */
21864 for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
21865 key = ISC_LIST_NEXT(key, link))
21866 {
21867 if (!key->force_sign && !key->hint_sign) {
21868 continue;
21869 }
21870
21871 result = zone_signwithkey(
21872 zone, dst_key_alg(key->key),
21873 dst_key_id(key->key), false);
21874 if (result != ISC_R_SUCCESS) {
21875 dnssec_log(zone, ISC_LOG_ERROR,
21876 "zone_signwithkey failed: "
21877 "%s",
21878 isc_result_totext(result));
21879 }
21880 }
21881 } else if (newalg) {
21882 /*
21883 * We haven't been told to sign fully, but a new
21884 * algorithm was added to the DNSKEY. We sign
21885 * the full zone, but only with newly active
21886 * keys.
21887 */
21888 for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
21889 key = ISC_LIST_NEXT(key, link))
21890 {
21891 if (!key->first_sign) {
21892 continue;
21893 }
21894
21895 result = zone_signwithkey(
21896 zone, dst_key_alg(key->key),
21897 dst_key_id(key->key), false);
21898 if (result != ISC_R_SUCCESS) {
21899 dnssec_log(zone, ISC_LOG_ERROR,
21900 "zone_signwithkey failed: "
21901 "%s",
21902 isc_result_totext(result));
21903 }
21904 }
21905 }
21906
21907 /*
21908 * Clear fullsign flag, if it was set, so we don't do
21909 * another full signing next time.
21910 */
21911 DNS_ZONEKEY_CLROPTION(zone, DNS_ZONEKEY_FULLSIGN);
21912
21913 /*
21914 * Cause the zone to add/delete NSEC3 chains for the
21915 * deferred NSEC3PARAM changes.
21916 */
21917 for (tuple = ISC_LIST_HEAD(zonediff.diff->tuples);
21918 tuple != NULL; tuple = ISC_LIST_NEXT(tuple, link))
21919 {
21920 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
21921 dns_rdata_t rdata = DNS_RDATA_INIT;
21922 dns_rdata_nsec3param_t nsec3param;
21923
21924 if (tuple->rdata.type != zone->privatetype ||
21925 tuple->op != DNS_DIFFOP_ADD)
21926 {
21927 continue;
21928 }
21929
21930 if (!dns_nsec3param_fromprivate(&tuple->rdata, &rdata,
21931 buf, sizeof(buf)))
21932 {
21933 continue;
21934 }
21935
21936 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
21937 RUNTIME_CHECK(result == ISC_R_SUCCESS);
21938 if (nsec3param.flags == 0) {
21939 continue;
21940 }
21941
21942 result = zone_addnsec3chain(zone, &nsec3param);
21943 if (result != ISC_R_SUCCESS) {
21944 dnssec_log(zone, ISC_LOG_ERROR,
21945 "zone_addnsec3chain failed: %s",
21946 isc_result_totext(result));
21947 }
21948 }
21949
21950 /*
21951 * Activate any NSEC3 chain updates that may have
21952 * been scheduled before this rekey.
21953 */
21954 if (fullsign || newalg) {
21955 resume_addnsec3chain(zone);
21956 }
21957
21958 /*
21959 * Schedule the next resigning event
21960 */
21961 set_resigntime(zone);
21962 }
21963
21964 isc_time_settoepoch(&zone->refreshkeytime);
21965
21966 /*
21967 * If keymgr provided a next time, use the calculated next rekey time.
21968 */
21969 if (kasp != NULL) {
21970 isc_time_t timenext;
21971 uint32_t nexttime_seconds;
21972
21973 /*
21974 * Set the key refresh timer to the next scheduled key event
21975 * or to 'dnssec-loadkeys-interval' seconds in the future
21976 * if no next key event is scheduled (nexttime == 0).
21977 */
21978 if (nexttime > 0) {
21979 nexttime_seconds = nexttime - now;
21980 } else {
21981 nexttime_seconds = zone->refreshkeyinterval;
21982 }
21983
21984 DNS_ZONE_TIME_ADD(&timenow, nexttime_seconds, &timenext);
21985 zone->refreshkeytime = timenext;
21986 zone_settimer(zone, &timenow);
21987 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
21988
21989 dnssec_log(zone, ISC_LOG_DEBUG(3),
21990 "next key event in %u seconds", nexttime_seconds);
21991 dnssec_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
21992 }
21993 /*
21994 * If we're doing key maintenance, set the key refresh timer to
21995 * the next scheduled key event or to 'dnssec-loadkeys-interval'
21996 * seconds in the future, whichever is sooner.
21997 */
21998 else if (DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
21999 {
22000 isc_time_t timethen;
22001 isc_stdtime_t then;
22002
22003 DNS_ZONE_TIME_ADD(&timenow, zone->refreshkeyinterval,
22004 &timethen);
22005 zone->refreshkeytime = timethen;
22006
22007 for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
22008 key = ISC_LIST_NEXT(key, link))
22009 {
22010 then = now;
22011 result = next_keyevent(key->key, &then);
22012 if (result != ISC_R_SUCCESS) {
22013 continue;
22014 }
22015
22016 DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
22017 if (isc_time_compare(&timethen, &zone->refreshkeytime) <
22018 0)
22019 {
22020 zone->refreshkeytime = timethen;
22021 }
22022 }
22023
22024 zone_settimer(zone, &timenow);
22025
22026 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
22027 dnssec_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
22028 }
22029 UNLOCK_ZONE(zone);
22030
22031 if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
22032 for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
22033 key = ISC_LIST_NEXT(key, link))
22034 {
22035 /* This debug log is used in the kasp system test */
22036 char algbuf[DNS_SECALG_FORMATSIZE];
22037 dns_secalg_format(dst_key_alg(key->key), algbuf,
22038 sizeof(algbuf));
22039 dnssec_log(zone, ISC_LOG_DEBUG(3),
22040 "zone_rekey done: key %d/%s",
22041 dst_key_id(key->key), algbuf);
22042 }
22043 }
22044
22045 result = ISC_R_SUCCESS;
22046
22047 failure:
22048 LOCK_ZONE(zone);
22049 if (result != ISC_R_SUCCESS) {
22050 /*
22051 * Something went wrong; try again in ten minutes or
22052 * after a key refresh interval, whichever is shorter.
22053 */
22054 dnssec_log(zone, ISC_LOG_DEBUG(3),
22055 "zone_rekey failure: %s (retry in %u seconds)",
22056 isc_result_totext(result),
22057 ISC_MIN(zone->refreshkeyinterval, 600));
22058 isc_interval_set(&ival, ISC_MIN(zone->refreshkeyinterval, 600),
22059 0);
22060 isc_time_nowplusinterval(&zone->refreshkeytime, &ival);
22061 }
22062 UNLOCK_ZONE(zone);
22063
22064 dns_diff_clear(&diff);
22065 dns_diff_clear(&_sig_diff);
22066
22067 clear_keylist(&dnskeys, mctx);
22068 clear_keylist(&keys, mctx);
22069 clear_keylist(&rmkeys, mctx);
22070
22071 if (ver != NULL) {
22072 dns_db_closeversion(db, &ver, false);
22073 }
22074 if (dns_rdataset_isassociated(&cdsset)) {
22075 dns_rdataset_disassociate(&cdsset);
22076 }
22077 if (dns_rdataset_isassociated(&keyset)) {
22078 dns_rdataset_disassociate(&keyset);
22079 }
22080 if (dns_rdataset_isassociated(&keysigs)) {
22081 dns_rdataset_disassociate(&keysigs);
22082 }
22083 if (dns_rdataset_isassociated(&soasigs)) {
22084 dns_rdataset_disassociate(&soasigs);
22085 }
22086 if (dns_rdataset_isassociated(&cdnskeyset)) {
22087 dns_rdataset_disassociate(&cdnskeyset);
22088 }
22089 if (node != NULL) {
22090 dns_db_detachnode(db, &node);
22091 }
22092 if (db != NULL) {
22093 dns_db_detach(&db);
22094 }
22095
22096 INSIST(ver == NULL);
22097 }
22098
22099 void
22100 dns_zone_rekey(dns_zone_t *zone, bool fullsign) {
22101 isc_time_t now;
22102
22103 if (zone->type == dns_zone_primary && zone->task != NULL) {
22104 LOCK_ZONE(zone);
22105
22106 if (fullsign) {
22107 DNS_ZONEKEY_SETOPTION(zone, DNS_ZONEKEY_FULLSIGN);
22108 }
22109
22110 TIME_NOW(&now);
22111 zone->refreshkeytime = now;
22112 zone_settimer(zone, &now);
22113
22114 UNLOCK_ZONE(zone);
22115 }
22116 }
22117
22118 isc_result_t
22119 dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
22120 unsigned int *errors) {
22121 isc_result_t result;
22122 dns_dbnode_t *node = NULL;
22123
22124 REQUIRE(DNS_ZONE_VALID(zone));
22125 REQUIRE(errors != NULL);
22126
22127 result = dns_db_getoriginnode(db, &node);
22128 if (result != ISC_R_SUCCESS) {
22129 return (result);
22130 }
22131 result = zone_count_ns_rr(zone, db, node, version, NULL, errors, false);
22132 dns_db_detachnode(db, &node);
22133 return (result);
22134 }
22135
22136 isc_result_t
22137 dns_zone_cdscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version) {
22138 isc_result_t result;
22139 dns_dbnode_t *node = NULL;
22140 dns_rdataset_t dnskey, cds, cdnskey;
22141 unsigned char algorithms[256];
22142 unsigned int i;
22143 bool empty = false;
22144
22145 enum { notexpected = 0, expected = 1, found = 2 };
22146
22147 REQUIRE(DNS_ZONE_VALID(zone));
22148
22149 result = dns_db_getoriginnode(db, &node);
22150 if (result != ISC_R_SUCCESS) {
22151 return (result);
22152 }
22153
22154 dns_rdataset_init(&cds);
22155 dns_rdataset_init(&dnskey);
22156 dns_rdataset_init(&cdnskey);
22157
22158 result = dns_db_findrdataset(db, node, version, dns_rdatatype_cds,
22159 dns_rdatatype_none, 0, &cds, NULL);
22160 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
22161 goto failure;
22162 }
22163
22164 result = dns_db_findrdataset(db, node, version, dns_rdatatype_cdnskey,
22165 dns_rdatatype_none, 0, &cdnskey, NULL);
22166 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
22167 goto failure;
22168 }
22169
22170 if (!dns_rdataset_isassociated(&cds) &&
22171 !dns_rdataset_isassociated(&cdnskey))
22172 {
22173 result = ISC_R_SUCCESS;
22174 goto failure;
22175 }
22176
22177 result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
22178 dns_rdatatype_none, 0, &dnskey, NULL);
22179 if (result == ISC_R_NOTFOUND) {
22180 empty = true;
22181 } else if (result != ISC_R_SUCCESS) {
22182 goto failure;
22183 }
22184
22185 /*
22186 * For each DNSSEC algorithm in the CDS RRset there must be
22187 * a matching DNSKEY record with the exception of a CDS deletion
22188 * record which must be by itself.
22189 */
22190 if (dns_rdataset_isassociated(&cds)) {
22191 bool delete = false;
22192 memset(algorithms, notexpected, sizeof(algorithms));
22193 for (result = dns_rdataset_first(&cds); result == ISC_R_SUCCESS;
22194 result = dns_rdataset_next(&cds))
22195 {
22196 dns_rdata_t crdata = DNS_RDATA_INIT;
22197 dns_rdata_cds_t structcds;
22198
22199 dns_rdataset_current(&cds, &crdata);
22200 /*
22201 * CDS deletion record has this form "0 0 0 00" which
22202 * is 5 zero octets.
22203 */
22204 if (crdata.length == 5U &&
22205 memcmp(crdata.data,
22206 (unsigned char[5]){ 0, 0, 0, 0, 0 }, 5) == 0)
22207 {
22208 delete = true;
22209 continue;
22210 }
22211
22212 if (empty) {
22213 result = DNS_R_BADCDS;
22214 goto failure;
22215 }
22216
22217 CHECK(dns_rdata_tostruct(&crdata, &structcds, NULL));
22218 if (algorithms[structcds.algorithm] == 0) {
22219 algorithms[structcds.algorithm] = expected;
22220 }
22221 for (result = dns_rdataset_first(&dnskey);
22222 result == ISC_R_SUCCESS;
22223 result = dns_rdataset_next(&dnskey))
22224 {
22225 dns_rdata_t rdata = DNS_RDATA_INIT;
22226 dns_rdata_dnskey_t structdnskey;
22227
22228 dns_rdataset_current(&dnskey, &rdata);
22229 CHECK(dns_rdata_tostruct(&rdata, &structdnskey,
22230 NULL));
22231
22232 if (structdnskey.algorithm ==
22233 structcds.algorithm)
22234 {
22235 algorithms[structcds.algorithm] = found;
22236 }
22237 }
22238 if (result != ISC_R_NOMORE) {
22239 goto failure;
22240 }
22241 }
22242 for (i = 0; i < sizeof(algorithms); i++) {
22243 if (delete) {
22244 if (algorithms[i] != notexpected) {
22245 result = DNS_R_BADCDS;
22246 goto failure;
22247 }
22248 } else if (algorithms[i] == expected) {
22249 result = DNS_R_BADCDS;
22250 goto failure;
22251 }
22252 }
22253 }
22254
22255 /*
22256 * For each DNSSEC algorithm in the CDNSKEY RRset there must be
22257 * a matching DNSKEY record with the exception of a CDNSKEY deletion
22258 * record which must be by itself.
22259 */
22260 if (dns_rdataset_isassociated(&cdnskey)) {
22261 bool delete = false;
22262 memset(algorithms, notexpected, sizeof(algorithms));
22263 for (result = dns_rdataset_first(&cdnskey);
22264 result == ISC_R_SUCCESS;
22265 result = dns_rdataset_next(&cdnskey))
22266 {
22267 dns_rdata_t crdata = DNS_RDATA_INIT;
22268 dns_rdata_cdnskey_t structcdnskey;
22269
22270 dns_rdataset_current(&cdnskey, &crdata);
22271 /*
22272 * CDNSKEY deletion record has this form
22273 * "0 3 0 AA==" which is 2 zero octets, a 3,
22274 * and 2 zero octets.
22275 */
22276 if (crdata.length == 5U &&
22277 memcmp(crdata.data,
22278 (unsigned char[5]){ 0, 0, 3, 0, 0 }, 5) == 0)
22279 {
22280 delete = true;
22281 continue;
22282 }
22283
22284 if (empty) {
22285 result = DNS_R_BADCDNSKEY;
22286 goto failure;
22287 }
22288
22289 CHECK(dns_rdata_tostruct(&crdata, &structcdnskey,
22290 NULL));
22291 if (algorithms[structcdnskey.algorithm] == 0) {
22292 algorithms[structcdnskey.algorithm] = expected;
22293 }
22294 for (result = dns_rdataset_first(&dnskey);
22295 result == ISC_R_SUCCESS;
22296 result = dns_rdataset_next(&dnskey))
22297 {
22298 dns_rdata_t rdata = DNS_RDATA_INIT;
22299 dns_rdata_dnskey_t structdnskey;
22300
22301 dns_rdataset_current(&dnskey, &rdata);
22302 CHECK(dns_rdata_tostruct(&rdata, &structdnskey,
22303 NULL));
22304
22305 if (structdnskey.algorithm ==
22306 structcdnskey.algorithm)
22307 {
22308 algorithms[structcdnskey.algorithm] =
22309 found;
22310 }
22311 }
22312 if (result != ISC_R_NOMORE) {
22313 goto failure;
22314 }
22315 }
22316 for (i = 0; i < sizeof(algorithms); i++) {
22317 if (delete) {
22318 if (algorithms[i] != notexpected) {
22319 result = DNS_R_BADCDNSKEY;
22320 goto failure;
22321 }
22322 } else if (algorithms[i] == expected) {
22323 result = DNS_R_BADCDNSKEY;
22324 goto failure;
22325 }
22326 }
22327 }
22328 result = ISC_R_SUCCESS;
22329
22330 failure:
22331 if (dns_rdataset_isassociated(&cds)) {
22332 dns_rdataset_disassociate(&cds);
22333 }
22334 if (dns_rdataset_isassociated(&dnskey)) {
22335 dns_rdataset_disassociate(&dnskey);
22336 }
22337 if (dns_rdataset_isassociated(&cdnskey)) {
22338 dns_rdataset_disassociate(&cdnskey);
22339 }
22340 dns_db_detachnode(db, &node);
22341 return (result);
22342 }
22343
22344 void
22345 dns_zone_setautomatic(dns_zone_t *zone, bool automatic) {
22346 REQUIRE(DNS_ZONE_VALID(zone));
22347
22348 LOCK_ZONE(zone);
22349 zone->automatic = automatic;
22350 UNLOCK_ZONE(zone);
22351 }
22352
22353 bool
22354 dns_zone_getautomatic(dns_zone_t *zone) {
22355 REQUIRE(DNS_ZONE_VALID(zone));
22356 return (zone->automatic);
22357 }
22358
22359 void
22360 dns_zone_setadded(dns_zone_t *zone, bool added) {
22361 REQUIRE(DNS_ZONE_VALID(zone));
22362
22363 LOCK_ZONE(zone);
22364 zone->added = added;
22365 UNLOCK_ZONE(zone);
22366 }
22367
22368 bool
22369 dns_zone_getadded(dns_zone_t *zone) {
22370 REQUIRE(DNS_ZONE_VALID(zone));
22371 return (zone->added);
22372 }
22373
22374 isc_result_t
22375 dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db) {
22376 isc_time_t loadtime;
22377 isc_result_t result;
22378 dns_zone_t *secure = NULL;
22379
22380 TIME_NOW(&loadtime);
22381
22382 /*
22383 * Lock hierarchy: zmgr, zone, raw.
22384 */
22385 again:
22386 LOCK_ZONE(zone);
22387 INSIST(zone != zone->raw);
22388 if (inline_secure(zone)) {
22389 LOCK_ZONE(zone->raw);
22390 } else if (inline_raw(zone)) {
22391 secure = zone->secure;
22392 TRYLOCK_ZONE(result, secure);
22393 if (result != ISC_R_SUCCESS) {
22394 UNLOCK_ZONE(zone);
22395 secure = NULL;
22396 isc_thread_yield();
22397 goto again;
22398 }
22399 }
22400 result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
22401 if (inline_secure(zone)) {
22402 UNLOCK_ZONE(zone->raw);
22403 } else if (secure != NULL) {
22404 UNLOCK_ZONE(secure);
22405 }
22406 UNLOCK_ZONE(zone);
22407 return (result);
22408 }
22409
22410 isc_result_t
22411 dns_zone_setrefreshkeyinterval(dns_zone_t *zone, uint32_t interval) {
22412 REQUIRE(DNS_ZONE_VALID(zone));
22413 if (interval == 0) {
22414 return (ISC_R_RANGE);
22415 }
22416 /* Maximum value: 24 hours (3600 minutes) */
22417 if (interval > (24 * 60)) {
22418 interval = (24 * 60);
22419 }
22420 /* Multiply by 60 for seconds */
22421 zone->refreshkeyinterval = interval * 60;
22422 return (ISC_R_SUCCESS);
22423 }
22424
22425 void
22426 dns_zone_setrequestixfr(dns_zone_t *zone, bool flag) {
22427 REQUIRE(DNS_ZONE_VALID(zone));
22428 zone->requestixfr = flag;
22429 }
22430
22431 bool
22432 dns_zone_getrequestixfr(dns_zone_t *zone) {
22433 REQUIRE(DNS_ZONE_VALID(zone));
22434 return (zone->requestixfr);
22435 }
22436
22437 void
22438 dns_zone_setixfrratio(dns_zone_t *zone, uint32_t ratio) {
22439 REQUIRE(DNS_ZONE_VALID(zone));
22440 zone->ixfr_ratio = ratio;
22441 }
22442
22443 uint32_t
22444 dns_zone_getixfrratio(dns_zone_t *zone) {
22445 REQUIRE(DNS_ZONE_VALID(zone));
22446 return (zone->ixfr_ratio);
22447 }
22448
22449 void
22450 dns_zone_setrequestexpire(dns_zone_t *zone, bool flag) {
22451 REQUIRE(DNS_ZONE_VALID(zone));
22452 zone->requestexpire = flag;
22453 }
22454
22455 bool
22456 dns_zone_getrequestexpire(dns_zone_t *zone) {
22457 REQUIRE(DNS_ZONE_VALID(zone));
22458 return (zone->requestexpire);
22459 }
22460
22461 void
22462 dns_zone_setserialupdatemethod(dns_zone_t *zone, dns_updatemethod_t method) {
22463 REQUIRE(DNS_ZONE_VALID(zone));
22464 zone->updatemethod = method;
22465 }
22466
22467 dns_updatemethod_t
22468 dns_zone_getserialupdatemethod(dns_zone_t *zone) {
22469 REQUIRE(DNS_ZONE_VALID(zone));
22470 return (zone->updatemethod);
22471 }
22472
22473 /*
22474 * Lock hierarchy: zmgr, zone, raw.
22475 */
22476 isc_result_t
22477 dns_zone_link(dns_zone_t *zone, dns_zone_t *raw) {
22478 isc_result_t result;
22479 dns_zonemgr_t *zmgr;
22480
22481 REQUIRE(DNS_ZONE_VALID(zone));
22482 REQUIRE(zone->zmgr != NULL);
22483 REQUIRE(zone->task != NULL);
22484 REQUIRE(zone->loadtask != NULL);
22485 REQUIRE(zone->raw == NULL);
22486
22487 REQUIRE(DNS_ZONE_VALID(raw));
22488 REQUIRE(raw->zmgr == NULL);
22489 REQUIRE(raw->task == NULL);
22490 REQUIRE(raw->loadtask == NULL);
22491 REQUIRE(raw->secure == NULL);
22492
22493 REQUIRE(zone != raw);
22494
22495 /*
22496 * Lock hierarchy: zmgr, zone, raw.
22497 */
22498 zmgr = zone->zmgr;
22499 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
22500 LOCK_ZONE(zone);
22501 LOCK_ZONE(raw);
22502
22503 result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive, NULL,
22504 NULL, zone->task, zone_timer, raw,
22505 &raw->timer);
22506 if (result != ISC_R_SUCCESS) {
22507 goto unlock;
22508 }
22509
22510 /*
22511 * The timer "holds" a iref.
22512 */
22513 isc_refcount_increment0(&raw->irefs);
22514
22515 /* dns_zone_attach(raw, &zone->raw); */
22516 isc_refcount_increment(&raw->erefs);
22517 zone->raw = raw;
22518
22519 /* dns_zone_iattach(zone, &raw->secure); */
22520 zone_iattach(zone, &raw->secure);
22521
22522 isc_task_attach(zone->task, &raw->task);
22523 isc_task_attach(zone->loadtask, &raw->loadtask);
22524
22525 ISC_LIST_APPEND(zmgr->zones, raw, link);
22526 raw->zmgr = zmgr;
22527 isc_refcount_increment(&zmgr->refs);
22528
22529 unlock:
22530 UNLOCK_ZONE(raw);
22531 UNLOCK_ZONE(zone);
22532 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
22533 return (result);
22534 }
22535
22536 void
22537 dns_zone_getraw(dns_zone_t *zone, dns_zone_t **raw) {
22538 REQUIRE(DNS_ZONE_VALID(zone));
22539 REQUIRE(raw != NULL && *raw == NULL);
22540
22541 LOCK(&zone->lock);
22542 INSIST(zone != zone->raw);
22543 if (zone->raw != NULL) {
22544 dns_zone_attach(zone->raw, raw);
22545 }
22546 UNLOCK(&zone->lock);
22547 }
22548
22549 struct keydone {
22550 isc_event_t event;
22551 bool all;
22552 unsigned char data[5];
22553 };
22554
22555 #define PENDINGFLAGS (DNS_NSEC3FLAG_CREATE | DNS_NSEC3FLAG_INITIAL)
22556
22557 static void
22558 keydone(isc_task_t *task, isc_event_t *event) {
22559 const char *me = "keydone";
22560 bool commit = false;
22561 isc_result_t result;
22562 dns_rdata_t rdata = DNS_RDATA_INIT;
22563 dns_dbversion_t *oldver = NULL, *newver = NULL;
22564 dns_zone_t *zone;
22565 dns_db_t *db = NULL;
22566 dns_dbnode_t *node = NULL;
22567 dns_rdataset_t rdataset;
22568 dns_diff_t diff;
22569 struct keydone *kd = (struct keydone *)event;
22570 dns_update_log_t log = { update_log_cb, NULL };
22571 bool clear_pending = false;
22572
22573 UNUSED(task);
22574
22575 zone = event->ev_arg;
22576 INSIST(DNS_ZONE_VALID(zone));
22577
22578 ENTER;
22579
22580 dns_rdataset_init(&rdataset);
22581 dns_diff_init(zone->mctx, &diff);
22582
22583 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
22584 if (zone->db != NULL) {
22585 dns_db_attach(zone->db, &db);
22586 }
22587 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
22588 if (db == NULL) {
22589 goto failure;
22590 }
22591
22592 dns_db_currentversion(db, &oldver);
22593 result = dns_db_newversion(db, &newver);
22594 if (result != ISC_R_SUCCESS) {
22595 dnssec_log(zone, ISC_LOG_ERROR,
22596 "keydone:dns_db_newversion -> %s",
22597 isc_result_totext(result));
22598 goto failure;
22599 }
22600
22601 result = dns_db_getoriginnode(db, &node);
22602 if (result != ISC_R_SUCCESS) {
22603 goto failure;
22604 }
22605
22606 result = dns_db_findrdataset(db, node, newver, zone->privatetype,
22607 dns_rdatatype_none, 0, &rdataset, NULL);
22608 if (result == ISC_R_NOTFOUND) {
22609 INSIST(!dns_rdataset_isassociated(&rdataset));
22610 goto failure;
22611 }
22612 if (result != ISC_R_SUCCESS) {
22613 INSIST(!dns_rdataset_isassociated(&rdataset));
22614 goto failure;
22615 }
22616
22617 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
22618 result = dns_rdataset_next(&rdataset))
22619 {
22620 bool found = false;
22621
22622 dns_rdataset_current(&rdataset, &rdata);
22623
22624 if (kd->all) {
22625 if (rdata.length == 5 && rdata.data[0] != 0 &&
22626 rdata.data[3] == 0 && rdata.data[4] == 1)
22627 {
22628 found = true;
22629 } else if (rdata.data[0] == 0 &&
22630 (rdata.data[2] & PENDINGFLAGS) != 0)
22631 {
22632 found = true;
22633 clear_pending = true;
22634 }
22635 } else if (rdata.length == 5 &&
22636 memcmp(rdata.data, kd->data, 5) == 0)
22637 {
22638 found = true;
22639 }
22640
22641 if (found) {
22642 CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_DEL,
22643 &zone->origin, rdataset.ttl,
22644 &rdata));
22645 }
22646 dns_rdata_reset(&rdata);
22647 }
22648
22649 if (!ISC_LIST_EMPTY(diff.tuples)) {
22650 /* Write changes to journal file. */
22651 CHECK(update_soa_serial(zone, db, newver, &diff, zone->mctx,
22652 zone->updatemethod));
22653
22654 result = dns_update_signatures(&log, zone, db, oldver, newver,
22655 &diff,
22656 zone->sigvalidityinterval);
22657 if (!clear_pending) {
22658 CHECK(result);
22659 }
22660
22661 CHECK(zone_journal(zone, &diff, NULL, "keydone"));
22662 commit = true;
22663
22664 LOCK_ZONE(zone);
22665 DNS_ZONE_SETFLAG(zone,
22666 DNS_ZONEFLG_LOADED | DNS_ZONEFLG_NEEDNOTIFY);
22667 zone_needdump(zone, 30);
22668 UNLOCK_ZONE(zone);
22669 }
22670
22671 failure:
22672 if (dns_rdataset_isassociated(&rdataset)) {
22673 dns_rdataset_disassociate(&rdataset);
22674 }
22675 if (db != NULL) {
22676 if (node != NULL) {
22677 dns_db_detachnode(db, &node);
22678 }
22679 if (oldver != NULL) {
22680 dns_db_closeversion(db, &oldver, false);
22681 }
22682 if (newver != NULL) {
22683 dns_db_closeversion(db, &newver, commit);
22684 }
22685 dns_db_detach(&db);
22686 }
22687 dns_diff_clear(&diff);
22688 isc_event_free(&event);
22689 dns_zone_idetach(&zone);
22690
22691 INSIST(oldver == NULL);
22692 INSIST(newver == NULL);
22693 }
22694
22695 isc_result_t
22696 dns_zone_keydone(dns_zone_t *zone, const char *keystr) {
22697 isc_result_t result = ISC_R_SUCCESS;
22698 isc_event_t *e;
22699 isc_buffer_t b;
22700 dns_zone_t *dummy = NULL;
22701 struct keydone *kd;
22702
22703 REQUIRE(DNS_ZONE_VALID(zone));
22704
22705 LOCK_ZONE(zone);
22706
22707 e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_KEYDONE, keydone,
22708 zone, sizeof(struct keydone));
22709
22710 kd = (struct keydone *)e;
22711 if (strcasecmp(keystr, "all") == 0) {
22712 kd->all = true;
22713 } else {
22714 isc_textregion_t r;
22715 const char *algstr;
22716 dns_keytag_t keyid;
22717 dns_secalg_t alg;
22718 size_t n;
22719
22720 kd->all = false;
22721
22722 n = sscanf(keystr, "%hu/", &keyid);
22723 if (n == 0U) {
22724 CHECK(ISC_R_FAILURE);
22725 }
22726
22727 algstr = strchr(keystr, '/');
22728 if (algstr != NULL) {
22729 algstr++;
22730 } else {
22731 CHECK(ISC_R_FAILURE);
22732 }
22733
22734 n = sscanf(algstr, "%hhu", &alg);
22735 if (n == 0U) {
22736 DE_CONST(algstr, r.base);
22737 r.length = strlen(algstr);
22738 CHECK(dns_secalg_fromtext(&alg, &r));
22739 }
22740
22741 /* construct a private-type rdata */
22742 isc_buffer_init(&b, kd->data, sizeof(kd->data));
22743 isc_buffer_putuint8(&b, alg);
22744 isc_buffer_putuint8(&b, (keyid & 0xff00) >> 8);
22745 isc_buffer_putuint8(&b, (keyid & 0xff));
22746 isc_buffer_putuint8(&b, 0);
22747 isc_buffer_putuint8(&b, 1);
22748 }
22749
22750 zone_iattach(zone, &dummy);
22751 isc_task_send(zone->task, &e);
22752
22753 failure:
22754 if (e != NULL) {
22755 isc_event_free(&e);
22756 }
22757 UNLOCK_ZONE(zone);
22758 return (result);
22759 }
22760
22761 /*
22762 * Called from the zone task's queue after the relevant event is posted by
22763 * dns_zone_setnsec3param().
22764 */
22765 static void
22766 setnsec3param(isc_task_t *task, isc_event_t *event) {
22767 const char *me = "setnsec3param";
22768 dns_zone_t *zone = event->ev_arg;
22769 bool loadpending;
22770
22771 INSIST(DNS_ZONE_VALID(zone));
22772
22773 UNUSED(task);
22774
22775 ENTER;
22776
22777 LOCK_ZONE(zone);
22778 loadpending = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING);
22779 UNLOCK_ZONE(zone);
22780
22781 /*
22782 * If receive_secure_serial is still processing or we have a
22783 * queued event append rss_post queue.
22784 */
22785 if (zone->rss_newver != NULL || ISC_LIST_HEAD(zone->rss_post) != NULL) {
22786 /*
22787 * Wait for receive_secure_serial() to finish processing.
22788 */
22789 ISC_LIST_APPEND(zone->rss_post, event, ev_link);
22790 } else {
22791 bool rescheduled = false;
22792 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
22793 /*
22794 * The zone is not yet fully loaded. Reschedule the event to
22795 * be picked up later. This turns this function into a busy
22796 * wait, but it only happens at startup.
22797 */
22798 if (zone->db == NULL && loadpending) {
22799 rescheduled = true;
22800 isc_task_send(task, &event);
22801 }
22802 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
22803 if (rescheduled) {
22804 return;
22805 }
22806
22807 rss_post(zone, event);
22808 }
22809 dns_zone_idetach(&zone);
22810 }
22811
22812 static void
22813 salt2text(unsigned char *salt, uint8_t saltlen, unsigned char *text,
22814 unsigned int textlen) {
22815 isc_region_t r;
22816 isc_buffer_t buf;
22817 isc_result_t result;
22818
22819 r.base = salt;
22820 r.length = (unsigned int)saltlen;
22821
22822 isc_buffer_init(&buf, text, textlen);
22823 result = isc_hex_totext(&r, 2, "", &buf);
22824 if (result == ISC_R_SUCCESS) {
22825 text[saltlen * 2] = 0;
22826 } else {
22827 text[0] = 0;
22828 }
22829 }
22830
22831 /*
22832 * Check whether NSEC3 chain addition or removal specified by the private-type
22833 * record passed with the event was already queued (or even fully performed).
22834 * If not, modify the relevant private-type records at the zone apex and call
22835 * resume_addnsec3chain().
22836 */
22837 static void
22838 rss_post(dns_zone_t *zone, isc_event_t *event) {
22839 const char *me = "rss_post";
22840 bool commit = false;
22841 isc_result_t result;
22842 dns_dbversion_t *oldver = NULL, *newver = NULL;
22843 dns_db_t *db = NULL;
22844 dns_dbnode_t *node = NULL;
22845 dns_rdataset_t prdataset, nrdataset;
22846 dns_diff_t diff;
22847 struct np3event *npe = (struct np3event *)event;
22848 nsec3param_t *np;
22849 dns_update_log_t log = { update_log_cb, NULL };
22850 dns_rdata_t rdata;
22851 bool nseconly;
22852 bool exists = false;
22853
22854 ENTER;
22855
22856 np = &npe->params;
22857
22858 dns_rdataset_init(&prdataset);
22859 dns_rdataset_init(&nrdataset);
22860 dns_diff_init(zone->mctx, &diff);
22861
22862 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
22863 if (zone->db != NULL) {
22864 dns_db_attach(zone->db, &db);
22865 }
22866 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
22867 if (db == NULL) {
22868 goto failure;
22869 }
22870
22871 dns_db_currentversion(db, &oldver);
22872 result = dns_db_newversion(db, &newver);
22873 if (result != ISC_R_SUCCESS) {
22874 dnssec_log(zone, ISC_LOG_ERROR,
22875 "setnsec3param:dns_db_newversion -> %s",
22876 isc_result_totext(result));
22877 goto failure;
22878 }
22879
22880 CHECK(dns_db_getoriginnode(db, &node));
22881
22882 /*
22883 * Do we need to look up the NSEC3 parameters?
22884 */
22885 if (np->lookup) {
22886 dns_rdata_nsec3param_t param;
22887 dns_rdata_t nrdata = DNS_RDATA_INIT;
22888 dns_rdata_t prdata = DNS_RDATA_INIT;
22889 unsigned char nbuf[DNS_NSEC3PARAM_BUFFERSIZE];
22890 unsigned char saltbuf[255];
22891 isc_buffer_t b;
22892
22893 param.salt = NULL;
22894 result = dns__zone_lookup_nsec3param(zone, &np->rdata, ¶m,
22895 saltbuf, np->resalt);
22896 if (result == ISC_R_SUCCESS) {
22897 /*
22898 * Success because the NSEC3PARAM already exists, but
22899 * function returns void, so goto failure to clean up.
22900 */
22901 goto failure;
22902 }
22903 if (result != DNS_R_NSEC3RESALT && result != ISC_R_NOTFOUND) {
22904 dnssec_log(zone, ISC_LOG_DEBUG(3),
22905 "setnsec3param:lookup nsec3param -> %s",
22906 isc_result_totext(result));
22907 goto failure;
22908 }
22909
22910 INSIST(param.salt != NULL);
22911
22912 /* Update NSEC3 parameters. */
22913 np->rdata.hash = param.hash;
22914 np->rdata.flags = param.flags;
22915 np->rdata.iterations = param.iterations;
22916 np->rdata.salt_length = param.salt_length;
22917 np->rdata.salt = param.salt;
22918
22919 isc_buffer_init(&b, nbuf, sizeof(nbuf));
22920 CHECK(dns_rdata_fromstruct(&nrdata, zone->rdclass,
22921 dns_rdatatype_nsec3param, &np->rdata,
22922 &b));
22923 dns_nsec3param_toprivate(&nrdata, &prdata, zone->privatetype,
22924 np->data, sizeof(np->data));
22925 np->length = prdata.length;
22926 np->nsec = false;
22927 }
22928
22929 /*
22930 * Does a private-type record already exist for this chain?
22931 */
22932 result = dns_db_findrdataset(db, node, newver, zone->privatetype,
22933 dns_rdatatype_none, 0, &prdataset, NULL);
22934 if (result == ISC_R_SUCCESS) {
22935 for (result = dns_rdataset_first(&prdataset);
22936 result == ISC_R_SUCCESS;
22937 result = dns_rdataset_next(&prdataset))
22938 {
22939 dns_rdata_init(&rdata);
22940 dns_rdataset_current(&prdataset, &rdata);
22941
22942 if (np->length == rdata.length &&
22943 memcmp(rdata.data, np->data, np->length) == 0)
22944 {
22945 exists = true;
22946 break;
22947 }
22948 }
22949 } else if (result != ISC_R_NOTFOUND) {
22950 INSIST(!dns_rdataset_isassociated(&prdataset));
22951 goto failure;
22952 }
22953
22954 /*
22955 * Does the chain already exist?
22956 */
22957 result = dns_db_findrdataset(db, node, newver, dns_rdatatype_nsec3param,
22958 dns_rdatatype_none, 0, &nrdataset, NULL);
22959 if (result == ISC_R_SUCCESS) {
22960 for (result = dns_rdataset_first(&nrdataset);
22961 result == ISC_R_SUCCESS;
22962 result = dns_rdataset_next(&nrdataset))
22963 {
22964 dns_rdata_init(&rdata);
22965 dns_rdataset_current(&nrdataset, &rdata);
22966
22967 if (np->length == (rdata.length + 1) &&
22968 memcmp(rdata.data, np->data + 1, np->length - 1) ==
22969 0)
22970 {
22971 exists = true;
22972 break;
22973 }
22974 }
22975 } else if (result != ISC_R_NOTFOUND) {
22976 INSIST(!dns_rdataset_isassociated(&nrdataset));
22977 goto failure;
22978 }
22979
22980 /*
22981 * We need to remove any existing NSEC3 chains if the supplied NSEC3
22982 * parameters are supposed to replace the current ones or if we are
22983 * switching to NSEC.
22984 */
22985 if (!exists && np->replace && (np->length != 0 || np->nsec)) {
22986 CHECK(dns_nsec3param_deletechains(db, newver, zone, !np->nsec,
22987 &diff));
22988 }
22989
22990 if (!exists && np->length != 0) {
22991 /*
22992 * We're creating an NSEC3 chain. Add the private-type record
22993 * passed in the event handler's argument to the zone apex.
22994 *
22995 * If the zone is not currently capable of supporting an NSEC3
22996 * chain (due to the DNSKEY RRset at the zone apex not existing
22997 * or containing at least one key using an NSEC-only
22998 * algorithm), add the INITIAL flag, so these parameters can be
22999 * used later when NSEC3 becomes available.
23000 */
23001 dns_rdata_init(&rdata);
23002
23003 np->data[2] |= DNS_NSEC3FLAG_CREATE;
23004 result = dns_nsec_nseconly(db, newver, NULL, &nseconly);
23005 if (result == ISC_R_NOTFOUND || nseconly) {
23006 np->data[2] |= DNS_NSEC3FLAG_INITIAL;
23007 }
23008
23009 rdata.length = np->length;
23010 rdata.data = np->data;
23011 rdata.type = zone->privatetype;
23012 rdata.rdclass = zone->rdclass;
23013 CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_ADD,
23014 &zone->origin, 0, &rdata));
23015 }
23016
23017 /*
23018 * If we changed anything in the zone, write changes to journal file
23019 * and set commit to true so that resume_addnsec3chain() will be
23020 * called below in order to kick off adding/removing relevant NSEC3
23021 * records.
23022 */
23023 if (!ISC_LIST_EMPTY(diff.tuples)) {
23024 CHECK(update_soa_serial(zone, db, newver, &diff, zone->mctx,
23025 zone->updatemethod));
23026 result = dns_update_signatures(&log, zone, db, oldver, newver,
23027 &diff,
23028 zone->sigvalidityinterval);
23029 if (result != ISC_R_NOTFOUND) {
23030 CHECK(result);
23031 }
23032 CHECK(zone_journal(zone, &diff, NULL, "setnsec3param"));
23033 commit = true;
23034
23035 LOCK_ZONE(zone);
23036 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
23037 zone_needdump(zone, 30);
23038 UNLOCK_ZONE(zone);
23039 }
23040
23041 failure:
23042 if (dns_rdataset_isassociated(&prdataset)) {
23043 dns_rdataset_disassociate(&prdataset);
23044 }
23045 if (dns_rdataset_isassociated(&nrdataset)) {
23046 dns_rdataset_disassociate(&nrdataset);
23047 }
23048 if (node != NULL) {
23049 dns_db_detachnode(db, &node);
23050 }
23051 if (oldver != NULL) {
23052 dns_db_closeversion(db, &oldver, false);
23053 }
23054 if (newver != NULL) {
23055 dns_db_closeversion(db, &newver, commit);
23056 }
23057 if (db != NULL) {
23058 dns_db_detach(&db);
23059 }
23060 if (commit) {
23061 LOCK_ZONE(zone);
23062 resume_addnsec3chain(zone);
23063 UNLOCK_ZONE(zone);
23064 }
23065 dns_diff_clear(&diff);
23066 isc_event_free(&event);
23067
23068 INSIST(oldver == NULL);
23069 INSIST(newver == NULL);
23070 }
23071
23072 /*
23073 * Check if zone has NSEC3PARAM (and thus a chain) with the right parameters.
23074 *
23075 * If 'salt' is NULL, a match is found if the salt has the requested length,
23076 * otherwise the NSEC3 salt must match the requested salt value too.
23077 *
23078 * Returns ISC_R_SUCCESS, if a match is found, or an error if no match is
23079 * found, or if the db lookup failed.
23080 */
23081 isc_result_t
23082 dns__zone_lookup_nsec3param(dns_zone_t *zone, dns_rdata_nsec3param_t *lookup,
23083 dns_rdata_nsec3param_t *param,
23084 unsigned char saltbuf[255], bool resalt) {
23085 isc_result_t result = ISC_R_UNEXPECTED;
23086 dns_dbnode_t *node = NULL;
23087 dns_db_t *db = NULL;
23088 dns_dbversion_t *version = NULL;
23089 dns_rdataset_t rdataset;
23090 dns_rdata_nsec3param_t nsec3param;
23091 dns_rdata_t rdata = DNS_RDATA_INIT;
23092
23093 REQUIRE(DNS_ZONE_VALID(zone));
23094
23095 dns_rdataset_init(&rdataset);
23096
23097 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
23098 if (zone->db != NULL) {
23099 dns_db_attach(zone->db, &db);
23100 }
23101 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
23102 if (db == NULL) {
23103 result = ISC_R_FAILURE;
23104 goto setparam;
23105 }
23106
23107 result = dns_db_findnode(db, &zone->origin, false, &node);
23108 if (result != ISC_R_SUCCESS) {
23109 dns_zone_log(zone, ISC_LOG_ERROR,
23110 "dns__zone_lookup_nsec3param:"
23111 "dns_db_findnode -> %s",
23112 isc_result_totext(result));
23113 result = ISC_R_FAILURE;
23114 goto setparam;
23115 }
23116 dns_db_currentversion(db, &version);
23117
23118 result = dns_db_findrdataset(db, node, version,
23119 dns_rdatatype_nsec3param,
23120 dns_rdatatype_none, 0, &rdataset, NULL);
23121 if (result != ISC_R_SUCCESS) {
23122 INSIST(!dns_rdataset_isassociated(&rdataset));
23123 if (result != ISC_R_NOTFOUND) {
23124 dns_zone_log(zone, ISC_LOG_ERROR,
23125 "dns__zone_lookup_nsec3param:"
23126 "dns_db_findrdataset -> %s",
23127 isc_result_totext(result));
23128 }
23129 goto setparam;
23130 }
23131
23132 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
23133 result = dns_rdataset_next(&rdataset))
23134 {
23135 dns_rdataset_current(&rdataset, &rdata);
23136 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
23137 INSIST(result == ISC_R_SUCCESS);
23138 dns_rdata_reset(&rdata);
23139
23140 /* Check parameters. */
23141 if (nsec3param.hash != lookup->hash) {
23142 continue;
23143 }
23144 if (nsec3param.iterations != lookup->iterations) {
23145 continue;
23146 }
23147 if (nsec3param.salt_length != lookup->salt_length) {
23148 continue;
23149 }
23150 if (lookup->salt != NULL) {
23151 if (memcmp(nsec3param.salt, lookup->salt,
23152 lookup->salt_length) != 0)
23153 {
23154 continue;
23155 }
23156 }
23157 /* Found a match. */
23158 result = ISC_R_SUCCESS;
23159 param->hash = nsec3param.hash;
23160 param->flags = nsec3param.flags;
23161 param->iterations = nsec3param.iterations;
23162 param->salt_length = nsec3param.salt_length;
23163 param->salt = nsec3param.salt;
23164 break;
23165 }
23166
23167 if (result == ISC_R_NOMORE) {
23168 result = ISC_R_NOTFOUND;
23169 }
23170
23171 setparam:
23172 if (result != ISC_R_SUCCESS) {
23173 /* Found no match. */
23174 param->hash = lookup->hash;
23175 param->flags = lookup->flags;
23176 param->iterations = lookup->iterations;
23177 param->salt_length = lookup->salt_length;
23178 param->salt = lookup->salt;
23179 }
23180
23181 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) {
23182 goto failure;
23183 }
23184
23185 if (param->salt_length == 0) {
23186 DE_CONST("-", param->salt);
23187 } else if (resalt || param->salt == NULL) {
23188 unsigned char *newsalt;
23189 unsigned char salttext[255 * 2 + 1];
23190 do {
23191 /* Generate a new salt. */
23192 result = dns_nsec3_generate_salt(saltbuf,
23193 param->salt_length);
23194 if (result != ISC_R_SUCCESS) {
23195 break;
23196 }
23197 newsalt = saltbuf;
23198 salt2text(newsalt, param->salt_length, salttext,
23199 sizeof(salttext));
23200 dnssec_log(zone, ISC_LOG_INFO, "generated salt: %s",
23201 salttext);
23202 /* Check for salt conflict. */
23203 if (param->salt != NULL &&
23204 memcmp(newsalt, param->salt, param->salt_length) ==
23205 0)
23206 {
23207 result = ISC_R_SUCCESS;
23208 } else {
23209 param->salt = newsalt;
23210 result = DNS_R_NSEC3RESALT;
23211 }
23212 } while (result == ISC_R_SUCCESS);
23213
23214 INSIST(result != ISC_R_SUCCESS);
23215 }
23216
23217 failure:
23218 if (dns_rdataset_isassociated(&rdataset)) {
23219 dns_rdataset_disassociate(&rdataset);
23220 }
23221 if (node != NULL) {
23222 dns_db_detachnode(db, &node);
23223 }
23224 if (version != NULL) {
23225 dns_db_closeversion(db, &version, false);
23226 }
23227 if (db != NULL) {
23228 dns_db_detach(&db);
23229 }
23230
23231 return (result);
23232 }
23233
23234 /*
23235 * Called when an "rndc signing -nsec3param ..." command is received, or the
23236 * 'dnssec-policy' has changed.
23237 *
23238 * Allocate and prepare an nsec3param_t structure which holds information about
23239 * the NSEC3 changes requested for the zone:
23240 *
23241 * - if NSEC3 is to be disabled ("-nsec3param none"), only set the "nsec"
23242 * field of the structure to true and the "replace" field to the value
23243 * of the "replace" argument, leaving other fields initialized to zeros, to
23244 * signal that the zone should be signed using NSEC instead of NSEC3,
23245 *
23246 * - otherwise, prepare NSEC3PARAM RDATA that will eventually be inserted at
23247 * the zone apex, convert it to a private-type record and store the latter
23248 * in the "data" field of the nsec3param_t structure.
23249 *
23250 * Once the nsec3param_t structure is prepared, post an event to the zone's
23251 * task which will cause setnsec3param() to be called with the prepared
23252 * structure passed as an argument.
23253 */
23254 isc_result_t
23255 dns_zone_setnsec3param(dns_zone_t *zone, uint8_t hash, uint8_t flags,
23256 uint16_t iter, uint8_t saltlen, unsigned char *salt,
23257 bool replace, bool resalt) {
23258 isc_result_t result = ISC_R_SUCCESS;
23259 dns_rdata_nsec3param_t param, lookup;
23260 dns_rdata_t nrdata = DNS_RDATA_INIT;
23261 dns_rdata_t prdata = DNS_RDATA_INIT;
23262 unsigned char nbuf[DNS_NSEC3PARAM_BUFFERSIZE];
23263 unsigned char saltbuf[255];
23264 struct np3event *npe;
23265 nsec3param_t *np;
23266 dns_zone_t *dummy = NULL;
23267 isc_buffer_t b;
23268 isc_event_t *e = NULL;
23269 bool do_lookup = false;
23270
23271 REQUIRE(DNS_ZONE_VALID(zone));
23272
23273 LOCK_ZONE(zone);
23274
23275 /*
23276 * First check if the requested NSEC3 parameters are already set,
23277 * if so, no need to set again.
23278 */
23279 if (hash != 0) {
23280 lookup.hash = hash;
23281 lookup.flags = flags;
23282 lookup.iterations = iter;
23283 lookup.salt_length = saltlen;
23284 lookup.salt = salt;
23285 param.salt = NULL;
23286 result = dns__zone_lookup_nsec3param(zone, &lookup, ¶m,
23287 saltbuf, resalt);
23288 if (result == ISC_R_SUCCESS) {
23289 UNLOCK_ZONE(zone);
23290 return (ISC_R_SUCCESS);
23291 }
23292 /*
23293 * Schedule lookup if lookup above failed (may happen if zone
23294 * db is NULL for example).
23295 */
23296 do_lookup = (param.salt == NULL) ? true : false;
23297 }
23298
23299 e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETNSEC3PARAM,
23300 setnsec3param, zone, sizeof(struct np3event));
23301
23302 npe = (struct np3event *)e;
23303 np = &npe->params;
23304 np->replace = replace;
23305 np->resalt = resalt;
23306 np->lookup = do_lookup;
23307 if (hash == 0) {
23308 np->length = 0;
23309 np->nsec = true;
23310 dnssec_log(zone, ISC_LOG_DEBUG(3), "setnsec3param:nsec");
23311 } else {
23312 param.common.rdclass = zone->rdclass;
23313 param.common.rdtype = dns_rdatatype_nsec3param;
23314 ISC_LINK_INIT(¶m.common, link);
23315 param.mctx = NULL;
23316 /* nsec3 specific param set in dns__zone_lookup_nsec3param() */
23317 isc_buffer_init(&b, nbuf, sizeof(nbuf));
23318
23319 if (param.salt != NULL) {
23320 CHECK(dns_rdata_fromstruct(&nrdata, zone->rdclass,
23321 dns_rdatatype_nsec3param,
23322 ¶m, &b));
23323 dns_nsec3param_toprivate(&nrdata, &prdata,
23324 zone->privatetype, np->data,
23325 sizeof(np->data));
23326 np->length = prdata.length;
23327 }
23328
23329 np->rdata = param;
23330 np->nsec = false;
23331
23332 if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
23333 unsigned char salttext[255 * 2 + 1];
23334 if (param.salt != NULL) {
23335 salt2text(param.salt, param.salt_length,
23336 salttext, sizeof(salttext));
23337 }
23338 dnssec_log(zone, ISC_LOG_DEBUG(3),
23339 "setnsec3param:nsec3 %u %u %u %u:%s",
23340 param.hash, param.flags, param.iterations,
23341 param.salt_length,
23342 param.salt == NULL ? "unknown"
23343 : (char *)salttext);
23344 }
23345 }
23346
23347 /*
23348 * setnsec3param() will silently return early if the zone does not yet
23349 * have a database. Prevent that by queueing the event up if zone->db
23350 * is NULL. All events queued here are subsequently processed by
23351 * receive_secure_db() if it ever gets called or simply freed by
23352 * zone_free() otherwise.
23353 */
23354
23355 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
23356 if (zone->db != NULL) {
23357 zone_iattach(zone, &dummy);
23358 isc_task_send(zone->task, &e);
23359 } else {
23360 ISC_LIST_APPEND(zone->setnsec3param_queue, e, ev_link);
23361 e = NULL;
23362 }
23363 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
23364
23365 result = ISC_R_SUCCESS;
23366
23367 failure:
23368 if (e != NULL) {
23369 isc_event_free(&e);
23370 }
23371 UNLOCK_ZONE(zone);
23372 return (result);
23373 }
23374
23375 isc_result_t
23376 dns_zone_getloadtime(dns_zone_t *zone, isc_time_t *loadtime) {
23377 REQUIRE(DNS_ZONE_VALID(zone));
23378 REQUIRE(loadtime != NULL);
23379
23380 LOCK_ZONE(zone);
23381 *loadtime = zone->loadtime;
23382 UNLOCK_ZONE(zone);
23383 return (ISC_R_SUCCESS);
23384 }
23385
23386 isc_result_t
23387 dns_zone_getexpiretime(dns_zone_t *zone, isc_time_t *expiretime) {
23388 REQUIRE(DNS_ZONE_VALID(zone));
23389 REQUIRE(expiretime != NULL);
23390
23391 LOCK_ZONE(zone);
23392 *expiretime = zone->expiretime;
23393 UNLOCK_ZONE(zone);
23394 return (ISC_R_SUCCESS);
23395 }
23396
23397 isc_result_t
23398 dns_zone_getrefreshtime(dns_zone_t *zone, isc_time_t *refreshtime) {
23399 REQUIRE(DNS_ZONE_VALID(zone));
23400 REQUIRE(refreshtime != NULL);
23401
23402 LOCK_ZONE(zone);
23403 *refreshtime = zone->refreshtime;
23404 UNLOCK_ZONE(zone);
23405 return (ISC_R_SUCCESS);
23406 }
23407
23408 isc_result_t
23409 dns_zone_getrefreshkeytime(dns_zone_t *zone, isc_time_t *refreshkeytime) {
23410 REQUIRE(DNS_ZONE_VALID(zone));
23411 REQUIRE(refreshkeytime != NULL);
23412
23413 LOCK_ZONE(zone);
23414 *refreshkeytime = zone->refreshkeytime;
23415 UNLOCK_ZONE(zone);
23416 return (ISC_R_SUCCESS);
23417 }
23418
23419 unsigned int
23420 dns_zone_getincludes(dns_zone_t *zone, char ***includesp) {
23421 dns_include_t *include;
23422 char **array = NULL;
23423 unsigned int n = 0;
23424
23425 REQUIRE(DNS_ZONE_VALID(zone));
23426 REQUIRE(includesp != NULL && *includesp == NULL);
23427
23428 LOCK_ZONE(zone);
23429 if (zone->nincludes == 0) {
23430 goto done;
23431 }
23432
23433 array = isc_mem_allocate(zone->mctx, sizeof(char *) * zone->nincludes);
23434 for (include = ISC_LIST_HEAD(zone->includes); include != NULL;
23435 include = ISC_LIST_NEXT(include, link))
23436 {
23437 INSIST(n < zone->nincludes);
23438 array[n++] = isc_mem_strdup(zone->mctx, include->name);
23439 }
23440 INSIST(n == zone->nincludes);
23441 *includesp = array;
23442
23443 done:
23444 UNLOCK_ZONE(zone);
23445 return (n);
23446 }
23447
23448 void
23449 dns_zone_setstatlevel(dns_zone_t *zone, dns_zonestat_level_t level) {
23450 REQUIRE(DNS_ZONE_VALID(zone));
23451
23452 zone->statlevel = level;
23453 }
23454
23455 dns_zonestat_level_t
23456 dns_zone_getstatlevel(dns_zone_t *zone) {
23457 REQUIRE(DNS_ZONE_VALID(zone));
23458
23459 return (zone->statlevel);
23460 }
23461
23462 static void
23463 setserial(isc_task_t *task, isc_event_t *event) {
23464 uint32_t oldserial, desired;
23465 const char *me = "setserial";
23466 bool commit = false;
23467 isc_result_t result;
23468 dns_dbversion_t *oldver = NULL, *newver = NULL;
23469 dns_zone_t *zone;
23470 dns_db_t *db = NULL;
23471 dns_diff_t diff;
23472 struct ssevent *sse = (struct ssevent *)event;
23473 dns_update_log_t log = { update_log_cb, NULL };
23474 dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
23475
23476 UNUSED(task);
23477
23478 zone = event->ev_arg;
23479 INSIST(DNS_ZONE_VALID(zone));
23480
23481 ENTER;
23482
23483 if (zone->update_disabled) {
23484 goto disabled;
23485 }
23486
23487 desired = sse->serial;
23488
23489 dns_diff_init(zone->mctx, &diff);
23490
23491 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
23492 if (zone->db != NULL) {
23493 dns_db_attach(zone->db, &db);
23494 }
23495 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
23496 if (db == NULL) {
23497 goto failure;
23498 }
23499
23500 dns_db_currentversion(db, &oldver);
23501 result = dns_db_newversion(db, &newver);
23502 if (result != ISC_R_SUCCESS) {
23503 dns_zone_log(zone, ISC_LOG_ERROR,
23504 "setserial:dns_db_newversion -> %s",
23505 isc_result_totext(result));
23506 goto failure;
23507 }
23508
23509 CHECK(dns_db_createsoatuple(db, oldver, diff.mctx, DNS_DIFFOP_DEL,
23510 &oldtuple));
23511 CHECK(dns_difftuple_copy(oldtuple, &newtuple));
23512 newtuple->op = DNS_DIFFOP_ADD;
23513
23514 oldserial = dns_soa_getserial(&oldtuple->rdata);
23515 if (desired == 0U) {
23516 desired = 1;
23517 }
23518 if (!isc_serial_gt(desired, oldserial)) {
23519 if (desired != oldserial) {
23520 dns_zone_log(zone, ISC_LOG_INFO,
23521 "setserial: desired serial (%u) "
23522 "out of range (%u-%u)",
23523 desired, oldserial + 1,
23524 (oldserial + 0x7fffffff));
23525 }
23526 goto failure;
23527 }
23528
23529 dns_soa_setserial(desired, &newtuple->rdata);
23530 CHECK(do_one_tuple(&oldtuple, db, newver, &diff));
23531 CHECK(do_one_tuple(&newtuple, db, newver, &diff));
23532 result = dns_update_signatures(&log, zone, db, oldver, newver, &diff,
23533 zone->sigvalidityinterval);
23534 if (result != ISC_R_NOTFOUND) {
23535 CHECK(result);
23536 }
23537
23538 /* Write changes to journal file. */
23539 CHECK(zone_journal(zone, &diff, NULL, "setserial"));
23540 commit = true;
23541
23542 LOCK_ZONE(zone);
23543 zone_needdump(zone, 30);
23544 UNLOCK_ZONE(zone);
23545
23546 failure:
23547 if (oldtuple != NULL) {
23548 dns_difftuple_free(&oldtuple);
23549 }
23550 if (newtuple != NULL) {
23551 dns_difftuple_free(&newtuple);
23552 }
23553 if (oldver != NULL) {
23554 dns_db_closeversion(db, &oldver, false);
23555 }
23556 if (newver != NULL) {
23557 dns_db_closeversion(db, &newver, commit);
23558 }
23559 if (db != NULL) {
23560 dns_db_detach(&db);
23561 }
23562 dns_diff_clear(&diff);
23563
23564 disabled:
23565 isc_event_free(&event);
23566 dns_zone_idetach(&zone);
23567
23568 INSIST(oldver == NULL);
23569 INSIST(newver == NULL);
23570 }
23571
23572 isc_result_t
23573 dns_zone_setserial(dns_zone_t *zone, uint32_t serial) {
23574 isc_result_t result = ISC_R_SUCCESS;
23575 dns_zone_t *dummy = NULL;
23576 isc_event_t *e = NULL;
23577 struct ssevent *sse;
23578
23579 REQUIRE(DNS_ZONE_VALID(zone));
23580
23581 LOCK_ZONE(zone);
23582
23583 if (!inline_secure(zone)) {
23584 if (!dns_zone_isdynamic(zone, true)) {
23585 result = DNS_R_NOTDYNAMIC;
23586 goto failure;
23587 }
23588 }
23589
23590 if (zone->update_disabled) {
23591 result = DNS_R_FROZEN;
23592 goto failure;
23593 }
23594
23595 e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETSERIAL, setserial,
23596 zone, sizeof(struct ssevent));
23597
23598 sse = (struct ssevent *)e;
23599 sse->serial = serial;
23600
23601 zone_iattach(zone, &dummy);
23602 isc_task_send(zone->task, &e);
23603
23604 failure:
23605 if (e != NULL) {
23606 isc_event_free(&e);
23607 }
23608 UNLOCK_ZONE(zone);
23609 return (result);
23610 }
23611
23612 isc_stats_t *
23613 dns_zone_getgluecachestats(dns_zone_t *zone) {
23614 REQUIRE(DNS_ZONE_VALID(zone));
23615
23616 return (zone->gluecachestats);
23617 }
23618
23619 bool
23620 dns_zone_isloaded(dns_zone_t *zone) {
23621 REQUIRE(DNS_ZONE_VALID(zone));
23622
23623 return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED));
23624 }
23625
23626 isc_result_t
23627 dns_zone_verifydb(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver) {
23628 dns_dbversion_t *version = NULL;
23629 dns_keytable_t *secroots = NULL;
23630 isc_result_t result;
23631 dns_name_t *origin;
23632
23633 const char me[] = "dns_zone_verifydb";
23634
23635 REQUIRE(DNS_ZONE_VALID(zone));
23636 REQUIRE(db != NULL);
23637
23638 ENTER;
23639
23640 if (dns_zone_gettype(zone) != dns_zone_mirror) {
23641 return (ISC_R_SUCCESS);
23642 }
23643
23644 if (ver == NULL) {
23645 dns_db_currentversion(db, &version);
23646 } else {
23647 version = ver;
23648 }
23649
23650 if (zone->view != NULL) {
23651 result = dns_view_getsecroots(zone->view, &secroots);
23652 if (result != ISC_R_SUCCESS) {
23653 goto done;
23654 }
23655 }
23656
23657 origin = dns_db_origin(db);
23658 result = dns_zoneverify_dnssec(zone, db, version, origin, secroots,
23659 zone->mctx, true, false, dnssec_report);
23660
23661 done:
23662 if (secroots != NULL) {
23663 dns_keytable_detach(&secroots);
23664 }
23665
23666 if (ver == NULL) {
23667 dns_db_closeversion(db, &version, false);
23668 }
23669
23670 if (result != ISC_R_SUCCESS) {
23671 dnssec_log(zone, ISC_LOG_ERROR, "zone verification failed: %s",
23672 isc_result_totext(result));
23673 result = DNS_R_VERIFYFAILURE;
23674 }
23675
23676 return (result);
23677 }
23678
23679 static dns_ttl_t
23680 zone_nsecttl(dns_zone_t *zone) {
23681 REQUIRE(DNS_ZONE_VALID(zone));
23682
23683 return (ISC_MIN(zone->minimum, zone->soattl));
23684 }
23685
23686 void
23687 dns_zonemgr_set_tlsctx_cache(dns_zonemgr_t *zmgr,
23688 isc_tlsctx_cache_t *tlsctx_cache) {
23689 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
23690 REQUIRE(tlsctx_cache != NULL);
23691
23692 RWLOCK(&zmgr->tlsctx_cache_rwlock, isc_rwlocktype_write);
23693
23694 if (zmgr->tlsctx_cache != NULL) {
23695 isc_tlsctx_cache_detach(&zmgr->tlsctx_cache);
23696 }
23697
23698 isc_tlsctx_cache_attach(tlsctx_cache, &zmgr->tlsctx_cache);
23699
23700 RWUNLOCK(&zmgr->tlsctx_cache_rwlock, isc_rwlocktype_write);
23701 }
23702
23703 static void
23704 zmgr_tlsctx_attach(dns_zonemgr_t *zmgr, isc_tlsctx_cache_t **ptlsctx_cache) {
23705 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
23706 REQUIRE(ptlsctx_cache != NULL && *ptlsctx_cache == NULL);
23707
23708 RWLOCK(&zmgr->tlsctx_cache_rwlock, isc_rwlocktype_read);
23709
23710 INSIST(zmgr->tlsctx_cache != NULL);
23711 isc_tlsctx_cache_attach(zmgr->tlsctx_cache, ptlsctx_cache);
23712
23713 RWUNLOCK(&zmgr->tlsctx_cache_rwlock, isc_rwlocktype_read);
23714 }
23715