zone.c revision 1.17 1 /* $NetBSD: zone.c,v 1.17 2023/01/25 21:43:30 christos Exp $ */
2
3 /*
4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5 *
6 * SPDX-License-Identifier: MPL-2.0
7 *
8 * This Source Code Form is subject to the terms of the Mozilla Public
9 * License, v. 2.0. If a copy of the MPL was not distributed with this
10 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11 *
12 * See the COPYRIGHT file distributed with this work for additional
13 * information regarding copyright ownership.
14 */
15
16 /*! \file */
17
18 #include <errno.h>
19 #include <inttypes.h>
20 #include <stdbool.h>
21
22 #include <isc/atomic.h>
23 #include <isc/file.h>
24 #include <isc/hex.h>
25 #include <isc/md.h>
26 #include <isc/mutex.h>
27 #include <isc/pool.h>
28 #include <isc/print.h>
29 #include <isc/random.h>
30 #include <isc/ratelimiter.h>
31 #include <isc/refcount.h>
32 #include <isc/rwlock.h>
33 #include <isc/serial.h>
34 #include <isc/stats.h>
35 #include <isc/stdtime.h>
36 #include <isc/strerr.h>
37 #include <isc/string.h>
38 #include <isc/taskpool.h>
39 #include <isc/thread.h>
40 #include <isc/timer.h>
41 #include <isc/util.h>
42
43 #include <dns/acl.h>
44 #include <dns/adb.h>
45 #include <dns/callbacks.h>
46 #include <dns/catz.h>
47 #include <dns/db.h>
48 #include <dns/dbiterator.h>
49 #include <dns/dlz.h>
50 #include <dns/dnssec.h>
51 #include <dns/events.h>
52 #include <dns/journal.h>
53 #include <dns/kasp.h>
54 #include <dns/keydata.h>
55 #include <dns/keymgr.h>
56 #include <dns/keytable.h>
57 #include <dns/keyvalues.h>
58 #include <dns/log.h>
59 #include <dns/master.h>
60 #include <dns/masterdump.h>
61 #include <dns/message.h>
62 #include <dns/name.h>
63 #include <dns/nsec.h>
64 #include <dns/nsec3.h>
65 #include <dns/opcode.h>
66 #include <dns/peer.h>
67 #include <dns/private.h>
68 #include <dns/rcode.h>
69 #include <dns/rdata.h>
70 #include <dns/rdataclass.h>
71 #include <dns/rdatalist.h>
72 #include <dns/rdataset.h>
73 #include <dns/rdatasetiter.h>
74 #include <dns/rdatastruct.h>
75 #include <dns/rdatatype.h>
76 #include <dns/request.h>
77 #include <dns/resolver.h>
78 #include <dns/result.h>
79 #include <dns/rriterator.h>
80 #include <dns/soa.h>
81 #include <dns/ssu.h>
82 #include <dns/stats.h>
83 #include <dns/time.h>
84 #include <dns/tsig.h>
85 #include <dns/update.h>
86 #include <dns/xfrin.h>
87 #include <dns/zone.h>
88 #include <dns/zoneverify.h>
89 #include <dns/zt.h>
90
91 #include <dst/dst.h>
92
93 #include "zone_p.h"
94
95 #define ZONE_MAGIC ISC_MAGIC('Z', 'O', 'N', 'E')
96 #define DNS_ZONE_VALID(zone) ISC_MAGIC_VALID(zone, ZONE_MAGIC)
97
98 #define NOTIFY_MAGIC ISC_MAGIC('N', 't', 'f', 'y')
99 #define DNS_NOTIFY_VALID(notify) ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)
100
101 #define CHECKDS_MAGIC ISC_MAGIC('C', 'h', 'D', 'S')
102 #define DNS_CHECKDS_VALID(checkds) ISC_MAGIC_VALID(checkds, CHECKDS_MAGIC)
103
104 #define STUB_MAGIC ISC_MAGIC('S', 't', 'u', 'b')
105 #define DNS_STUB_VALID(stub) ISC_MAGIC_VALID(stub, STUB_MAGIC)
106
107 #define ZONEMGR_MAGIC ISC_MAGIC('Z', 'm', 'g', 'r')
108 #define DNS_ZONEMGR_VALID(stub) ISC_MAGIC_VALID(stub, ZONEMGR_MAGIC)
109
110 #define LOAD_MAGIC ISC_MAGIC('L', 'o', 'a', 'd')
111 #define DNS_LOAD_VALID(load) ISC_MAGIC_VALID(load, LOAD_MAGIC)
112
113 #define FORWARD_MAGIC ISC_MAGIC('F', 'o', 'r', 'w')
114 #define DNS_FORWARD_VALID(load) ISC_MAGIC_VALID(load, FORWARD_MAGIC)
115
116 #define IO_MAGIC ISC_MAGIC('Z', 'm', 'I', 'O')
117 #define DNS_IO_VALID(load) ISC_MAGIC_VALID(load, IO_MAGIC)
118
119 #define KEYMGMT_MAGIC ISC_MAGIC('M', 'g', 'm', 't')
120 #define DNS_KEYMGMT_VALID(load) ISC_MAGIC_VALID(load, KEYMGMT_MAGIC)
121
122 #define KEYFILEIO_MAGIC ISC_MAGIC('K', 'y', 'I', 'O')
123 #define DNS_KEYFILEIO_VALID(kfio) ISC_MAGIC_VALID(kfio, KEYFILEIO_MAGIC)
124
125 /*%
126 * Ensure 'a' is at least 'min' but not more than 'max'.
127 */
128 #define RANGE(a, min, max) (((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max)))
129
130 #define NSEC3REMOVE(x) (((x)&DNS_NSEC3FLAG_REMOVE) != 0)
131
132 /*%
133 * Key flags
134 */
135 #define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
136 #define KSK(x) ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
137 #define ID(x) dst_key_id(x)
138 #define ALG(x) dst_key_alg(x)
139
140 /*%
141 * KASP flags
142 */
143 #define KASP_LOCK(k) \
144 if ((k) != NULL) { \
145 LOCK((&((k)->lock))); \
146 }
147
148 #define KASP_UNLOCK(k) \
149 if ((k) != NULL) { \
150 UNLOCK((&((k)->lock))); \
151 }
152
153 /*
154 * Default values.
155 */
156 #define DNS_DEFAULT_IDLEIN 3600 /*%< 1 hour */
157 #define DNS_DEFAULT_IDLEOUT 3600 /*%< 1 hour */
158 #define MAX_XFER_TIME (2 * 3600) /*%< Documented default is 2 hours */
159 #define RESIGN_DELAY 3600 /*%< 1 hour */
160
161 #ifndef DNS_MAX_EXPIRE
162 #define DNS_MAX_EXPIRE 14515200 /*%< 24 weeks */
163 #endif /* ifndef DNS_MAX_EXPIRE */
164
165 #ifndef DNS_DUMP_DELAY
166 #define DNS_DUMP_DELAY 900 /*%< 15 minutes */
167 #endif /* ifndef DNS_DUMP_DELAY */
168
169 typedef struct dns_notify dns_notify_t;
170 typedef struct dns_checkds dns_checkds_t;
171 typedef struct dns_stub dns_stub_t;
172 typedef struct dns_load dns_load_t;
173 typedef struct dns_forward dns_forward_t;
174 typedef ISC_LIST(dns_forward_t) dns_forwardlist_t;
175 typedef struct dns_io dns_io_t;
176 typedef ISC_LIST(dns_io_t) dns_iolist_t;
177 typedef struct dns_keymgmt dns_keymgmt_t;
178 typedef struct dns_signing dns_signing_t;
179 typedef ISC_LIST(dns_signing_t) dns_signinglist_t;
180 typedef struct dns_nsec3chain dns_nsec3chain_t;
181 typedef ISC_LIST(dns_nsec3chain_t) dns_nsec3chainlist_t;
182 typedef struct dns_keyfetch dns_keyfetch_t;
183 typedef struct dns_asyncload dns_asyncload_t;
184 typedef struct dns_include dns_include_t;
185
186 #define DNS_ZONE_CHECKLOCK
187 #ifdef DNS_ZONE_CHECKLOCK
188 #define LOCK_ZONE(z) \
189 do { \
190 LOCK(&(z)->lock); \
191 INSIST(!(z)->locked); \
192 (z)->locked = true; \
193 } while (0)
194 #define UNLOCK_ZONE(z) \
195 do { \
196 (z)->locked = false; \
197 UNLOCK(&(z)->lock); \
198 } while (0)
199 #define LOCKED_ZONE(z) ((z)->locked)
200 #define TRYLOCK_ZONE(result, z) \
201 do { \
202 result = isc_mutex_trylock(&(z)->lock); \
203 if (result == ISC_R_SUCCESS) { \
204 INSIST(!(z)->locked); \
205 (z)->locked = true; \
206 } \
207 } while (0)
208 #else /* ifdef DNS_ZONE_CHECKLOCK */
209 #define LOCK_ZONE(z) LOCK(&(z)->lock)
210 #define UNLOCK_ZONE(z) UNLOCK(&(z)->lock)
211 #define LOCKED_ZONE(z) true
212 #define TRYLOCK_ZONE(result, z) \
213 do { \
214 result = isc_mutex_trylock(&(z)->lock); \
215 } while (0)
216 #endif /* ifdef DNS_ZONE_CHECKLOCK */
217
218 #define ZONEDB_INITLOCK(l) isc_rwlock_init((l), 0, 0)
219 #define ZONEDB_DESTROYLOCK(l) isc_rwlock_destroy(l)
220 #define ZONEDB_LOCK(l, t) RWLOCK((l), (t))
221 #define ZONEDB_UNLOCK(l, t) RWUNLOCK((l), (t))
222
223 #ifdef ENABLE_AFL
224 extern bool dns_fuzzing_resolver;
225 #endif /* ifdef ENABLE_AFL */
226
227 /*%
228 * Hold key file IO locks.
229 */
230 typedef struct dns_keyfileio {
231 unsigned int magic;
232 struct dns_keyfileio *next;
233 uint32_t hashval;
234 dns_fixedname_t fname;
235 dns_name_t *name;
236 isc_refcount_t references;
237 isc_mutex_t lock;
238 } dns_keyfileio_t;
239
240 struct dns_keymgmt {
241 unsigned int magic;
242 isc_rwlock_t lock;
243 isc_mem_t *mctx;
244
245 dns_keyfileio_t **table;
246
247 atomic_uint_fast32_t count;
248
249 uint32_t bits;
250 };
251
252 struct dns_zone {
253 /* Unlocked */
254 unsigned int magic;
255 isc_mutex_t lock;
256 #ifdef DNS_ZONE_CHECKLOCK
257 bool locked;
258 #endif /* ifdef DNS_ZONE_CHECKLOCK */
259 isc_mem_t *mctx;
260 isc_refcount_t erefs;
261
262 isc_rwlock_t dblock;
263 dns_db_t *db; /* Locked by dblock */
264
265 /* Locked */
266 dns_zonemgr_t *zmgr;
267 ISC_LINK(dns_zone_t) link; /* Used by zmgr. */
268 isc_timer_t *timer;
269 isc_refcount_t irefs;
270 dns_name_t origin;
271 char *masterfile;
272 ISC_LIST(dns_include_t) includes; /* Include files */
273 ISC_LIST(dns_include_t) newincludes; /* Loading */
274 unsigned int nincludes;
275 dns_masterformat_t masterformat;
276 const dns_master_style_t *masterstyle;
277 char *journal;
278 int32_t journalsize;
279 dns_rdataclass_t rdclass;
280 dns_zonetype_t type;
281 #ifdef __NetBSD__
282 atomic_uint_fast32_t flags;
283 atomic_uint_fast32_t options;
284 #else
285 atomic_uint_fast64_t flags;
286 atomic_uint_fast64_t options;
287 #endif
288 unsigned int db_argc;
289 char **db_argv;
290 isc_time_t expiretime;
291 isc_time_t refreshtime;
292 isc_time_t dumptime;
293 isc_time_t loadtime;
294 isc_time_t notifytime;
295 isc_time_t resigntime;
296 isc_time_t keywarntime;
297 isc_time_t signingtime;
298 isc_time_t nsec3chaintime;
299 isc_time_t refreshkeytime;
300 uint32_t refreshkeyinterval;
301 uint32_t refreshkeycount;
302 uint32_t refresh;
303 uint32_t retry;
304 uint32_t expire;
305 uint32_t minimum;
306 isc_stdtime_t key_expiry;
307 isc_stdtime_t log_key_expired_timer;
308 char *keydirectory;
309 dns_keyfileio_t *kfio;
310
311 uint32_t maxrefresh;
312 uint32_t minrefresh;
313 uint32_t maxretry;
314 uint32_t minretry;
315
316 uint32_t maxrecords;
317
318 isc_sockaddr_t *masters;
319 isc_dscp_t *masterdscps;
320 dns_name_t **masterkeynames;
321 bool *mastersok;
322 unsigned int masterscnt;
323 unsigned int curmaster;
324 isc_sockaddr_t masteraddr;
325
326 isc_sockaddr_t *parentals;
327 isc_dscp_t *parentaldscps;
328 dns_name_t **parentalkeynames;
329 dns_dnsseckeylist_t checkds_ok;
330 unsigned int parentalscnt;
331 isc_sockaddr_t parentaladdr;
332
333 dns_notifytype_t notifytype;
334 isc_sockaddr_t *notify;
335 dns_name_t **notifykeynames;
336 isc_dscp_t *notifydscp;
337 unsigned int notifycnt;
338 isc_sockaddr_t notifyfrom;
339 isc_task_t *task;
340 isc_task_t *loadtask;
341 isc_sockaddr_t notifysrc4;
342 isc_sockaddr_t notifysrc6;
343 isc_sockaddr_t parentalsrc4;
344 isc_sockaddr_t parentalsrc6;
345 isc_sockaddr_t xfrsource4;
346 isc_sockaddr_t xfrsource6;
347 isc_sockaddr_t altxfrsource4;
348 isc_sockaddr_t altxfrsource6;
349 isc_sockaddr_t sourceaddr;
350 isc_dscp_t notifysrc4dscp;
351 isc_dscp_t notifysrc6dscp;
352 isc_dscp_t parentalsrc4dscp;
353 isc_dscp_t parentalsrc6dscp;
354 isc_dscp_t xfrsource4dscp;
355 isc_dscp_t xfrsource6dscp;
356 isc_dscp_t altxfrsource4dscp;
357 isc_dscp_t altxfrsource6dscp;
358 dns_xfrin_ctx_t *xfr; /* task locked */
359 dns_tsigkey_t *tsigkey; /* key used for xfr */
360 /* Access Control Lists */
361 dns_acl_t *update_acl;
362 dns_acl_t *forward_acl;
363 dns_acl_t *notify_acl;
364 dns_acl_t *query_acl;
365 dns_acl_t *queryon_acl;
366 dns_acl_t *xfr_acl;
367 bool update_disabled;
368 bool zero_no_soa_ttl;
369 dns_severity_t check_names;
370 ISC_LIST(dns_notify_t) notifies;
371 ISC_LIST(dns_checkds_t) checkds_requests;
372 dns_request_t *request;
373 dns_loadctx_t *lctx;
374 dns_io_t *readio;
375 dns_dumpctx_t *dctx;
376 dns_io_t *writeio;
377 uint32_t maxxfrin;
378 uint32_t maxxfrout;
379 uint32_t idlein;
380 uint32_t idleout;
381 isc_event_t ctlevent;
382 dns_ssutable_t *ssutable;
383 uint32_t sigvalidityinterval;
384 uint32_t keyvalidityinterval;
385 uint32_t sigresigninginterval;
386 dns_view_t *view;
387 dns_view_t *prev_view;
388 dns_kasp_t *kasp;
389 dns_checkmxfunc_t checkmx;
390 dns_checksrvfunc_t checksrv;
391 dns_checknsfunc_t checkns;
392 /*%
393 * Zones in certain states such as "waiting for zone transfer"
394 * or "zone transfer in progress" are kept on per-state linked lists
395 * in the zone manager using the 'statelink' field. The 'statelist'
396 * field points at the list the zone is currently on. It the zone
397 * is not on any such list, statelist is NULL.
398 */
399 ISC_LINK(dns_zone_t) statelink;
400 dns_zonelist_t *statelist;
401 /*%
402 * Statistics counters about zone management.
403 */
404 isc_stats_t *stats;
405 /*%
406 * Optional per-zone statistics counters. Counted outside of this
407 * module.
408 */
409 dns_zonestat_level_t statlevel;
410 bool requeststats_on;
411 isc_stats_t *requeststats;
412 dns_stats_t *rcvquerystats;
413 dns_stats_t *dnssecsignstats;
414 uint32_t notifydelay;
415 dns_isselffunc_t isself;
416 void *isselfarg;
417
418 char *strnamerd;
419 char *strname;
420 char *strrdclass;
421 char *strviewname;
422
423 /*%
424 * Serial number for deferred journal compaction.
425 */
426 uint32_t compact_serial;
427 /*%
428 * Keys that are signing the zone for the first time.
429 */
430 dns_signinglist_t signing;
431 dns_nsec3chainlist_t nsec3chain;
432 /*%
433 * List of outstanding NSEC3PARAM change requests.
434 */
435 isc_eventlist_t setnsec3param_queue;
436 /*%
437 * Signing / re-signing quantum stopping parameters.
438 */
439 uint32_t signatures;
440 uint32_t nodes;
441 dns_rdatatype_t privatetype;
442
443 /*%
444 * Autosigning/key-maintenance options
445 */
446 #ifdef __NetBSD__
447 atomic_uint_fast32_t keyopts;
448 #else
449 atomic_uint_fast64_t keyopts;
450 #endif
451
452 /*%
453 * True if added by "rndc addzone"
454 */
455 bool added;
456
457 /*%
458 * True if added by automatically by named.
459 */
460 bool automatic;
461
462 /*%
463 * response policy data to be relayed to the database
464 */
465 dns_rpz_zones_t *rpzs;
466 dns_rpz_num_t rpz_num;
467
468 /*%
469 * catalog zone data
470 */
471 dns_catz_zones_t *catzs;
472
473 /*%
474 * parent catalog zone
475 */
476 dns_catz_zone_t *parentcatz;
477
478 /*%
479 * Serial number update method.
480 */
481 dns_updatemethod_t updatemethod;
482
483 /*%
484 * whether ixfr is requested
485 */
486 bool requestixfr;
487 uint32_t ixfr_ratio;
488
489 /*%
490 * whether EDNS EXPIRE is requested
491 */
492 bool requestexpire;
493
494 /*%
495 * Outstanding forwarded UPDATE requests.
496 */
497 dns_forwardlist_t forwards;
498
499 dns_zone_t *raw;
500 dns_zone_t *secure;
501
502 bool sourceserialset;
503 uint32_t sourceserial;
504
505 /*%
506 * soa and maximum zone ttl
507 */
508 dns_ttl_t soattl;
509 dns_ttl_t maxttl;
510
511 /*
512 * Inline zone signing state.
513 */
514 dns_diff_t rss_diff;
515 isc_eventlist_t rss_events;
516 isc_eventlist_t rss_post;
517 dns_dbversion_t *rss_newver;
518 dns_dbversion_t *rss_oldver;
519 dns_db_t *rss_db;
520 dns_zone_t *rss_raw;
521 isc_event_t *rss_event;
522 dns_update_state_t *rss_state;
523
524 isc_stats_t *gluecachestats;
525 };
526
527 #define zonediff_init(z, d) \
528 do { \
529 dns__zonediff_t *_z = (z); \
530 (_z)->diff = (d); \
531 (_z)->offline = false; \
532 } while (0)
533
534 #define DNS_ZONE_FLAG(z, f) ((atomic_load_relaxed(&(z)->flags) & (f)) != 0)
535 #define DNS_ZONE_SETFLAG(z, f) atomic_fetch_or(&(z)->flags, (f))
536 #define DNS_ZONE_CLRFLAG(z, f) atomic_fetch_and(&(z)->flags, ~(f))
537 typedef enum {
538 DNS_ZONEFLG_REFRESH = 0x00000001U, /*%< refresh check in progress */
539 DNS_ZONEFLG_NEEDDUMP = 0x00000002U, /*%< zone need consolidation */
540 DNS_ZONEFLG_USEVC = 0x00000004U, /*%< use tcp for refresh query */
541 DNS_ZONEFLG_DUMPING = 0x00000008U, /*%< a dump is in progress */
542 DNS_ZONEFLG_HASINCLUDE = 0x00000010U, /*%< $INCLUDE in zone file */
543 DNS_ZONEFLG_LOADED = 0x00000020U, /*%< database has loaded */
544 DNS_ZONEFLG_EXITING = 0x00000040U, /*%< zone is being destroyed */
545 DNS_ZONEFLG_EXPIRED = 0x00000080U, /*%< zone has expired */
546 DNS_ZONEFLG_NEEDREFRESH = 0x00000100U, /*%< refresh check needed */
547 DNS_ZONEFLG_UPTODATE = 0x00000200U, /*%< zone contents are
548 * up-to-date */
549 DNS_ZONEFLG_NEEDNOTIFY = 0x00000400U, /*%< need to send out notify
550 * messages */
551 DNS_ZONEFLG_FIXJOURNAL = 0x00000800U, /*%< journal file had
552 * recoverable error,
553 * needs rewriting */
554 DNS_ZONEFLG_NOMASTERS = 0x00001000U, /*%< an attempt to refresh a
555 * zone with no primaries
556 * occurred */
557 DNS_ZONEFLG_LOADING = 0x00002000U, /*%< load from disk in progress*/
558 DNS_ZONEFLG_HAVETIMERS = 0x00004000U, /*%< timer values have been set
559 * from SOA (if not set, we
560 * are still using
561 * default timer values) */
562 DNS_ZONEFLG_FORCEXFER = 0x00008000U, /*%< Force a zone xfer */
563 DNS_ZONEFLG_NOREFRESH = 0x00010000U,
564 DNS_ZONEFLG_DIALNOTIFY = 0x00020000U,
565 DNS_ZONEFLG_DIALREFRESH = 0x00040000U,
566 DNS_ZONEFLG_SHUTDOWN = 0x00080000U,
567 DNS_ZONEFLG_NOIXFR = 0x00100000U, /*%< IXFR failed, force AXFR */
568 DNS_ZONEFLG_FLUSH = 0x00200000U,
569 DNS_ZONEFLG_NOEDNS = 0x00400000U,
570 DNS_ZONEFLG_USEALTXFRSRC = 0x00800000U,
571 DNS_ZONEFLG_SOABEFOREAXFR = 0x01000000U,
572 DNS_ZONEFLG_NEEDCOMPACT = 0x02000000U,
573 DNS_ZONEFLG_REFRESHING = 0x04000000U, /*%< Refreshing keydata */
574 DNS_ZONEFLG_THAW = 0x08000000U,
575 DNS_ZONEFLG_LOADPENDING = 0x10000000U, /*%< Loading scheduled */
576 DNS_ZONEFLG_NODELAY = 0x20000000U,
577 DNS_ZONEFLG_SENDSECURE = 0x40000000U,
578 DNS_ZONEFLG_NEEDSTARTUPNOTIFY = 0x80000000U, /*%< need to send out
579 * notify due to the zone
580 * just being loaded for
581 * the first time. */
582 #ifndef __NetBSD__
583 /*
584 * DO NOT add any new zone flags here until all platforms
585 * support 64-bit enum values. Currently they fail on
586 * Windows.
587 */
588 DNS_ZONEFLG___MAX = UINT64_MAX, /* trick to make the ENUM 64-bit wide */
589 #endif
590 } dns_zoneflg_t;
591
592 #define DNS_ZONE_OPTION(z, o) ((atomic_load_relaxed(&(z)->options) & (o)) != 0)
593 #define DNS_ZONE_SETOPTION(z, o) atomic_fetch_or(&(z)->options, (o))
594 #define DNS_ZONE_CLROPTION(z, o) atomic_fetch_and(&(z)->options, ~(o))
595
596 #define DNS_ZONEKEY_OPTION(z, o) \
597 ((atomic_load_relaxed(&(z)->keyopts) & (o)) != 0)
598 #define DNS_ZONEKEY_SETOPTION(z, o) atomic_fetch_or(&(z)->keyopts, (o))
599 #define DNS_ZONEKEY_CLROPTION(z, o) atomic_fetch_and(&(z)->keyopts, ~(o))
600
601 /* Flags for zone_load() */
602 typedef enum {
603 DNS_ZONELOADFLAG_NOSTAT = 0x00000001U, /* Do not stat() master files */
604 DNS_ZONELOADFLAG_THAW = 0x00000002U, /* Thaw the zone on successful
605 * load. */
606 } dns_zoneloadflag_t;
607
608 #define UNREACH_CACHE_SIZE 10U
609 #define UNREACH_HOLD_TIME 600 /* 10 minutes */
610
611 #define CHECK(op) \
612 do { \
613 result = (op); \
614 if (result != ISC_R_SUCCESS) \
615 goto failure; \
616 } while (0)
617
618 struct dns_unreachable {
619 isc_sockaddr_t remote;
620 isc_sockaddr_t local;
621 atomic_uint_fast32_t expire;
622 atomic_uint_fast32_t last;
623 uint32_t count;
624 };
625
626 struct dns_zonemgr {
627 unsigned int magic;
628 isc_mem_t *mctx;
629 isc_refcount_t refs;
630 isc_taskmgr_t *taskmgr;
631 isc_timermgr_t *timermgr;
632 isc_socketmgr_t *socketmgr;
633 isc_taskpool_t *zonetasks;
634 isc_taskpool_t *loadtasks;
635 isc_task_t *task;
636 isc_pool_t *mctxpool;
637 isc_ratelimiter_t *checkdsrl;
638 isc_ratelimiter_t *notifyrl;
639 isc_ratelimiter_t *refreshrl;
640 isc_ratelimiter_t *startupnotifyrl;
641 isc_ratelimiter_t *startuprefreshrl;
642 isc_rwlock_t rwlock;
643 isc_mutex_t iolock;
644 isc_rwlock_t urlock;
645
646 /* Locked by rwlock. */
647 dns_zonelist_t zones;
648 dns_zonelist_t waiting_for_xfrin;
649 dns_zonelist_t xfrin_in_progress;
650
651 /* Configuration data. */
652 uint32_t transfersin;
653 uint32_t transfersperns;
654 unsigned int checkdsrate;
655 unsigned int notifyrate;
656 unsigned int startupnotifyrate;
657 unsigned int serialqueryrate;
658 unsigned int startupserialqueryrate;
659
660 /* Locked by iolock */
661 uint32_t iolimit;
662 uint32_t ioactive;
663 dns_iolist_t high;
664 dns_iolist_t low;
665
666 /* Locked by urlock. */
667 /* LRU cache */
668 struct dns_unreachable unreachable[UNREACH_CACHE_SIZE];
669
670 dns_keymgmt_t *keymgmt;
671 };
672
673 /*%
674 * Hold notify state.
675 */
676 struct dns_notify {
677 unsigned int magic;
678 unsigned int flags;
679 isc_mem_t *mctx;
680 dns_zone_t *zone;
681 dns_adbfind_t *find;
682 dns_request_t *request;
683 dns_name_t ns;
684 isc_sockaddr_t dst;
685 dns_tsigkey_t *key;
686 isc_dscp_t dscp;
687 ISC_LINK(dns_notify_t) link;
688 isc_event_t *event;
689 };
690
691 #define DNS_NOTIFY_NOSOA 0x0001U
692 #define DNS_NOTIFY_STARTUP 0x0002U
693
694 /*%
695 * Hold checkds state.
696 */
697 struct dns_checkds {
698 unsigned int magic;
699 unsigned int flags;
700 isc_mem_t *mctx;
701 dns_zone_t *zone;
702 dns_request_t *request;
703 isc_sockaddr_t dst;
704 dns_tsigkey_t *key;
705 isc_dscp_t dscp;
706 ISC_LINK(dns_checkds_t) link;
707 isc_event_t *event;
708 };
709
710 /*%
711 * dns_stub holds state while performing a 'stub' transfer.
712 * 'db' is the zone's 'db' or a new one if this is the initial
713 * transfer.
714 */
715
716 struct dns_stub {
717 unsigned int magic;
718 isc_mem_t *mctx;
719 dns_zone_t *zone;
720 dns_db_t *db;
721 dns_dbversion_t *version;
722 atomic_uint_fast32_t pending_requests;
723 };
724
725 /*%
726 * Hold load state.
727 */
728 struct dns_load {
729 unsigned int magic;
730 isc_mem_t *mctx;
731 dns_zone_t *zone;
732 dns_db_t *db;
733 isc_time_t loadtime;
734 dns_rdatacallbacks_t callbacks;
735 };
736
737 /*%
738 * Hold forward state.
739 */
740 struct dns_forward {
741 unsigned int magic;
742 isc_mem_t *mctx;
743 dns_zone_t *zone;
744 isc_buffer_t *msgbuf;
745 dns_request_t *request;
746 uint32_t which;
747 isc_sockaddr_t addr;
748 dns_updatecallback_t callback;
749 void *callback_arg;
750 unsigned int options;
751 ISC_LINK(dns_forward_t) link;
752 };
753
754 /*%
755 * Hold IO request state.
756 */
757 struct dns_io {
758 unsigned int magic;
759 dns_zonemgr_t *zmgr;
760 bool high;
761 isc_task_t *task;
762 ISC_LINK(dns_io_t) link;
763 isc_event_t *event;
764 };
765
766 /*%
767 * Hold state for when we are signing a zone with a new
768 * DNSKEY as result of an update.
769 */
770 struct dns_signing {
771 unsigned int magic;
772 dns_db_t *db;
773 dns_dbiterator_t *dbiterator;
774 dns_secalg_t algorithm;
775 uint16_t keyid;
776 bool deleteit;
777 bool done;
778 ISC_LINK(dns_signing_t) link;
779 };
780
781 struct dns_nsec3chain {
782 unsigned int magic;
783 dns_db_t *db;
784 dns_dbiterator_t *dbiterator;
785 dns_rdata_nsec3param_t nsec3param;
786 unsigned char salt[255];
787 bool done;
788 bool seen_nsec;
789 bool delete_nsec;
790 bool save_delete_nsec;
791 ISC_LINK(dns_nsec3chain_t) link;
792 };
793
794 /*%<
795 * 'dbiterator' contains a iterator for the database. If we are creating
796 * a NSEC3 chain only the non-NSEC3 nodes will be iterated. If we are
797 * removing a NSEC3 chain then both NSEC3 and non-NSEC3 nodes will be
798 * iterated.
799 *
800 * 'nsec3param' contains the parameters of the NSEC3 chain being created
801 * or removed.
802 *
803 * 'salt' is buffer space and is referenced via 'nsec3param.salt'.
804 *
805 * 'seen_nsec' will be set to true if, while iterating the zone to create a
806 * NSEC3 chain, a NSEC record is seen.
807 *
808 * 'delete_nsec' will be set to true if, at the completion of the creation
809 * of a NSEC3 chain, 'seen_nsec' is true. If 'delete_nsec' is true then we
810 * are in the process of deleting the NSEC chain.
811 *
812 * 'save_delete_nsec' is used to store the initial state of 'delete_nsec'
813 * so it can be recovered in the event of a error.
814 */
815
816 struct dns_keyfetch {
817 isc_mem_t *mctx;
818 dns_fixedname_t name;
819 dns_rdataset_t keydataset;
820 dns_rdataset_t dnskeyset;
821 dns_rdataset_t dnskeysigset;
822 dns_zone_t *zone;
823 dns_db_t *db;
824 dns_fetch_t *fetch;
825 };
826
827 /*%
828 * Hold state for an asynchronous load
829 */
830 struct dns_asyncload {
831 dns_zone_t *zone;
832 unsigned int flags;
833 dns_zt_zoneloaded_t loaded;
834 void *loaded_arg;
835 };
836
837 /*%
838 * Reference to an include file encountered during loading
839 */
840 struct dns_include {
841 char *name;
842 isc_time_t filetime;
843 ISC_LINK(dns_include_t) link;
844 };
845
846 /*
847 * These can be overridden by the -T mkeytimers option on the command
848 * line, so that we can test with shorter periods than specified in
849 * RFC 5011.
850 */
851 #define HOUR 3600
852 #define DAY (24 * HOUR)
853 #define MONTH (30 * DAY)
854 LIBDNS_EXTERNAL_DATA unsigned int dns_zone_mkey_hour = HOUR;
855 LIBDNS_EXTERNAL_DATA unsigned int dns_zone_mkey_day = DAY;
856 LIBDNS_EXTERNAL_DATA unsigned int dns_zone_mkey_month = MONTH;
857
858 #define SEND_BUFFER_SIZE 2048
859
860 static void
861 zone_settimer(dns_zone_t *, isc_time_t *);
862 static void
863 cancel_refresh(dns_zone_t *);
864 static void
865 zone_debuglog(dns_zone_t *zone, const char *, int debuglevel, const char *msg,
866 ...) ISC_FORMAT_PRINTF(4, 5);
867 static void
868 notify_log(dns_zone_t *zone, int level, const char *fmt, ...)
869 ISC_FORMAT_PRINTF(3, 4);
870 static void
871 dnssec_log(dns_zone_t *zone, int level, const char *fmt, ...)
872 ISC_FORMAT_PRINTF(3, 4);
873 static void
874 queue_xfrin(dns_zone_t *zone);
875 static isc_result_t
876 update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
877 dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
878 dns_rdata_t *rdata);
879 static void
880 zone_unload(dns_zone_t *zone);
881 static void
882 zone_expire(dns_zone_t *zone);
883 static void
884 zone_iattach(dns_zone_t *source, dns_zone_t **target);
885 static void
886 zone_idetach(dns_zone_t **zonep);
887 static isc_result_t
888 zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump);
889 static void
890 zone_attachdb(dns_zone_t *zone, dns_db_t *db);
891 static void
892 zone_detachdb(dns_zone_t *zone);
893 static void
894 zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs);
895 static void
896 zone_catz_disable(dns_zone_t *zone);
897 static isc_result_t
898 default_journal(dns_zone_t *zone);
899 static void
900 zone_xfrdone(dns_zone_t *zone, isc_result_t result);
901 static isc_result_t
902 zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
903 isc_result_t result);
904 static void
905 zone_needdump(dns_zone_t *zone, unsigned int delay);
906 static void
907 zone_shutdown(isc_task_t *, isc_event_t *);
908 static void
909 zone_loaddone(void *arg, isc_result_t result);
910 static isc_result_t
911 zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime);
912 static void
913 zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length);
914 static void
915 zone_name_tostr(dns_zone_t *zone, char *buf, size_t length);
916 static void
917 zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length);
918 static void
919 zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length);
920 static isc_result_t
921 zone_send_secureserial(dns_zone_t *zone, uint32_t serial);
922 static void
923 refresh_callback(isc_task_t *, isc_event_t *);
924 static void
925 stub_callback(isc_task_t *, isc_event_t *);
926 static void
927 queue_soa_query(dns_zone_t *zone);
928 static void
929 soa_query(isc_task_t *, isc_event_t *);
930 static void
931 ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub);
932 static int
933 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type);
934 static void
935 checkds_cancel(dns_zone_t *zone);
936 static void
937 checkds_send(dns_zone_t *zone);
938 static isc_result_t
939 checkds_createmessage(dns_zone_t *zone, dns_message_t **messagep);
940 static void
941 checkds_done(isc_task_t *task, isc_event_t *event);
942 static void
943 checkds_send_toaddr(isc_task_t *task, isc_event_t *event);
944 static void
945 notify_cancel(dns_zone_t *zone);
946 static void
947 notify_find_address(dns_notify_t *notify);
948 static void
949 notify_send(dns_notify_t *notify);
950 static isc_result_t
951 notify_createmessage(dns_zone_t *zone, unsigned int flags,
952 dns_message_t **messagep);
953 static void
954 notify_done(isc_task_t *task, isc_event_t *event);
955 static void
956 notify_send_toaddr(isc_task_t *task, isc_event_t *event);
957 static isc_result_t
958 zone_dump(dns_zone_t *, bool);
959 static void
960 got_transfer_quota(isc_task_t *task, isc_event_t *event);
961 static isc_result_t
962 zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone);
963 static void
964 zmgr_resume_xfrs(dns_zonemgr_t *zmgr, bool multi);
965 static void
966 zonemgr_free(dns_zonemgr_t *zmgr);
967 static isc_result_t
968 zonemgr_getio(dns_zonemgr_t *zmgr, bool high, isc_task_t *task,
969 isc_taskaction_t action, void *arg, dns_io_t **iop);
970 static void
971 zonemgr_putio(dns_io_t **iop);
972 static void
973 zonemgr_cancelio(dns_io_t *io);
974 static void
975 rss_post(dns_zone_t *, isc_event_t *);
976
977 static isc_result_t
978 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
979 unsigned int *soacount, uint32_t *soattl, uint32_t *serial,
980 uint32_t *refresh, uint32_t *retry, uint32_t *expire,
981 uint32_t *minimum, unsigned int *errors);
982
983 static void
984 zone_freedbargs(dns_zone_t *zone);
985 static void
986 forward_callback(isc_task_t *task, isc_event_t *event);
987 static void
988 zone_saveunique(dns_zone_t *zone, const char *path, const char *templat);
989 static void
990 zone_maintenance(dns_zone_t *zone);
991 static void
992 zone_notify(dns_zone_t *zone, isc_time_t *now);
993 static void
994 dump_done(void *arg, isc_result_t result);
995 static isc_result_t
996 zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid,
997 bool deleteit);
998 static isc_result_t
999 delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
1000 dns_name_t *name, dns_diff_t *diff);
1001 static void
1002 zone_rekey(dns_zone_t *zone);
1003 static isc_result_t
1004 zone_send_securedb(dns_zone_t *zone, dns_db_t *db);
1005 static dns_ttl_t
1006 zone_nsecttl(dns_zone_t *zone);
1007 static void
1008 setrl(isc_ratelimiter_t *rl, unsigned int *rate, unsigned int value);
1009 static void
1010 zone_journal_compact(dns_zone_t *zone, dns_db_t *db, uint32_t serial);
1011 static isc_result_t
1012 zone_journal_rollforward(dns_zone_t *zone, dns_db_t *db, bool *needdump,
1013 bool *fixjournal);
1014
1015 #define ENTER zone_debuglog(zone, me, 1, "enter")
1016
1017 static const unsigned int dbargc_default = 1;
1018 static const char *dbargv_default[] = { "rbt" };
1019
1020 #define DNS_ZONE_JITTER_ADD(a, b, c) \
1021 do { \
1022 isc_interval_t _i; \
1023 uint32_t _j; \
1024 _j = (b)-isc_random_uniform((b) / 4); \
1025 isc_interval_set(&_i, _j, 0); \
1026 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
1027 dns_zone_log(zone, ISC_LOG_WARNING, \
1028 "epoch approaching: upgrade required: " \
1029 "now + %s failed", \
1030 #b); \
1031 isc_interval_set(&_i, _j / 2, 0); \
1032 (void)isc_time_add((a), &_i, (c)); \
1033 } \
1034 } while (0)
1035
1036 #define DNS_ZONE_TIME_ADD(a, b, c) \
1037 do { \
1038 isc_interval_t _i; \
1039 isc_interval_set(&_i, (b), 0); \
1040 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
1041 dns_zone_log(zone, ISC_LOG_WARNING, \
1042 "epoch approaching: upgrade required: " \
1043 "now + %s failed", \
1044 #b); \
1045 isc_interval_set(&_i, (b) / 2, 0); \
1046 (void)isc_time_add((a), &_i, (c)); \
1047 } \
1048 } while (0)
1049
1050 typedef struct nsec3param nsec3param_t;
1051 struct nsec3param {
1052 dns_rdata_nsec3param_t rdata;
1053 unsigned char data[DNS_NSEC3PARAM_BUFFERSIZE + 1];
1054 unsigned int length;
1055 bool nsec;
1056 bool replace;
1057 bool resalt;
1058 bool lookup;
1059 ISC_LINK(nsec3param_t) link;
1060 };
1061 typedef ISC_LIST(nsec3param_t) nsec3paramlist_t;
1062 struct np3event {
1063 isc_event_t event;
1064 nsec3param_t params;
1065 };
1066
1067 struct ssevent {
1068 isc_event_t event;
1069 uint32_t serial;
1070 };
1071
1072 struct stub_cb_args {
1073 dns_stub_t *stub;
1074 dns_tsigkey_t *tsig_key;
1075 isc_dscp_t dscp;
1076 uint16_t udpsize;
1077 int timeout;
1078 bool reqnsid;
1079 };
1080
1081 struct stub_glue_request {
1082 dns_request_t *request;
1083 dns_name_t name;
1084 struct stub_cb_args *args;
1085 bool ipv4;
1086 };
1087
1088 /*%
1089 * Increment resolver-related statistics counters. Zone must be locked.
1090 */
1091 static void
1092 inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
1093 if (zone->stats != NULL) {
1094 isc_stats_increment(zone->stats, counter);
1095 }
1096 }
1097
1098 /***
1099 *** Public functions.
1100 ***/
1101
1102 isc_result_t
1103 dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
1104 isc_result_t result;
1105 isc_time_t now;
1106 dns_zone_t *zone = NULL;
1107 dns_zone_t z = { .masterformat = dns_masterformat_none,
1108 .journalsize = -1,
1109 .rdclass = dns_rdataclass_none,
1110 .type = dns_zone_none,
1111 .refresh = DNS_ZONE_DEFAULTREFRESH,
1112 .retry = DNS_ZONE_DEFAULTRETRY,
1113 .maxrefresh = DNS_ZONE_MAXREFRESH,
1114 .minrefresh = DNS_ZONE_MINREFRESH,
1115 .maxretry = DNS_ZONE_MAXRETRY,
1116 .minretry = DNS_ZONE_MINRETRY,
1117 .notifytype = dns_notifytype_yes,
1118 .zero_no_soa_ttl = true,
1119 .check_names = dns_severity_ignore,
1120 .idlein = DNS_DEFAULT_IDLEIN,
1121 .idleout = DNS_DEFAULT_IDLEOUT,
1122 .notifysrc4dscp = -1,
1123 .notifysrc6dscp = -1,
1124 .parentalsrc4dscp = -1,
1125 .parentalsrc6dscp = -1,
1126 .xfrsource4dscp = -1,
1127 .xfrsource6dscp = -1,
1128 .altxfrsource4dscp = -1,
1129 .altxfrsource6dscp = -1,
1130 .maxxfrin = MAX_XFER_TIME,
1131 .maxxfrout = MAX_XFER_TIME,
1132 .sigvalidityinterval = 30 * 24 * 3600,
1133 .sigresigninginterval = 7 * 24 * 3600,
1134 .statlevel = dns_zonestat_none,
1135 .notifydelay = 5,
1136 .signatures = 10,
1137 .nodes = 100,
1138 .privatetype = (dns_rdatatype_t)0xffffU,
1139 .rpz_num = DNS_RPZ_INVALID_NUM,
1140 .requestixfr = true,
1141 .ixfr_ratio = 100,
1142 .requestexpire = true,
1143 .updatemethod = dns_updatemethod_increment,
1144 .magic = ZONE_MAGIC };
1145
1146 REQUIRE(zonep != NULL && *zonep == NULL);
1147 REQUIRE(mctx != NULL);
1148
1149 TIME_NOW(&now);
1150 zone = isc_mem_get(mctx, sizeof(*zone));
1151 *zone = z;
1152
1153 zone->mctx = NULL;
1154 isc_mem_attach(mctx, &zone->mctx);
1155 isc_mutex_init(&zone->lock);
1156 ZONEDB_INITLOCK(&zone->dblock);
1157 /* XXX MPA check that all elements are initialised */
1158 #ifdef DNS_ZONE_CHECKLOCK
1159 zone->locked = false;
1160 #endif /* ifdef DNS_ZONE_CHECKLOCK */
1161
1162 zone->notifytime = now;
1163
1164 ISC_LINK_INIT(zone, link);
1165 isc_refcount_init(&zone->erefs, 1);
1166 isc_refcount_init(&zone->irefs, 0);
1167 dns_name_init(&zone->origin, NULL);
1168 ISC_LIST_INIT(zone->includes);
1169 ISC_LIST_INIT(zone->newincludes);
1170 atomic_init(&zone->flags, 0);
1171 atomic_init(&zone->options, 0);
1172 atomic_init(&zone->keyopts, 0);
1173 isc_time_settoepoch(&zone->expiretime);
1174 isc_time_settoepoch(&zone->refreshtime);
1175 isc_time_settoepoch(&zone->dumptime);
1176 isc_time_settoepoch(&zone->loadtime);
1177 isc_time_settoepoch(&zone->resigntime);
1178 isc_time_settoepoch(&zone->keywarntime);
1179 isc_time_settoepoch(&zone->signingtime);
1180 isc_time_settoepoch(&zone->nsec3chaintime);
1181 isc_time_settoepoch(&zone->refreshkeytime);
1182 ISC_LIST_INIT(zone->notifies);
1183 ISC_LIST_INIT(zone->checkds_requests);
1184 isc_sockaddr_any(&zone->notifysrc4);
1185 isc_sockaddr_any6(&zone->notifysrc6);
1186 isc_sockaddr_any(&zone->parentalsrc4);
1187 isc_sockaddr_any6(&zone->parentalsrc6);
1188 isc_sockaddr_any(&zone->xfrsource4);
1189 isc_sockaddr_any6(&zone->xfrsource6);
1190 isc_sockaddr_any(&zone->altxfrsource4);
1191 isc_sockaddr_any6(&zone->altxfrsource6);
1192 ISC_LINK_INIT(zone, statelink);
1193 ISC_LIST_INIT(zone->signing);
1194 ISC_LIST_INIT(zone->nsec3chain);
1195 ISC_LIST_INIT(zone->setnsec3param_queue);
1196 ISC_LIST_INIT(zone->forwards);
1197 ISC_LIST_INIT(zone->rss_events);
1198 ISC_LIST_INIT(zone->rss_post);
1199
1200 result = isc_stats_create(mctx, &zone->gluecachestats,
1201 dns_gluecachestatscounter_max);
1202 if (result != ISC_R_SUCCESS) {
1203 goto free_refs;
1204 }
1205
1206 /* Must be after magic is set. */
1207 dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
1208
1209 ISC_EVENT_INIT(&zone->ctlevent, sizeof(zone->ctlevent), 0, NULL,
1210 DNS_EVENT_ZONECONTROL, zone_shutdown, zone, zone, NULL,
1211 NULL);
1212 *zonep = zone;
1213 return (ISC_R_SUCCESS);
1214
1215 free_refs:
1216 isc_refcount_decrement0(&zone->erefs);
1217 isc_refcount_destroy(&zone->erefs);
1218 isc_refcount_destroy(&zone->irefs);
1219 ZONEDB_DESTROYLOCK(&zone->dblock);
1220 isc_mutex_destroy(&zone->lock);
1221 isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
1222 return (result);
1223 }
1224
1225 static void
1226 clear_keylist(dns_dnsseckeylist_t *list, isc_mem_t *mctx) {
1227 dns_dnsseckey_t *key;
1228 while (!ISC_LIST_EMPTY(*list)) {
1229 key = ISC_LIST_HEAD(*list);
1230 ISC_LIST_UNLINK(*list, key, link);
1231 dns_dnsseckey_destroy(mctx, &key);
1232 }
1233 }
1234
1235 /*
1236 * Free a zone. Because we require that there be no more
1237 * outstanding events or references, no locking is necessary.
1238 */
1239 static void
1240 zone_free(dns_zone_t *zone) {
1241 dns_signing_t *signing;
1242 dns_nsec3chain_t *nsec3chain;
1243 isc_event_t *event;
1244 dns_include_t *include;
1245
1246 REQUIRE(DNS_ZONE_VALID(zone));
1247 isc_refcount_destroy(&zone->erefs);
1248 isc_refcount_destroy(&zone->irefs);
1249 REQUIRE(!LOCKED_ZONE(zone));
1250 REQUIRE(zone->timer == NULL);
1251 REQUIRE(zone->zmgr == NULL);
1252
1253 /*
1254 * Managed objects. Order is important.
1255 */
1256 if (zone->request != NULL) {
1257 dns_request_destroy(&zone->request); /* XXXMPA */
1258 }
1259 INSIST(zone->readio == NULL);
1260 INSIST(zone->statelist == NULL);
1261 INSIST(zone->writeio == NULL);
1262
1263 if (zone->task != NULL) {
1264 isc_task_detach(&zone->task);
1265 }
1266 if (zone->loadtask != NULL) {
1267 isc_task_detach(&zone->loadtask);
1268 }
1269 if (zone->view != NULL) {
1270 dns_view_weakdetach(&zone->view);
1271 }
1272 if (zone->prev_view != NULL) {
1273 dns_view_weakdetach(&zone->prev_view);
1274 }
1275
1276 /* Unmanaged objects */
1277 while (!ISC_LIST_EMPTY(zone->setnsec3param_queue)) {
1278 event = ISC_LIST_HEAD(zone->setnsec3param_queue);
1279 ISC_LIST_UNLINK(zone->setnsec3param_queue, event, ev_link);
1280 isc_event_free(&event);
1281 }
1282 while (!ISC_LIST_EMPTY(zone->rss_post)) {
1283 event = ISC_LIST_HEAD(zone->rss_post);
1284 ISC_LIST_UNLINK(zone->rss_post, event, ev_link);
1285 isc_event_free(&event);
1286 }
1287 for (signing = ISC_LIST_HEAD(zone->signing); signing != NULL;
1288 signing = ISC_LIST_HEAD(zone->signing))
1289 {
1290 ISC_LIST_UNLINK(zone->signing, signing, link);
1291 dns_db_detach(&signing->db);
1292 dns_dbiterator_destroy(&signing->dbiterator);
1293 isc_mem_put(zone->mctx, signing, sizeof *signing);
1294 }
1295 for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain); nsec3chain != NULL;
1296 nsec3chain = ISC_LIST_HEAD(zone->nsec3chain))
1297 {
1298 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
1299 dns_db_detach(&nsec3chain->db);
1300 dns_dbiterator_destroy(&nsec3chain->dbiterator);
1301 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
1302 }
1303 for (include = ISC_LIST_HEAD(zone->includes); include != NULL;
1304 include = ISC_LIST_HEAD(zone->includes))
1305 {
1306 ISC_LIST_UNLINK(zone->includes, include, link);
1307 isc_mem_free(zone->mctx, include->name);
1308 isc_mem_put(zone->mctx, include, sizeof *include);
1309 }
1310 for (include = ISC_LIST_HEAD(zone->newincludes); include != NULL;
1311 include = ISC_LIST_HEAD(zone->newincludes))
1312 {
1313 ISC_LIST_UNLINK(zone->newincludes, include, link);
1314 isc_mem_free(zone->mctx, include->name);
1315 isc_mem_put(zone->mctx, include, sizeof *include);
1316 }
1317 if (zone->masterfile != NULL) {
1318 isc_mem_free(zone->mctx, zone->masterfile);
1319 }
1320 zone->masterfile = NULL;
1321 if (zone->keydirectory != NULL) {
1322 isc_mem_free(zone->mctx, zone->keydirectory);
1323 }
1324 zone->keydirectory = NULL;
1325 if (zone->kasp != NULL) {
1326 dns_kasp_detach(&zone->kasp);
1327 }
1328 if (!ISC_LIST_EMPTY(zone->checkds_ok)) {
1329 clear_keylist(&zone->checkds_ok, zone->mctx);
1330 }
1331
1332 zone->journalsize = -1;
1333 if (zone->journal != NULL) {
1334 isc_mem_free(zone->mctx, zone->journal);
1335 }
1336 zone->journal = NULL;
1337 if (zone->stats != NULL) {
1338 isc_stats_detach(&zone->stats);
1339 }
1340 if (zone->requeststats != NULL) {
1341 isc_stats_detach(&zone->requeststats);
1342 }
1343 if (zone->rcvquerystats != NULL) {
1344 dns_stats_detach(&zone->rcvquerystats);
1345 }
1346 if (zone->dnssecsignstats != NULL) {
1347 dns_stats_detach(&zone->dnssecsignstats);
1348 }
1349 if (zone->db != NULL) {
1350 zone_detachdb(zone);
1351 }
1352 if (zone->rpzs != NULL) {
1353 REQUIRE(zone->rpz_num < zone->rpzs->p.num_zones);
1354 dns_rpz_detach_rpzs(&zone->rpzs);
1355 zone->rpz_num = DNS_RPZ_INVALID_NUM;
1356 }
1357 if (zone->catzs != NULL) {
1358 dns_catz_catzs_detach(&zone->catzs);
1359 }
1360 zone_freedbargs(zone);
1361
1362 RUNTIME_CHECK(dns_zone_setparentals(zone, NULL, NULL, 0) ==
1363 ISC_R_SUCCESS);
1364 RUNTIME_CHECK(dns_zone_setprimarieswithkeys(zone, NULL, NULL, 0) ==
1365 ISC_R_SUCCESS);
1366 RUNTIME_CHECK(dns_zone_setalsonotify(zone, NULL, 0) == ISC_R_SUCCESS);
1367 zone->check_names = dns_severity_ignore;
1368 if (zone->update_acl != NULL) {
1369 dns_acl_detach(&zone->update_acl);
1370 }
1371 if (zone->forward_acl != NULL) {
1372 dns_acl_detach(&zone->forward_acl);
1373 }
1374 if (zone->notify_acl != NULL) {
1375 dns_acl_detach(&zone->notify_acl);
1376 }
1377 if (zone->query_acl != NULL) {
1378 dns_acl_detach(&zone->query_acl);
1379 }
1380 if (zone->queryon_acl != NULL) {
1381 dns_acl_detach(&zone->queryon_acl);
1382 }
1383 if (zone->xfr_acl != NULL) {
1384 dns_acl_detach(&zone->xfr_acl);
1385 }
1386 if (dns_name_dynamic(&zone->origin)) {
1387 dns_name_free(&zone->origin, zone->mctx);
1388 }
1389 if (zone->strnamerd != NULL) {
1390 isc_mem_free(zone->mctx, zone->strnamerd);
1391 }
1392 if (zone->strname != NULL) {
1393 isc_mem_free(zone->mctx, zone->strname);
1394 }
1395 if (zone->strrdclass != NULL) {
1396 isc_mem_free(zone->mctx, zone->strrdclass);
1397 }
1398 if (zone->strviewname != NULL) {
1399 isc_mem_free(zone->mctx, zone->strviewname);
1400 }
1401 if (zone->ssutable != NULL) {
1402 dns_ssutable_detach(&zone->ssutable);
1403 }
1404 if (zone->gluecachestats != NULL) {
1405 isc_stats_detach(&zone->gluecachestats);
1406 }
1407
1408 /* last stuff */
1409 ZONEDB_DESTROYLOCK(&zone->dblock);
1410 isc_mutex_destroy(&zone->lock);
1411 zone->magic = 0;
1412 isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
1413 }
1414
1415 /*
1416 * Returns true iff this the signed side of an inline-signing zone.
1417 * Caller should hold zone lock.
1418 */
1419 static bool
1420 inline_secure(dns_zone_t *zone) {
1421 REQUIRE(DNS_ZONE_VALID(zone));
1422 if (zone->raw != NULL) {
1423 return (true);
1424 }
1425 return (false);
1426 }
1427
1428 /*
1429 * Returns true iff this the unsigned side of an inline-signing zone
1430 * Caller should hold zone lock.
1431 */
1432 static bool
1433 inline_raw(dns_zone_t *zone) {
1434 REQUIRE(DNS_ZONE_VALID(zone));
1435 if (zone->secure != NULL) {
1436 return (true);
1437 }
1438 return (false);
1439 }
1440
1441 /*
1442 * Single shot.
1443 */
1444 void
1445 dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
1446 char namebuf[1024];
1447
1448 REQUIRE(DNS_ZONE_VALID(zone));
1449 REQUIRE(rdclass != dns_rdataclass_none);
1450
1451 /*
1452 * Test and set.
1453 */
1454 LOCK_ZONE(zone);
1455 INSIST(zone != zone->raw);
1456 REQUIRE(zone->rdclass == dns_rdataclass_none ||
1457 zone->rdclass == rdclass);
1458 zone->rdclass = rdclass;
1459
1460 if (zone->strnamerd != NULL) {
1461 isc_mem_free(zone->mctx, zone->strnamerd);
1462 }
1463 if (zone->strrdclass != NULL) {
1464 isc_mem_free(zone->mctx, zone->strrdclass);
1465 }
1466
1467 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1468 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1469 zone_rdclass_tostr(zone, namebuf, sizeof namebuf);
1470 zone->strrdclass = isc_mem_strdup(zone->mctx, namebuf);
1471
1472 if (inline_secure(zone)) {
1473 dns_zone_setclass(zone->raw, rdclass);
1474 }
1475 UNLOCK_ZONE(zone);
1476 }
1477
1478 dns_rdataclass_t
1479 dns_zone_getclass(dns_zone_t *zone) {
1480 REQUIRE(DNS_ZONE_VALID(zone));
1481
1482 return (zone->rdclass);
1483 }
1484
1485 void
1486 dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
1487 REQUIRE(DNS_ZONE_VALID(zone));
1488
1489 LOCK_ZONE(zone);
1490 zone->notifytype = notifytype;
1491 UNLOCK_ZONE(zone);
1492 }
1493
1494 isc_result_t
1495 dns_zone_getserial(dns_zone_t *zone, uint32_t *serialp) {
1496 isc_result_t result;
1497 unsigned int soacount;
1498
1499 REQUIRE(DNS_ZONE_VALID(zone));
1500 REQUIRE(serialp != NULL);
1501
1502 LOCK_ZONE(zone);
1503 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1504 if (zone->db != NULL) {
1505 result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL,
1506 serialp, NULL, NULL, NULL, NULL,
1507 NULL);
1508 if (result == ISC_R_SUCCESS && soacount == 0) {
1509 result = ISC_R_FAILURE;
1510 }
1511 } else {
1512 result = DNS_R_NOTLOADED;
1513 }
1514 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1515 UNLOCK_ZONE(zone);
1516
1517 return (result);
1518 }
1519
1520 /*
1521 * Single shot.
1522 */
1523 void
1524 dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) {
1525 char namebuf[1024];
1526
1527 REQUIRE(DNS_ZONE_VALID(zone));
1528 REQUIRE(type != dns_zone_none);
1529
1530 /*
1531 * Test and set.
1532 */
1533 LOCK_ZONE(zone);
1534 REQUIRE(zone->type == dns_zone_none || zone->type == type);
1535 zone->type = type;
1536
1537 if (zone->strnamerd != NULL) {
1538 isc_mem_free(zone->mctx, zone->strnamerd);
1539 }
1540
1541 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1542 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1543 UNLOCK_ZONE(zone);
1544 }
1545
1546 static void
1547 zone_freedbargs(dns_zone_t *zone) {
1548 unsigned int i;
1549
1550 /* Free the old database argument list. */
1551 if (zone->db_argv != NULL) {
1552 for (i = 0; i < zone->db_argc; i++) {
1553 isc_mem_free(zone->mctx, zone->db_argv[i]);
1554 }
1555 isc_mem_put(zone->mctx, zone->db_argv,
1556 zone->db_argc * sizeof(*zone->db_argv));
1557 }
1558 zone->db_argc = 0;
1559 zone->db_argv = NULL;
1560 }
1561
1562 isc_result_t
1563 dns_zone_getdbtype(dns_zone_t *zone, char ***argv, isc_mem_t *mctx) {
1564 size_t size = 0;
1565 unsigned int i;
1566 isc_result_t result = ISC_R_SUCCESS;
1567 void *mem;
1568 char **tmp, *tmp2, *base;
1569
1570 REQUIRE(DNS_ZONE_VALID(zone));
1571 REQUIRE(argv != NULL && *argv == NULL);
1572
1573 LOCK_ZONE(zone);
1574 size = (zone->db_argc + 1) * sizeof(char *);
1575 for (i = 0; i < zone->db_argc; i++) {
1576 size += strlen(zone->db_argv[i]) + 1;
1577 }
1578 mem = isc_mem_allocate(mctx, size);
1579 {
1580 tmp = mem;
1581 tmp2 = mem;
1582 base = mem;
1583 tmp2 += (zone->db_argc + 1) * sizeof(char *);
1584 for (i = 0; i < zone->db_argc; i++) {
1585 *tmp++ = tmp2;
1586 strlcpy(tmp2, zone->db_argv[i], size - (tmp2 - base));
1587 tmp2 += strlen(tmp2) + 1;
1588 }
1589 *tmp = NULL;
1590 }
1591 UNLOCK_ZONE(zone);
1592 *argv = mem;
1593 return (result);
1594 }
1595
1596 void
1597 dns_zone_setdbtype(dns_zone_t *zone, unsigned int dbargc,
1598 const char *const *dbargv) {
1599 char **argv = NULL;
1600 unsigned int i;
1601
1602 REQUIRE(DNS_ZONE_VALID(zone));
1603 REQUIRE(dbargc >= 1);
1604 REQUIRE(dbargv != NULL);
1605
1606 LOCK_ZONE(zone);
1607
1608 /* Set up a new database argument list. */
1609 argv = isc_mem_get(zone->mctx, dbargc * sizeof(*argv));
1610 for (i = 0; i < dbargc; i++) {
1611 argv[i] = NULL;
1612 }
1613 for (i = 0; i < dbargc; i++) {
1614 argv[i] = isc_mem_strdup(zone->mctx, dbargv[i]);
1615 }
1616
1617 /* Free the old list. */
1618 zone_freedbargs(zone);
1619
1620 zone->db_argc = dbargc;
1621 zone->db_argv = argv;
1622
1623 UNLOCK_ZONE(zone);
1624 }
1625
1626 static void
1627 dns_zone_setview_helper(dns_zone_t *zone, dns_view_t *view) {
1628 char namebuf[1024];
1629
1630 if (zone->prev_view == NULL && zone->view != NULL) {
1631 dns_view_weakattach(zone->view, &zone->prev_view);
1632 }
1633
1634 INSIST(zone != zone->raw);
1635 if (zone->view != NULL) {
1636 dns_view_weakdetach(&zone->view);
1637 }
1638 dns_view_weakattach(view, &zone->view);
1639
1640 if (zone->strviewname != NULL) {
1641 isc_mem_free(zone->mctx, zone->strviewname);
1642 }
1643 if (zone->strnamerd != NULL) {
1644 isc_mem_free(zone->mctx, zone->strnamerd);
1645 }
1646
1647 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1648 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1649 zone_viewname_tostr(zone, namebuf, sizeof namebuf);
1650 zone->strviewname = isc_mem_strdup(zone->mctx, namebuf);
1651
1652 if (inline_secure(zone)) {
1653 dns_zone_setview(zone->raw, view);
1654 }
1655 }
1656
1657 void
1658 dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
1659 REQUIRE(DNS_ZONE_VALID(zone));
1660
1661 LOCK_ZONE(zone);
1662 dns_zone_setview_helper(zone, view);
1663 UNLOCK_ZONE(zone);
1664 }
1665
1666 dns_view_t *
1667 dns_zone_getview(dns_zone_t *zone) {
1668 REQUIRE(DNS_ZONE_VALID(zone));
1669
1670 return (zone->view);
1671 }
1672
1673 void
1674 dns_zone_setviewcommit(dns_zone_t *zone) {
1675 REQUIRE(DNS_ZONE_VALID(zone));
1676
1677 LOCK_ZONE(zone);
1678 if (zone->prev_view != NULL) {
1679 dns_view_weakdetach(&zone->prev_view);
1680 }
1681 if (inline_secure(zone)) {
1682 dns_zone_setviewcommit(zone->raw);
1683 }
1684 UNLOCK_ZONE(zone);
1685 }
1686
1687 void
1688 dns_zone_setviewrevert(dns_zone_t *zone) {
1689 REQUIRE(DNS_ZONE_VALID(zone));
1690
1691 LOCK_ZONE(zone);
1692 if (zone->prev_view != NULL) {
1693 dns_zone_setview_helper(zone, zone->prev_view);
1694 dns_view_weakdetach(&zone->prev_view);
1695 }
1696 if (zone->catzs != NULL) {
1697 zone_catz_enable(zone, zone->catzs);
1698 }
1699 if (inline_secure(zone)) {
1700 dns_zone_setviewrevert(zone->raw);
1701 }
1702 UNLOCK_ZONE(zone);
1703 }
1704
1705 isc_result_t
1706 dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
1707 isc_result_t result = ISC_R_SUCCESS;
1708 char namebuf[1024];
1709
1710 REQUIRE(DNS_ZONE_VALID(zone));
1711 REQUIRE(origin != NULL);
1712
1713 LOCK_ZONE(zone);
1714 INSIST(zone != zone->raw);
1715 if (dns_name_dynamic(&zone->origin)) {
1716 dns_name_free(&zone->origin, zone->mctx);
1717 dns_name_init(&zone->origin, NULL);
1718 }
1719 dns_name_dup(origin, zone->mctx, &zone->origin);
1720
1721 if (zone->strnamerd != NULL) {
1722 isc_mem_free(zone->mctx, zone->strnamerd);
1723 }
1724 if (zone->strname != NULL) {
1725 isc_mem_free(zone->mctx, zone->strname);
1726 }
1727
1728 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1729 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1730 zone_name_tostr(zone, namebuf, sizeof namebuf);
1731 zone->strname = isc_mem_strdup(zone->mctx, namebuf);
1732
1733 if (inline_secure(zone)) {
1734 result = dns_zone_setorigin(zone->raw, origin);
1735 }
1736 UNLOCK_ZONE(zone);
1737 return (result);
1738 }
1739
1740 static isc_result_t
1741 dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
1742 char *copy;
1743
1744 if (value != NULL) {
1745 copy = isc_mem_strdup(zone->mctx, value);
1746 } else {
1747 copy = NULL;
1748 }
1749
1750 if (*field != NULL) {
1751 isc_mem_free(zone->mctx, *field);
1752 }
1753
1754 *field = copy;
1755 return (ISC_R_SUCCESS);
1756 }
1757
1758 isc_result_t
1759 dns_zone_setfile(dns_zone_t *zone, const char *file, dns_masterformat_t format,
1760 const dns_master_style_t *style) {
1761 isc_result_t result = ISC_R_SUCCESS;
1762
1763 REQUIRE(DNS_ZONE_VALID(zone));
1764
1765 LOCK_ZONE(zone);
1766 result = dns_zone_setstring(zone, &zone->masterfile, file);
1767 if (result == ISC_R_SUCCESS) {
1768 zone->masterformat = format;
1769 if (format == dns_masterformat_text) {
1770 zone->masterstyle = style;
1771 }
1772 result = default_journal(zone);
1773 }
1774 UNLOCK_ZONE(zone);
1775
1776 return (result);
1777 }
1778
1779 const char *
1780 dns_zone_getfile(dns_zone_t *zone) {
1781 REQUIRE(DNS_ZONE_VALID(zone));
1782
1783 return (zone->masterfile);
1784 }
1785
1786 dns_ttl_t
1787 dns_zone_getmaxttl(dns_zone_t *zone) {
1788 REQUIRE(DNS_ZONE_VALID(zone));
1789
1790 return (zone->maxttl);
1791 }
1792
1793 void
1794 dns_zone_setmaxttl(dns_zone_t *zone, dns_ttl_t maxttl) {
1795 REQUIRE(DNS_ZONE_VALID(zone));
1796
1797 LOCK_ZONE(zone);
1798 if (maxttl != 0) {
1799 DNS_ZONE_SETOPTION(zone, DNS_ZONEOPT_CHECKTTL);
1800 } else {
1801 DNS_ZONE_CLROPTION(zone, DNS_ZONEOPT_CHECKTTL);
1802 }
1803 zone->maxttl = maxttl;
1804 UNLOCK_ZONE(zone);
1805
1806 return;
1807 }
1808
1809 static isc_result_t
1810 default_journal(dns_zone_t *zone) {
1811 isc_result_t result;
1812 char *journal;
1813
1814 REQUIRE(DNS_ZONE_VALID(zone));
1815 REQUIRE(LOCKED_ZONE(zone));
1816
1817 if (zone->masterfile != NULL) {
1818 /* Calculate string length including '\0'. */
1819 int len = strlen(zone->masterfile) + sizeof(".jnl");
1820 journal = isc_mem_allocate(zone->mctx, len);
1821 strlcpy(journal, zone->masterfile, len);
1822 strlcat(journal, ".jnl", len);
1823 } else {
1824 journal = NULL;
1825 }
1826 result = dns_zone_setstring(zone, &zone->journal, journal);
1827 if (journal != NULL) {
1828 isc_mem_free(zone->mctx, journal);
1829 }
1830 return (result);
1831 }
1832
1833 isc_result_t
1834 dns_zone_setjournal(dns_zone_t *zone, const char *myjournal) {
1835 isc_result_t result = ISC_R_SUCCESS;
1836
1837 REQUIRE(DNS_ZONE_VALID(zone));
1838
1839 LOCK_ZONE(zone);
1840 result = dns_zone_setstring(zone, &zone->journal, myjournal);
1841 UNLOCK_ZONE(zone);
1842
1843 return (result);
1844 }
1845
1846 char *
1847 dns_zone_getjournal(dns_zone_t *zone) {
1848 REQUIRE(DNS_ZONE_VALID(zone));
1849
1850 return (zone->journal);
1851 }
1852
1853 /*
1854 * Return true iff the zone is "dynamic", in the sense that the zone's
1855 * master file (if any) is written by the server, rather than being
1856 * updated manually and read by the server.
1857 *
1858 * This is true for slave zones, mirror zones, stub zones, key zones,
1859 * and zones that allow dynamic updates either by having an update
1860 * policy ("ssutable") or an "allow-update" ACL with a value other than
1861 * exactly "{ none; }".
1862 */
1863 bool
1864 dns_zone_isdynamic(dns_zone_t *zone, bool ignore_freeze) {
1865 REQUIRE(DNS_ZONE_VALID(zone));
1866
1867 if (zone->type == dns_zone_secondary || zone->type == dns_zone_mirror ||
1868 zone->type == dns_zone_stub || zone->type == dns_zone_key ||
1869 (zone->type == dns_zone_redirect && zone->masters != NULL))
1870 {
1871 return (true);
1872 }
1873
1874 /* Inline zones are always dynamic. */
1875 if (zone->type == dns_zone_primary && zone->raw != NULL) {
1876 return (true);
1877 }
1878
1879 /* If !ignore_freeze, we need check whether updates are disabled. */
1880 if (zone->type == dns_zone_primary &&
1881 (!zone->update_disabled || ignore_freeze) &&
1882 ((zone->ssutable != NULL) ||
1883 (zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl))))
1884 {
1885 return (true);
1886 }
1887
1888 return (false);
1889 }
1890
1891 /*
1892 * Set the response policy index and information for a zone.
1893 */
1894 isc_result_t
1895 dns_zone_rpz_enable(dns_zone_t *zone, dns_rpz_zones_t *rpzs,
1896 dns_rpz_num_t rpz_num) {
1897 /*
1898 * Only RBTDB zones can be used for response policy zones,
1899 * because only they have the code to create the summary data.
1900 * Only zones that are loaded instead of mmap()ed create the
1901 * summary data and so can be policy zones.
1902 */
1903 if (strcmp(zone->db_argv[0], "rbt") != 0 &&
1904 strcmp(zone->db_argv[0], "rbt64") != 0)
1905 {
1906 return (ISC_R_NOTIMPLEMENTED);
1907 }
1908 if (zone->masterformat == dns_masterformat_map) {
1909 return (ISC_R_NOTIMPLEMENTED);
1910 }
1911
1912 /*
1913 * This must happen only once or be redundant.
1914 */
1915 LOCK_ZONE(zone);
1916 if (zone->rpzs != NULL) {
1917 REQUIRE(zone->rpzs == rpzs && zone->rpz_num == rpz_num);
1918 } else {
1919 REQUIRE(zone->rpz_num == DNS_RPZ_INVALID_NUM);
1920 dns_rpz_attach_rpzs(rpzs, &zone->rpzs);
1921 zone->rpz_num = rpz_num;
1922 }
1923 rpzs->defined |= DNS_RPZ_ZBIT(rpz_num);
1924 UNLOCK_ZONE(zone);
1925
1926 return (ISC_R_SUCCESS);
1927 }
1928
1929 dns_rpz_num_t
1930 dns_zone_get_rpz_num(dns_zone_t *zone) {
1931 return (zone->rpz_num);
1932 }
1933
1934 /*
1935 * If a zone is a response policy zone, mark its new database.
1936 */
1937 void
1938 dns_zone_rpz_enable_db(dns_zone_t *zone, dns_db_t *db) {
1939 isc_result_t result;
1940 if (zone->rpz_num == DNS_RPZ_INVALID_NUM) {
1941 return;
1942 }
1943 REQUIRE(zone->rpzs != NULL);
1944 result = dns_db_updatenotify_register(db, dns_rpz_dbupdate_callback,
1945 zone->rpzs->zones[zone->rpz_num]);
1946 REQUIRE(result == ISC_R_SUCCESS);
1947 }
1948
1949 static void
1950 dns_zone_rpz_disable_db(dns_zone_t *zone, dns_db_t *db) {
1951 if (zone->rpz_num == DNS_RPZ_INVALID_NUM) {
1952 return;
1953 }
1954 REQUIRE(zone->rpzs != NULL);
1955 (void)dns_db_updatenotify_unregister(db, dns_rpz_dbupdate_callback,
1956 zone->rpzs->zones[zone->rpz_num]);
1957 }
1958
1959 /*
1960 * If a zone is a catalog zone, attach it to update notification in database.
1961 */
1962 void
1963 dns_zone_catz_enable_db(dns_zone_t *zone, dns_db_t *db) {
1964 REQUIRE(DNS_ZONE_VALID(zone));
1965 REQUIRE(db != NULL);
1966
1967 if (zone->catzs != NULL) {
1968 dns_db_updatenotify_register(db, dns_catz_dbupdate_callback,
1969 zone->catzs);
1970 }
1971 }
1972
1973 static void
1974 dns_zone_catz_disable_db(dns_zone_t *zone, dns_db_t *db) {
1975 REQUIRE(DNS_ZONE_VALID(zone));
1976 REQUIRE(db != NULL);
1977
1978 if (zone->catzs != NULL) {
1979 dns_db_updatenotify_unregister(db, dns_catz_dbupdate_callback,
1980 zone->catzs);
1981 }
1982 }
1983
1984 static void
1985 zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs) {
1986 REQUIRE(DNS_ZONE_VALID(zone));
1987 REQUIRE(catzs != NULL);
1988
1989 INSIST(zone->catzs == NULL || zone->catzs == catzs);
1990 dns_catz_catzs_set_view(catzs, zone->view);
1991 if (zone->catzs == NULL) {
1992 dns_catz_catzs_attach(catzs, &zone->catzs);
1993 }
1994 }
1995
1996 void
1997 dns_zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs) {
1998 REQUIRE(DNS_ZONE_VALID(zone));
1999
2000 LOCK_ZONE(zone);
2001 zone_catz_enable(zone, catzs);
2002 UNLOCK_ZONE(zone);
2003 }
2004
2005 static void
2006 zone_catz_disable(dns_zone_t *zone) {
2007 REQUIRE(DNS_ZONE_VALID(zone));
2008
2009 if (zone->catzs != NULL) {
2010 if (zone->db != NULL) {
2011 dns_zone_catz_disable_db(zone, zone->db);
2012 }
2013 dns_catz_catzs_detach(&zone->catzs);
2014 }
2015 }
2016
2017 void
2018 dns_zone_catz_disable(dns_zone_t *zone) {
2019 REQUIRE(DNS_ZONE_VALID(zone));
2020
2021 LOCK_ZONE(zone);
2022 zone_catz_disable(zone);
2023 UNLOCK_ZONE(zone);
2024 }
2025
2026 bool
2027 dns_zone_catz_is_enabled(dns_zone_t *zone) {
2028 REQUIRE(DNS_ZONE_VALID(zone));
2029
2030 return (zone->catzs != NULL);
2031 }
2032
2033 /*
2034 * Set catalog zone ownership of the zone
2035 */
2036 void
2037 dns_zone_set_parentcatz(dns_zone_t *zone, dns_catz_zone_t *catz) {
2038 REQUIRE(DNS_ZONE_VALID(zone));
2039 REQUIRE(catz != NULL);
2040 LOCK_ZONE(zone);
2041 INSIST(zone->parentcatz == NULL || zone->parentcatz == catz);
2042 zone->parentcatz = catz;
2043 UNLOCK_ZONE(zone);
2044 }
2045
2046 dns_catz_zone_t *
2047 dns_zone_get_parentcatz(const dns_zone_t *zone) {
2048 REQUIRE(DNS_ZONE_VALID(zone));
2049 return (zone->parentcatz);
2050 }
2051
2052 static bool
2053 zone_touched(dns_zone_t *zone) {
2054 isc_result_t result;
2055 isc_time_t modtime;
2056 dns_include_t *include;
2057
2058 REQUIRE(DNS_ZONE_VALID(zone));
2059
2060 result = isc_file_getmodtime(zone->masterfile, &modtime);
2061 if (result != ISC_R_SUCCESS ||
2062 isc_time_compare(&modtime, &zone->loadtime) > 0)
2063 {
2064 return (true);
2065 }
2066
2067 for (include = ISC_LIST_HEAD(zone->includes); include != NULL;
2068 include = ISC_LIST_NEXT(include, link))
2069 {
2070 result = isc_file_getmodtime(include->name, &modtime);
2071 if (result != ISC_R_SUCCESS ||
2072 isc_time_compare(&modtime, &include->filetime) > 0)
2073 {
2074 return (true);
2075 }
2076 }
2077
2078 return (false);
2079 }
2080
2081 /*
2082 * Note: when dealing with inline-signed zones, external callers will always
2083 * call zone_load() for the secure zone; zone_load() calls itself recursively
2084 * in order to load the raw zone.
2085 */
2086 static isc_result_t
2087 zone_load(dns_zone_t *zone, unsigned int flags, bool locked) {
2088 isc_result_t result;
2089 isc_time_t now;
2090 isc_time_t loadtime;
2091 dns_db_t *db = NULL;
2092 bool rbt, hasraw, is_dynamic;
2093
2094 REQUIRE(DNS_ZONE_VALID(zone));
2095
2096 if (!locked) {
2097 LOCK_ZONE(zone);
2098 }
2099
2100 INSIST(zone != zone->raw);
2101 hasraw = inline_secure(zone);
2102 if (hasraw) {
2103 /*
2104 * We are trying to load an inline-signed zone. First call
2105 * self recursively to try loading the raw version of the zone.
2106 * Assuming the raw zone file is readable, there are two
2107 * possibilities:
2108 *
2109 * a) the raw zone was not yet loaded and thus it will be
2110 * loaded now, synchronously; if this succeeds, a
2111 * subsequent attempt to load the signed zone file will
2112 * take place and thus zone_postload() will be called
2113 * twice: first for the raw zone and then for the secure
2114 * zone; the latter call will take care of syncing the raw
2115 * version with the secure version,
2116 *
2117 * b) the raw zone was already loaded and we are trying to
2118 * reload it, which will happen asynchronously; this means
2119 * zone_postload() will only be called for the raw zone
2120 * because "result" returned by the zone_load() call below
2121 * will not be ISC_R_SUCCESS but rather DNS_R_CONTINUE;
2122 * zone_postload() called for the raw zone will take care
2123 * of syncing the raw version with the secure version.
2124 */
2125 result = zone_load(zone->raw, flags, false);
2126 if (result != ISC_R_SUCCESS) {
2127 if (!locked) {
2128 UNLOCK_ZONE(zone);
2129 }
2130 return (result);
2131 }
2132 LOCK_ZONE(zone->raw);
2133 }
2134
2135 TIME_NOW(&now);
2136
2137 INSIST(zone->type != dns_zone_none);
2138
2139 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
2140 if ((flags & DNS_ZONELOADFLAG_THAW) != 0) {
2141 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
2142 }
2143 result = DNS_R_CONTINUE;
2144 goto cleanup;
2145 }
2146
2147 INSIST(zone->db_argc >= 1);
2148
2149 rbt = strcmp(zone->db_argv[0], "rbt") == 0 ||
2150 strcmp(zone->db_argv[0], "rbt64") == 0;
2151
2152 if (zone->db != NULL && zone->masterfile == NULL && rbt) {
2153 /*
2154 * The zone has no master file configured.
2155 */
2156 result = ISC_R_SUCCESS;
2157 goto cleanup;
2158 }
2159
2160 is_dynamic = dns_zone_isdynamic(zone, false);
2161 if (zone->db != NULL && is_dynamic) {
2162 /*
2163 * This is a slave, stub, or dynamically updated zone being
2164 * reloaded. Do nothing - the database we already
2165 * have is guaranteed to be up-to-date.
2166 */
2167 if (zone->type == dns_zone_primary && !hasraw) {
2168 result = DNS_R_DYNAMIC;
2169 } else {
2170 result = ISC_R_SUCCESS;
2171 }
2172 goto cleanup;
2173 }
2174
2175 /*
2176 * Store the current time before the zone is loaded, so that if the
2177 * file changes between the time of the load and the time that
2178 * zone->loadtime is set, then the file will still be reloaded
2179 * the next time dns_zone_load is called.
2180 */
2181 TIME_NOW(&loadtime);
2182
2183 /*
2184 * Don't do the load if the file that stores the zone is older
2185 * than the last time the zone was loaded. If the zone has not
2186 * been loaded yet, zone->loadtime will be the epoch.
2187 */
2188 if (zone->masterfile != NULL) {
2189 isc_time_t filetime;
2190
2191 /*
2192 * The file is already loaded. If we are just doing a
2193 * "rndc reconfig", we are done.
2194 */
2195 if (!isc_time_isepoch(&zone->loadtime) &&
2196 (flags & DNS_ZONELOADFLAG_NOSTAT) != 0)
2197 {
2198 result = ISC_R_SUCCESS;
2199 goto cleanup;
2200 }
2201
2202 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
2203 !zone_touched(zone))
2204 {
2205 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2206 ISC_LOG_DEBUG(1),
2207 "skipping load: master file "
2208 "older than last load");
2209 result = DNS_R_UPTODATE;
2210 goto cleanup;
2211 }
2212
2213 /*
2214 * If the file modification time is in the past
2215 * set loadtime to that value.
2216 */
2217 result = isc_file_getmodtime(zone->masterfile, &filetime);
2218 if (result == ISC_R_SUCCESS &&
2219 isc_time_compare(&loadtime, &filetime) > 0)
2220 {
2221 loadtime = filetime;
2222 }
2223 }
2224
2225 /*
2226 * Built in zones (with the exception of empty zones) don't need
2227 * to be reloaded.
2228 */
2229 if (zone->type == dns_zone_primary &&
2230 strcmp(zone->db_argv[0], "_builtin") == 0 &&
2231 (zone->db_argc < 2 || strcmp(zone->db_argv[1], "empty") != 0) &&
2232 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
2233 {
2234 result = ISC_R_SUCCESS;
2235 goto cleanup;
2236 }
2237
2238 /*
2239 * Zones associated with a DLZ don't need to be loaded either,
2240 * but we need to associate the database with the zone object.
2241 */
2242 if (strcmp(zone->db_argv[0], "dlz") == 0) {
2243 dns_dlzdb_t *dlzdb;
2244 dns_dlzfindzone_t findzone;
2245
2246 for (dlzdb = ISC_LIST_HEAD(zone->view->dlz_unsearched);
2247 dlzdb != NULL; dlzdb = ISC_LIST_NEXT(dlzdb, link))
2248 {
2249 INSIST(DNS_DLZ_VALID(dlzdb));
2250 if (strcmp(zone->db_argv[1], dlzdb->dlzname) == 0) {
2251 break;
2252 }
2253 }
2254
2255 if (dlzdb == NULL) {
2256 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2257 ISC_LOG_ERROR,
2258 "DLZ %s does not exist or is set "
2259 "to 'search yes;'",
2260 zone->db_argv[1]);
2261 result = ISC_R_NOTFOUND;
2262 goto cleanup;
2263 }
2264
2265 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
2266 /* ask SDLZ driver if the zone is supported */
2267 findzone = dlzdb->implementation->methods->findzone;
2268 result = (*findzone)(dlzdb->implementation->driverarg,
2269 dlzdb->dbdata, dlzdb->mctx,
2270 zone->view->rdclass, &zone->origin, NULL,
2271 NULL, &db);
2272 if (result != ISC_R_NOTFOUND) {
2273 if (zone->db != NULL) {
2274 zone_detachdb(zone);
2275 }
2276 zone_attachdb(zone, db);
2277 dns_db_detach(&db);
2278 result = ISC_R_SUCCESS;
2279 }
2280 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
2281
2282 if (result == ISC_R_SUCCESS) {
2283 if (dlzdb->configure_callback == NULL) {
2284 goto cleanup;
2285 }
2286
2287 result = (*dlzdb->configure_callback)(zone->view, dlzdb,
2288 zone);
2289 if (result != ISC_R_SUCCESS) {
2290 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2291 ISC_LOG_ERROR,
2292 "DLZ configuration callback: %s",
2293 isc_result_totext(result));
2294 }
2295 }
2296 goto cleanup;
2297 }
2298
2299 if ((zone->type == dns_zone_secondary ||
2300 zone->type == dns_zone_mirror || zone->type == dns_zone_stub ||
2301 (zone->type == dns_zone_redirect && zone->masters != NULL)) &&
2302 rbt)
2303 {
2304 if (zone->masterfile == NULL ||
2305 !isc_file_exists(zone->masterfile))
2306 {
2307 if (zone->masterfile != NULL) {
2308 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2309 ISC_LOG_DEBUG(1),
2310 "no master file");
2311 }
2312 zone->refreshtime = now;
2313 if (zone->task != NULL) {
2314 zone_settimer(zone, &now);
2315 }
2316 result = ISC_R_SUCCESS;
2317 goto cleanup;
2318 }
2319 }
2320
2321 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
2322 "starting load");
2323
2324 result = dns_db_create(zone->mctx, zone->db_argv[0], &zone->origin,
2325 (zone->type == dns_zone_stub) ? dns_dbtype_stub
2326 : dns_dbtype_zone,
2327 zone->rdclass, zone->db_argc - 1,
2328 zone->db_argv + 1, &db);
2329
2330 if (result != ISC_R_SUCCESS) {
2331 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
2332 "loading zone: creating database: %s",
2333 isc_result_totext(result));
2334 goto cleanup;
2335 }
2336 dns_db_settask(db, zone->task);
2337
2338 if (zone->type == dns_zone_primary ||
2339 zone->type == dns_zone_secondary || zone->type == dns_zone_mirror)
2340 {
2341 result = dns_db_setgluecachestats(db, zone->gluecachestats);
2342 if (result == ISC_R_NOTIMPLEMENTED) {
2343 result = ISC_R_SUCCESS;
2344 }
2345 if (result != ISC_R_SUCCESS) {
2346 goto cleanup;
2347 }
2348 }
2349
2350 if (!dns_db_ispersistent(db)) {
2351 if (zone->masterfile != NULL) {
2352 result = zone_startload(db, zone, loadtime);
2353 } else {
2354 result = DNS_R_NOMASTERFILE;
2355 if (zone->type == dns_zone_primary ||
2356 (zone->type == dns_zone_redirect &&
2357 zone->masters == NULL))
2358 {
2359 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2360 ISC_LOG_ERROR,
2361 "loading zone: "
2362 "no master file configured");
2363 goto cleanup;
2364 }
2365 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2366 ISC_LOG_INFO,
2367 "loading zone: "
2368 "no master file configured: continuing");
2369 }
2370 }
2371
2372 if (result == DNS_R_CONTINUE) {
2373 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING);
2374 if ((flags & DNS_ZONELOADFLAG_THAW) != 0) {
2375 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
2376 }
2377 goto cleanup;
2378 }
2379
2380 result = zone_postload(zone, db, loadtime, result);
2381
2382 cleanup:
2383 if (hasraw) {
2384 UNLOCK_ZONE(zone->raw);
2385 }
2386 if (!locked) {
2387 UNLOCK_ZONE(zone);
2388 }
2389 if (db != NULL) {
2390 dns_db_detach(&db);
2391 }
2392 return (result);
2393 }
2394
2395 isc_result_t
2396 dns_zone_load(dns_zone_t *zone, bool newonly) {
2397 return (zone_load(zone, newonly ? DNS_ZONELOADFLAG_NOSTAT : 0, false));
2398 }
2399
2400 static void
2401 zone_asyncload(isc_task_t *task, isc_event_t *event) {
2402 dns_asyncload_t *asl = event->ev_arg;
2403 dns_zone_t *zone = asl->zone;
2404 isc_result_t result;
2405
2406 UNUSED(task);
2407
2408 REQUIRE(DNS_ZONE_VALID(zone));
2409
2410 isc_event_free(&event);
2411
2412 LOCK_ZONE(zone);
2413 result = zone_load(zone, asl->flags, true);
2414 if (result != DNS_R_CONTINUE) {
2415 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
2416 }
2417 UNLOCK_ZONE(zone);
2418
2419 /* Inform the zone table we've finished loading */
2420 if (asl->loaded != NULL) {
2421 (asl->loaded)(asl->loaded_arg, zone, task);
2422 }
2423
2424 isc_mem_put(zone->mctx, asl, sizeof(*asl));
2425 dns_zone_idetach(&zone);
2426 }
2427
2428 isc_result_t
2429 dns_zone_asyncload(dns_zone_t *zone, bool newonly, dns_zt_zoneloaded_t done,
2430 void *arg) {
2431 isc_event_t *e;
2432 dns_asyncload_t *asl = NULL;
2433
2434 REQUIRE(DNS_ZONE_VALID(zone));
2435
2436 if (zone->zmgr == NULL) {
2437 return (ISC_R_FAILURE);
2438 }
2439
2440 /* If we already have a load pending, stop now */
2441 LOCK_ZONE(zone);
2442 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING)) {
2443 UNLOCK_ZONE(zone);
2444 return (ISC_R_ALREADYRUNNING);
2445 }
2446
2447 asl = isc_mem_get(zone->mctx, sizeof(*asl));
2448
2449 asl->zone = NULL;
2450 asl->flags = newonly ? DNS_ZONELOADFLAG_NOSTAT : 0;
2451 asl->loaded = done;
2452 asl->loaded_arg = arg;
2453
2454 e = isc_event_allocate(zone->zmgr->mctx, zone->zmgr, DNS_EVENT_ZONELOAD,
2455 zone_asyncload, asl, sizeof(isc_event_t));
2456
2457 zone_iattach(zone, &asl->zone);
2458 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADPENDING);
2459 isc_task_send(zone->loadtask, &e);
2460 UNLOCK_ZONE(zone);
2461
2462 return (ISC_R_SUCCESS);
2463 }
2464
2465 bool
2466 dns__zone_loadpending(dns_zone_t *zone) {
2467 REQUIRE(DNS_ZONE_VALID(zone));
2468
2469 return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING));
2470 }
2471
2472 isc_result_t
2473 dns_zone_loadandthaw(dns_zone_t *zone) {
2474 isc_result_t result;
2475
2476 if (inline_raw(zone)) {
2477 result = zone_load(zone->secure, DNS_ZONELOADFLAG_THAW, false);
2478 } else {
2479 /*
2480 * When thawing a zone, we don't know what changes
2481 * have been made. If we do DNSSEC maintenance on this
2482 * zone, schedule a full sign for this zone.
2483 */
2484 if (zone->type == dns_zone_primary &&
2485 DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
2486 {
2487 DNS_ZONEKEY_SETOPTION(zone, DNS_ZONEKEY_FULLSIGN);
2488 }
2489 result = zone_load(zone, DNS_ZONELOADFLAG_THAW, false);
2490 }
2491
2492 switch (result) {
2493 case DNS_R_CONTINUE:
2494 /* Deferred thaw. */
2495 break;
2496 case DNS_R_UPTODATE:
2497 case ISC_R_SUCCESS:
2498 case DNS_R_SEENINCLUDE:
2499 zone->update_disabled = false;
2500 break;
2501 case DNS_R_NOMASTERFILE:
2502 zone->update_disabled = false;
2503 break;
2504 default:
2505 /* Error, remain in disabled state. */
2506 break;
2507 }
2508 return (result);
2509 }
2510
2511 static unsigned int
2512 get_master_options(dns_zone_t *zone) {
2513 unsigned int options;
2514
2515 options = DNS_MASTER_ZONE | DNS_MASTER_RESIGN;
2516 if (zone->type == dns_zone_secondary || zone->type == dns_zone_mirror ||
2517 (zone->type == dns_zone_redirect && zone->masters == NULL))
2518 {
2519 options |= DNS_MASTER_SLAVE;
2520 }
2521 if (zone->type == dns_zone_key) {
2522 options |= DNS_MASTER_KEY;
2523 }
2524 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS)) {
2525 options |= DNS_MASTER_CHECKNS;
2526 }
2527 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS)) {
2528 options |= DNS_MASTER_FATALNS;
2529 }
2530 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES)) {
2531 options |= DNS_MASTER_CHECKNAMES;
2532 }
2533 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) {
2534 options |= DNS_MASTER_CHECKNAMESFAIL;
2535 }
2536 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMX)) {
2537 options |= DNS_MASTER_CHECKMX;
2538 }
2539 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL)) {
2540 options |= DNS_MASTER_CHECKMXFAIL;
2541 }
2542 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKWILDCARD)) {
2543 options |= DNS_MASTER_CHECKWILDCARD;
2544 }
2545 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKTTL)) {
2546 options |= DNS_MASTER_CHECKTTL;
2547 }
2548
2549 return (options);
2550 }
2551
2552 static void
2553 zone_registerinclude(const char *filename, void *arg) {
2554 isc_result_t result;
2555 dns_zone_t *zone = (dns_zone_t *)arg;
2556 dns_include_t *inc = NULL;
2557
2558 REQUIRE(DNS_ZONE_VALID(zone));
2559
2560 if (filename == NULL) {
2561 return;
2562 }
2563
2564 /*
2565 * Suppress duplicates.
2566 */
2567 for (inc = ISC_LIST_HEAD(zone->newincludes); inc != NULL;
2568 inc = ISC_LIST_NEXT(inc, link))
2569 {
2570 if (strcmp(filename, inc->name) == 0) {
2571 return;
2572 }
2573 }
2574
2575 inc = isc_mem_get(zone->mctx, sizeof(dns_include_t));
2576 inc->name = isc_mem_strdup(zone->mctx, filename);
2577 ISC_LINK_INIT(inc, link);
2578
2579 result = isc_file_getmodtime(filename, &inc->filetime);
2580 if (result != ISC_R_SUCCESS) {
2581 isc_time_settoepoch(&inc->filetime);
2582 }
2583
2584 ISC_LIST_APPEND(zone->newincludes, inc, link);
2585 }
2586
2587 static void
2588 zone_gotreadhandle(isc_task_t *task, isc_event_t *event) {
2589 dns_load_t *load = event->ev_arg;
2590 isc_result_t result = ISC_R_SUCCESS;
2591 unsigned int options;
2592
2593 REQUIRE(DNS_LOAD_VALID(load));
2594
2595 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) {
2596 result = ISC_R_CANCELED;
2597 }
2598 isc_event_free(&event);
2599 if (result == ISC_R_CANCELED) {
2600 goto fail;
2601 }
2602
2603 options = get_master_options(load->zone);
2604
2605 result = dns_master_loadfileinc(
2606 load->zone->masterfile, dns_db_origin(load->db),
2607 dns_db_origin(load->db), load->zone->rdclass, options, 0,
2608 &load->callbacks, task, zone_loaddone, load, &load->zone->lctx,
2609 zone_registerinclude, load->zone, load->zone->mctx,
2610 load->zone->masterformat, load->zone->maxttl);
2611 if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE &&
2612 result != DNS_R_SEENINCLUDE)
2613 {
2614 goto fail;
2615 }
2616 return;
2617
2618 fail:
2619 zone_loaddone(load, result);
2620 }
2621
2622 static void
2623 get_raw_serial(dns_zone_t *raw, dns_masterrawheader_t *rawdata) {
2624 isc_result_t result;
2625 unsigned int soacount;
2626
2627 LOCK(&raw->lock);
2628 if (raw->db != NULL) {
2629 result = zone_get_from_db(raw, raw->db, NULL, &soacount, NULL,
2630 &rawdata->sourceserial, NULL, NULL,
2631 NULL, NULL, NULL);
2632 if (result == ISC_R_SUCCESS && soacount > 0U) {
2633 rawdata->flags |= DNS_MASTERRAW_SOURCESERIALSET;
2634 }
2635 }
2636 UNLOCK(&raw->lock);
2637 }
2638
2639 static void
2640 zone_gotwritehandle(isc_task_t *task, isc_event_t *event) {
2641 const char me[] = "zone_gotwritehandle";
2642 dns_zone_t *zone = event->ev_arg;
2643 isc_result_t result = ISC_R_SUCCESS;
2644 dns_dbversion_t *version = NULL;
2645 dns_masterrawheader_t rawdata;
2646 dns_db_t *db = NULL;
2647
2648 REQUIRE(DNS_ZONE_VALID(zone));
2649 INSIST(task == zone->task);
2650 ENTER;
2651
2652 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) {
2653 result = ISC_R_CANCELED;
2654 }
2655 isc_event_free(&event);
2656 if (result == ISC_R_CANCELED) {
2657 goto fail;
2658 }
2659
2660 LOCK_ZONE(zone);
2661 INSIST(zone != zone->raw);
2662 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
2663 if (zone->db != NULL) {
2664 dns_db_attach(zone->db, &db);
2665 }
2666 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
2667 if (db != NULL) {
2668 const dns_master_style_t *output_style;
2669 dns_db_currentversion(db, &version);
2670 dns_master_initrawheader(&rawdata);
2671 if (inline_secure(zone)) {
2672 get_raw_serial(zone->raw, &rawdata);
2673 }
2674 if (zone->type == dns_zone_key) {
2675 output_style = &dns_master_style_keyzone;
2676 } else if (zone->masterstyle != NULL) {
2677 output_style = zone->masterstyle;
2678 } else {
2679 output_style = &dns_master_style_default;
2680 }
2681 result = dns_master_dumpasync(
2682 zone->mctx, db, version, output_style, zone->masterfile,
2683 zone->task, dump_done, zone, &zone->dctx,
2684 zone->masterformat, &rawdata);
2685 dns_db_closeversion(db, &version, false);
2686 } else {
2687 result = ISC_R_CANCELED;
2688 }
2689 if (db != NULL) {
2690 dns_db_detach(&db);
2691 }
2692 UNLOCK_ZONE(zone);
2693 if (result != DNS_R_CONTINUE) {
2694 goto fail;
2695 }
2696 return;
2697
2698 fail:
2699 dump_done(zone, result);
2700 }
2701
2702 /*
2703 * Save the raw serial number for inline-signing zones.
2704 * (XXX: Other information from the header will be used
2705 * for other purposes in the future, but for now this is
2706 * all we're interested in.)
2707 */
2708 static void
2709 zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
2710 if ((header->flags & DNS_MASTERRAW_SOURCESERIALSET) == 0) {
2711 return;
2712 }
2713
2714 zone->sourceserial = header->sourceserial;
2715 zone->sourceserialset = true;
2716 }
2717
2718 void
2719 dns_zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
2720 if (zone == NULL) {
2721 return;
2722 }
2723
2724 LOCK_ZONE(zone);
2725 zone_setrawdata(zone, header);
2726 UNLOCK_ZONE(zone);
2727 }
2728
2729 static isc_result_t
2730 zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
2731 const char me[] = "zone_startload";
2732 dns_load_t *load;
2733 isc_result_t result;
2734 isc_result_t tresult;
2735 unsigned int options;
2736
2737 ENTER;
2738
2739 dns_zone_rpz_enable_db(zone, db);
2740 dns_zone_catz_enable_db(zone, db);
2741
2742 options = get_master_options(zone);
2743 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS)) {
2744 options |= DNS_MASTER_MANYERRORS;
2745 }
2746
2747 if (zone->zmgr != NULL && zone->db != NULL && zone->loadtask != NULL) {
2748 load = isc_mem_get(zone->mctx, sizeof(*load));
2749
2750 load->mctx = NULL;
2751 load->zone = NULL;
2752 load->db = NULL;
2753 load->loadtime = loadtime;
2754 load->magic = LOAD_MAGIC;
2755
2756 isc_mem_attach(zone->mctx, &load->mctx);
2757 zone_iattach(zone, &load->zone);
2758 dns_db_attach(db, &load->db);
2759 dns_rdatacallbacks_init(&load->callbacks);
2760 load->callbacks.rawdata = zone_setrawdata;
2761 zone_iattach(zone, &load->callbacks.zone);
2762 result = dns_db_beginload(db, &load->callbacks);
2763 if (result != ISC_R_SUCCESS) {
2764 goto cleanup;
2765 }
2766 result = zonemgr_getio(zone->zmgr, true, zone->loadtask,
2767 zone_gotreadhandle, load, &zone->readio);
2768 if (result != ISC_R_SUCCESS) {
2769 /*
2770 * We can't report multiple errors so ignore
2771 * the result of dns_db_endload().
2772 */
2773 (void)dns_db_endload(load->db, &load->callbacks);
2774 goto cleanup;
2775 } else {
2776 result = DNS_R_CONTINUE;
2777 }
2778 } else {
2779 dns_rdatacallbacks_t callbacks;
2780
2781 dns_rdatacallbacks_init(&callbacks);
2782 callbacks.rawdata = zone_setrawdata;
2783 zone_iattach(zone, &callbacks.zone);
2784 result = dns_db_beginload(db, &callbacks);
2785 if (result != ISC_R_SUCCESS) {
2786 zone_idetach(&callbacks.zone);
2787 return (result);
2788 }
2789 result = dns_master_loadfile(
2790 zone->masterfile, &zone->origin, &zone->origin,
2791 zone->rdclass, options, 0, &callbacks,
2792 zone_registerinclude, zone, zone->mctx,
2793 zone->masterformat, zone->maxttl);
2794 tresult = dns_db_endload(db, &callbacks);
2795 if (result == ISC_R_SUCCESS) {
2796 result = tresult;
2797 }
2798 zone_idetach(&callbacks.zone);
2799 }
2800
2801 return (result);
2802
2803 cleanup:
2804 load->magic = 0;
2805 dns_db_detach(&load->db);
2806 zone_idetach(&load->zone);
2807 zone_idetach(&load->callbacks.zone);
2808 isc_mem_detach(&load->mctx);
2809 isc_mem_put(zone->mctx, load, sizeof(*load));
2810 return (result);
2811 }
2812
2813 static bool
2814 zone_check_mx(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2815 dns_name_t *owner) {
2816 isc_result_t result;
2817 char ownerbuf[DNS_NAME_FORMATSIZE];
2818 char namebuf[DNS_NAME_FORMATSIZE];
2819 char altbuf[DNS_NAME_FORMATSIZE];
2820 dns_fixedname_t fixed;
2821 dns_name_t *foundname;
2822 int level;
2823
2824 /*
2825 * "." means the services does not exist.
2826 */
2827 if (dns_name_equal(name, dns_rootname)) {
2828 return (true);
2829 }
2830
2831 /*
2832 * Outside of zone.
2833 */
2834 if (!dns_name_issubdomain(name, &zone->origin)) {
2835 if (zone->checkmx != NULL) {
2836 return ((zone->checkmx)(zone, name, owner));
2837 }
2838 return (true);
2839 }
2840
2841 if (zone->type == dns_zone_primary) {
2842 level = ISC_LOG_ERROR;
2843 } else {
2844 level = ISC_LOG_WARNING;
2845 }
2846
2847 foundname = dns_fixedname_initname(&fixed);
2848
2849 result = dns_db_find(db, name, NULL, dns_rdatatype_a, 0, 0, NULL,
2850 foundname, NULL, NULL);
2851 if (result == ISC_R_SUCCESS) {
2852 return (true);
2853 }
2854
2855 if (result == DNS_R_NXRRSET) {
2856 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa, 0, 0,
2857 NULL, foundname, NULL, NULL);
2858 if (result == ISC_R_SUCCESS) {
2859 return (true);
2860 }
2861 }
2862
2863 dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2864 dns_name_format(name, namebuf, sizeof namebuf);
2865 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2866 result == DNS_R_EMPTYNAME)
2867 {
2868 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL)) {
2869 level = ISC_LOG_WARNING;
2870 }
2871 dns_zone_log(zone, level,
2872 "%s/MX '%s' has no address records (A or AAAA)",
2873 ownerbuf, namebuf);
2874 return ((level == ISC_LOG_WARNING) ? true : false);
2875 }
2876
2877 if (result == DNS_R_CNAME) {
2878 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
2879 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2880 {
2881 level = ISC_LOG_WARNING;
2882 }
2883 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
2884 dns_zone_log(zone, level,
2885 "%s/MX '%s' is a CNAME (illegal)",
2886 ownerbuf, namebuf);
2887 }
2888 return ((level == ISC_LOG_WARNING) ? true : false);
2889 }
2890
2891 if (result == DNS_R_DNAME) {
2892 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
2893 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2894 {
2895 level = ISC_LOG_WARNING;
2896 }
2897 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
2898 dns_name_format(foundname, altbuf, sizeof altbuf);
2899 dns_zone_log(zone, level,
2900 "%s/MX '%s' is below a DNAME"
2901 " '%s' (illegal)",
2902 ownerbuf, namebuf, altbuf);
2903 }
2904 return ((level == ISC_LOG_WARNING) ? true : false);
2905 }
2906
2907 if (zone->checkmx != NULL && result == DNS_R_DELEGATION) {
2908 return ((zone->checkmx)(zone, name, owner));
2909 }
2910
2911 return (true);
2912 }
2913
2914 static bool
2915 zone_check_srv(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2916 dns_name_t *owner) {
2917 isc_result_t result;
2918 char ownerbuf[DNS_NAME_FORMATSIZE];
2919 char namebuf[DNS_NAME_FORMATSIZE];
2920 char altbuf[DNS_NAME_FORMATSIZE];
2921 dns_fixedname_t fixed;
2922 dns_name_t *foundname;
2923 int level;
2924
2925 /*
2926 * "." means the services does not exist.
2927 */
2928 if (dns_name_equal(name, dns_rootname)) {
2929 return (true);
2930 }
2931
2932 /*
2933 * Outside of zone.
2934 */
2935 if (!dns_name_issubdomain(name, &zone->origin)) {
2936 if (zone->checksrv != NULL) {
2937 return ((zone->checksrv)(zone, name, owner));
2938 }
2939 return (true);
2940 }
2941
2942 if (zone->type == dns_zone_primary) {
2943 level = ISC_LOG_ERROR;
2944 } else {
2945 level = ISC_LOG_WARNING;
2946 }
2947
2948 foundname = dns_fixedname_initname(&fixed);
2949
2950 result = dns_db_find(db, name, NULL, dns_rdatatype_a, 0, 0, NULL,
2951 foundname, NULL, NULL);
2952 if (result == ISC_R_SUCCESS) {
2953 return (true);
2954 }
2955
2956 if (result == DNS_R_NXRRSET) {
2957 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa, 0, 0,
2958 NULL, foundname, NULL, NULL);
2959 if (result == ISC_R_SUCCESS) {
2960 return (true);
2961 }
2962 }
2963
2964 dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2965 dns_name_format(name, namebuf, sizeof namebuf);
2966 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2967 result == DNS_R_EMPTYNAME)
2968 {
2969 dns_zone_log(zone, level,
2970 "%s/SRV '%s' has no address records (A or AAAA)",
2971 ownerbuf, namebuf);
2972 /* XXX950 make fatal for 9.5.0. */
2973 return (true);
2974 }
2975
2976 if (result == DNS_R_CNAME) {
2977 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
2978 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2979 {
2980 level = ISC_LOG_WARNING;
2981 }
2982 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
2983 dns_zone_log(zone, level,
2984 "%s/SRV '%s' is a CNAME (illegal)",
2985 ownerbuf, namebuf);
2986 }
2987 return ((level == ISC_LOG_WARNING) ? true : false);
2988 }
2989
2990 if (result == DNS_R_DNAME) {
2991 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
2992 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2993 {
2994 level = ISC_LOG_WARNING;
2995 }
2996 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
2997 dns_name_format(foundname, altbuf, sizeof altbuf);
2998 dns_zone_log(zone, level,
2999 "%s/SRV '%s' is below a "
3000 "DNAME '%s' (illegal)",
3001 ownerbuf, namebuf, altbuf);
3002 }
3003 return ((level == ISC_LOG_WARNING) ? true : false);
3004 }
3005
3006 if (zone->checksrv != NULL && result == DNS_R_DELEGATION) {
3007 return ((zone->checksrv)(zone, name, owner));
3008 }
3009
3010 return (true);
3011 }
3012
3013 static bool
3014 zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
3015 dns_name_t *owner) {
3016 bool answer = true;
3017 isc_result_t result, tresult;
3018 char ownerbuf[DNS_NAME_FORMATSIZE];
3019 char namebuf[DNS_NAME_FORMATSIZE];
3020 char altbuf[DNS_NAME_FORMATSIZE];
3021 dns_fixedname_t fixed;
3022 dns_name_t *foundname;
3023 dns_rdataset_t a;
3024 dns_rdataset_t aaaa;
3025 int level;
3026
3027 /*
3028 * Outside of zone.
3029 */
3030 if (!dns_name_issubdomain(name, &zone->origin)) {
3031 if (zone->checkns != NULL) {
3032 return ((zone->checkns)(zone, name, owner, NULL, NULL));
3033 }
3034 return (true);
3035 }
3036
3037 if (zone->type == dns_zone_primary) {
3038 level = ISC_LOG_ERROR;
3039 } else {
3040 level = ISC_LOG_WARNING;
3041 }
3042
3043 foundname = dns_fixedname_initname(&fixed);
3044 dns_rdataset_init(&a);
3045 dns_rdataset_init(&aaaa);
3046
3047 /*
3048 * Perform a regular lookup to catch DNAME records then look
3049 * for glue.
3050 */
3051 result = dns_db_find(db, name, NULL, dns_rdatatype_a, 0, 0, NULL,
3052 foundname, &a, NULL);
3053 switch (result) {
3054 case ISC_R_SUCCESS:
3055 case DNS_R_DNAME:
3056 case DNS_R_CNAME:
3057 break;
3058 default:
3059 if (dns_rdataset_isassociated(&a)) {
3060 dns_rdataset_disassociate(&a);
3061 }
3062 result = dns_db_find(db, name, NULL, dns_rdatatype_a,
3063 DNS_DBFIND_GLUEOK, 0, NULL, foundname, &a,
3064 NULL);
3065 }
3066 if (result == ISC_R_SUCCESS) {
3067 dns_rdataset_disassociate(&a);
3068 return (true);
3069 } else if (result == DNS_R_DELEGATION) {
3070 dns_rdataset_disassociate(&a);
3071 }
3072
3073 if (result == DNS_R_NXRRSET || result == DNS_R_DELEGATION ||
3074 result == DNS_R_GLUE)
3075 {
3076 tresult = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
3077 DNS_DBFIND_GLUEOK, 0, NULL, foundname,
3078 &aaaa, NULL);
3079 if (tresult == ISC_R_SUCCESS) {
3080 if (dns_rdataset_isassociated(&a)) {
3081 dns_rdataset_disassociate(&a);
3082 }
3083 dns_rdataset_disassociate(&aaaa);
3084 return (true);
3085 }
3086 if (tresult == DNS_R_DELEGATION || tresult == DNS_R_DNAME) {
3087 dns_rdataset_disassociate(&aaaa);
3088 }
3089 if (result == DNS_R_GLUE || tresult == DNS_R_GLUE) {
3090 /*
3091 * Check glue against child zone.
3092 */
3093 if (zone->checkns != NULL) {
3094 answer = (zone->checkns)(zone, name, owner, &a,
3095 &aaaa);
3096 }
3097 if (dns_rdataset_isassociated(&a)) {
3098 dns_rdataset_disassociate(&a);
3099 }
3100 if (dns_rdataset_isassociated(&aaaa)) {
3101 dns_rdataset_disassociate(&aaaa);
3102 }
3103 return (answer);
3104 }
3105 }
3106
3107 dns_name_format(owner, ownerbuf, sizeof ownerbuf);
3108 dns_name_format(name, namebuf, sizeof namebuf);
3109 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
3110 result == DNS_R_EMPTYNAME || result == DNS_R_DELEGATION)
3111 {
3112 const char *what;
3113 bool required = false;
3114 if (dns_name_issubdomain(name, owner)) {
3115 what = "REQUIRED GLUE ";
3116 required = true;
3117 } else if (result == DNS_R_DELEGATION) {
3118 what = "SIBLING GLUE ";
3119 } else {
3120 what = "";
3121 }
3122
3123 if (result != DNS_R_DELEGATION || required ||
3124 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSIBLING))
3125 {
3126 dns_zone_log(zone, level,
3127 "%s/NS '%s' has no %s"
3128 "address records (A or AAAA)",
3129 ownerbuf, namebuf, what);
3130 /*
3131 * Log missing address record.
3132 */
3133 if (result == DNS_R_DELEGATION && zone->checkns != NULL)
3134 {
3135 (void)(zone->checkns)(zone, name, owner, &a,
3136 &aaaa);
3137 }
3138 /* XXX950 make fatal for 9.5.0. */
3139 /* answer = false; */
3140 }
3141 } else if (result == DNS_R_CNAME) {
3142 dns_zone_log(zone, level, "%s/NS '%s' is a CNAME (illegal)",
3143 ownerbuf, namebuf);
3144 /* XXX950 make fatal for 9.5.0. */
3145 /* answer = false; */
3146 } else if (result == DNS_R_DNAME) {
3147 dns_name_format(foundname, altbuf, sizeof altbuf);
3148 dns_zone_log(zone, level,
3149 "%s/NS '%s' is below a DNAME '%s' (illegal)",
3150 ownerbuf, namebuf, altbuf);
3151 /* XXX950 make fatal for 9.5.0. */
3152 /* answer = false; */
3153 }
3154
3155 if (dns_rdataset_isassociated(&a)) {
3156 dns_rdataset_disassociate(&a);
3157 }
3158 if (dns_rdataset_isassociated(&aaaa)) {
3159 dns_rdataset_disassociate(&aaaa);
3160 }
3161 return (answer);
3162 }
3163
3164 static bool
3165 zone_rrset_check_dup(dns_zone_t *zone, dns_name_t *owner,
3166 dns_rdataset_t *rdataset) {
3167 dns_rdataset_t tmprdataset;
3168 isc_result_t result;
3169 bool answer = true;
3170 bool format = true;
3171 int level = ISC_LOG_WARNING;
3172 char ownerbuf[DNS_NAME_FORMATSIZE];
3173 char typebuf[DNS_RDATATYPE_FORMATSIZE];
3174 unsigned int count1 = 0;
3175
3176 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRRFAIL)) {
3177 level = ISC_LOG_ERROR;
3178 }
3179
3180 dns_rdataset_init(&tmprdataset);
3181 for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
3182 result = dns_rdataset_next(rdataset))
3183 {
3184 dns_rdata_t rdata1 = DNS_RDATA_INIT;
3185 unsigned int count2 = 0;
3186
3187 count1++;
3188 dns_rdataset_current(rdataset, &rdata1);
3189 dns_rdataset_clone(rdataset, &tmprdataset);
3190 for (result = dns_rdataset_first(&tmprdataset);
3191 result == ISC_R_SUCCESS;
3192 result = dns_rdataset_next(&tmprdataset))
3193 {
3194 dns_rdata_t rdata2 = DNS_RDATA_INIT;
3195 count2++;
3196 if (count1 >= count2) {
3197 continue;
3198 }
3199 dns_rdataset_current(&tmprdataset, &rdata2);
3200 if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) {
3201 if (format) {
3202 dns_name_format(owner, ownerbuf,
3203 sizeof ownerbuf);
3204 dns_rdatatype_format(rdata1.type,
3205 typebuf,
3206 sizeof(typebuf));
3207 format = false;
3208 }
3209 dns_zone_log(zone, level,
3210 "%s/%s has "
3211 "semantically identical records",
3212 ownerbuf, typebuf);
3213 if (level == ISC_LOG_ERROR) {
3214 answer = false;
3215 }
3216 break;
3217 }
3218 }
3219 dns_rdataset_disassociate(&tmprdataset);
3220 if (!format) {
3221 break;
3222 }
3223 }
3224 return (answer);
3225 }
3226
3227 static bool
3228 zone_check_dup(dns_zone_t *zone, dns_db_t *db) {
3229 dns_dbiterator_t *dbiterator = NULL;
3230 dns_dbnode_t *node = NULL;
3231 dns_fixedname_t fixed;
3232 dns_name_t *name;
3233 dns_rdataset_t rdataset;
3234 dns_rdatasetiter_t *rdsit = NULL;
3235 bool ok = true;
3236 isc_result_t result;
3237
3238 name = dns_fixedname_initname(&fixed);
3239 dns_rdataset_init(&rdataset);
3240
3241 result = dns_db_createiterator(db, 0, &dbiterator);
3242 if (result != ISC_R_SUCCESS) {
3243 return (true);
3244 }
3245
3246 for (result = dns_dbiterator_first(dbiterator); result == ISC_R_SUCCESS;
3247 result = dns_dbiterator_next(dbiterator))
3248 {
3249 result = dns_dbiterator_current(dbiterator, &node, name);
3250 if (result != ISC_R_SUCCESS) {
3251 continue;
3252 }
3253
3254 result = dns_db_allrdatasets(db, node, NULL, 0, 0, &rdsit);
3255 if (result != ISC_R_SUCCESS) {
3256 continue;
3257 }
3258
3259 for (result = dns_rdatasetiter_first(rdsit);
3260 result == ISC_R_SUCCESS;
3261 result = dns_rdatasetiter_next(rdsit))
3262 {
3263 dns_rdatasetiter_current(rdsit, &rdataset);
3264 if (!zone_rrset_check_dup(zone, name, &rdataset)) {
3265 ok = false;
3266 }
3267 dns_rdataset_disassociate(&rdataset);
3268 }
3269 dns_rdatasetiter_destroy(&rdsit);
3270 dns_db_detachnode(db, &node);
3271 }
3272
3273 if (node != NULL) {
3274 dns_db_detachnode(db, &node);
3275 }
3276 dns_dbiterator_destroy(&dbiterator);
3277
3278 return (ok);
3279 }
3280
3281 static bool
3282 isspf(const dns_rdata_t *rdata) {
3283 char buf[1024];
3284 const unsigned char *data = rdata->data;
3285 unsigned int rdl = rdata->length, i = 0, tl, len;
3286
3287 while (rdl > 0U) {
3288 len = tl = *data;
3289 ++data;
3290 --rdl;
3291 INSIST(tl <= rdl);
3292 if (len > sizeof(buf) - i - 1) {
3293 len = sizeof(buf) - i - 1;
3294 }
3295 memmove(buf + i, data, len);
3296 i += len;
3297 data += tl;
3298 rdl -= tl;
3299 }
3300
3301 if (i < 6U) {
3302 return (false);
3303 }
3304
3305 buf[i] = 0;
3306 if (strncmp(buf, "v=spf1", 6) == 0 && (buf[6] == 0 || buf[6] == ' ')) {
3307 return (true);
3308 }
3309 return (false);
3310 }
3311
3312 static bool
3313 integrity_checks(dns_zone_t *zone, dns_db_t *db) {
3314 dns_dbiterator_t *dbiterator = NULL;
3315 dns_dbnode_t *node = NULL;
3316 dns_rdataset_t rdataset;
3317 dns_fixedname_t fixed;
3318 dns_fixedname_t fixedbottom;
3319 dns_rdata_mx_t mx;
3320 dns_rdata_ns_t ns;
3321 dns_rdata_in_srv_t srv;
3322 dns_rdata_t rdata;
3323 dns_name_t *name;
3324 dns_name_t *bottom;
3325 isc_result_t result;
3326 bool ok = true, have_spf, have_txt;
3327
3328 name = dns_fixedname_initname(&fixed);
3329 bottom = dns_fixedname_initname(&fixedbottom);
3330 dns_rdataset_init(&rdataset);
3331 dns_rdata_init(&rdata);
3332
3333 result = dns_db_createiterator(db, 0, &dbiterator);
3334 if (result != ISC_R_SUCCESS) {
3335 return (true);
3336 }
3337
3338 result = dns_dbiterator_first(dbiterator);
3339 while (result == ISC_R_SUCCESS) {
3340 result = dns_dbiterator_current(dbiterator, &node, name);
3341 if (result != ISC_R_SUCCESS) {
3342 goto cleanup;
3343 }
3344
3345 /*
3346 * Is this name visible in the zone?
3347 */
3348 if (!dns_name_issubdomain(name, &zone->origin) ||
3349 (dns_name_countlabels(bottom) > 0 &&
3350 dns_name_issubdomain(name, bottom)))
3351 {
3352 goto next;
3353 }
3354
3355 dns_dbiterator_pause(dbiterator);
3356
3357 /*
3358 * Don't check the NS records at the origin.
3359 */
3360 if (dns_name_equal(name, &zone->origin)) {
3361 goto checkfordname;
3362 }
3363
3364 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ns,
3365 0, 0, &rdataset, NULL);
3366 if (result != ISC_R_SUCCESS) {
3367 goto checkfordname;
3368 }
3369 /*
3370 * Remember bottom of zone due to NS.
3371 */
3372 dns_name_copynf(name, bottom);
3373
3374 result = dns_rdataset_first(&rdataset);
3375 while (result == ISC_R_SUCCESS) {
3376 dns_rdataset_current(&rdataset, &rdata);
3377 result = dns_rdata_tostruct(&rdata, &ns, NULL);
3378 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3379 if (!zone_check_glue(zone, db, &ns.name, name)) {
3380 ok = false;
3381 }
3382 dns_rdata_reset(&rdata);
3383 result = dns_rdataset_next(&rdataset);
3384 }
3385 dns_rdataset_disassociate(&rdataset);
3386 goto next;
3387
3388 checkfordname:
3389 result = dns_db_findrdataset(db, node, NULL,
3390 dns_rdatatype_dname, 0, 0,
3391 &rdataset, NULL);
3392 if (result == ISC_R_SUCCESS) {
3393 /*
3394 * Remember bottom of zone due to DNAME.
3395 */
3396 dns_name_copynf(name, bottom);
3397 dns_rdataset_disassociate(&rdataset);
3398 }
3399
3400 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_mx,
3401 0, 0, &rdataset, NULL);
3402 if (result != ISC_R_SUCCESS) {
3403 goto checksrv;
3404 }
3405 result = dns_rdataset_first(&rdataset);
3406 while (result == ISC_R_SUCCESS) {
3407 dns_rdataset_current(&rdataset, &rdata);
3408 result = dns_rdata_tostruct(&rdata, &mx, NULL);
3409 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3410 if (!zone_check_mx(zone, db, &mx.mx, name)) {
3411 ok = false;
3412 }
3413 dns_rdata_reset(&rdata);
3414 result = dns_rdataset_next(&rdataset);
3415 }
3416 dns_rdataset_disassociate(&rdataset);
3417
3418 checksrv:
3419 if (zone->rdclass != dns_rdataclass_in) {
3420 goto next;
3421 }
3422 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_srv,
3423 0, 0, &rdataset, NULL);
3424 if (result != ISC_R_SUCCESS) {
3425 goto checkspf;
3426 }
3427 result = dns_rdataset_first(&rdataset);
3428 while (result == ISC_R_SUCCESS) {
3429 dns_rdataset_current(&rdataset, &rdata);
3430 result = dns_rdata_tostruct(&rdata, &srv, NULL);
3431 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3432 if (!zone_check_srv(zone, db, &srv.target, name)) {
3433 ok = false;
3434 }
3435 dns_rdata_reset(&rdata);
3436 result = dns_rdataset_next(&rdataset);
3437 }
3438 dns_rdataset_disassociate(&rdataset);
3439
3440 checkspf:
3441 /*
3442 * Check if there is a type SPF record without an
3443 * SPF-formatted type TXT record also being present.
3444 */
3445 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSPF)) {
3446 goto next;
3447 }
3448 if (zone->rdclass != dns_rdataclass_in) {
3449 goto next;
3450 }
3451 have_spf = have_txt = false;
3452 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_spf,
3453 0, 0, &rdataset, NULL);
3454 if (result == ISC_R_SUCCESS) {
3455 dns_rdataset_disassociate(&rdataset);
3456 have_spf = true;
3457 }
3458 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_txt,
3459 0, 0, &rdataset, NULL);
3460 if (result != ISC_R_SUCCESS) {
3461 goto notxt;
3462 }
3463 result = dns_rdataset_first(&rdataset);
3464 while (result == ISC_R_SUCCESS) {
3465 dns_rdataset_current(&rdataset, &rdata);
3466 have_txt = isspf(&rdata);
3467 dns_rdata_reset(&rdata);
3468 if (have_txt) {
3469 break;
3470 }
3471 result = dns_rdataset_next(&rdataset);
3472 }
3473 dns_rdataset_disassociate(&rdataset);
3474
3475 notxt:
3476 if (have_spf && !have_txt) {
3477 char namebuf[DNS_NAME_FORMATSIZE];
3478
3479 dns_name_format(name, namebuf, sizeof(namebuf));
3480 dns_zone_log(zone, ISC_LOG_WARNING,
3481 "'%s' found type "
3482 "SPF record but no SPF TXT record found, "
3483 "add matching type TXT record",
3484 namebuf);
3485 }
3486
3487 next:
3488 dns_db_detachnode(db, &node);
3489 result = dns_dbiterator_next(dbiterator);
3490 }
3491
3492 cleanup:
3493 if (node != NULL) {
3494 dns_db_detachnode(db, &node);
3495 }
3496 dns_dbiterator_destroy(&dbiterator);
3497
3498 return (ok);
3499 }
3500
3501 /*
3502 * OpenSSL verification of RSA keys with exponent 3 is known to be
3503 * broken prior OpenSSL 0.9.8c/0.9.7k. Look for such keys and warn
3504 * if they are in use.
3505 */
3506 static void
3507 zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
3508 dns_dbnode_t *node = NULL;
3509 dns_dbversion_t *version = NULL;
3510 dns_rdata_dnskey_t dnskey;
3511 dns_rdata_t rdata = DNS_RDATA_INIT;
3512 dns_rdataset_t rdataset;
3513 isc_result_t result;
3514
3515 result = dns_db_findnode(db, &zone->origin, false, &node);
3516 if (result != ISC_R_SUCCESS) {
3517 goto cleanup;
3518 }
3519
3520 dns_db_currentversion(db, &version);
3521 dns_rdataset_init(&rdataset);
3522 result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
3523 dns_rdatatype_none, 0, &rdataset, NULL);
3524 if (result != ISC_R_SUCCESS) {
3525 goto cleanup;
3526 }
3527
3528 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
3529 result = dns_rdataset_next(&rdataset))
3530 {
3531 dns_rdataset_current(&rdataset, &rdata);
3532 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
3533 INSIST(result == ISC_R_SUCCESS);
3534
3535 /*
3536 * RFC 3110, section 4: Performance Considerations:
3537 *
3538 * A public exponent of 3 minimizes the effort needed to verify
3539 * a signature. Use of 3 as the public exponent is weak for
3540 * confidentiality uses since, if the same data can be collected
3541 * encrypted under three different keys with an exponent of 3
3542 * then, using the Chinese Remainder Theorem [NETSEC], the
3543 * original plain text can be easily recovered. If a key is
3544 * known to be used only for authentication, as is the case with
3545 * DNSSEC, then an exponent of 3 is acceptable. However other
3546 * applications in the future may wish to leverage DNS
3547 * distributed keys for applications that do require
3548 * confidentiality. For keys which might have such other uses,
3549 * a more conservative choice would be 65537 (F4, the fourth
3550 * fermat number).
3551 */
3552 if (dnskey.datalen > 1 && dnskey.data[0] == 1 &&
3553 dnskey.data[1] == 3 &&
3554 (dnskey.algorithm == DNS_KEYALG_RSAMD5 ||
3555 dnskey.algorithm == DNS_KEYALG_RSASHA1 ||
3556 dnskey.algorithm == DNS_KEYALG_NSEC3RSASHA1 ||
3557 dnskey.algorithm == DNS_KEYALG_RSASHA256 ||
3558 dnskey.algorithm == DNS_KEYALG_RSASHA512))
3559 {
3560 char algorithm[DNS_SECALG_FORMATSIZE];
3561 isc_region_t r;
3562
3563 dns_rdata_toregion(&rdata, &r);
3564 dns_secalg_format(dnskey.algorithm, algorithm,
3565 sizeof(algorithm));
3566
3567 dnssec_log(zone, ISC_LOG_WARNING,
3568 "weak %s (%u) key found (exponent=3, id=%u)",
3569 algorithm, dnskey.algorithm,
3570 dst_region_computeid(&r));
3571 }
3572 dns_rdata_reset(&rdata);
3573 }
3574 dns_rdataset_disassociate(&rdataset);
3575
3576 cleanup:
3577 if (node != NULL) {
3578 dns_db_detachnode(db, &node);
3579 }
3580 if (version != NULL) {
3581 dns_db_closeversion(db, &version, false);
3582 }
3583 }
3584
3585 static void
3586 resume_signingwithkey(dns_zone_t *zone) {
3587 dns_dbnode_t *node = NULL;
3588 dns_dbversion_t *version = NULL;
3589 dns_rdata_t rdata = DNS_RDATA_INIT;
3590 dns_rdataset_t rdataset;
3591 isc_result_t result;
3592 dns_db_t *db = NULL;
3593
3594 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3595 if (zone->db != NULL) {
3596 dns_db_attach(zone->db, &db);
3597 }
3598 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3599 if (db == NULL) {
3600 goto cleanup;
3601 }
3602
3603 result = dns_db_findnode(db, &zone->origin, false, &node);
3604 if (result != ISC_R_SUCCESS) {
3605 goto cleanup;
3606 }
3607
3608 dns_db_currentversion(db, &version);
3609 dns_rdataset_init(&rdataset);
3610 result = dns_db_findrdataset(db, node, version, zone->privatetype,
3611 dns_rdatatype_none, 0, &rdataset, NULL);
3612 if (result != ISC_R_SUCCESS) {
3613 INSIST(!dns_rdataset_isassociated(&rdataset));
3614 goto cleanup;
3615 }
3616
3617 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
3618 result = dns_rdataset_next(&rdataset))
3619 {
3620 dns_rdataset_current(&rdataset, &rdata);
3621 if (rdata.length != 5 || rdata.data[0] == 0 ||
3622 rdata.data[4] != 0)
3623 {
3624 dns_rdata_reset(&rdata);
3625 continue;
3626 }
3627
3628 result = zone_signwithkey(zone, rdata.data[0],
3629 (rdata.data[1] << 8) | rdata.data[2],
3630 rdata.data[3]);
3631 if (result != ISC_R_SUCCESS) {
3632 dnssec_log(zone, ISC_LOG_ERROR,
3633 "zone_signwithkey failed: %s",
3634 dns_result_totext(result));
3635 }
3636 dns_rdata_reset(&rdata);
3637 }
3638 dns_rdataset_disassociate(&rdataset);
3639
3640 cleanup:
3641 if (db != NULL) {
3642 if (node != NULL) {
3643 dns_db_detachnode(db, &node);
3644 }
3645 if (version != NULL) {
3646 dns_db_closeversion(db, &version, false);
3647 }
3648 dns_db_detach(&db);
3649 }
3650 }
3651
3652 /*
3653 * Initiate adding/removing NSEC3 records belonging to the chain defined by the
3654 * supplied NSEC3PARAM RDATA.
3655 *
3656 * Zone must be locked by caller.
3657 */
3658 static isc_result_t
3659 zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
3660 dns_nsec3chain_t *nsec3chain, *current;
3661 dns_dbversion_t *version = NULL;
3662 bool nseconly = false, nsec3ok = false;
3663 isc_result_t result;
3664 isc_time_t now;
3665 unsigned int options = 0;
3666 char saltbuf[255 * 2 + 1];
3667 char flags[sizeof("INITIAL|REMOVE|CREATE|NONSEC|OPTOUT")];
3668 dns_db_t *db = NULL;
3669
3670 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3671 if (zone->db != NULL) {
3672 dns_db_attach(zone->db, &db);
3673 }
3674 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3675
3676 if (db == NULL) {
3677 result = ISC_R_SUCCESS;
3678 goto cleanup;
3679 }
3680
3681 /*
3682 * If this zone is not NSEC3-capable, attempting to remove any NSEC3
3683 * chain from it is pointless as it would not be possible for the
3684 * latter to exist in the first place.
3685 */
3686 dns_db_currentversion(db, &version);
3687 result = dns_nsec_nseconly(db, version, &nseconly);
3688 nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
3689 dns_db_closeversion(db, &version, false);
3690 if (!nsec3ok && (nsec3param->flags & DNS_NSEC3FLAG_REMOVE) == 0) {
3691 result = ISC_R_SUCCESS;
3692 goto cleanup;
3693 }
3694
3695 /*
3696 * Allocate and initialize structure preserving state of
3697 * adding/removing records belonging to this NSEC3 chain between
3698 * separate zone_nsec3chain() calls.
3699 */
3700 nsec3chain = isc_mem_get(zone->mctx, sizeof *nsec3chain);
3701
3702 nsec3chain->magic = 0;
3703 nsec3chain->done = false;
3704 nsec3chain->db = NULL;
3705 nsec3chain->dbiterator = NULL;
3706 nsec3chain->nsec3param.common.rdclass = nsec3param->common.rdclass;
3707 nsec3chain->nsec3param.common.rdtype = nsec3param->common.rdtype;
3708 nsec3chain->nsec3param.hash = nsec3param->hash;
3709 nsec3chain->nsec3param.iterations = nsec3param->iterations;
3710 nsec3chain->nsec3param.flags = nsec3param->flags;
3711 nsec3chain->nsec3param.salt_length = nsec3param->salt_length;
3712 memmove(nsec3chain->salt, nsec3param->salt, nsec3param->salt_length);
3713 nsec3chain->nsec3param.salt = nsec3chain->salt;
3714 nsec3chain->seen_nsec = false;
3715 nsec3chain->delete_nsec = false;
3716 nsec3chain->save_delete_nsec = false;
3717
3718 /*
3719 * Log NSEC3 parameters defined by supplied NSEC3PARAM RDATA.
3720 */
3721 if (nsec3param->flags == 0) {
3722 strlcpy(flags, "NONE", sizeof(flags));
3723 } else {
3724 flags[0] = '\0';
3725 if ((nsec3param->flags & DNS_NSEC3FLAG_REMOVE) != 0) {
3726 strlcat(flags, "REMOVE", sizeof(flags));
3727 }
3728 if ((nsec3param->flags & DNS_NSEC3FLAG_INITIAL) != 0) {
3729 if (flags[0] == '\0') {
3730 strlcpy(flags, "INITIAL", sizeof(flags));
3731 } else {
3732 strlcat(flags, "|INITIAL", sizeof(flags));
3733 }
3734 }
3735 if ((nsec3param->flags & DNS_NSEC3FLAG_CREATE) != 0) {
3736 if (flags[0] == '\0') {
3737 strlcpy(flags, "CREATE", sizeof(flags));
3738 } else {
3739 strlcat(flags, "|CREATE", sizeof(flags));
3740 }
3741 }
3742 if ((nsec3param->flags & DNS_NSEC3FLAG_NONSEC) != 0) {
3743 if (flags[0] == '\0') {
3744 strlcpy(flags, "NONSEC", sizeof(flags));
3745 } else {
3746 strlcat(flags, "|NONSEC", sizeof(flags));
3747 }
3748 }
3749 if ((nsec3param->flags & DNS_NSEC3FLAG_OPTOUT) != 0) {
3750 if (flags[0] == '\0') {
3751 strlcpy(flags, "OPTOUT", sizeof(flags));
3752 } else {
3753 strlcat(flags, "|OPTOUT", sizeof(flags));
3754 }
3755 }
3756 }
3757 result = dns_nsec3param_salttotext(nsec3param, saltbuf,
3758 sizeof(saltbuf));
3759 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3760 dnssec_log(zone, ISC_LOG_INFO, "zone_addnsec3chain(%u,%s,%u,%s)",
3761 nsec3param->hash, flags, nsec3param->iterations, saltbuf);
3762
3763 /*
3764 * If the NSEC3 chain defined by the supplied NSEC3PARAM RDATA is
3765 * currently being processed, interrupt its processing to avoid
3766 * simultaneously adding and removing records for the same NSEC3 chain.
3767 */
3768 for (current = ISC_LIST_HEAD(zone->nsec3chain); current != NULL;
3769 current = ISC_LIST_NEXT(current, link))
3770 {
3771 if ((current->db == db) &&
3772 (current->nsec3param.hash == nsec3param->hash) &&
3773 (current->nsec3param.iterations ==
3774 nsec3param->iterations) &&
3775 (current->nsec3param.salt_length ==
3776 nsec3param->salt_length) &&
3777 memcmp(current->nsec3param.salt, nsec3param->salt,
3778 nsec3param->salt_length) == 0)
3779 {
3780 current->done = true;
3781 }
3782 }
3783
3784 /*
3785 * Attach zone database to the structure initialized above and create
3786 * an iterator for it with appropriate options in order to avoid
3787 * creating NSEC3 records for NSEC3 records.
3788 */
3789 dns_db_attach(db, &nsec3chain->db);
3790 if ((nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0) {
3791 options = DNS_DB_NONSEC3;
3792 }
3793 result = dns_db_createiterator(nsec3chain->db, options,
3794 &nsec3chain->dbiterator);
3795 if (result == ISC_R_SUCCESS) {
3796 result = dns_dbiterator_first(nsec3chain->dbiterator);
3797 }
3798 if (result == ISC_R_SUCCESS) {
3799 /*
3800 * Database iterator initialization succeeded. We are now
3801 * ready to kick off adding/removing records belonging to this
3802 * NSEC3 chain. Append the structure initialized above to the
3803 * "nsec3chain" list for the zone and set the appropriate zone
3804 * timer so that zone_nsec3chain() is called as soon as
3805 * possible.
3806 */
3807 dns_dbiterator_pause(nsec3chain->dbiterator);
3808 ISC_LIST_INITANDAPPEND(zone->nsec3chain, nsec3chain, link);
3809 nsec3chain = NULL;
3810 if (isc_time_isepoch(&zone->nsec3chaintime)) {
3811 TIME_NOW(&now);
3812 zone->nsec3chaintime = now;
3813 if (zone->task != NULL) {
3814 zone_settimer(zone, &now);
3815 }
3816 }
3817 }
3818
3819 if (nsec3chain != NULL) {
3820 if (nsec3chain->db != NULL) {
3821 dns_db_detach(&nsec3chain->db);
3822 }
3823 if (nsec3chain->dbiterator != NULL) {
3824 dns_dbiterator_destroy(&nsec3chain->dbiterator);
3825 }
3826 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
3827 }
3828
3829 cleanup:
3830 if (db != NULL) {
3831 dns_db_detach(&db);
3832 }
3833 return (result);
3834 }
3835
3836 /*
3837 * Find private-type records at the zone apex which signal that an NSEC3 chain
3838 * should be added or removed. For each such record, extract NSEC3PARAM RDATA
3839 * and pass it to zone_addnsec3chain().
3840 *
3841 * Zone must be locked by caller.
3842 */
3843 static void
3844 resume_addnsec3chain(dns_zone_t *zone) {
3845 dns_dbnode_t *node = NULL;
3846 dns_dbversion_t *version = NULL;
3847 dns_rdataset_t rdataset;
3848 isc_result_t result;
3849 dns_rdata_nsec3param_t nsec3param;
3850 bool nseconly = false, nsec3ok = false;
3851 dns_db_t *db = NULL;
3852
3853 INSIST(LOCKED_ZONE(zone));
3854
3855 if (zone->privatetype == 0) {
3856 return;
3857 }
3858
3859 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3860 if (zone->db != NULL) {
3861 dns_db_attach(zone->db, &db);
3862 }
3863 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3864 if (db == NULL) {
3865 goto cleanup;
3866 }
3867
3868 result = dns_db_findnode(db, &zone->origin, false, &node);
3869 if (result != ISC_R_SUCCESS) {
3870 goto cleanup;
3871 }
3872
3873 dns_db_currentversion(db, &version);
3874
3875 /*
3876 * In order to create NSEC3 chains we need the DNSKEY RRset at zone
3877 * apex to exist and contain no keys using NSEC-only algorithms.
3878 */
3879 result = dns_nsec_nseconly(db, version, &nseconly);
3880 nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
3881
3882 /*
3883 * Get the RRset containing all private-type records at the zone apex.
3884 */
3885 dns_rdataset_init(&rdataset);
3886 result = dns_db_findrdataset(db, node, version, zone->privatetype,
3887 dns_rdatatype_none, 0, &rdataset, NULL);
3888 if (result != ISC_R_SUCCESS) {
3889 INSIST(!dns_rdataset_isassociated(&rdataset));
3890 goto cleanup;
3891 }
3892
3893 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
3894 result = dns_rdataset_next(&rdataset))
3895 {
3896 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
3897 dns_rdata_t rdata = DNS_RDATA_INIT;
3898 dns_rdata_t private = DNS_RDATA_INIT;
3899
3900 dns_rdataset_current(&rdataset, &private);
3901 /*
3902 * Try extracting NSEC3PARAM RDATA from this private-type
3903 * record. Failure means this private-type record does not
3904 * represent an NSEC3PARAM record, so skip it.
3905 */
3906 if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
3907 sizeof(buf)))
3908 {
3909 continue;
3910 }
3911 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
3912 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3913 if (((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) ||
3914 ((nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0 && nsec3ok))
3915 {
3916 /*
3917 * Pass the NSEC3PARAM RDATA contained in this
3918 * private-type record to zone_addnsec3chain() so that
3919 * it can kick off adding or removing NSEC3 records.
3920 */
3921 result = zone_addnsec3chain(zone, &nsec3param);
3922 if (result != ISC_R_SUCCESS) {
3923 dnssec_log(zone, ISC_LOG_ERROR,
3924 "zone_addnsec3chain failed: %s",
3925 dns_result_totext(result));
3926 }
3927 }
3928 }
3929 dns_rdataset_disassociate(&rdataset);
3930
3931 cleanup:
3932 if (db != NULL) {
3933 if (node != NULL) {
3934 dns_db_detachnode(db, &node);
3935 }
3936 if (version != NULL) {
3937 dns_db_closeversion(db, &version, false);
3938 }
3939 dns_db_detach(&db);
3940 }
3941 }
3942
3943 static void
3944 set_resigntime(dns_zone_t *zone) {
3945 dns_rdataset_t rdataset;
3946 dns_fixedname_t fixed;
3947 unsigned int resign;
3948 isc_result_t result;
3949 uint32_t nanosecs;
3950 dns_db_t *db = NULL;
3951
3952 INSIST(LOCKED_ZONE(zone));
3953
3954 /* We only re-sign zones that can be dynamically updated */
3955 if (zone->update_disabled) {
3956 return;
3957 }
3958
3959 if (!inline_secure(zone) &&
3960 (zone->type != dns_zone_primary ||
3961 (zone->ssutable == NULL &&
3962 (zone->update_acl == NULL || dns_acl_isnone(zone->update_acl)))))
3963 {
3964 return;
3965 }
3966
3967 dns_rdataset_init(&rdataset);
3968 dns_fixedname_init(&fixed);
3969
3970 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3971 if (zone->db != NULL) {
3972 dns_db_attach(zone->db, &db);
3973 }
3974 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3975 if (db == NULL) {
3976 isc_time_settoepoch(&zone->resigntime);
3977 return;
3978 }
3979
3980 result = dns_db_getsigningtime(db, &rdataset,
3981 dns_fixedname_name(&fixed));
3982 if (result != ISC_R_SUCCESS) {
3983 isc_time_settoepoch(&zone->resigntime);
3984 goto cleanup;
3985 }
3986
3987 resign = rdataset.resign - dns_zone_getsigresigninginterval(zone);
3988 dns_rdataset_disassociate(&rdataset);
3989 nanosecs = isc_random_uniform(1000000000);
3990 isc_time_set(&zone->resigntime, resign, nanosecs);
3991
3992 cleanup:
3993 dns_db_detach(&db);
3994 return;
3995 }
3996
3997 static isc_result_t
3998 check_nsec3param(dns_zone_t *zone, dns_db_t *db) {
3999 bool ok = false;
4000 dns_dbnode_t *node = NULL;
4001 dns_dbversion_t *version = NULL;
4002 dns_rdata_nsec3param_t nsec3param;
4003 dns_rdataset_t rdataset;
4004 isc_result_t result;
4005 bool dynamic = (zone->type == dns_zone_primary)
4006 ? dns_zone_isdynamic(zone, false)
4007 : false;
4008
4009 dns_rdataset_init(&rdataset);
4010 result = dns_db_findnode(db, &zone->origin, false, &node);
4011 if (result != ISC_R_SUCCESS) {
4012 dns_zone_log(zone, ISC_LOG_ERROR,
4013 "nsec3param lookup failure: %s",
4014 dns_result_totext(result));
4015 return (result);
4016 }
4017 dns_db_currentversion(db, &version);
4018
4019 result = dns_db_findrdataset(db, node, version,
4020 dns_rdatatype_nsec3param,
4021 dns_rdatatype_none, 0, &rdataset, NULL);
4022 if (result == ISC_R_NOTFOUND) {
4023 INSIST(!dns_rdataset_isassociated(&rdataset));
4024 result = ISC_R_SUCCESS;
4025 goto cleanup;
4026 }
4027 if (result != ISC_R_SUCCESS) {
4028 INSIST(!dns_rdataset_isassociated(&rdataset));
4029 dns_zone_log(zone, ISC_LOG_ERROR,
4030 "nsec3param lookup failure: %s",
4031 dns_result_totext(result));
4032 goto cleanup;
4033 }
4034
4035 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
4036 result = dns_rdataset_next(&rdataset))
4037 {
4038 dns_rdata_t rdata = DNS_RDATA_INIT;
4039
4040 dns_rdataset_current(&rdataset, &rdata);
4041 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
4042 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4043
4044 /*
4045 * For dynamic zones we must support every algorithm so we
4046 * can regenerate all the NSEC3 chains.
4047 * For non-dynamic zones we only need to find a supported
4048 * algorithm.
4049 */
4050 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NSEC3TESTZONE) &&
4051 nsec3param.hash == DNS_NSEC3_UNKNOWNALG && !dynamic)
4052 {
4053 dns_zone_log(zone, ISC_LOG_WARNING,
4054 "nsec3 test \"unknown\" hash algorithm "
4055 "found: %u",
4056 nsec3param.hash);
4057 ok = true;
4058 } else if (!dns_nsec3_supportedhash(nsec3param.hash)) {
4059 if (dynamic) {
4060 dns_zone_log(zone, ISC_LOG_ERROR,
4061 "unsupported nsec3 hash algorithm"
4062 " in dynamic zone: %u",
4063 nsec3param.hash);
4064 result = DNS_R_BADZONE;
4065 /* Stop second error message. */
4066 ok = true;
4067 break;
4068 } else {
4069 dns_zone_log(zone, ISC_LOG_WARNING,
4070 "unsupported nsec3 hash "
4071 "algorithm: %u",
4072 nsec3param.hash);
4073 }
4074 } else {
4075 ok = true;
4076 }
4077
4078 /*
4079 * Warn if the zone has excessive NSEC3 iterations.
4080 */
4081 if (nsec3param.iterations > dns_nsec3_maxiterations()) {
4082 dnssec_log(zone, ISC_LOG_WARNING,
4083 "excessive NSEC3PARAM iterations %u > %u",
4084 nsec3param.iterations,
4085 dns_nsec3_maxiterations());
4086 }
4087 }
4088 if (result == ISC_R_NOMORE) {
4089 result = ISC_R_SUCCESS;
4090 }
4091
4092 if (!ok) {
4093 result = DNS_R_BADZONE;
4094 dns_zone_log(zone, ISC_LOG_ERROR,
4095 "no supported nsec3 hash algorithm");
4096 }
4097
4098 cleanup:
4099 if (dns_rdataset_isassociated(&rdataset)) {
4100 dns_rdataset_disassociate(&rdataset);
4101 }
4102 dns_db_closeversion(db, &version, false);
4103 dns_db_detachnode(db, &node);
4104 return (result);
4105 }
4106
4107 /*
4108 * Set the timer for refreshing the key zone to the soonest future time
4109 * of the set (current timer, keydata->refresh, keydata->addhd,
4110 * keydata->removehd).
4111 */
4112 static void
4113 set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key,
4114 isc_stdtime_t now, bool force) {
4115 const char me[] = "set_refreshkeytimer";
4116 isc_stdtime_t then;
4117 isc_time_t timenow, timethen;
4118 char timebuf[80];
4119
4120 ENTER;
4121 then = key->refresh;
4122 if (force) {
4123 then = now;
4124 }
4125 if (key->addhd > now && key->addhd < then) {
4126 then = key->addhd;
4127 }
4128 if (key->removehd > now && key->removehd < then) {
4129 then = key->removehd;
4130 }
4131
4132 TIME_NOW(&timenow);
4133 if (then > now) {
4134 DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
4135 } else {
4136 timethen = timenow;
4137 }
4138 if (isc_time_compare(&zone->refreshkeytime, &timenow) < 0 ||
4139 isc_time_compare(&timethen, &zone->refreshkeytime) < 0)
4140 {
4141 zone->refreshkeytime = timethen;
4142 }
4143
4144 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
4145 dns_zone_log(zone, ISC_LOG_DEBUG(1), "next key refresh: %s", timebuf);
4146 zone_settimer(zone, &timenow);
4147 }
4148
4149 /*
4150 * If keynode references a key or a DS rdataset, and if the key
4151 * zone does not contain a KEYDATA record for the corresponding name,
4152 * then create an empty KEYDATA and push it into the zone as a placeholder,
4153 * then schedule a key refresh immediately. This new KEYDATA record will be
4154 * updated during the refresh.
4155 *
4156 * If the key zone is changed, set '*changed' to true.
4157 */
4158 static isc_result_t
4159 create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
4160 dns_diff_t *diff, dns_keynode_t *keynode, dns_name_t *keyname,
4161 bool *changed) {
4162 const char me[] = "create_keydata";
4163 isc_result_t result = ISC_R_SUCCESS;
4164 dns_rdata_t rdata = DNS_RDATA_INIT;
4165 dns_rdata_keydata_t kd;
4166 unsigned char rrdata[4096];
4167 isc_buffer_t rrdatabuf;
4168 isc_stdtime_t now;
4169
4170 REQUIRE(keynode != NULL);
4171
4172 ENTER;
4173 isc_stdtime_get(&now);
4174
4175 /*
4176 * If the keynode has no trust anchor set, we shouldn't be here.
4177 */
4178 if (!dns_keynode_dsset(keynode, NULL)) {
4179 return (ISC_R_FAILURE);
4180 }
4181
4182 memset(&kd, 0, sizeof(kd));
4183 kd.common.rdclass = zone->rdclass;
4184 kd.common.rdtype = dns_rdatatype_keydata;
4185 ISC_LINK_INIT(&kd.common, link);
4186
4187 isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
4188
4189 CHECK(dns_rdata_fromstruct(&rdata, zone->rdclass, dns_rdatatype_keydata,
4190 &kd, &rrdatabuf));
4191 /* Add rdata to zone. */
4192 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, keyname, 0, &rdata));
4193 *changed = true;
4194
4195 /* Refresh new keys from the zone apex as soon as possible. */
4196 set_refreshkeytimer(zone, &kd, now, true);
4197 return (ISC_R_SUCCESS);
4198
4199 failure:
4200 return (result);
4201 }
4202
4203 /*
4204 * Remove from the key zone all the KEYDATA records found in rdataset.
4205 */
4206 static isc_result_t
4207 delete_keydata(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
4208 dns_name_t *name, dns_rdataset_t *rdataset) {
4209 dns_rdata_t rdata = DNS_RDATA_INIT;
4210 isc_result_t result, uresult;
4211
4212 for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
4213 result = dns_rdataset_next(rdataset))
4214 {
4215 dns_rdata_reset(&rdata);
4216 dns_rdataset_current(rdataset, &rdata);
4217 uresult = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name, 0,
4218 &rdata);
4219 if (uresult != ISC_R_SUCCESS) {
4220 return (uresult);
4221 }
4222 }
4223 if (result == ISC_R_NOMORE) {
4224 result = ISC_R_SUCCESS;
4225 }
4226 return (result);
4227 }
4228
4229 /*
4230 * Compute the DNSSEC key ID for a DNSKEY record.
4231 */
4232 static isc_result_t
4233 compute_tag(dns_name_t *name, dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx,
4234 dns_keytag_t *tag) {
4235 isc_result_t result;
4236 dns_rdata_t rdata = DNS_RDATA_INIT;
4237 unsigned char data[4096];
4238 isc_buffer_t buffer;
4239 dst_key_t *dstkey = NULL;
4240
4241 isc_buffer_init(&buffer, data, sizeof(data));
4242 dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
4243 dns_rdatatype_dnskey, dnskey, &buffer);
4244
4245 result = dns_dnssec_keyfromrdata(name, &rdata, mctx, &dstkey);
4246 if (result == ISC_R_SUCCESS) {
4247 *tag = dst_key_id(dstkey);
4248 dst_key_free(&dstkey);
4249 }
4250
4251 return (result);
4252 }
4253
4254 /*
4255 * Add key to the security roots.
4256 */
4257 static void
4258 trust_key(dns_zone_t *zone, dns_name_t *keyname, dns_rdata_dnskey_t *dnskey,
4259 bool initial) {
4260 isc_result_t result;
4261 dns_rdata_t rdata = DNS_RDATA_INIT;
4262 unsigned char data[4096], digest[ISC_MAX_MD_SIZE];
4263 isc_buffer_t buffer;
4264 dns_keytable_t *sr = NULL;
4265 dns_rdata_ds_t ds;
4266
4267 result = dns_view_getsecroots(zone->view, &sr);
4268 if (result != ISC_R_SUCCESS) {
4269 return;
4270 }
4271
4272 /* Build DS record for key. */
4273 isc_buffer_init(&buffer, data, sizeof(data));
4274 dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
4275 dns_rdatatype_dnskey, dnskey, &buffer);
4276 CHECK(dns_ds_fromkeyrdata(keyname, &rdata, DNS_DSDIGEST_SHA256, digest,
4277 &ds));
4278 CHECK(dns_keytable_add(sr, true, initial, keyname, &ds));
4279
4280 dns_keytable_detach(&sr);
4281
4282 failure:
4283 if (sr != NULL) {
4284 dns_keytable_detach(&sr);
4285 }
4286 return;
4287 }
4288
4289 /*
4290 * Add a null key to the security roots for so that all queries
4291 * to the zone will fail.
4292 */
4293 static void
4294 fail_secure(dns_zone_t *zone, dns_name_t *keyname) {
4295 isc_result_t result;
4296 dns_keytable_t *sr = NULL;
4297
4298 result = dns_view_getsecroots(zone->view, &sr);
4299 if (result == ISC_R_SUCCESS) {
4300 dns_keytable_marksecure(sr, keyname);
4301 dns_keytable_detach(&sr);
4302 }
4303 }
4304
4305 /*
4306 * Scan a set of KEYDATA records from the key zone. The ones that are
4307 * valid (i.e., the add holddown timer has expired) become trusted keys.
4308 */
4309 static void
4310 load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
4311 isc_result_t result;
4312 dns_rdata_t rdata = DNS_RDATA_INIT;
4313 dns_rdata_keydata_t keydata;
4314 dns_rdata_dnskey_t dnskey;
4315 int trusted = 0, revoked = 0, pending = 0;
4316 isc_stdtime_t now;
4317 dns_keytable_t *sr = NULL;
4318
4319 isc_stdtime_get(&now);
4320
4321 result = dns_view_getsecroots(zone->view, &sr);
4322 if (result == ISC_R_SUCCESS) {
4323 dns_keytable_delete(sr, name);
4324 dns_keytable_detach(&sr);
4325 }
4326
4327 /* Now insert all the accepted trust anchors from this keydata set. */
4328 for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
4329 result = dns_rdataset_next(rdataset))
4330 {
4331 dns_rdata_reset(&rdata);
4332 dns_rdataset_current(rdataset, &rdata);
4333
4334 /* Convert rdata to keydata. */
4335 result = dns_rdata_tostruct(&rdata, &keydata, NULL);
4336 if (result == ISC_R_UNEXPECTEDEND) {
4337 continue;
4338 }
4339 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4340
4341 /* Set the key refresh timer to force a fast refresh. */
4342 set_refreshkeytimer(zone, &keydata, now, true);
4343
4344 /* If the removal timer is nonzero, this key was revoked. */
4345 if (keydata.removehd != 0) {
4346 revoked++;
4347 continue;
4348 }
4349
4350 /*
4351 * If the add timer is still pending, this key is not
4352 * trusted yet.
4353 */
4354 if (now < keydata.addhd) {
4355 pending++;
4356 continue;
4357 }
4358
4359 /* Convert keydata to dnskey. */
4360 dns_keydata_todnskey(&keydata, &dnskey, NULL);
4361
4362 /* Add to keytables. */
4363 trusted++;
4364 trust_key(zone, name, &dnskey, (keydata.addhd == 0));
4365 }
4366
4367 if (trusted == 0 && pending != 0) {
4368 char namebuf[DNS_NAME_FORMATSIZE];
4369 dns_name_format(name, namebuf, sizeof namebuf);
4370 dnssec_log(zone, ISC_LOG_ERROR,
4371 "No valid trust anchors for '%s'!", namebuf);
4372 dnssec_log(zone, ISC_LOG_ERROR,
4373 "%d key(s) revoked, %d still pending", revoked,
4374 pending);
4375 dnssec_log(zone, ISC_LOG_ERROR, "All queries to '%s' will fail",
4376 namebuf);
4377 fail_secure(zone, name);
4378 }
4379 }
4380
4381 static isc_result_t
4382 do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
4383 dns_diff_t *diff) {
4384 dns_diff_t temp_diff;
4385 isc_result_t result;
4386
4387 /*
4388 * Create a singleton diff.
4389 */
4390 dns_diff_init(diff->mctx, &temp_diff);
4391 ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
4392
4393 /*
4394 * Apply it to the database.
4395 */
4396 result = dns_diff_apply(&temp_diff, db, ver);
4397 ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
4398 if (result != ISC_R_SUCCESS) {
4399 dns_difftuple_free(tuple);
4400 return (result);
4401 }
4402
4403 /*
4404 * Merge it into the current pending journal entry.
4405 */
4406 dns_diff_appendminimal(diff, tuple);
4407
4408 /*
4409 * Do not clear temp_diff.
4410 */
4411 return (ISC_R_SUCCESS);
4412 }
4413
4414 static isc_result_t
4415 update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
4416 dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
4417 dns_rdata_t *rdata) {
4418 dns_difftuple_t *tuple = NULL;
4419 isc_result_t result;
4420 result = dns_difftuple_create(diff->mctx, op, name, ttl, rdata, &tuple);
4421 if (result != ISC_R_SUCCESS) {
4422 return (result);
4423 }
4424 return (do_one_tuple(&tuple, db, ver, diff));
4425 }
4426
4427 static isc_result_t
4428 update_soa_serial(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
4429 dns_diff_t *diff, isc_mem_t *mctx,
4430 dns_updatemethod_t method) {
4431 dns_difftuple_t *deltuple = NULL;
4432 dns_difftuple_t *addtuple = NULL;
4433 uint32_t serial;
4434 isc_result_t result;
4435 dns_updatemethod_t used = dns_updatemethod_none;
4436
4437 INSIST(method != dns_updatemethod_none);
4438
4439 CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple));
4440 CHECK(dns_difftuple_copy(deltuple, &addtuple));
4441 addtuple->op = DNS_DIFFOP_ADD;
4442
4443 serial = dns_soa_getserial(&addtuple->rdata);
4444 serial = dns_update_soaserial(serial, method, &used);
4445 if (method != used) {
4446 dns_zone_log(zone, ISC_LOG_WARNING,
4447 "update_soa_serial:new serial would be lower than "
4448 "old serial, using increment method instead");
4449 }
4450 dns_soa_setserial(serial, &addtuple->rdata);
4451 CHECK(do_one_tuple(&deltuple, db, ver, diff));
4452 CHECK(do_one_tuple(&addtuple, db, ver, diff));
4453 result = ISC_R_SUCCESS;
4454
4455 failure:
4456 if (addtuple != NULL) {
4457 dns_difftuple_free(&addtuple);
4458 }
4459 if (deltuple != NULL) {
4460 dns_difftuple_free(&deltuple);
4461 }
4462 return (result);
4463 }
4464
4465 /*
4466 * Write all transactions in 'diff' to the zone journal file.
4467 */
4468 static isc_result_t
4469 zone_journal(dns_zone_t *zone, dns_diff_t *diff, uint32_t *sourceserial,
4470 const char *caller) {
4471 const char me[] = "zone_journal";
4472 const char *journalfile;
4473 isc_result_t result = ISC_R_SUCCESS;
4474 dns_journal_t *journal = NULL;
4475 unsigned int mode = DNS_JOURNAL_CREATE | DNS_JOURNAL_WRITE;
4476
4477 ENTER;
4478 journalfile = dns_zone_getjournal(zone);
4479 if (journalfile != NULL) {
4480 result = dns_journal_open(zone->mctx, journalfile, mode,
4481 &journal);
4482 if (result != ISC_R_SUCCESS) {
4483 dns_zone_log(zone, ISC_LOG_ERROR,
4484 "%s:dns_journal_open -> %s", caller,
4485 dns_result_totext(result));
4486 return (result);
4487 }
4488
4489 if (sourceserial != NULL) {
4490 dns_journal_set_sourceserial(journal, *sourceserial);
4491 }
4492
4493 result = dns_journal_write_transaction(journal, diff);
4494 if (result != ISC_R_SUCCESS) {
4495 dns_zone_log(zone, ISC_LOG_ERROR,
4496 "%s:dns_journal_write_transaction -> %s",
4497 caller, dns_result_totext(result));
4498 }
4499 dns_journal_destroy(&journal);
4500 }
4501
4502 return (result);
4503 }
4504
4505 /*
4506 * Create an SOA record for a newly-created zone
4507 */
4508 static isc_result_t
4509 add_soa(dns_zone_t *zone, dns_db_t *db) {
4510 isc_result_t result;
4511 dns_rdata_t rdata = DNS_RDATA_INIT;
4512 unsigned char buf[DNS_SOA_BUFFERSIZE];
4513 dns_dbversion_t *ver = NULL;
4514 dns_diff_t diff;
4515
4516 dns_zone_log(zone, ISC_LOG_DEBUG(1), "creating SOA");
4517
4518 dns_diff_init(zone->mctx, &diff);
4519 result = dns_db_newversion(db, &ver);
4520 if (result != ISC_R_SUCCESS) {
4521 dns_zone_log(zone, ISC_LOG_ERROR,
4522 "add_soa:dns_db_newversion -> %s",
4523 dns_result_totext(result));
4524 goto failure;
4525 }
4526
4527 /* Build SOA record */
4528 result = dns_soa_buildrdata(&zone->origin, dns_rootname, zone->rdclass,
4529 0, 0, 0, 0, 0, buf, &rdata);
4530 if (result != ISC_R_SUCCESS) {
4531 dns_zone_log(zone, ISC_LOG_ERROR,
4532 "add_soa:dns_soa_buildrdata -> %s",
4533 dns_result_totext(result));
4534 goto failure;
4535 }
4536
4537 result = update_one_rr(db, ver, &diff, DNS_DIFFOP_ADD, &zone->origin, 0,
4538 &rdata);
4539
4540 failure:
4541 dns_diff_clear(&diff);
4542 if (ver != NULL) {
4543 dns_db_closeversion(db, &ver, (result == ISC_R_SUCCESS));
4544 }
4545
4546 INSIST(ver == NULL);
4547
4548 return (result);
4549 }
4550
4551 struct addifmissing_arg {
4552 dns_db_t *db;
4553 dns_dbversion_t *ver;
4554 dns_diff_t *diff;
4555 dns_zone_t *zone;
4556 bool *changed;
4557 isc_result_t result;
4558 };
4559
4560 static void
4561 addifmissing(dns_keytable_t *keytable, dns_keynode_t *keynode,
4562 dns_name_t *keyname, void *arg) {
4563 dns_db_t *db = ((struct addifmissing_arg *)arg)->db;
4564 dns_dbversion_t *ver = ((struct addifmissing_arg *)arg)->ver;
4565 dns_diff_t *diff = ((struct addifmissing_arg *)arg)->diff;
4566 dns_zone_t *zone = ((struct addifmissing_arg *)arg)->zone;
4567 bool *changed = ((struct addifmissing_arg *)arg)->changed;
4568 isc_result_t result;
4569 dns_fixedname_t fname;
4570
4571 UNUSED(keytable);
4572
4573 if (((struct addifmissing_arg *)arg)->result != ISC_R_SUCCESS) {
4574 return;
4575 }
4576
4577 if (!dns_keynode_managed(keynode)) {
4578 return;
4579 }
4580
4581 /*
4582 * If the keynode has no trust anchor set, return.
4583 */
4584 if (!dns_keynode_dsset(keynode, NULL)) {
4585 return;
4586 }
4587
4588 /*
4589 * Check whether there's already a KEYDATA entry for this name;
4590 * if so, we don't need to add another.
4591 */
4592 dns_fixedname_init(&fname);
4593 result = dns_db_find(db, keyname, ver, dns_rdatatype_keydata,
4594 DNS_DBFIND_NOWILD, 0, NULL,
4595 dns_fixedname_name(&fname), NULL, NULL);
4596 if (result == ISC_R_SUCCESS) {
4597 return;
4598 }
4599
4600 /*
4601 * Create the keydata.
4602 */
4603 result = create_keydata(zone, db, ver, diff, keynode, keyname, changed);
4604 if (result != ISC_R_SUCCESS && result != ISC_R_NOMORE) {
4605 ((struct addifmissing_arg *)arg)->result = result;
4606 }
4607 }
4608
4609 /*
4610 * Synchronize the set of initializing keys found in managed-keys {}
4611 * statements with the set of trust anchors found in the managed-keys.bind
4612 * zone. If a domain is no longer named in managed-keys, delete all keys
4613 * from that domain from the key zone. If a domain is configured as an
4614 * initial-key in trust-anchors, but there are no references to it in the
4615 * key zone, load the key zone with the initializing key(s) for that
4616 * domain and schedule a key refresh. If a domain is configured as
4617 * an initial-ds in trust-anchors, fetch the DNSKEY RRset, load the key
4618 * zone with the matching key, and schedule a key refresh.
4619 */
4620 static isc_result_t
4621 sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
4622 isc_result_t result = ISC_R_SUCCESS;
4623 bool changed = false;
4624 bool commit = false;
4625 dns_keynode_t *keynode = NULL;
4626 dns_view_t *view = zone->view;
4627 dns_keytable_t *sr = NULL;
4628 dns_dbversion_t *ver = NULL;
4629 dns_diff_t diff;
4630 dns_rriterator_t rrit;
4631 struct addifmissing_arg arg;
4632
4633 dns_zone_log(zone, ISC_LOG_DEBUG(1), "synchronizing trusted keys");
4634
4635 dns_diff_init(zone->mctx, &diff);
4636
4637 CHECK(dns_view_getsecroots(view, &sr));
4638
4639 result = dns_db_newversion(db, &ver);
4640 if (result != ISC_R_SUCCESS) {
4641 dnssec_log(zone, ISC_LOG_ERROR,
4642 "sync_keyzone:dns_db_newversion -> %s",
4643 dns_result_totext(result));
4644 goto failure;
4645 }
4646
4647 /*
4648 * Walk the zone DB. If we find any keys whose names are no longer
4649 * in trust-anchors, or which have been changed from initial to static,
4650 * (meaning they are permanent and not RFC5011-maintained), delete
4651 * them from the zone. Otherwise call load_secroots(), which
4652 * loads keys into secroots as appropriate.
4653 */
4654 dns_rriterator_init(&rrit, db, ver, 0);
4655 for (result = dns_rriterator_first(&rrit); result == ISC_R_SUCCESS;
4656 result = dns_rriterator_nextrrset(&rrit))
4657 {
4658 dns_rdataset_t *rdataset = NULL;
4659 dns_rdata_t rdata = DNS_RDATA_INIT;
4660 dns_rdata_keydata_t keydata;
4661 isc_stdtime_t now;
4662 bool load = true;
4663 dns_name_t *rrname = NULL;
4664 uint32_t ttl;
4665
4666 isc_stdtime_get(&now);
4667
4668 dns_rriterator_current(&rrit, &rrname, &ttl, &rdataset, NULL);
4669 if (!dns_rdataset_isassociated(rdataset)) {
4670 dns_rriterator_destroy(&rrit);
4671 goto failure;
4672 }
4673
4674 if (rdataset->type != dns_rdatatype_keydata) {
4675 continue;
4676 }
4677
4678 /*
4679 * The managed-keys zone can contain a placeholder instead of
4680 * legitimate data, in which case we will not use it, and we
4681 * will try to refresh it.
4682 */
4683 for (result = dns_rdataset_first(rdataset);
4684 result == ISC_R_SUCCESS;
4685 result = dns_rdataset_next(rdataset))
4686 {
4687 isc_result_t iresult;
4688
4689 dns_rdata_reset(&rdata);
4690 dns_rdataset_current(rdataset, &rdata);
4691
4692 iresult = dns_rdata_tostruct(&rdata, &keydata, NULL);
4693 /* Do we have a valid placeholder KEYDATA record? */
4694 if (iresult == ISC_R_SUCCESS && keydata.flags == 0 &&
4695 keydata.protocol == 0 && keydata.algorithm == 0)
4696 {
4697 set_refreshkeytimer(zone, &keydata, now, true);
4698 load = false;
4699 }
4700 }
4701
4702 /*
4703 * Release db wrlock to prevent LOR reports against
4704 * dns_keytable_forall() call below.
4705 */
4706 dns_rriterator_pause(&rrit);
4707 result = dns_keytable_find(sr, rrname, &keynode);
4708 if (result != ISC_R_SUCCESS || !dns_keynode_managed(keynode)) {
4709 CHECK(delete_keydata(db, ver, &diff, rrname, rdataset));
4710 changed = true;
4711 } else if (load) {
4712 load_secroots(zone, rrname, rdataset);
4713 }
4714
4715 if (keynode != NULL) {
4716 dns_keytable_detachkeynode(sr, &keynode);
4717 }
4718 }
4719 dns_rriterator_destroy(&rrit);
4720
4721 /*
4722 * Walk secroots to find any initial keys that aren't in
4723 * the zone. If we find any, add them to the zone directly.
4724 * If any DS-style initial keys are found, refresh the key
4725 * zone so that they'll be looked up.
4726 */
4727 arg.db = db;
4728 arg.ver = ver;
4729 arg.result = ISC_R_SUCCESS;
4730 arg.diff = &diff;
4731 arg.zone = zone;
4732 arg.changed = &changed;
4733 dns_keytable_forall(sr, addifmissing, &arg);
4734 result = arg.result;
4735 if (changed) {
4736 /* Write changes to journal file. */
4737 CHECK(update_soa_serial(zone, db, ver, &diff, zone->mctx,
4738 zone->updatemethod));
4739 CHECK(zone_journal(zone, &diff, NULL, "sync_keyzone"));
4740
4741 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
4742 zone_needdump(zone, 30);
4743 commit = true;
4744 }
4745
4746 failure:
4747 if (result != ISC_R_SUCCESS && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
4748 {
4749 dnssec_log(zone, ISC_LOG_ERROR,
4750 "unable to synchronize managed keys: %s",
4751 dns_result_totext(result));
4752 isc_time_settoepoch(&zone->refreshkeytime);
4753 }
4754 if (keynode != NULL) {
4755 dns_keytable_detachkeynode(sr, &keynode);
4756 }
4757 if (sr != NULL) {
4758 dns_keytable_detach(&sr);
4759 }
4760 if (ver != NULL) {
4761 dns_db_closeversion(db, &ver, commit);
4762 }
4763 dns_diff_clear(&diff);
4764
4765 INSIST(ver == NULL);
4766
4767 return (result);
4768 }
4769
4770 isc_result_t
4771 dns_zone_synckeyzone(dns_zone_t *zone) {
4772 isc_result_t result;
4773 dns_db_t *db = NULL;
4774
4775 if (zone->type != dns_zone_key) {
4776 return (DNS_R_BADZONE);
4777 }
4778
4779 CHECK(dns_zone_getdb(zone, &db));
4780
4781 LOCK_ZONE(zone);
4782 result = sync_keyzone(zone, db);
4783 UNLOCK_ZONE(zone);
4784
4785 failure:
4786 if (db != NULL) {
4787 dns_db_detach(&db);
4788 }
4789 return (result);
4790 }
4791
4792 static void
4793 maybe_send_secure(dns_zone_t *zone) {
4794 isc_result_t result;
4795
4796 /*
4797 * We've finished loading, or else failed to load, an inline-signing
4798 * 'secure' zone. We now need information about the status of the
4799 * 'raw' zone. If we failed to load, then we need it to send a
4800 * copy of its database; if we succeeded, we need it to send its
4801 * serial number so that we can sync with it. If it has not yet
4802 * loaded, we set a flag so that it will send the necessary
4803 * information when it has finished loading.
4804 */
4805 if (zone->raw->db != NULL) {
4806 if (zone->db != NULL) {
4807 uint32_t serial;
4808 unsigned int soacount;
4809
4810 result = zone_get_from_db(
4811 zone->raw, zone->raw->db, NULL, &soacount, NULL,
4812 &serial, NULL, NULL, NULL, NULL, NULL);
4813 if (result == ISC_R_SUCCESS && soacount > 0U) {
4814 zone_send_secureserial(zone->raw, serial);
4815 }
4816 } else {
4817 zone_send_securedb(zone->raw, zone->raw->db);
4818 }
4819 } else {
4820 DNS_ZONE_SETFLAG(zone->raw, DNS_ZONEFLG_SENDSECURE);
4821 }
4822 }
4823
4824 static bool
4825 zone_unchanged(dns_db_t *db1, dns_db_t *db2, isc_mem_t *mctx) {
4826 isc_result_t result;
4827 bool answer = false;
4828 dns_diff_t diff;
4829
4830 dns_diff_init(mctx, &diff);
4831 result = dns_db_diffx(&diff, db1, NULL, db2, NULL, NULL);
4832 if (result == ISC_R_SUCCESS && ISC_LIST_EMPTY(diff.tuples)) {
4833 answer = true;
4834 }
4835 dns_diff_clear(&diff);
4836 return (answer);
4837 }
4838
4839 /*
4840 * The zone is presumed to be locked.
4841 * If this is a inline_raw zone the secure version is also locked.
4842 */
4843 static isc_result_t
4844 zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
4845 isc_result_t result) {
4846 unsigned int soacount = 0;
4847 unsigned int nscount = 0;
4848 unsigned int errors = 0;
4849 uint32_t serial, oldserial, refresh, retry, expire, minimum, soattl;
4850 isc_time_t now;
4851 bool needdump = false;
4852 bool fixjournal = false;
4853 bool hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE);
4854 bool nomaster = false;
4855 bool had_db = false;
4856 dns_include_t *inc;
4857 bool is_dynamic = false;
4858
4859 INSIST(LOCKED_ZONE(zone));
4860 if (inline_raw(zone)) {
4861 INSIST(LOCKED_ZONE(zone->secure));
4862 }
4863
4864 TIME_NOW(&now);
4865
4866 /*
4867 * Initiate zone transfer? We may need a error code that
4868 * indicates that the "permanent" form does not exist.
4869 * XXX better error feedback to log.
4870 */
4871 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
4872 if (zone->type == dns_zone_secondary ||
4873 zone->type == dns_zone_mirror ||
4874 zone->type == dns_zone_stub ||
4875 (zone->type == dns_zone_redirect && zone->masters == NULL))
4876 {
4877 if (result == ISC_R_FILENOTFOUND) {
4878 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4879 ISC_LOG_DEBUG(1),
4880 "no master file");
4881 } else if (result != DNS_R_NOMASTERFILE) {
4882 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4883 ISC_LOG_ERROR,
4884 "loading from master file %s "
4885 "failed: %s",
4886 zone->masterfile,
4887 dns_result_totext(result));
4888 }
4889 } else if (zone->type == dns_zone_primary &&
4890 inline_secure(zone) && result == ISC_R_FILENOTFOUND)
4891 {
4892 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4893 ISC_LOG_DEBUG(1),
4894 "no master file, requesting db");
4895 maybe_send_secure(zone);
4896 } else {
4897 int level = ISC_LOG_ERROR;
4898 if (zone->type == dns_zone_key &&
4899 result == ISC_R_FILENOTFOUND)
4900 {
4901 level = ISC_LOG_DEBUG(1);
4902 }
4903 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, level,
4904 "loading from master file %s failed: %s",
4905 zone->masterfile,
4906 dns_result_totext(result));
4907 nomaster = true;
4908 }
4909
4910 if (zone->type != dns_zone_key) {
4911 goto cleanup;
4912 }
4913 }
4914
4915 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(2),
4916 "number of nodes in database: %u", dns_db_nodecount(db));
4917
4918 if (result == DNS_R_SEENINCLUDE) {
4919 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
4920 } else {
4921 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
4922 }
4923
4924 /*
4925 * If there's no master file for a key zone, then the zone is new:
4926 * create an SOA record. (We do this now, instead of later, so that
4927 * if there happens to be a journal file, we can roll forward from
4928 * a sane starting point.)
4929 */
4930 if (nomaster && zone->type == dns_zone_key) {
4931 result = add_soa(zone, db);
4932 if (result != ISC_R_SUCCESS) {
4933 goto cleanup;
4934 }
4935 }
4936
4937 /*
4938 * Apply update log, if any, on initial load.
4939 */
4940 if (zone->journal != NULL &&
4941 !DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE) &&
4942 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
4943 {
4944 result = zone_journal_rollforward(zone, db, &needdump,
4945 &fixjournal);
4946 if (result != ISC_R_SUCCESS) {
4947 goto cleanup;
4948 }
4949 }
4950
4951 /*
4952 * Obtain ns, soa and cname counts for top of zone.
4953 */
4954 INSIST(db != NULL);
4955 result = zone_get_from_db(zone, db, &nscount, &soacount, &soattl,
4956 &serial, &refresh, &retry, &expire, &minimum,
4957 &errors);
4958 if (result != ISC_R_SUCCESS && zone->type != dns_zone_key) {
4959 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
4960 "could not find NS and/or SOA records");
4961 }
4962
4963 /*
4964 * Process any queued NSEC3PARAM change requests. Only for dynamic
4965 * zones, an inline-signing zone will perform this action when
4966 * receiving the secure db (receive_secure_db).
4967 */
4968 is_dynamic = dns_zone_isdynamic(zone, true);
4969 if (is_dynamic) {
4970 isc_event_t *setnsec3param_event;
4971 dns_zone_t *dummy;
4972
4973 while (!ISC_LIST_EMPTY(zone->setnsec3param_queue)) {
4974 setnsec3param_event =
4975 ISC_LIST_HEAD(zone->setnsec3param_queue);
4976 ISC_LIST_UNLINK(zone->setnsec3param_queue,
4977 setnsec3param_event, ev_link);
4978 dummy = NULL;
4979 zone_iattach(zone, &dummy);
4980 isc_task_send(zone->task, &setnsec3param_event);
4981 }
4982 }
4983
4984 /*
4985 * Check to make sure the journal is up to date, and remove the
4986 * journal file if it isn't, as we wouldn't be able to apply
4987 * updates otherwise.
4988 */
4989 if (zone->journal != NULL && is_dynamic &&
4990 !DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS))
4991 {
4992 uint32_t jserial;
4993 dns_journal_t *journal = NULL;
4994 bool empty = false;
4995
4996 result = dns_journal_open(zone->mctx, zone->journal,
4997 DNS_JOURNAL_READ, &journal);
4998 if (result == ISC_R_SUCCESS) {
4999 jserial = dns_journal_last_serial(journal);
5000 empty = dns_journal_empty(journal);
5001 dns_journal_destroy(&journal);
5002 } else {
5003 jserial = serial;
5004 result = ISC_R_SUCCESS;
5005 }
5006
5007 if (jserial != serial) {
5008 if (!empty) {
5009 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5010 ISC_LOG_INFO,
5011 "journal file is out of date: "
5012 "removing journal file");
5013 }
5014 if (remove(zone->journal) < 0 && errno != ENOENT) {
5015 char strbuf[ISC_STRERRORSIZE];
5016 strerror_r(errno, strbuf, sizeof(strbuf));
5017 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
5018 DNS_LOGMODULE_ZONE,
5019 ISC_LOG_WARNING,
5020 "unable to remove journal "
5021 "'%s': '%s'",
5022 zone->journal, strbuf);
5023 }
5024 }
5025 }
5026
5027 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
5028 "loaded; checking validity");
5029
5030 /*
5031 * Master / Slave / Mirror / Stub zones require both NS and SOA records
5032 * at the top of the zone.
5033 */
5034
5035 switch (zone->type) {
5036 case dns_zone_dlz:
5037 case dns_zone_primary:
5038 case dns_zone_secondary:
5039 case dns_zone_mirror:
5040 case dns_zone_stub:
5041 case dns_zone_redirect:
5042 if (soacount != 1) {
5043 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5044 ISC_LOG_ERROR, "has %d SOA records",
5045 soacount);
5046 result = DNS_R_BADZONE;
5047 }
5048 if (nscount == 0) {
5049 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5050 ISC_LOG_ERROR, "has no NS records");
5051 result = DNS_R_BADZONE;
5052 }
5053 if (result != ISC_R_SUCCESS) {
5054 goto cleanup;
5055 }
5056 if (zone->type == dns_zone_primary && errors != 0) {
5057 result = DNS_R_BADZONE;
5058 goto cleanup;
5059 }
5060 if (zone->type != dns_zone_stub &&
5061 zone->type != dns_zone_redirect)
5062 {
5063 result = check_nsec3param(zone, db);
5064 if (result != ISC_R_SUCCESS) {
5065 goto cleanup;
5066 }
5067 }
5068 if (zone->type == dns_zone_primary &&
5069 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKINTEGRITY) &&
5070 !integrity_checks(zone, db))
5071 {
5072 result = DNS_R_BADZONE;
5073 goto cleanup;
5074 }
5075 if (zone->type == dns_zone_primary &&
5076 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRR) &&
5077 !zone_check_dup(zone, db))
5078 {
5079 result = DNS_R_BADZONE;
5080 goto cleanup;
5081 }
5082
5083 if (zone->type == dns_zone_primary) {
5084 result = dns_zone_cdscheck(zone, db, NULL);
5085 if (result != ISC_R_SUCCESS) {
5086 dns_zone_log(zone, ISC_LOG_ERROR,
5087 "CDS/CDNSKEY consistency checks "
5088 "failed");
5089 goto cleanup;
5090 }
5091 }
5092
5093 result = dns_zone_verifydb(zone, db, NULL);
5094 if (result != ISC_R_SUCCESS) {
5095 goto cleanup;
5096 }
5097
5098 if (zone->db != NULL) {
5099 unsigned int oldsoacount;
5100
5101 /*
5102 * This is checked in zone_replacedb() for slave zones
5103 * as they don't reload from disk.
5104 */
5105 result = zone_get_from_db(
5106 zone, zone->db, NULL, &oldsoacount, NULL,
5107 &oldserial, NULL, NULL, NULL, NULL, NULL);
5108 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5109 RUNTIME_CHECK(oldsoacount > 0U);
5110 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
5111 !isc_serial_gt(serial, oldserial))
5112 {
5113 uint32_t serialmin, serialmax;
5114
5115 INSIST(zone->type == dns_zone_primary);
5116 INSIST(zone->raw == NULL);
5117
5118 if (serial == oldserial &&
5119 zone_unchanged(zone->db, db, zone->mctx))
5120 {
5121 dns_zone_logc(zone,
5122 DNS_LOGCATEGORY_ZONELOAD,
5123 ISC_LOG_INFO,
5124 "ixfr-from-differences: "
5125 "unchanged");
5126 zone->loadtime = loadtime;
5127 goto done;
5128 }
5129
5130 serialmin = (oldserial + 1) & 0xffffffffU;
5131 serialmax = (oldserial + 0x7fffffffU) &
5132 0xffffffffU;
5133 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5134 ISC_LOG_ERROR,
5135 "ixfr-from-differences: "
5136 "new serial (%u) out of range "
5137 "[%u - %u]",
5138 serial, serialmin, serialmax);
5139 result = DNS_R_BADZONE;
5140 goto cleanup;
5141 } else if (!isc_serial_ge(serial, oldserial)) {
5142 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5143 ISC_LOG_ERROR,
5144 "zone serial (%u/%u) has gone "
5145 "backwards",
5146 serial, oldserial);
5147 } else if (serial == oldserial && !hasinclude &&
5148 strcmp(zone->db_argv[0], "_builtin") != 0)
5149 {
5150 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5151 ISC_LOG_ERROR,
5152 "zone serial (%u) unchanged. "
5153 "zone may fail to transfer "
5154 "to slaves.",
5155 serial);
5156 }
5157 }
5158
5159 if (zone->type == dns_zone_primary &&
5160 (zone->update_acl != NULL || zone->ssutable != NULL) &&
5161 dns_zone_getsigresigninginterval(zone) < (3 * refresh) &&
5162 dns_db_issecure(db))
5163 {
5164 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5165 ISC_LOG_WARNING,
5166 "sig-re-signing-interval less than "
5167 "3 * refresh.");
5168 }
5169
5170 zone->refresh = RANGE(refresh, zone->minrefresh,
5171 zone->maxrefresh);
5172 zone->retry = RANGE(retry, zone->minretry, zone->maxretry);
5173 zone->expire = RANGE(expire, zone->refresh + zone->retry,
5174 DNS_MAX_EXPIRE);
5175 zone->soattl = soattl;
5176 zone->minimum = minimum;
5177 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
5178
5179 if (zone->type == dns_zone_secondary ||
5180 zone->type == dns_zone_mirror ||
5181 zone->type == dns_zone_stub ||
5182 (zone->type == dns_zone_redirect && zone->masters != NULL))
5183 {
5184 isc_time_t t;
5185 uint32_t delay;
5186
5187 result = isc_file_getmodtime(zone->journal, &t);
5188 if (result != ISC_R_SUCCESS) {
5189 result = isc_file_getmodtime(zone->masterfile,
5190 &t);
5191 }
5192 if (result == ISC_R_SUCCESS) {
5193 DNS_ZONE_TIME_ADD(&t, zone->expire,
5194 &zone->expiretime);
5195 } else {
5196 DNS_ZONE_TIME_ADD(&now, zone->retry,
5197 &zone->expiretime);
5198 }
5199
5200 delay = (zone->retry -
5201 isc_random_uniform((zone->retry * 3) / 4));
5202 DNS_ZONE_TIME_ADD(&now, delay, &zone->refreshtime);
5203 if (isc_time_compare(&zone->refreshtime,
5204 &zone->expiretime) >= 0)
5205 {
5206 zone->refreshtime = now;
5207 }
5208 }
5209
5210 break;
5211
5212 case dns_zone_key:
5213 result = sync_keyzone(zone, db);
5214 if (result != ISC_R_SUCCESS) {
5215 goto cleanup;
5216 }
5217 break;
5218
5219 default:
5220 UNEXPECTED_ERROR(__FILE__, __LINE__, "unexpected zone type %d",
5221 zone->type);
5222 result = ISC_R_UNEXPECTED;
5223 goto cleanup;
5224 }
5225
5226 /*
5227 * Check for weak DNSKEY's.
5228 */
5229 if (zone->type == dns_zone_primary) {
5230 zone_check_dnskeys(zone, db);
5231 }
5232
5233 /*
5234 * Schedule DNSSEC key refresh.
5235 */
5236 if (zone->type == dns_zone_primary &&
5237 DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
5238 {
5239 zone->refreshkeytime = now;
5240 }
5241
5242 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
5243 if (zone->db != NULL) {
5244 had_db = true;
5245 result = zone_replacedb(zone, db, false);
5246 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
5247 if (result != ISC_R_SUCCESS) {
5248 goto cleanup;
5249 }
5250 } else {
5251 zone_attachdb(zone, db);
5252 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
5253 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED |
5254 DNS_ZONEFLG_NEEDSTARTUPNOTIFY);
5255 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SENDSECURE) &&
5256 inline_raw(zone))
5257 {
5258 if (zone->secure->db == NULL) {
5259 zone_send_securedb(zone, db);
5260 } else {
5261 zone_send_secureserial(zone, serial);
5262 }
5263 }
5264 }
5265
5266 /*
5267 * Finished loading inline-signing zone; need to get status
5268 * from the raw side now.
5269 */
5270 if (zone->type == dns_zone_primary && inline_secure(zone)) {
5271 maybe_send_secure(zone);
5272 }
5273
5274 result = ISC_R_SUCCESS;
5275
5276 if (fixjournal) {
5277 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FIXJOURNAL);
5278 zone_journal_compact(zone, zone->db, 0);
5279 }
5280 if (needdump) {
5281 if (zone->type == dns_zone_key) {
5282 zone_needdump(zone, 30);
5283 } else {
5284 zone_needdump(zone, DNS_DUMP_DELAY);
5285 }
5286 }
5287
5288 if (zone->task != NULL) {
5289 if (zone->type == dns_zone_primary) {
5290 set_resigntime(zone);
5291 resume_signingwithkey(zone);
5292 resume_addnsec3chain(zone);
5293 }
5294
5295 is_dynamic = dns_zone_isdynamic(zone, false);
5296 if (zone->type == dns_zone_primary &&
5297 !DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN) &&
5298 is_dynamic && dns_db_issecure(db))
5299 {
5300 dns_name_t *name;
5301 dns_fixedname_t fixed;
5302 dns_rdataset_t next;
5303
5304 dns_rdataset_init(&next);
5305 name = dns_fixedname_initname(&fixed);
5306
5307 result = dns_db_getsigningtime(db, &next, name);
5308 if (result == ISC_R_SUCCESS) {
5309 isc_stdtime_t timenow;
5310 char namebuf[DNS_NAME_FORMATSIZE];
5311 char typebuf[DNS_RDATATYPE_FORMATSIZE];
5312
5313 isc_stdtime_get(&timenow);
5314 dns_name_format(name, namebuf, sizeof(namebuf));
5315 dns_rdatatype_format(next.covers, typebuf,
5316 sizeof(typebuf));
5317 dnssec_log(
5318 zone, ISC_LOG_DEBUG(3),
5319 "next resign: %s/%s "
5320 "in %d seconds",
5321 namebuf, typebuf,
5322 next.resign - timenow -
5323 dns_zone_getsigresigninginterval(
5324 zone));
5325 dns_rdataset_disassociate(&next);
5326 } else {
5327 dnssec_log(zone, ISC_LOG_WARNING,
5328 "signed dynamic zone has no "
5329 "resign event scheduled");
5330 }
5331 }
5332
5333 zone_settimer(zone, &now);
5334 }
5335
5336 /*
5337 * Clear old include list.
5338 */
5339 for (inc = ISC_LIST_HEAD(zone->includes); inc != NULL;
5340 inc = ISC_LIST_HEAD(zone->includes))
5341 {
5342 ISC_LIST_UNLINK(zone->includes, inc, link);
5343 isc_mem_free(zone->mctx, inc->name);
5344 isc_mem_put(zone->mctx, inc, sizeof(*inc));
5345 }
5346 zone->nincludes = 0;
5347
5348 /*
5349 * Transfer new include list.
5350 */
5351 for (inc = ISC_LIST_HEAD(zone->newincludes); inc != NULL;
5352 inc = ISC_LIST_HEAD(zone->newincludes))
5353 {
5354 ISC_LIST_UNLINK(zone->newincludes, inc, link);
5355 ISC_LIST_APPEND(zone->includes, inc, link);
5356 zone->nincludes++;
5357 }
5358
5359 if (!dns_db_ispersistent(db)) {
5360 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_INFO,
5361 "loaded serial %u%s", serial,
5362 dns_db_issecure(db) ? " (DNSSEC signed)" : "");
5363 }
5364
5365 if (!had_db && zone->type == dns_zone_mirror) {
5366 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_INFO,
5367 "mirror zone is now in use");
5368 }
5369
5370 zone->loadtime = loadtime;
5371 goto done;
5372
5373 cleanup:
5374 if (zone->type == dns_zone_key && result != ISC_R_SUCCESS) {
5375 dnssec_log(zone, ISC_LOG_ERROR,
5376 "failed to initialize managed-keys (%s): "
5377 "DNSSEC validation is at risk",
5378 isc_result_totext(result));
5379 }
5380
5381 if (result != ISC_R_SUCCESS) {
5382 dns_zone_rpz_disable_db(zone, db);
5383 dns_zone_catz_disable_db(zone, db);
5384 }
5385
5386 for (inc = ISC_LIST_HEAD(zone->newincludes); inc != NULL;
5387 inc = ISC_LIST_HEAD(zone->newincludes))
5388 {
5389 ISC_LIST_UNLINK(zone->newincludes, inc, link);
5390 isc_mem_free(zone->mctx, inc->name);
5391 isc_mem_put(zone->mctx, inc, sizeof(*inc));
5392 }
5393 if (zone->type == dns_zone_secondary || zone->type == dns_zone_mirror ||
5394 zone->type == dns_zone_stub || zone->type == dns_zone_key ||
5395 (zone->type == dns_zone_redirect && zone->masters != NULL))
5396 {
5397 if (result != ISC_R_NOMEMORY) {
5398 if (zone->journal != NULL) {
5399 zone_saveunique(zone, zone->journal,
5400 "jn-XXXXXXXX");
5401 }
5402 if (zone->masterfile != NULL) {
5403 zone_saveunique(zone, zone->masterfile,
5404 "db-XXXXXXXX");
5405 }
5406 }
5407
5408 /* Mark the zone for immediate refresh. */
5409 zone->refreshtime = now;
5410 if (zone->task != NULL) {
5411 zone_settimer(zone, &now);
5412 }
5413 result = ISC_R_SUCCESS;
5414 } else if (zone->type == dns_zone_primary ||
5415 zone->type == dns_zone_redirect)
5416 {
5417 if (!(inline_secure(zone) && result == ISC_R_FILENOTFOUND)) {
5418 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5419 ISC_LOG_ERROR,
5420 "not loaded due to errors.");
5421 } else if (zone->type == dns_zone_primary) {
5422 result = ISC_R_SUCCESS;
5423 }
5424 }
5425
5426 done:
5427 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
5428 /*
5429 * If this is an inline-signed zone and we were called for the raw
5430 * zone, we need to clear DNS_ZONEFLG_LOADPENDING for the secure zone
5431 * as well, but only if this is a reload, not an initial zone load: in
5432 * the former case, zone_postload() will not be run for the secure
5433 * zone; in the latter case, it will be. Check which case we are
5434 * dealing with by consulting the DNS_ZONEFLG_LOADED flag for the
5435 * secure zone: if it is set, this must be a reload.
5436 */
5437 if (inline_raw(zone) && DNS_ZONE_FLAG(zone->secure, DNS_ZONEFLG_LOADED))
5438 {
5439 DNS_ZONE_CLRFLAG(zone->secure, DNS_ZONEFLG_LOADPENDING);
5440 /*
5441 * Re-start zone maintenance if it had been stalled
5442 * due to DNS_ZONEFLG_LOADPENDING being set when
5443 * zone_maintenance was called.
5444 */
5445 if (zone->secure->task != NULL) {
5446 zone_settimer(zone->secure, &now);
5447 }
5448 }
5449
5450 zone_debuglog(zone, "zone_postload", 99, "done");
5451
5452 return (result);
5453 }
5454
5455 static bool
5456 exit_check(dns_zone_t *zone) {
5457 REQUIRE(LOCKED_ZONE(zone));
5458
5459 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) &&
5460 isc_refcount_current(&zone->irefs) == 0)
5461 {
5462 /*
5463 * DNS_ZONEFLG_SHUTDOWN can only be set if erefs == 0.
5464 */
5465 INSIST(isc_refcount_current(&zone->erefs) == 0);
5466 return (true);
5467 }
5468 return (false);
5469 }
5470
5471 static bool
5472 zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
5473 dns_name_t *name, bool logit) {
5474 isc_result_t result;
5475 char namebuf[DNS_NAME_FORMATSIZE];
5476 char altbuf[DNS_NAME_FORMATSIZE];
5477 dns_fixedname_t fixed;
5478 dns_name_t *foundname;
5479 int level;
5480
5481 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOCHECKNS)) {
5482 return (true);
5483 }
5484
5485 if (zone->type == dns_zone_primary) {
5486 level = ISC_LOG_ERROR;
5487 } else {
5488 level = ISC_LOG_WARNING;
5489 }
5490
5491 foundname = dns_fixedname_initname(&fixed);
5492
5493 result = dns_db_find(db, name, version, dns_rdatatype_a, 0, 0, NULL,
5494 foundname, NULL, NULL);
5495 if (result == ISC_R_SUCCESS) {
5496 return (true);
5497 }
5498
5499 if (result == DNS_R_NXRRSET) {
5500 result = dns_db_find(db, name, version, dns_rdatatype_aaaa, 0,
5501 0, NULL, foundname, NULL, NULL);
5502 if (result == ISC_R_SUCCESS) {
5503 return (true);
5504 }
5505 }
5506
5507 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
5508 result == DNS_R_EMPTYNAME)
5509 {
5510 if (logit) {
5511 dns_name_format(name, namebuf, sizeof namebuf);
5512 dns_zone_log(zone, level,
5513 "NS '%s' has no address "
5514 "records (A or AAAA)",
5515 namebuf);
5516 }
5517 return (false);
5518 }
5519
5520 if (result == DNS_R_CNAME) {
5521 if (logit) {
5522 dns_name_format(name, namebuf, sizeof namebuf);
5523 dns_zone_log(zone, level,
5524 "NS '%s' is a CNAME "
5525 "(illegal)",
5526 namebuf);
5527 }
5528 return (false);
5529 }
5530
5531 if (result == DNS_R_DNAME) {
5532 if (logit) {
5533 dns_name_format(name, namebuf, sizeof namebuf);
5534 dns_name_format(foundname, altbuf, sizeof altbuf);
5535 dns_zone_log(zone, level,
5536 "NS '%s' is below a DNAME "
5537 "'%s' (illegal)",
5538 namebuf, altbuf);
5539 }
5540 return (false);
5541 }
5542
5543 return (true);
5544 }
5545
5546 static isc_result_t
5547 zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
5548 dns_dbversion_t *version, unsigned int *nscount,
5549 unsigned int *errors, bool logit) {
5550 isc_result_t result;
5551 unsigned int count = 0;
5552 unsigned int ecount = 0;
5553 dns_rdataset_t rdataset;
5554 dns_rdata_t rdata;
5555 dns_rdata_ns_t ns;
5556
5557 dns_rdataset_init(&rdataset);
5558 result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns,
5559 dns_rdatatype_none, 0, &rdataset, NULL);
5560 if (result == ISC_R_NOTFOUND) {
5561 INSIST(!dns_rdataset_isassociated(&rdataset));
5562 goto success;
5563 }
5564 if (result != ISC_R_SUCCESS) {
5565 INSIST(!dns_rdataset_isassociated(&rdataset));
5566 goto invalidate_rdataset;
5567 }
5568
5569 result = dns_rdataset_first(&rdataset);
5570 while (result == ISC_R_SUCCESS) {
5571 if (errors != NULL && zone->rdclass == dns_rdataclass_in &&
5572 (zone->type == dns_zone_primary ||
5573 zone->type == dns_zone_secondary ||
5574 zone->type == dns_zone_mirror))
5575 {
5576 dns_rdata_init(&rdata);
5577 dns_rdataset_current(&rdataset, &rdata);
5578 result = dns_rdata_tostruct(&rdata, &ns, NULL);
5579 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5580 if (dns_name_issubdomain(&ns.name, &zone->origin) &&
5581 !zone_check_ns(zone, db, version, &ns.name, logit))
5582 {
5583 ecount++;
5584 }
5585 }
5586 count++;
5587 result = dns_rdataset_next(&rdataset);
5588 }
5589 dns_rdataset_disassociate(&rdataset);
5590
5591 success:
5592 if (nscount != NULL) {
5593 *nscount = count;
5594 }
5595 if (errors != NULL) {
5596 *errors = ecount;
5597 }
5598
5599 result = ISC_R_SUCCESS;
5600
5601 invalidate_rdataset:
5602 dns_rdataset_invalidate(&rdataset);
5603
5604 return (result);
5605 }
5606
5607 #define SET_IF_NOT_NULL(obj, val) \
5608 if (obj != NULL) { \
5609 *obj = val; \
5610 }
5611
5612 #define SET_SOA_VALUES(soattl_v, serial_v, refresh_v, retry_v, expire_v, \
5613 minimum_v) \
5614 { \
5615 SET_IF_NOT_NULL(soattl, soattl_v); \
5616 SET_IF_NOT_NULL(serial, serial_v); \
5617 SET_IF_NOT_NULL(refresh, refresh_v); \
5618 SET_IF_NOT_NULL(retry, retry_v); \
5619 SET_IF_NOT_NULL(expire, expire_v); \
5620 SET_IF_NOT_NULL(minimum, minimum_v); \
5621 }
5622
5623 #define CLR_SOA_VALUES() \
5624 { \
5625 SET_SOA_VALUES(0, 0, 0, 0, 0, 0); \
5626 }
5627
5628 static isc_result_t
5629 zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
5630 unsigned int *soacount, uint32_t *soattl, uint32_t *serial,
5631 uint32_t *refresh, uint32_t *retry, uint32_t *expire,
5632 uint32_t *minimum) {
5633 isc_result_t result;
5634 unsigned int count = 0;
5635 dns_rdataset_t rdataset;
5636 dns_rdata_t rdata = DNS_RDATA_INIT;
5637
5638 dns_rdataset_init(&rdataset);
5639 result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
5640 dns_rdatatype_none, 0, &rdataset, NULL);
5641 if (result == ISC_R_NOTFOUND) {
5642 INSIST(!dns_rdataset_isassociated(&rdataset));
5643 result = ISC_R_SUCCESS;
5644 goto invalidate_rdataset;
5645 }
5646 if (result != ISC_R_SUCCESS) {
5647 INSIST(!dns_rdataset_isassociated(&rdataset));
5648 goto invalidate_rdataset;
5649 }
5650
5651 result = dns_rdataset_first(&rdataset);
5652 while (result == ISC_R_SUCCESS) {
5653 dns_rdata_init(&rdata);
5654 dns_rdataset_current(&rdataset, &rdata);
5655 count++;
5656 if (count == 1) {
5657 dns_rdata_soa_t soa;
5658 result = dns_rdata_tostruct(&rdata, &soa, NULL);
5659 SET_SOA_VALUES(rdataset.ttl, soa.serial, soa.refresh,
5660 soa.retry, soa.expire, soa.minimum);
5661 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5662 }
5663
5664 result = dns_rdataset_next(&rdataset);
5665 dns_rdata_reset(&rdata);
5666 }
5667 dns_rdataset_disassociate(&rdataset);
5668
5669 result = ISC_R_SUCCESS;
5670
5671 invalidate_rdataset:
5672 SET_IF_NOT_NULL(soacount, count);
5673 if (count == 0) {
5674 CLR_SOA_VALUES();
5675 }
5676
5677 dns_rdataset_invalidate(&rdataset);
5678
5679 return (result);
5680 }
5681
5682 /*
5683 * zone must be locked.
5684 */
5685 static isc_result_t
5686 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
5687 unsigned int *soacount, uint32_t *soattl, uint32_t *serial,
5688 uint32_t *refresh, uint32_t *retry, uint32_t *expire,
5689 uint32_t *minimum, unsigned int *errors) {
5690 isc_result_t result;
5691 isc_result_t answer = ISC_R_SUCCESS;
5692 dns_dbversion_t *version = NULL;
5693 dns_dbnode_t *node;
5694
5695 REQUIRE(db != NULL);
5696 REQUIRE(zone != NULL);
5697
5698 dns_db_currentversion(db, &version);
5699
5700 SET_IF_NOT_NULL(nscount, 0);
5701 SET_IF_NOT_NULL(soacount, 0);
5702 SET_IF_NOT_NULL(errors, 0);
5703 CLR_SOA_VALUES();
5704
5705 node = NULL;
5706 result = dns_db_findnode(db, &zone->origin, false, &node);
5707 if (result != ISC_R_SUCCESS) {
5708 answer = result;
5709 goto closeversion;
5710 }
5711
5712 if (nscount != NULL || errors != NULL) {
5713 result = zone_count_ns_rr(zone, db, node, version, nscount,
5714 errors, true);
5715 if (result != ISC_R_SUCCESS) {
5716 answer = result;
5717 }
5718 }
5719
5720 if (soacount != NULL || soattl != NULL || serial != NULL ||
5721 refresh != NULL || retry != NULL || expire != NULL ||
5722 minimum != NULL)
5723 {
5724 result = zone_load_soa_rr(db, node, version, soacount, soattl,
5725 serial, refresh, retry, expire,
5726 minimum);
5727 if (result != ISC_R_SUCCESS) {
5728 answer = result;
5729 }
5730 }
5731
5732 dns_db_detachnode(db, &node);
5733 closeversion:
5734 dns_db_closeversion(db, &version, false);
5735
5736 return (answer);
5737 }
5738
5739 void
5740 dns_zone_attach(dns_zone_t *source, dns_zone_t **target) {
5741 REQUIRE(DNS_ZONE_VALID(source));
5742 REQUIRE(target != NULL && *target == NULL);
5743 isc_refcount_increment(&source->erefs);
5744 *target = source;
5745 }
5746
5747 void
5748 dns_zone_detach(dns_zone_t **zonep) {
5749 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
5750
5751 dns_zone_t *zone = *zonep;
5752 *zonep = NULL;
5753
5754 if (isc_refcount_decrement(&zone->erefs) == 1) {
5755 isc_event_t *ev = &zone->ctlevent;
5756
5757 isc_refcount_destroy(&zone->erefs);
5758
5759 /*
5760 * Stop things being restarted after we cancel them below.
5761 */
5762 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
5763 dns_zone_log(zone, ISC_LOG_DEBUG(1),
5764 "final reference detached");
5765 if (zone->task != NULL) {
5766 /*
5767 * This zone has a task; it can clean
5768 * itself up asynchronously.
5769 */
5770 isc_task_send(zone->task, &ev);
5771 return;
5772 }
5773
5774 /*
5775 * This zone is unmanaged; we're probably running in
5776 * named-checkzone or a unit test. There's no task,
5777 * so we need to free it immediately.
5778 *
5779 * Unmanaged zones must not have null views; we have no way
5780 * of detaching from the view here without causing deadlock
5781 * because this code is called with the view already
5782 * locked.
5783 */
5784 INSIST(zone->view == NULL);
5785
5786 zone_shutdown(zone->task, ev);
5787 ev = NULL;
5788 }
5789 }
5790
5791 void
5792 dns_zone_iattach(dns_zone_t *source, dns_zone_t **target) {
5793 REQUIRE(DNS_ZONE_VALID(source));
5794
5795 LOCK_ZONE(source);
5796 zone_iattach(source, target);
5797 UNLOCK_ZONE(source);
5798 }
5799
5800 static void
5801 zone_iattach(dns_zone_t *source, dns_zone_t **target) {
5802 REQUIRE(DNS_ZONE_VALID(source));
5803 REQUIRE(LOCKED_ZONE(source));
5804 REQUIRE(target != NULL && *target == NULL);
5805 INSIST(isc_refcount_increment0(&source->irefs) +
5806 isc_refcount_current(&source->erefs) >
5807 0);
5808 *target = source;
5809 }
5810
5811 static void
5812 zone_idetach(dns_zone_t **zonep) {
5813 dns_zone_t *zone;
5814
5815 /*
5816 * 'zone' locked by caller.
5817 */
5818 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
5819 REQUIRE(LOCKED_ZONE(*zonep));
5820
5821 zone = *zonep;
5822 *zonep = NULL;
5823
5824 INSIST(isc_refcount_decrement(&zone->irefs) - 1 +
5825 isc_refcount_current(&zone->erefs) >
5826 0);
5827 }
5828
5829 void
5830 dns_zone_idetach(dns_zone_t **zonep) {
5831 dns_zone_t *zone;
5832
5833 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
5834
5835 zone = *zonep;
5836 *zonep = NULL;
5837
5838 if (isc_refcount_decrement(&zone->irefs) == 1) {
5839 bool free_needed;
5840 LOCK_ZONE(zone);
5841 free_needed = exit_check(zone);
5842 UNLOCK_ZONE(zone);
5843 if (free_needed) {
5844 zone_free(zone);
5845 }
5846 }
5847 }
5848
5849 isc_mem_t *
5850 dns_zone_getmctx(dns_zone_t *zone) {
5851 REQUIRE(DNS_ZONE_VALID(zone));
5852
5853 return (zone->mctx);
5854 }
5855
5856 dns_zonemgr_t *
5857 dns_zone_getmgr(dns_zone_t *zone) {
5858 REQUIRE(DNS_ZONE_VALID(zone));
5859
5860 return (zone->zmgr);
5861 }
5862
5863 void
5864 dns_zone_setkasp(dns_zone_t *zone, dns_kasp_t *kasp) {
5865 REQUIRE(DNS_ZONE_VALID(zone));
5866
5867 LOCK_ZONE(zone);
5868 if (zone->kasp != NULL) {
5869 dns_kasp_t *oldkasp = zone->kasp;
5870 zone->kasp = NULL;
5871 dns_kasp_detach(&oldkasp);
5872 }
5873 zone->kasp = kasp;
5874 UNLOCK_ZONE(zone);
5875 }
5876
5877 dns_kasp_t *
5878 dns_zone_getkasp(dns_zone_t *zone) {
5879 REQUIRE(DNS_ZONE_VALID(zone));
5880
5881 return (zone->kasp);
5882 }
5883
5884 void
5885 dns_zone_setoption(dns_zone_t *zone, dns_zoneopt_t option, bool value) {
5886 REQUIRE(DNS_ZONE_VALID(zone));
5887
5888 if (value) {
5889 DNS_ZONE_SETOPTION(zone, option);
5890 } else {
5891 DNS_ZONE_CLROPTION(zone, option);
5892 }
5893 }
5894
5895 dns_zoneopt_t
5896 dns_zone_getoptions(dns_zone_t *zone) {
5897 REQUIRE(DNS_ZONE_VALID(zone));
5898
5899 return (atomic_load_relaxed(&zone->options));
5900 }
5901
5902 void
5903 dns_zone_setkeyopt(dns_zone_t *zone, unsigned int keyopt, bool value) {
5904 REQUIRE(DNS_ZONE_VALID(zone));
5905
5906 if (value) {
5907 DNS_ZONEKEY_SETOPTION(zone, keyopt);
5908 } else {
5909 DNS_ZONEKEY_CLROPTION(zone, keyopt);
5910 }
5911 }
5912
5913 unsigned int
5914 dns_zone_getkeyopts(dns_zone_t *zone) {
5915 REQUIRE(DNS_ZONE_VALID(zone));
5916
5917 return (atomic_load_relaxed(&zone->keyopts));
5918 }
5919
5920 isc_result_t
5921 dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
5922 REQUIRE(DNS_ZONE_VALID(zone));
5923
5924 LOCK_ZONE(zone);
5925 zone->xfrsource4 = *xfrsource;
5926 UNLOCK_ZONE(zone);
5927
5928 return (ISC_R_SUCCESS);
5929 }
5930
5931 isc_sockaddr_t *
5932 dns_zone_getxfrsource4(dns_zone_t *zone) {
5933 REQUIRE(DNS_ZONE_VALID(zone));
5934 return (&zone->xfrsource4);
5935 }
5936
5937 isc_result_t
5938 dns_zone_setxfrsource4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5939 REQUIRE(DNS_ZONE_VALID(zone));
5940
5941 LOCK_ZONE(zone);
5942 zone->xfrsource4dscp = dscp;
5943 UNLOCK_ZONE(zone);
5944
5945 return (ISC_R_SUCCESS);
5946 }
5947
5948 isc_dscp_t
5949 dns_zone_getxfrsource4dscp(dns_zone_t *zone) {
5950 REQUIRE(DNS_ZONE_VALID(zone));
5951 return (zone->xfrsource4dscp);
5952 }
5953
5954 isc_result_t
5955 dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
5956 REQUIRE(DNS_ZONE_VALID(zone));
5957
5958 LOCK_ZONE(zone);
5959 zone->xfrsource6 = *xfrsource;
5960 UNLOCK_ZONE(zone);
5961
5962 return (ISC_R_SUCCESS);
5963 }
5964
5965 isc_sockaddr_t *
5966 dns_zone_getxfrsource6(dns_zone_t *zone) {
5967 REQUIRE(DNS_ZONE_VALID(zone));
5968 return (&zone->xfrsource6);
5969 }
5970
5971 isc_dscp_t
5972 dns_zone_getxfrsource6dscp(dns_zone_t *zone) {
5973 REQUIRE(DNS_ZONE_VALID(zone));
5974 return (zone->xfrsource6dscp);
5975 }
5976
5977 isc_result_t
5978 dns_zone_setxfrsource6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5979 REQUIRE(DNS_ZONE_VALID(zone));
5980
5981 LOCK_ZONE(zone);
5982 zone->xfrsource6dscp = dscp;
5983 UNLOCK_ZONE(zone);
5984
5985 return (ISC_R_SUCCESS);
5986 }
5987
5988 isc_result_t
5989 dns_zone_setaltxfrsource4(dns_zone_t *zone,
5990 const isc_sockaddr_t *altxfrsource) {
5991 REQUIRE(DNS_ZONE_VALID(zone));
5992
5993 LOCK_ZONE(zone);
5994 zone->altxfrsource4 = *altxfrsource;
5995 UNLOCK_ZONE(zone);
5996
5997 return (ISC_R_SUCCESS);
5998 }
5999
6000 isc_sockaddr_t *
6001 dns_zone_getaltxfrsource4(dns_zone_t *zone) {
6002 REQUIRE(DNS_ZONE_VALID(zone));
6003 return (&zone->altxfrsource4);
6004 }
6005
6006 isc_result_t
6007 dns_zone_setaltxfrsource4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
6008 REQUIRE(DNS_ZONE_VALID(zone));
6009
6010 LOCK_ZONE(zone);
6011 zone->altxfrsource4dscp = dscp;
6012 UNLOCK_ZONE(zone);
6013
6014 return (ISC_R_SUCCESS);
6015 }
6016
6017 isc_dscp_t
6018 dns_zone_getaltxfrsource4dscp(dns_zone_t *zone) {
6019 REQUIRE(DNS_ZONE_VALID(zone));
6020 return (zone->altxfrsource4dscp);
6021 }
6022
6023 isc_result_t
6024 dns_zone_setaltxfrsource6(dns_zone_t *zone,
6025 const isc_sockaddr_t *altxfrsource) {
6026 REQUIRE(DNS_ZONE_VALID(zone));
6027
6028 LOCK_ZONE(zone);
6029 zone->altxfrsource6 = *altxfrsource;
6030 UNLOCK_ZONE(zone);
6031
6032 return (ISC_R_SUCCESS);
6033 }
6034
6035 isc_sockaddr_t *
6036 dns_zone_getaltxfrsource6(dns_zone_t *zone) {
6037 REQUIRE(DNS_ZONE_VALID(zone));
6038 return (&zone->altxfrsource6);
6039 }
6040
6041 isc_result_t
6042 dns_zone_setaltxfrsource6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
6043 REQUIRE(DNS_ZONE_VALID(zone));
6044
6045 LOCK_ZONE(zone);
6046 zone->altxfrsource6dscp = dscp;
6047 UNLOCK_ZONE(zone);
6048
6049 return (ISC_R_SUCCESS);
6050 }
6051
6052 isc_dscp_t
6053 dns_zone_getaltxfrsource6dscp(dns_zone_t *zone) {
6054 REQUIRE(DNS_ZONE_VALID(zone));
6055 return (zone->altxfrsource6dscp);
6056 }
6057
6058 isc_result_t
6059 dns_zone_setparentalsrc4(dns_zone_t *zone, const isc_sockaddr_t *parentalsrc) {
6060 REQUIRE(DNS_ZONE_VALID(zone));
6061
6062 LOCK_ZONE(zone);
6063 zone->parentalsrc4 = *parentalsrc;
6064 UNLOCK_ZONE(zone);
6065
6066 return (ISC_R_SUCCESS);
6067 }
6068
6069 isc_sockaddr_t *
6070 dns_zone_getparentalsrc4(dns_zone_t *zone) {
6071 REQUIRE(DNS_ZONE_VALID(zone));
6072 return (&zone->parentalsrc4);
6073 }
6074
6075 isc_result_t
6076 dns_zone_setparentalsrc4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
6077 REQUIRE(DNS_ZONE_VALID(zone));
6078
6079 LOCK_ZONE(zone);
6080 zone->parentalsrc4dscp = dscp;
6081 UNLOCK_ZONE(zone);
6082
6083 return (ISC_R_SUCCESS);
6084 }
6085
6086 isc_dscp_t
6087 dns_zone_getparentalsrc4dscp(dns_zone_t *zone) {
6088 REQUIRE(DNS_ZONE_VALID(zone));
6089 return (zone->parentalsrc4dscp);
6090 }
6091
6092 isc_result_t
6093 dns_zone_setparentalsrc6(dns_zone_t *zone, const isc_sockaddr_t *parentalsrc) {
6094 REQUIRE(DNS_ZONE_VALID(zone));
6095
6096 LOCK_ZONE(zone);
6097 zone->parentalsrc6 = *parentalsrc;
6098 UNLOCK_ZONE(zone);
6099
6100 return (ISC_R_SUCCESS);
6101 }
6102
6103 isc_sockaddr_t *
6104 dns_zone_getparentalsrc6(dns_zone_t *zone) {
6105 REQUIRE(DNS_ZONE_VALID(zone));
6106 return (&zone->parentalsrc6);
6107 }
6108
6109 isc_result_t
6110 dns_zone_setparentalsrc6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
6111 REQUIRE(DNS_ZONE_VALID(zone));
6112
6113 LOCK_ZONE(zone);
6114 zone->parentalsrc6dscp = dscp;
6115 UNLOCK_ZONE(zone);
6116
6117 return (ISC_R_SUCCESS);
6118 }
6119
6120 isc_dscp_t
6121 dns_zone_getparentalsrc6dscp(dns_zone_t *zone) {
6122 REQUIRE(DNS_ZONE_VALID(zone));
6123 return (zone->parentalsrc6dscp);
6124 }
6125
6126 isc_result_t
6127 dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
6128 REQUIRE(DNS_ZONE_VALID(zone));
6129
6130 LOCK_ZONE(zone);
6131 zone->notifysrc4 = *notifysrc;
6132 UNLOCK_ZONE(zone);
6133
6134 return (ISC_R_SUCCESS);
6135 }
6136
6137 isc_sockaddr_t *
6138 dns_zone_getnotifysrc4(dns_zone_t *zone) {
6139 REQUIRE(DNS_ZONE_VALID(zone));
6140 return (&zone->notifysrc4);
6141 }
6142
6143 isc_result_t
6144 dns_zone_setnotifysrc4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
6145 REQUIRE(DNS_ZONE_VALID(zone));
6146
6147 LOCK_ZONE(zone);
6148 zone->notifysrc4dscp = dscp;
6149 UNLOCK_ZONE(zone);
6150
6151 return (ISC_R_SUCCESS);
6152 }
6153
6154 isc_dscp_t
6155 dns_zone_getnotifysrc4dscp(dns_zone_t *zone) {
6156 REQUIRE(DNS_ZONE_VALID(zone));
6157 return (zone->notifysrc4dscp);
6158 }
6159
6160 isc_result_t
6161 dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
6162 REQUIRE(DNS_ZONE_VALID(zone));
6163
6164 LOCK_ZONE(zone);
6165 zone->notifysrc6 = *notifysrc;
6166 UNLOCK_ZONE(zone);
6167
6168 return (ISC_R_SUCCESS);
6169 }
6170
6171 isc_sockaddr_t *
6172 dns_zone_getnotifysrc6(dns_zone_t *zone) {
6173 REQUIRE(DNS_ZONE_VALID(zone));
6174 return (&zone->notifysrc6);
6175 }
6176
6177 isc_result_t
6178 dns_zone_setnotifysrc6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
6179 REQUIRE(DNS_ZONE_VALID(zone));
6180
6181 LOCK_ZONE(zone);
6182 zone->notifysrc6dscp = dscp;
6183 UNLOCK_ZONE(zone);
6184
6185 return (ISC_R_SUCCESS);
6186 }
6187
6188 isc_dscp_t
6189 dns_zone_getnotifysrc6dscp(dns_zone_t *zone) {
6190 REQUIRE(DNS_ZONE_VALID(zone));
6191 return (zone->notifysrc6dscp);
6192 }
6193
6194 static bool
6195 same_addrs(isc_sockaddr_t const *oldlist, isc_sockaddr_t const *newlist,
6196 uint32_t count) {
6197 unsigned int i;
6198
6199 for (i = 0; i < count; i++) {
6200 if (!isc_sockaddr_equal(&oldlist[i], &newlist[i])) {
6201 return (false);
6202 }
6203 }
6204 return (true);
6205 }
6206
6207 static bool
6208 same_keynames(dns_name_t *const *oldlist, dns_name_t *const *newlist,
6209 uint32_t count) {
6210 unsigned int i;
6211
6212 if (oldlist == NULL && newlist == NULL) {
6213 return (true);
6214 }
6215 if (oldlist == NULL || newlist == NULL) {
6216 return (false);
6217 }
6218
6219 for (i = 0; i < count; i++) {
6220 if (oldlist[i] == NULL && newlist[i] == NULL) {
6221 continue;
6222 }
6223 if (oldlist[i] == NULL || newlist[i] == NULL ||
6224 !dns_name_equal(oldlist[i], newlist[i]))
6225 {
6226 return (false);
6227 }
6228 }
6229 return (true);
6230 }
6231
6232 static void
6233 clear_serverslist(isc_sockaddr_t **addrsp, isc_dscp_t **dscpsp,
6234 dns_name_t ***keynamesp, unsigned int *countp,
6235 isc_mem_t *mctx) {
6236 unsigned int count;
6237 isc_sockaddr_t *addrs;
6238 isc_dscp_t *dscps;
6239 dns_name_t **keynames;
6240
6241 REQUIRE(countp != NULL && addrsp != NULL && dscpsp != NULL &&
6242 keynamesp != NULL);
6243
6244 count = *countp;
6245 *countp = 0;
6246 addrs = *addrsp;
6247 *addrsp = NULL;
6248 dscps = *dscpsp;
6249 *dscpsp = NULL;
6250 keynames = *keynamesp;
6251 *keynamesp = NULL;
6252
6253 if (addrs != NULL) {
6254 isc_mem_put(mctx, addrs, count * sizeof(isc_sockaddr_t));
6255 }
6256
6257 if (dscps != NULL) {
6258 isc_mem_put(mctx, dscps, count * sizeof(isc_dscp_t));
6259 }
6260
6261 if (keynames != NULL) {
6262 unsigned int i;
6263 for (i = 0; i < count; i++) {
6264 if (keynames[i] != NULL) {
6265 dns_name_free(keynames[i], mctx);
6266 isc_mem_put(mctx, keynames[i],
6267 sizeof(dns_name_t));
6268 keynames[i] = NULL;
6269 }
6270 }
6271 isc_mem_put(mctx, keynames, count * sizeof(dns_name_t *));
6272 }
6273 }
6274
6275 static isc_result_t
6276 set_serverslist(unsigned int count, const isc_sockaddr_t *addrs,
6277 isc_sockaddr_t **newaddrsp, const isc_dscp_t *dscp,
6278 isc_dscp_t **newdscpp, dns_name_t **names,
6279 dns_name_t ***newnamesp, isc_mem_t *mctx) {
6280 isc_sockaddr_t *newaddrs = NULL;
6281 isc_dscp_t *newdscp = NULL;
6282 dns_name_t **newnames = NULL;
6283 unsigned int i;
6284
6285 REQUIRE(newaddrsp != NULL && *newaddrsp == NULL);
6286 REQUIRE(newdscpp != NULL && *newdscpp == NULL);
6287 REQUIRE(newnamesp != NULL && *newnamesp == NULL);
6288
6289 newaddrs = isc_mem_get(mctx, count * sizeof(*newaddrs));
6290 memmove(newaddrs, addrs, count * sizeof(*newaddrs));
6291
6292 if (dscp != NULL) {
6293 newdscp = isc_mem_get(mctx, count * sizeof(*newdscp));
6294 memmove(newdscp, dscp, count * sizeof(*newdscp));
6295 } else {
6296 newdscp = NULL;
6297 }
6298
6299 if (names != NULL) {
6300 newnames = isc_mem_get(mctx, count * sizeof(*newnames));
6301 for (i = 0; i < count; i++) {
6302 newnames[i] = NULL;
6303 }
6304 for (i = 0; i < count; i++) {
6305 if (names[i] != NULL) {
6306 newnames[i] = isc_mem_get(mctx,
6307 sizeof(dns_name_t));
6308 dns_name_init(newnames[i], NULL);
6309 dns_name_dup(names[i], mctx, newnames[i]);
6310 }
6311 }
6312 } else {
6313 newnames = NULL;
6314 }
6315
6316 *newdscpp = newdscp;
6317 *newaddrsp = newaddrs;
6318 *newnamesp = newnames;
6319 return (ISC_R_SUCCESS);
6320 }
6321
6322 isc_result_t
6323 dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify,
6324 uint32_t count) {
6325 return (dns_zone_setalsonotifydscpkeys(zone, notify, NULL, NULL,
6326 count));
6327 }
6328
6329 isc_result_t
6330 dns_zone_setalsonotifywithkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
6331 dns_name_t **keynames, uint32_t count) {
6332 return (dns_zone_setalsonotifydscpkeys(zone, notify, NULL, keynames,
6333 count));
6334 }
6335
6336 isc_result_t
6337 dns_zone_setalsonotifydscpkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
6338 const isc_dscp_t *dscps, dns_name_t **keynames,
6339 uint32_t count) {
6340 isc_result_t result;
6341 isc_sockaddr_t *newaddrs = NULL;
6342 isc_dscp_t *newdscps = NULL;
6343 dns_name_t **newnames = NULL;
6344
6345 REQUIRE(DNS_ZONE_VALID(zone));
6346 REQUIRE(count == 0 || notify != NULL);
6347 if (keynames != NULL) {
6348 REQUIRE(count != 0);
6349 }
6350
6351 LOCK_ZONE(zone);
6352
6353 if (count == zone->notifycnt &&
6354 same_addrs(zone->notify, notify, count) &&
6355 same_keynames(zone->notifykeynames, keynames, count))
6356 {
6357 goto unlock;
6358 }
6359
6360 clear_serverslist(&zone->notify, &zone->notifydscp,
6361 &zone->notifykeynames, &zone->notifycnt, zone->mctx);
6362
6363 if (count == 0) {
6364 goto unlock;
6365 }
6366
6367 /*
6368 * Set up the notify and notifykey lists
6369 */
6370 result = set_serverslist(count, notify, &newaddrs, dscps, &newdscps,
6371 keynames, &newnames, zone->mctx);
6372 if (result != ISC_R_SUCCESS) {
6373 goto unlock;
6374 }
6375
6376 /*
6377 * Everything is ok so attach to the zone.
6378 */
6379 zone->notify = newaddrs;
6380 zone->notifydscp = newdscps;
6381 zone->notifykeynames = newnames;
6382 zone->notifycnt = count;
6383 unlock:
6384 UNLOCK_ZONE(zone);
6385 return (ISC_R_SUCCESS);
6386 }
6387
6388 isc_result_t
6389 dns_zone_setprimaries(dns_zone_t *zone, const isc_sockaddr_t *masters,
6390 uint32_t count) {
6391 isc_result_t result;
6392
6393 result = dns_zone_setprimarieswithkeys(zone, masters, NULL, count);
6394 return (result);
6395 }
6396
6397 isc_result_t
6398 dns_zone_setprimarieswithkeys(dns_zone_t *zone, const isc_sockaddr_t *masters,
6399 dns_name_t **keynames, uint32_t count) {
6400 isc_result_t result = ISC_R_SUCCESS;
6401 isc_sockaddr_t *newaddrs = NULL;
6402 isc_dscp_t *newdscps = NULL;
6403 dns_name_t **newnames = NULL;
6404 bool *newok;
6405 unsigned int i;
6406
6407 REQUIRE(DNS_ZONE_VALID(zone));
6408 REQUIRE(count == 0 || masters != NULL);
6409 if (keynames != NULL) {
6410 REQUIRE(count != 0);
6411 }
6412
6413 LOCK_ZONE(zone);
6414 /*
6415 * The refresh code assumes that 'primaries' wouldn't change under it.
6416 * If it will change then kill off any current refresh in progress
6417 * and update the primaries info. If it won't change then we can just
6418 * unlock and exit.
6419 */
6420 if (count != zone->masterscnt ||
6421 !same_addrs(zone->masters, masters, count) ||
6422 !same_keynames(zone->masterkeynames, keynames, count))
6423 {
6424 if (zone->request != NULL) {
6425 dns_request_cancel(zone->request);
6426 }
6427 } else {
6428 goto unlock;
6429 }
6430
6431 /*
6432 * This needs to happen before clear_addresskeylist() sets
6433 * zone->masterscnt to 0:
6434 */
6435 if (zone->mastersok != NULL) {
6436 isc_mem_put(zone->mctx, zone->mastersok,
6437 zone->masterscnt * sizeof(bool));
6438 zone->mastersok = NULL;
6439 }
6440 clear_serverslist(&zone->masters, &zone->masterdscps,
6441 &zone->masterkeynames, &zone->masterscnt, zone->mctx);
6442 /*
6443 * If count == 0, don't allocate any space for masters, mastersok or
6444 * keynames so internally, those pointers are NULL if count == 0
6445 */
6446 if (count == 0) {
6447 goto unlock;
6448 }
6449
6450 /*
6451 * mastersok must contain count elements
6452 */
6453 newok = isc_mem_get(zone->mctx, count * sizeof(*newok));
6454 for (i = 0; i < count; i++) {
6455 newok[i] = false;
6456 }
6457
6458 /*
6459 * Now set up the primaries and primary key lists
6460 */
6461 result = set_serverslist(count, masters, &newaddrs, NULL, &newdscps,
6462 keynames, &newnames, zone->mctx);
6463 INSIST(newdscps == NULL);
6464 if (result != ISC_R_SUCCESS) {
6465 isc_mem_put(zone->mctx, newok, count * sizeof(*newok));
6466 goto unlock;
6467 }
6468
6469 /*
6470 * Everything is ok so attach to the zone.
6471 */
6472 zone->curmaster = 0;
6473 zone->mastersok = newok;
6474 zone->masters = newaddrs;
6475 zone->masterdscps = newdscps;
6476 zone->masterkeynames = newnames;
6477 zone->masterscnt = count;
6478 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS);
6479
6480 unlock:
6481 UNLOCK_ZONE(zone);
6482 return (result);
6483 }
6484
6485 isc_result_t
6486 dns_zone_setparentals(dns_zone_t *zone, const isc_sockaddr_t *parentals,
6487 dns_name_t **keynames, uint32_t count) {
6488 isc_result_t result = ISC_R_SUCCESS;
6489 isc_sockaddr_t *newaddrs = NULL;
6490 isc_dscp_t *newdscps = NULL;
6491 dns_name_t **newkeynames = NULL;
6492
6493 REQUIRE(DNS_ZONE_VALID(zone));
6494 REQUIRE(count == 0 || parentals != NULL);
6495 if (keynames != NULL) {
6496 REQUIRE(count != 0);
6497 }
6498
6499 LOCK_ZONE(zone);
6500
6501 clear_serverslist(&zone->parentals, &zone->parentaldscps,
6502 &zone->parentalkeynames, &zone->parentalscnt,
6503 zone->mctx);
6504 /*
6505 * If count == 0, don't allocate any space for parentals, or keynames
6506 * so internally, those pointers are NULL if count == 0
6507 */
6508 if (count == 0) {
6509 goto unlock;
6510 }
6511
6512 /*
6513 * Now set up the parentals and parental key lists
6514 */
6515 result = set_serverslist(count, parentals, &newaddrs, NULL, &newdscps,
6516 keynames, &newkeynames, zone->mctx);
6517 INSIST(newdscps == NULL);
6518 if (result != ISC_R_SUCCESS) {
6519 goto unlock;
6520 }
6521
6522 /*
6523 * Everything is ok so attach to the zone.
6524 */
6525 zone->parentals = newaddrs;
6526 zone->parentaldscps = newdscps;
6527 zone->parentalkeynames = newkeynames;
6528 zone->parentalscnt = count;
6529
6530 dns_zone_log(zone, ISC_LOG_NOTICE, "checkds: set %u parentals", count);
6531
6532 unlock:
6533 UNLOCK_ZONE(zone);
6534 return (result);
6535 }
6536
6537 isc_result_t
6538 dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) {
6539 isc_result_t result = ISC_R_SUCCESS;
6540
6541 REQUIRE(DNS_ZONE_VALID(zone));
6542
6543 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6544 if (zone->db == NULL) {
6545 result = DNS_R_NOTLOADED;
6546 } else {
6547 dns_db_attach(zone->db, dpb);
6548 }
6549 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6550
6551 return (result);
6552 }
6553
6554 void
6555 dns_zone_setdb(dns_zone_t *zone, dns_db_t *db) {
6556 REQUIRE(DNS_ZONE_VALID(zone));
6557 REQUIRE(zone->type == dns_zone_staticstub);
6558
6559 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
6560 REQUIRE(zone->db == NULL);
6561 dns_db_attach(db, &zone->db);
6562 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
6563 }
6564
6565 /*
6566 * Coordinates the starting of routine jobs.
6567 */
6568 void
6569 dns_zone_maintenance(dns_zone_t *zone) {
6570 const char me[] = "dns_zone_maintenance";
6571 isc_time_t now;
6572
6573 REQUIRE(DNS_ZONE_VALID(zone));
6574 ENTER;
6575
6576 LOCK_ZONE(zone);
6577 TIME_NOW(&now);
6578 zone_settimer(zone, &now);
6579 UNLOCK_ZONE(zone);
6580 }
6581
6582 static bool
6583 was_dumping(dns_zone_t *zone) {
6584 REQUIRE(LOCKED_ZONE(zone));
6585
6586 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
6587 return (true);
6588 }
6589
6590 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
6591 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
6592 isc_time_settoepoch(&zone->dumptime);
6593 return (false);
6594 }
6595
6596 /*%
6597 * Find up to 'maxkeys' DNSSEC keys used for signing version 'ver' of database
6598 * 'db' for zone 'zone' in its key directory, then load these keys into 'keys'.
6599 * Only load the public part of a given key if it is not active at timestamp
6600 * 'now'. Store the number of keys found in 'nkeys'.
6601 */
6602 isc_result_t
6603 dns__zone_findkeys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
6604 isc_stdtime_t now, isc_mem_t *mctx, unsigned int maxkeys,
6605 dst_key_t **keys, unsigned int *nkeys) {
6606 isc_result_t result;
6607 dns_dbnode_t *node = NULL;
6608 const char *directory = dns_zone_getkeydirectory(zone);
6609
6610 CHECK(dns_db_findnode(db, dns_db_origin(db), false, &node));
6611 memset(keys, 0, sizeof(*keys) * maxkeys);
6612
6613 dns_zone_lock_keyfiles(zone);
6614
6615 result = dns_dnssec_findzonekeys(db, ver, node, dns_db_origin(db),
6616 directory, now, mctx, maxkeys, keys,
6617 nkeys);
6618
6619 dns_zone_unlock_keyfiles(zone);
6620
6621 if (result == ISC_R_NOTFOUND) {
6622 result = ISC_R_SUCCESS;
6623 }
6624
6625 failure:
6626
6627 if (node != NULL) {
6628 dns_db_detachnode(db, &node);
6629 }
6630 return (result);
6631 }
6632
6633 /*%
6634 * Find DNSSEC keys used for signing zone with dnssec-policy. Load these keys
6635 * into 'keys'. Requires KASP to be locked.
6636 */
6637 isc_result_t
6638 dns_zone_getdnsseckeys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
6639 isc_stdtime_t now, dns_dnsseckeylist_t *keys) {
6640 isc_result_t result;
6641 const char *dir = dns_zone_getkeydirectory(zone);
6642 dns_dbnode_t *node = NULL;
6643 dns_dnsseckey_t *key, *key_next;
6644 dns_dnsseckeylist_t dnskeys;
6645 dns_name_t *origin = dns_zone_getorigin(zone);
6646 dns_kasp_t *kasp = dns_zone_getkasp(zone);
6647 dns_rdataset_t keyset;
6648
6649 REQUIRE(DNS_ZONE_VALID(zone));
6650 REQUIRE(kasp != NULL);
6651
6652 ISC_LIST_INIT(dnskeys);
6653
6654 dns_rdataset_init(&keyset);
6655
6656 CHECK(dns_db_findnode(db, origin, false, &node));
6657
6658 /* Get keys from private key files. */
6659 dns_zone_lock_keyfiles(zone);
6660 result = dns_dnssec_findmatchingkeys(origin, dir, now,
6661 dns_zone_getmctx(zone), keys);
6662 dns_zone_unlock_keyfiles(zone);
6663
6664 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
6665 goto failure;
6666 }
6667
6668 /* Get public keys (dnskeys). */
6669 dns_rdataset_init(&keyset);
6670 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
6671 dns_rdatatype_none, 0, &keyset, NULL);
6672 if (result == ISC_R_SUCCESS) {
6673 CHECK(dns_dnssec_keylistfromrdataset(
6674 origin, dir, dns_zone_getmctx(zone), &keyset, NULL,
6675 NULL, false, false, &dnskeys));
6676 } else if (result != ISC_R_NOTFOUND) {
6677 CHECK(result);
6678 }
6679
6680 /* Add new 'dnskeys' to 'keys'. */
6681 for (dns_dnsseckey_t *k1 = ISC_LIST_HEAD(dnskeys); k1 != NULL;
6682 k1 = key_next)
6683 {
6684 dns_dnsseckey_t *k2 = NULL;
6685 key_next = ISC_LIST_NEXT(k1, link);
6686
6687 for (k2 = ISC_LIST_HEAD(*keys); k2 != NULL;
6688 k2 = ISC_LIST_NEXT(k2, link))
6689 {
6690 if (dst_key_compare(k1->key, k2->key)) {
6691 break;
6692 }
6693 }
6694 /* No match found, add the new key. */
6695 if (k2 == NULL) {
6696 ISC_LIST_UNLINK(dnskeys, k1, link);
6697 ISC_LIST_APPEND(*keys, k1, link);
6698 }
6699 }
6700
6701 failure:
6702 if (dns_rdataset_isassociated(&keyset)) {
6703 dns_rdataset_disassociate(&keyset);
6704 }
6705 if (node != NULL) {
6706 dns_db_detachnode(db, &node);
6707 }
6708 while (!ISC_LIST_EMPTY(dnskeys)) {
6709 key = ISC_LIST_HEAD(dnskeys);
6710 ISC_LIST_UNLINK(dnskeys, key, link);
6711 dns_dnsseckey_destroy(dns_zone_getmctx(zone), &key);
6712 }
6713 return (result);
6714 }
6715
6716 static isc_result_t
6717 offline(dns_db_t *db, dns_dbversion_t *ver, dns__zonediff_t *zonediff,
6718 dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata) {
6719 isc_result_t result;
6720
6721 if ((rdata->flags & DNS_RDATA_OFFLINE) != 0) {
6722 return (ISC_R_SUCCESS);
6723 }
6724 result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_DELRESIGN,
6725 name, ttl, rdata);
6726 if (result != ISC_R_SUCCESS) {
6727 return (result);
6728 }
6729 rdata->flags |= DNS_RDATA_OFFLINE;
6730 result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_ADDRESIGN,
6731 name, ttl, rdata);
6732 zonediff->offline = true;
6733 return (result);
6734 }
6735
6736 static void
6737 set_key_expiry_warning(dns_zone_t *zone, isc_stdtime_t when,
6738 isc_stdtime_t now) {
6739 unsigned int delta;
6740 char timebuf[80];
6741
6742 LOCK_ZONE(zone);
6743 zone->key_expiry = when;
6744 if (when <= now) {
6745 dns_zone_log(zone, ISC_LOG_ERROR,
6746 "DNSKEY RRSIG(s) have expired");
6747 isc_time_settoepoch(&zone->keywarntime);
6748 } else if (when < now + 7 * 24 * 3600) {
6749 isc_time_t t;
6750 isc_time_set(&t, when, 0);
6751 isc_time_formattimestamp(&t, timebuf, 80);
6752 dns_zone_log(zone, ISC_LOG_WARNING,
6753 "DNSKEY RRSIG(s) will expire within 7 days: %s",
6754 timebuf);
6755 delta = when - now;
6756 delta--; /* loop prevention */
6757 delta /= 24 * 3600; /* to whole days */
6758 delta *= 24 * 3600; /* to seconds */
6759 isc_time_set(&zone->keywarntime, when - delta, 0);
6760 } else {
6761 isc_time_set(&zone->keywarntime, when - 7 * 24 * 3600, 0);
6762 isc_time_formattimestamp(&zone->keywarntime, timebuf, 80);
6763 dns_zone_log(zone, ISC_LOG_NOTICE, "setting keywarntime to %s",
6764 timebuf);
6765 }
6766 UNLOCK_ZONE(zone);
6767 }
6768
6769 /*
6770 * Helper function to del_sigs(). We don't want to delete RRSIGs that
6771 * have no new key.
6772 */
6773 static bool
6774 delsig_ok(dns_rdata_rrsig_t *rrsig_ptr, dst_key_t **keys, unsigned int nkeys,
6775 bool kasp, bool *warn) {
6776 unsigned int i = 0;
6777 isc_result_t ret;
6778 bool have_ksk = false, have_zsk = false;
6779 bool have_pksk = false, have_pzsk = false;
6780
6781 for (i = 0; i < nkeys; i++) {
6782 bool ksk, zsk;
6783
6784 if (have_pksk && have_ksk && have_pzsk && have_zsk) {
6785 break;
6786 }
6787
6788 if (rrsig_ptr->algorithm != dst_key_alg(keys[i])) {
6789 continue;
6790 }
6791
6792 ret = dst_key_getbool(keys[i], DST_BOOL_KSK, &ksk);
6793 if (ret != ISC_R_SUCCESS) {
6794 ksk = KSK(keys[i]);
6795 }
6796 ret = dst_key_getbool(keys[i], DST_BOOL_ZSK, &zsk);
6797 if (ret != ISC_R_SUCCESS) {
6798 zsk = !KSK(keys[i]);
6799 }
6800
6801 if (ksk) {
6802 have_ksk = true;
6803 if (dst_key_isprivate(keys[i])) {
6804 have_pksk = true;
6805 }
6806 }
6807 if (zsk) {
6808 have_zsk = true;
6809 if (dst_key_isprivate(keys[i])) {
6810 have_pzsk = true;
6811 }
6812 }
6813 }
6814
6815 if (have_zsk && have_ksk && !have_pzsk) {
6816 *warn = true;
6817 }
6818
6819 if (have_pksk && have_pzsk) {
6820 return (true);
6821 }
6822
6823 /*
6824 * Deleting the SOA RRSIG is always okay.
6825 */
6826 if (rrsig_ptr->covered == dns_rdatatype_soa) {
6827 return (true);
6828 }
6829
6830 /*
6831 * It's okay to delete a signature if there is an active key with the
6832 * same algorithm to replace it, unless that violates the DNSSEC
6833 * policy.
6834 */
6835 if (have_pksk || have_pzsk) {
6836 if (kasp && have_pzsk) {
6837 return (true);
6838 }
6839 return (!kasp);
6840 }
6841
6842 /*
6843 * Failing that, it is *not* okay to delete a signature
6844 * if the associated public key is still in the DNSKEY RRset
6845 */
6846 for (i = 0; i < nkeys; i++) {
6847 if ((rrsig_ptr->algorithm == dst_key_alg(keys[i])) &&
6848 (rrsig_ptr->keyid == dst_key_id(keys[i])))
6849 {
6850 return (false);
6851 }
6852 }
6853
6854 /*
6855 * But if the key is gone, then go ahead.
6856 */
6857 return (true);
6858 }
6859
6860 /*
6861 * Delete expired RRsigs and any RRsigs we are about to re-sign.
6862 * See also update.c:del_keysigs().
6863 */
6864 static isc_result_t
6865 del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
6866 dns_rdatatype_t type, dns__zonediff_t *zonediff, dst_key_t **keys,
6867 unsigned int nkeys, isc_stdtime_t now, bool incremental) {
6868 isc_result_t result;
6869 dns_dbnode_t *node = NULL;
6870 dns_rdataset_t rdataset;
6871 unsigned int i;
6872 dns_rdata_rrsig_t rrsig;
6873 bool kasp = (dns_zone_getkasp(zone) != NULL);
6874 bool found;
6875 int64_t timewarn = 0, timemaybe = 0;
6876
6877 dns_rdataset_init(&rdataset);
6878
6879 if (type == dns_rdatatype_nsec3) {
6880 result = dns_db_findnsec3node(db, name, false, &node);
6881 } else {
6882 result = dns_db_findnode(db, name, false, &node);
6883 }
6884 if (result == ISC_R_NOTFOUND) {
6885 return (ISC_R_SUCCESS);
6886 }
6887 if (result != ISC_R_SUCCESS) {
6888 goto failure;
6889 }
6890 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig, type,
6891 (isc_stdtime_t)0, &rdataset, NULL);
6892 dns_db_detachnode(db, &node);
6893
6894 if (result == ISC_R_NOTFOUND) {
6895 INSIST(!dns_rdataset_isassociated(&rdataset));
6896 return (ISC_R_SUCCESS);
6897 }
6898 if (result != ISC_R_SUCCESS) {
6899 INSIST(!dns_rdataset_isassociated(&rdataset));
6900 goto failure;
6901 }
6902
6903 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
6904 result = dns_rdataset_next(&rdataset))
6905 {
6906 dns_rdata_t rdata = DNS_RDATA_INIT;
6907
6908 dns_rdataset_current(&rdataset, &rdata);
6909 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
6910 RUNTIME_CHECK(result == ISC_R_SUCCESS);
6911
6912 if (type != dns_rdatatype_dnskey && type != dns_rdatatype_cds &&
6913 type != dns_rdatatype_cdnskey)
6914 {
6915 bool warn = false, deleted = false;
6916 if (delsig_ok(&rrsig, keys, nkeys, kasp, &warn)) {
6917 result = update_one_rr(db, ver, zonediff->diff,
6918 DNS_DIFFOP_DELRESIGN,
6919 name, rdataset.ttl,
6920 &rdata);
6921 if (result != ISC_R_SUCCESS) {
6922 break;
6923 }
6924 deleted = true;
6925 }
6926 if (warn && !deleted) {
6927 /*
6928 * At this point, we've got an RRSIG,
6929 * which is signed by an inactive key.
6930 * An administrator needs to provide a new
6931 * key/alg, but until that time, we want to
6932 * keep the old RRSIG. Marking the key as
6933 * offline will prevent us spinning waiting
6934 * for the private part.
6935 */
6936 if (incremental) {
6937 result = offline(db, ver, zonediff,
6938 name, rdataset.ttl,
6939 &rdata);
6940 if (result != ISC_R_SUCCESS) {
6941 break;
6942 }
6943 }
6944
6945 /*
6946 * Log the key id and algorithm of
6947 * the inactive key with no replacement
6948 */
6949 if (zone->log_key_expired_timer <= now) {
6950 char origin[DNS_NAME_FORMATSIZE];
6951 char algbuf[DNS_NAME_FORMATSIZE];
6952 dns_name_format(&zone->origin, origin,
6953 sizeof(origin));
6954 dns_secalg_format(rrsig.algorithm,
6955 algbuf,
6956 sizeof(algbuf));
6957 dns_zone_log(zone, ISC_LOG_WARNING,
6958 "Key %s/%s/%d "
6959 "missing or inactive "
6960 "and has no replacement: "
6961 "retaining signatures.",
6962 origin, algbuf,
6963 rrsig.keyid);
6964 zone->log_key_expired_timer = now +
6965 3600;
6966 }
6967 }
6968 continue;
6969 }
6970
6971 /*
6972 * KSK RRSIGs requires special processing.
6973 */
6974 found = false;
6975 for (i = 0; i < nkeys; i++) {
6976 if (rrsig.algorithm == dst_key_alg(keys[i]) &&
6977 rrsig.keyid == dst_key_id(keys[i]))
6978 {
6979 found = true;
6980 /*
6981 * Mark offline DNSKEY.
6982 * We want the earliest offline expire time
6983 * iff there is a new offline signature.
6984 */
6985 if (!dst_key_inactive(keys[i]) &&
6986 !dst_key_isprivate(keys[i]))
6987 {
6988 int64_t timeexpire = dns_time64_from32(
6989 rrsig.timeexpire);
6990 if (timewarn != 0 &&
6991 timewarn > timeexpire)
6992 {
6993 timewarn = timeexpire;
6994 }
6995 if (rdata.flags & DNS_RDATA_OFFLINE) {
6996 if (timemaybe == 0 ||
6997 timemaybe > timeexpire)
6998 {
6999 timemaybe = timeexpire;
7000 }
7001 break;
7002 }
7003 if (timewarn == 0) {
7004 timewarn = timemaybe;
7005 }
7006 if (timewarn == 0 ||
7007 timewarn > timeexpire)
7008 {
7009 timewarn = timeexpire;
7010 }
7011 result = offline(db, ver, zonediff,
7012 name, rdataset.ttl,
7013 &rdata);
7014 break;
7015 }
7016 result = update_one_rr(db, ver, zonediff->diff,
7017 DNS_DIFFOP_DELRESIGN,
7018 name, rdataset.ttl,
7019 &rdata);
7020 break;
7021 }
7022 }
7023
7024 /*
7025 * If there is not a matching DNSKEY then
7026 * delete the RRSIG.
7027 */
7028 if (!found) {
7029 result = update_one_rr(db, ver, zonediff->diff,
7030 DNS_DIFFOP_DELRESIGN, name,
7031 rdataset.ttl, &rdata);
7032 }
7033 if (result != ISC_R_SUCCESS) {
7034 break;
7035 }
7036 }
7037
7038 dns_rdataset_disassociate(&rdataset);
7039 if (result == ISC_R_NOMORE) {
7040 result = ISC_R_SUCCESS;
7041 }
7042 if (timewarn > 0) {
7043 isc_stdtime_t stdwarn = (isc_stdtime_t)timewarn;
7044 if (timewarn == stdwarn) {
7045 set_key_expiry_warning(zone, (isc_stdtime_t)timewarn,
7046 now);
7047 } else {
7048 dns_zone_log(zone, ISC_LOG_ERROR,
7049 "key expiry warning time out of range");
7050 }
7051 }
7052 failure:
7053 if (node != NULL) {
7054 dns_db_detachnode(db, &node);
7055 }
7056 return (result);
7057 }
7058
7059 static isc_result_t
7060 add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_zone_t *zone,
7061 dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
7062 unsigned int nkeys, isc_mem_t *mctx, isc_stdtime_t inception,
7063 isc_stdtime_t expire, bool check_ksk, bool keyset_kskonly) {
7064 isc_result_t result;
7065 dns_dbnode_t *node = NULL;
7066 dns_stats_t *dnssecsignstats;
7067 dns_rdataset_t rdataset;
7068 dns_rdata_t sig_rdata = DNS_RDATA_INIT;
7069 unsigned char data[1024]; /* XXX */
7070 isc_buffer_t buffer;
7071 unsigned int i, j;
7072 bool use_kasp = false;
7073
7074 if (dns_zone_getkasp(zone) != NULL) {
7075 check_ksk = false;
7076 keyset_kskonly = true;
7077 use_kasp = true;
7078 }
7079
7080 dns_rdataset_init(&rdataset);
7081 isc_buffer_init(&buffer, data, sizeof(data));
7082
7083 if (type == dns_rdatatype_nsec3) {
7084 result = dns_db_findnsec3node(db, name, false, &node);
7085 } else {
7086 result = dns_db_findnode(db, name, false, &node);
7087 }
7088 if (result == ISC_R_NOTFOUND) {
7089 return (ISC_R_SUCCESS);
7090 }
7091 if (result != ISC_R_SUCCESS) {
7092 goto failure;
7093 }
7094 result = dns_db_findrdataset(db, node, ver, type, 0, (isc_stdtime_t)0,
7095 &rdataset, NULL);
7096 dns_db_detachnode(db, &node);
7097 if (result == ISC_R_NOTFOUND) {
7098 INSIST(!dns_rdataset_isassociated(&rdataset));
7099 return (ISC_R_SUCCESS);
7100 }
7101 if (result != ISC_R_SUCCESS) {
7102 INSIST(!dns_rdataset_isassociated(&rdataset));
7103 goto failure;
7104 }
7105
7106 for (i = 0; i < nkeys; i++) {
7107 bool both = false;
7108
7109 /* Don't add signatures for offline or inactive keys */
7110 if (!dst_key_isprivate(keys[i])) {
7111 continue;
7112 }
7113 if (dst_key_inactive(keys[i])) {
7114 continue;
7115 }
7116
7117 if (check_ksk && !REVOKE(keys[i])) {
7118 bool have_ksk, have_nonksk;
7119 if (KSK(keys[i])) {
7120 have_ksk = true;
7121 have_nonksk = false;
7122 } else {
7123 have_ksk = false;
7124 have_nonksk = true;
7125 }
7126
7127 for (j = 0; j < nkeys; j++) {
7128 if (j == i || ALG(keys[i]) != ALG(keys[j])) {
7129 continue;
7130 }
7131
7132 /*
7133 * Don't consider inactive keys, however
7134 * the KSK may be temporary offline, so do
7135 * consider keys which private key files are
7136 * unavailable.
7137 */
7138 if (dst_key_inactive(keys[j])) {
7139 continue;
7140 }
7141
7142 if (REVOKE(keys[j])) {
7143 continue;
7144 }
7145 if (KSK(keys[j])) {
7146 have_ksk = true;
7147 } else if (dst_key_isprivate(keys[j])) {
7148 have_nonksk = true;
7149 }
7150 both = have_ksk && have_nonksk;
7151 if (both) {
7152 break;
7153 }
7154 }
7155 }
7156 if (use_kasp) {
7157 /*
7158 * A dnssec-policy is found. Check what RRsets this
7159 * key should sign.
7160 */
7161 isc_result_t kresult;
7162 isc_stdtime_t when;
7163 bool ksk = false;
7164 bool zsk = false;
7165 bool have_ksk = false;
7166 bool have_zsk = false;
7167
7168 kresult = dst_key_getbool(keys[i], DST_BOOL_KSK, &ksk);
7169 if (kresult != ISC_R_SUCCESS) {
7170 if (KSK(keys[i])) {
7171 ksk = true;
7172 }
7173 }
7174 kresult = dst_key_getbool(keys[i], DST_BOOL_ZSK, &zsk);
7175 if (kresult != ISC_R_SUCCESS) {
7176 if (!KSK(keys[i])) {
7177 zsk = true;
7178 }
7179 }
7180
7181 have_ksk = ksk;
7182 have_zsk = zsk;
7183 both = have_ksk && have_zsk;
7184
7185 for (j = 0; j < nkeys; j++) {
7186 if (both) {
7187 break;
7188 }
7189
7190 if (j == i || ALG(keys[i]) != ALG(keys[j])) {
7191 continue;
7192 }
7193
7194 /*
7195 * Don't consider inactive keys or offline keys.
7196 */
7197 if (!dst_key_isprivate(keys[j])) {
7198 continue;
7199 }
7200 if (dst_key_inactive(keys[j])) {
7201 continue;
7202 }
7203
7204 if (REVOKE(keys[j])) {
7205 continue;
7206 }
7207
7208 if (!have_ksk) {
7209 kresult = dst_key_getbool(keys[j],
7210 DST_BOOL_KSK,
7211 &have_ksk);
7212 if (kresult != ISC_R_SUCCESS) {
7213 if (KSK(keys[j])) {
7214 have_ksk = true;
7215 }
7216 }
7217 }
7218 if (!have_zsk) {
7219 kresult = dst_key_getbool(keys[j],
7220 DST_BOOL_ZSK,
7221 &have_zsk);
7222 if (kresult != ISC_R_SUCCESS) {
7223 if (!KSK(keys[j])) {
7224 have_zsk = true;
7225 }
7226 }
7227 }
7228 both = have_ksk && have_zsk;
7229 }
7230
7231 if (type == dns_rdatatype_dnskey ||
7232 type == dns_rdatatype_cdnskey ||
7233 type == dns_rdatatype_cds)
7234 {
7235 /*
7236 * DNSKEY RRset is signed with KSK.
7237 * CDS and CDNSKEY RRsets too (RFC 7344, 4.1).
7238 */
7239 if (!ksk) {
7240 continue;
7241 }
7242 } else if (!zsk) {
7243 /*
7244 * Other RRsets are signed with ZSK.
7245 */
7246 if (type != dns_rdatatype_soa &&
7247 type != zone->privatetype)
7248 {
7249 continue;
7250 }
7251 if (have_zsk) {
7252 continue;
7253 }
7254 } else if (!dst_key_is_signing(keys[i], DST_BOOL_ZSK,
7255 inception, &when))
7256 {
7257 /*
7258 * This key is not active for zone-signing.
7259 */
7260 continue;
7261 }
7262
7263 /*
7264 * If this key is revoked, it may only sign the
7265 * DNSKEY RRset.
7266 */
7267 if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey) {
7268 continue;
7269 }
7270 } else if (both) {
7271 /*
7272 * CDS and CDNSKEY are signed with KSK (RFC 7344, 4.1).
7273 */
7274 if (type == dns_rdatatype_dnskey ||
7275 type == dns_rdatatype_cdnskey ||
7276 type == dns_rdatatype_cds)
7277 {
7278 if (!KSK(keys[i]) && keyset_kskonly) {
7279 continue;
7280 }
7281 } else if (KSK(keys[i])) {
7282 continue;
7283 }
7284 } else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey) {
7285 continue;
7286 }
7287
7288 /* Calculate the signature, creating a RRSIG RDATA. */
7289 isc_buffer_clear(&buffer);
7290 CHECK(dns_dnssec_sign(name, &rdataset, keys[i], &inception,
7291 &expire, mctx, &buffer, &sig_rdata));
7292
7293 /* Update the database and journal with the RRSIG. */
7294 /* XXX inefficient - will cause dataset merging */
7295 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN, name,
7296 rdataset.ttl, &sig_rdata));
7297 dns_rdata_reset(&sig_rdata);
7298 isc_buffer_init(&buffer, data, sizeof(data));
7299
7300 /* Update DNSSEC sign statistics. */
7301 dnssecsignstats = dns_zone_getdnssecsignstats(zone);
7302 if (dnssecsignstats != NULL) {
7303 /* Generated a new signature. */
7304 dns_dnssecsignstats_increment(dnssecsignstats,
7305 ID(keys[i]),
7306 (uint8_t)ALG(keys[i]),
7307 dns_dnssecsignstats_sign);
7308 /* This is a refresh. */
7309 dns_dnssecsignstats_increment(
7310 dnssecsignstats, ID(keys[i]),
7311 (uint8_t)ALG(keys[i]),
7312 dns_dnssecsignstats_refresh);
7313 }
7314 }
7315
7316 failure:
7317 if (dns_rdataset_isassociated(&rdataset)) {
7318 dns_rdataset_disassociate(&rdataset);
7319 }
7320 if (node != NULL) {
7321 dns_db_detachnode(db, &node);
7322 }
7323 return (result);
7324 }
7325
7326 static void
7327 zone_resigninc(dns_zone_t *zone) {
7328 const char *me = "zone_resigninc";
7329 dns_db_t *db = NULL;
7330 dns_dbversion_t *version = NULL;
7331 dns_diff_t _sig_diff;
7332 dns__zonediff_t zonediff;
7333 dns_fixedname_t fixed;
7334 dns_name_t *name;
7335 dns_rdataset_t rdataset;
7336 dns_rdatatype_t covers;
7337 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
7338 bool check_ksk, keyset_kskonly = false;
7339 isc_result_t result;
7340 isc_stdtime_t now, inception, soaexpire, expire, fullexpire, stop;
7341 uint32_t sigvalidityinterval, expiryinterval;
7342 unsigned int i;
7343 unsigned int nkeys = 0;
7344 unsigned int resign;
7345
7346 ENTER;
7347
7348 dns_rdataset_init(&rdataset);
7349 dns_diff_init(zone->mctx, &_sig_diff);
7350 zonediff_init(&zonediff, &_sig_diff);
7351
7352 /*
7353 * Zone is frozen or automatic resigning is disabled.
7354 * Pause for 5 minutes.
7355 */
7356 if (zone->update_disabled ||
7357 DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN))
7358 {
7359 result = ISC_R_FAILURE;
7360 goto failure;
7361 }
7362
7363 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
7364 dns_db_attach(zone->db, &db);
7365 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7366
7367 result = dns_db_newversion(db, &version);
7368 if (result != ISC_R_SUCCESS) {
7369 dns_zone_log(zone, ISC_LOG_ERROR,
7370 "zone_resigninc:dns_db_newversion -> %s",
7371 dns_result_totext(result));
7372 goto failure;
7373 }
7374
7375 isc_stdtime_get(&now);
7376
7377 result = dns__zone_findkeys(zone, db, version, now, zone->mctx,
7378 DNS_MAXZONEKEYS, zone_keys, &nkeys);
7379 if (result != ISC_R_SUCCESS) {
7380 dns_zone_log(zone, ISC_LOG_ERROR,
7381 "zone_resigninc:dns__zone_findkeys -> %s",
7382 dns_result_totext(result));
7383 goto failure;
7384 }
7385
7386 sigvalidityinterval = dns_zone_getsigvalidityinterval(zone);
7387 inception = now - 3600; /* Allow for clock skew. */
7388 soaexpire = now + sigvalidityinterval;
7389 expiryinterval = dns_zone_getsigresigninginterval(zone);
7390 if (expiryinterval > sigvalidityinterval) {
7391 expiryinterval = sigvalidityinterval;
7392 } else {
7393 expiryinterval = sigvalidityinterval - expiryinterval;
7394 }
7395
7396 /*
7397 * Spread out signatures over time if they happen to be
7398 * clumped. We don't do this for each add_sigs() call as
7399 * we still want some clustering to occur. In normal operations
7400 * the records should be re-signed as they fall due and they should
7401 * already be spread out. However if the server is off for a
7402 * period we need to ensure that the clusters don't become
7403 * synchronised by using the full jitter range.
7404 */
7405 if (sigvalidityinterval >= 3600U) {
7406 uint32_t normaljitter, fulljitter;
7407 if (sigvalidityinterval > 7200U) {
7408 normaljitter = isc_random_uniform(3600);
7409 fulljitter = isc_random_uniform(expiryinterval);
7410 } else {
7411 normaljitter = fulljitter = isc_random_uniform(1200);
7412 }
7413 expire = soaexpire - normaljitter - 1;
7414 fullexpire = soaexpire - fulljitter - 1;
7415 } else {
7416 expire = fullexpire = soaexpire - 1;
7417 }
7418 stop = now + 5;
7419
7420 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
7421 keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
7422
7423 name = dns_fixedname_initname(&fixed);
7424 result = dns_db_getsigningtime(db, &rdataset, name);
7425 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
7426 dns_zone_log(zone, ISC_LOG_ERROR,
7427 "zone_resigninc:dns_db_getsigningtime -> %s",
7428 dns_result_totext(result));
7429 }
7430
7431 i = 0;
7432 while (result == ISC_R_SUCCESS) {
7433 resign = rdataset.resign -
7434 dns_zone_getsigresigninginterval(zone);
7435 covers = rdataset.covers;
7436 dns_rdataset_disassociate(&rdataset);
7437
7438 /*
7439 * Stop if we hit the SOA as that means we have walked the
7440 * entire zone. The SOA record should always be the most
7441 * recent signature.
7442 */
7443 /* XXXMPA increase number of RRsets signed pre call */
7444 if ((covers == dns_rdatatype_soa &&
7445 dns_name_equal(name, &zone->origin)) ||
7446 i++ > zone->signatures || resign > stop)
7447 {
7448 break;
7449 }
7450
7451 result = del_sigs(zone, db, version, name, covers, &zonediff,
7452 zone_keys, nkeys, now, true);
7453 if (result != ISC_R_SUCCESS) {
7454 dns_zone_log(zone, ISC_LOG_ERROR,
7455 "zone_resigninc:del_sigs -> %s",
7456 dns_result_totext(result));
7457 break;
7458 }
7459
7460 /*
7461 * If re-signing is over 5 minutes late use 'fullexpire'
7462 * to redistribute the signature over the complete
7463 * re-signing window, otherwise only add a small amount
7464 * of jitter.
7465 */
7466 result = add_sigs(db, version, name, zone, covers,
7467 zonediff.diff, zone_keys, nkeys, zone->mctx,
7468 inception,
7469 resign > (now - 300) ? expire : fullexpire,
7470 check_ksk, keyset_kskonly);
7471 if (result != ISC_R_SUCCESS) {
7472 dns_zone_log(zone, ISC_LOG_ERROR,
7473 "zone_resigninc:add_sigs -> %s",
7474 dns_result_totext(result));
7475 break;
7476 }
7477 result = dns_db_getsigningtime(db, &rdataset, name);
7478 if (nkeys == 0 && result == ISC_R_NOTFOUND) {
7479 result = ISC_R_SUCCESS;
7480 break;
7481 }
7482 if (result != ISC_R_SUCCESS) {
7483 dns_zone_log(zone, ISC_LOG_ERROR,
7484 "zone_resigninc:dns_db_getsigningtime -> "
7485 "%s",
7486 dns_result_totext(result));
7487 }
7488 }
7489
7490 if (result != ISC_R_NOMORE && result != ISC_R_SUCCESS) {
7491 goto failure;
7492 }
7493
7494 result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
7495 &zonediff, zone_keys, nkeys, now, true);
7496 if (result != ISC_R_SUCCESS) {
7497 dns_zone_log(zone, ISC_LOG_ERROR,
7498 "zone_resigninc:del_sigs -> %s",
7499 dns_result_totext(result));
7500 goto failure;
7501 }
7502
7503 /*
7504 * Did we change anything in the zone?
7505 */
7506 if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
7507 /*
7508 * Commit the changes if any key has been marked as offline.
7509 */
7510 if (zonediff.offline) {
7511 dns_db_closeversion(db, &version, true);
7512 }
7513 goto failure;
7514 }
7515
7516 /* Increment SOA serial if we have made changes */
7517 result = update_soa_serial(zone, db, version, zonediff.diff, zone->mctx,
7518 zone->updatemethod);
7519 if (result != ISC_R_SUCCESS) {
7520 dns_zone_log(zone, ISC_LOG_ERROR,
7521 "zone_resigninc:update_soa_serial -> %s",
7522 dns_result_totext(result));
7523 goto failure;
7524 }
7525
7526 /*
7527 * Generate maximum life time signatures so that the above loop
7528 * termination is sensible.
7529 */
7530 result = add_sigs(db, version, &zone->origin, zone, dns_rdatatype_soa,
7531 zonediff.diff, zone_keys, nkeys, zone->mctx,
7532 inception, soaexpire, check_ksk, keyset_kskonly);
7533 if (result != ISC_R_SUCCESS) {
7534 dns_zone_log(zone, ISC_LOG_ERROR,
7535 "zone_resigninc:add_sigs -> %s",
7536 dns_result_totext(result));
7537 goto failure;
7538 }
7539
7540 /* Write changes to journal file. */
7541 CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_resigninc"));
7542
7543 /* Everything has succeeded. Commit the changes. */
7544 dns_db_closeversion(db, &version, true);
7545
7546 failure:
7547 dns_diff_clear(&_sig_diff);
7548 for (i = 0; i < nkeys; i++) {
7549 dst_key_free(&zone_keys[i]);
7550 }
7551 if (version != NULL) {
7552 dns_db_closeversion(db, &version, false);
7553 dns_db_detach(&db);
7554 } else if (db != NULL) {
7555 dns_db_detach(&db);
7556 }
7557
7558 LOCK_ZONE(zone);
7559 if (result == ISC_R_SUCCESS) {
7560 set_resigntime(zone);
7561 zone_needdump(zone, DNS_DUMP_DELAY);
7562 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
7563 } else {
7564 /*
7565 * Something failed. Retry in 5 minutes.
7566 */
7567 isc_interval_t ival;
7568 isc_interval_set(&ival, 300, 0);
7569 isc_time_nowplusinterval(&zone->resigntime, &ival);
7570 }
7571 UNLOCK_ZONE(zone);
7572
7573 INSIST(version == NULL);
7574 }
7575
7576 static isc_result_t
7577 next_active(dns_db_t *db, dns_dbversion_t *version, dns_name_t *oldname,
7578 dns_name_t *newname, bool bottom) {
7579 isc_result_t result;
7580 dns_dbiterator_t *dbit = NULL;
7581 dns_rdatasetiter_t *rdsit = NULL;
7582 dns_dbnode_t *node = NULL;
7583
7584 CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit));
7585 CHECK(dns_dbiterator_seek(dbit, oldname));
7586 do {
7587 result = dns_dbiterator_next(dbit);
7588 if (result == ISC_R_NOMORE) {
7589 CHECK(dns_dbiterator_first(dbit));
7590 }
7591 CHECK(dns_dbiterator_current(dbit, &node, newname));
7592 if (bottom && dns_name_issubdomain(newname, oldname) &&
7593 !dns_name_equal(newname, oldname))
7594 {
7595 dns_db_detachnode(db, &node);
7596 continue;
7597 }
7598 /*
7599 * Is this node empty?
7600 */
7601 CHECK(dns_db_allrdatasets(db, node, version, 0, 0, &rdsit));
7602 result = dns_rdatasetiter_first(rdsit);
7603 dns_db_detachnode(db, &node);
7604 dns_rdatasetiter_destroy(&rdsit);
7605 if (result != ISC_R_NOMORE) {
7606 break;
7607 }
7608 } while (1);
7609 failure:
7610 if (node != NULL) {
7611 dns_db_detachnode(db, &node);
7612 }
7613 if (dbit != NULL) {
7614 dns_dbiterator_destroy(&dbit);
7615 }
7616 return (result);
7617 }
7618
7619 static bool
7620 signed_with_good_key(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
7621 dns_dbversion_t *version, dns_rdatatype_t type,
7622 dst_key_t *key) {
7623 isc_result_t result;
7624 dns_rdataset_t rdataset;
7625 dns_rdata_t rdata = DNS_RDATA_INIT;
7626 dns_rdata_rrsig_t rrsig;
7627 int count = 0;
7628 dns_kasp_t *kasp = dns_zone_getkasp(zone);
7629
7630 dns_rdataset_init(&rdataset);
7631 result = dns_db_findrdataset(db, node, version, dns_rdatatype_rrsig,
7632 type, 0, &rdataset, NULL);
7633 if (result != ISC_R_SUCCESS) {
7634 INSIST(!dns_rdataset_isassociated(&rdataset));
7635 return (false);
7636 }
7637 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
7638 result = dns_rdataset_next(&rdataset))
7639 {
7640 dns_rdataset_current(&rdataset, &rdata);
7641 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
7642 INSIST(result == ISC_R_SUCCESS);
7643 if (rrsig.algorithm == dst_key_alg(key) &&
7644 rrsig.keyid == dst_key_id(key))
7645 {
7646 dns_rdataset_disassociate(&rdataset);
7647 return (true);
7648 }
7649 if (rrsig.algorithm == dst_key_alg(key)) {
7650 count++;
7651 }
7652 dns_rdata_reset(&rdata);
7653 }
7654
7655 if (dns_zone_getkasp(zone) != NULL) {
7656 dns_kasp_key_t *kkey;
7657 int zsk_count = 0;
7658 bool approved;
7659
7660 KASP_LOCK(kasp);
7661 for (kkey = ISC_LIST_HEAD(dns_kasp_keys(kasp)); kkey != NULL;
7662 kkey = ISC_LIST_NEXT(kkey, link))
7663 {
7664 if (dns_kasp_key_algorithm(kkey) != dst_key_alg(key)) {
7665 continue;
7666 }
7667 if (dns_kasp_key_zsk(kkey)) {
7668 zsk_count++;
7669 }
7670 }
7671 KASP_UNLOCK(kasp);
7672
7673 if (type == dns_rdatatype_dnskey ||
7674 type == dns_rdatatype_cdnskey || type == dns_rdatatype_cds)
7675 {
7676 /*
7677 * CDS and CDNSKEY are signed with KSK like DNSKEY.
7678 * (RFC 7344, section 4.1 specifies that they must
7679 * be signed with a key in the current DS RRset,
7680 * which would only include KSK's.)
7681 */
7682 approved = false;
7683 } else {
7684 approved = (zsk_count == count);
7685 }
7686
7687 dns_rdataset_disassociate(&rdataset);
7688 return (approved);
7689 }
7690
7691 dns_rdataset_disassociate(&rdataset);
7692 return (false);
7693 }
7694
7695 static isc_result_t
7696 add_nsec(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
7697 dns_dbnode_t *node, dns_ttl_t ttl, bool bottom, dns_diff_t *diff) {
7698 dns_fixedname_t fixed;
7699 dns_name_t *next;
7700 dns_rdata_t rdata = DNS_RDATA_INIT;
7701 isc_result_t result;
7702 unsigned char nsecbuffer[DNS_NSEC_BUFFERSIZE];
7703
7704 next = dns_fixedname_initname(&fixed);
7705
7706 CHECK(next_active(db, version, name, next, bottom));
7707 CHECK(dns_nsec_buildrdata(db, version, node, next, nsecbuffer, &rdata));
7708 CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADD, name, ttl,
7709 &rdata));
7710 failure:
7711 return (result);
7712 }
7713
7714 static isc_result_t
7715 check_if_bottom_of_zone(dns_db_t *db, dns_dbnode_t *node,
7716 dns_dbversion_t *version, bool *is_bottom_of_zone) {
7717 isc_result_t result;
7718 dns_rdatasetiter_t *iterator = NULL;
7719 dns_rdataset_t rdataset;
7720 bool seen_soa = false, seen_ns = false, seen_dname = false;
7721
7722 REQUIRE(is_bottom_of_zone != NULL);
7723
7724 result = dns_db_allrdatasets(db, node, version, 0, 0, &iterator);
7725 if (result != ISC_R_SUCCESS) {
7726 if (result == ISC_R_NOTFOUND) {
7727 result = ISC_R_SUCCESS;
7728 }
7729 return (result);
7730 }
7731
7732 dns_rdataset_init(&rdataset);
7733 for (result = dns_rdatasetiter_first(iterator); result == ISC_R_SUCCESS;
7734 result = dns_rdatasetiter_next(iterator))
7735 {
7736 dns_rdatasetiter_current(iterator, &rdataset);
7737 switch (rdataset.type) {
7738 case dns_rdatatype_soa:
7739 seen_soa = true;
7740 break;
7741 case dns_rdatatype_ns:
7742 seen_ns = true;
7743 break;
7744 case dns_rdatatype_dname:
7745 seen_dname = true;
7746 break;
7747 }
7748 dns_rdataset_disassociate(&rdataset);
7749 }
7750 if (result != ISC_R_NOMORE) {
7751 goto failure;
7752 }
7753 if ((seen_ns && !seen_soa) || seen_dname) {
7754 *is_bottom_of_zone = true;
7755 }
7756 result = ISC_R_SUCCESS;
7757
7758 failure:
7759 dns_rdatasetiter_destroy(&iterator);
7760
7761 return (result);
7762 }
7763
7764 static isc_result_t
7765 sign_a_node(dns_db_t *db, dns_zone_t *zone, dns_name_t *name,
7766 dns_dbnode_t *node, dns_dbversion_t *version, bool build_nsec3,
7767 bool build_nsec, dst_key_t *key, isc_stdtime_t inception,
7768 isc_stdtime_t expire, dns_ttl_t nsecttl, bool is_ksk, bool is_zsk,
7769 bool keyset_kskonly, bool is_bottom_of_zone, dns_diff_t *diff,
7770 int32_t *signatures, isc_mem_t *mctx) {
7771 isc_result_t result;
7772 dns_rdatasetiter_t *iterator = NULL;
7773 dns_rdataset_t rdataset;
7774 dns_rdata_t rdata = DNS_RDATA_INIT;
7775 dns_stats_t *dnssecsignstats;
7776
7777 isc_buffer_t buffer;
7778 unsigned char data[1024];
7779 bool seen_soa, seen_ns, seen_rr, seen_nsec, seen_nsec3, seen_ds;
7780
7781 result = dns_db_allrdatasets(db, node, version, 0, 0, &iterator);
7782 if (result != ISC_R_SUCCESS) {
7783 if (result == ISC_R_NOTFOUND) {
7784 result = ISC_R_SUCCESS;
7785 }
7786 return (result);
7787 }
7788
7789 dns_rdataset_init(&rdataset);
7790 isc_buffer_init(&buffer, data, sizeof(data));
7791 seen_rr = seen_soa = seen_ns = seen_nsec = seen_nsec3 = seen_ds = false;
7792 for (result = dns_rdatasetiter_first(iterator); result == ISC_R_SUCCESS;
7793 result = dns_rdatasetiter_next(iterator))
7794 {
7795 dns_rdatasetiter_current(iterator, &rdataset);
7796 if (rdataset.type == dns_rdatatype_soa) {
7797 seen_soa = true;
7798 } else if (rdataset.type == dns_rdatatype_ns) {
7799 seen_ns = true;
7800 } else if (rdataset.type == dns_rdatatype_ds) {
7801 seen_ds = true;
7802 } else if (rdataset.type == dns_rdatatype_nsec) {
7803 seen_nsec = true;
7804 } else if (rdataset.type == dns_rdatatype_nsec3) {
7805 seen_nsec3 = true;
7806 }
7807 if (rdataset.type != dns_rdatatype_rrsig) {
7808 seen_rr = true;
7809 }
7810 dns_rdataset_disassociate(&rdataset);
7811 }
7812 if (result != ISC_R_NOMORE) {
7813 goto failure;
7814 }
7815 /*
7816 * Going from insecure to NSEC3.
7817 * Don't generate NSEC3 records for NSEC3 records.
7818 */
7819 if (build_nsec3 && !seen_nsec3 && seen_rr) {
7820 bool unsecure = !seen_ds && seen_ns && !seen_soa;
7821 CHECK(dns_nsec3_addnsec3s(db, version, name, nsecttl, unsecure,
7822 diff));
7823 (*signatures)--;
7824 }
7825 /*
7826 * Going from insecure to NSEC.
7827 * Don't generate NSEC records for NSEC3 records.
7828 */
7829 if (build_nsec && !seen_nsec3 && !seen_nsec && seen_rr) {
7830 /*
7831 * Build a NSEC record except at the origin.
7832 */
7833 if (!dns_name_equal(name, dns_db_origin(db))) {
7834 CHECK(add_nsec(db, version, name, node, nsecttl,
7835 is_bottom_of_zone, diff));
7836 /* Count a NSEC generation as a signature generation. */
7837 (*signatures)--;
7838 }
7839 }
7840 result = dns_rdatasetiter_first(iterator);
7841 while (result == ISC_R_SUCCESS) {
7842 isc_stdtime_t when;
7843
7844 dns_rdatasetiter_current(iterator, &rdataset);
7845 if (rdataset.type == dns_rdatatype_soa ||
7846 rdataset.type == dns_rdatatype_rrsig)
7847 {
7848 goto next_rdataset;
7849 }
7850 if (rdataset.type == dns_rdatatype_dnskey ||
7851 rdataset.type == dns_rdatatype_cdnskey ||
7852 rdataset.type == dns_rdatatype_cds)
7853 {
7854 /*
7855 * CDS and CDNSKEY are signed with KSK like DNSKEY.
7856 * (RFC 7344, section 4.1 specifies that they must
7857 * be signed with a key in the current DS RRset,
7858 * which would only include KSK's.)
7859 */
7860 if (!is_ksk && keyset_kskonly) {
7861 goto next_rdataset;
7862 }
7863 } else if (!is_zsk) {
7864 goto next_rdataset;
7865 } else if (is_zsk && !dst_key_is_signing(key, DST_BOOL_ZSK,
7866 inception, &when))
7867 {
7868 /* Only applies to dnssec-policy. */
7869 if (dns_zone_getkasp(zone) != NULL) {
7870 goto next_rdataset;
7871 }
7872 }
7873
7874 if (seen_ns && !seen_soa && rdataset.type != dns_rdatatype_ds &&
7875 rdataset.type != dns_rdatatype_nsec)
7876 {
7877 goto next_rdataset;
7878 }
7879 if (signed_with_good_key(zone, db, node, version, rdataset.type,
7880 key))
7881 {
7882 goto next_rdataset;
7883 }
7884
7885 /* Calculate the signature, creating a RRSIG RDATA. */
7886 isc_buffer_clear(&buffer);
7887 CHECK(dns_dnssec_sign(name, &rdataset, key, &inception, &expire,
7888 mctx, &buffer, &rdata));
7889 /* Update the database and journal with the RRSIG. */
7890 /* XXX inefficient - will cause dataset merging */
7891 CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADDRESIGN,
7892 name, rdataset.ttl, &rdata));
7893 dns_rdata_reset(&rdata);
7894
7895 /* Update DNSSEC sign statistics. */
7896 dnssecsignstats = dns_zone_getdnssecsignstats(zone);
7897 if (dnssecsignstats != NULL) {
7898 /* Generated a new signature. */
7899 dns_dnssecsignstats_increment(dnssecsignstats, ID(key),
7900 ALG(key),
7901 dns_dnssecsignstats_sign);
7902 /* This is a refresh. */
7903 dns_dnssecsignstats_increment(
7904 dnssecsignstats, ID(key), ALG(key),
7905 dns_dnssecsignstats_refresh);
7906 }
7907
7908 (*signatures)--;
7909 next_rdataset:
7910 dns_rdataset_disassociate(&rdataset);
7911 result = dns_rdatasetiter_next(iterator);
7912 }
7913 if (result == ISC_R_NOMORE) {
7914 result = ISC_R_SUCCESS;
7915 }
7916 failure:
7917 if (dns_rdataset_isassociated(&rdataset)) {
7918 dns_rdataset_disassociate(&rdataset);
7919 }
7920 if (iterator != NULL) {
7921 dns_rdatasetiter_destroy(&iterator);
7922 }
7923 return (result);
7924 }
7925
7926 /*
7927 * If 'update_only' is set then don't create a NSEC RRset if it doesn't exist.
7928 */
7929 static isc_result_t
7930 updatesecure(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
7931 dns_ttl_t nsecttl, bool update_only, dns_diff_t *diff) {
7932 isc_result_t result;
7933 dns_rdataset_t rdataset;
7934 dns_dbnode_t *node = NULL;
7935
7936 CHECK(dns_db_getoriginnode(db, &node));
7937 if (update_only) {
7938 dns_rdataset_init(&rdataset);
7939 result = dns_db_findrdataset(
7940 db, node, version, dns_rdatatype_nsec,
7941 dns_rdatatype_none, 0, &rdataset, NULL);
7942 if (dns_rdataset_isassociated(&rdataset)) {
7943 dns_rdataset_disassociate(&rdataset);
7944 }
7945 if (result == ISC_R_NOTFOUND) {
7946 goto success;
7947 }
7948 if (result != ISC_R_SUCCESS) {
7949 goto failure;
7950 }
7951 }
7952 CHECK(delete_nsec(db, version, node, name, diff));
7953 CHECK(add_nsec(db, version, name, node, nsecttl, false, diff));
7954 success:
7955 result = ISC_R_SUCCESS;
7956 failure:
7957 if (node != NULL) {
7958 dns_db_detachnode(db, &node);
7959 }
7960 return (result);
7961 }
7962
7963 static isc_result_t
7964 updatesignwithkey(dns_zone_t *zone, dns_signing_t *signing,
7965 dns_dbversion_t *version, bool build_nsec3, dns_ttl_t nsecttl,
7966 dns_diff_t *diff) {
7967 isc_result_t result;
7968 dns_dbnode_t *node = NULL;
7969 dns_rdataset_t rdataset;
7970 dns_rdata_t rdata = DNS_RDATA_INIT;
7971 unsigned char data[5];
7972 bool seen_done = false;
7973 bool have_rr = false;
7974
7975 dns_rdataset_init(&rdataset);
7976 result = dns_db_getoriginnode(signing->db, &node);
7977 if (result != ISC_R_SUCCESS) {
7978 goto failure;
7979 }
7980
7981 result = dns_db_findrdataset(signing->db, node, version,
7982 zone->privatetype, dns_rdatatype_none, 0,
7983 &rdataset, NULL);
7984 if (result == ISC_R_NOTFOUND) {
7985 INSIST(!dns_rdataset_isassociated(&rdataset));
7986 result = ISC_R_SUCCESS;
7987 goto failure;
7988 }
7989 if (result != ISC_R_SUCCESS) {
7990 INSIST(!dns_rdataset_isassociated(&rdataset));
7991 goto failure;
7992 }
7993 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
7994 result = dns_rdataset_next(&rdataset))
7995 {
7996 dns_rdataset_current(&rdataset, &rdata);
7997 /*
7998 * If we don't match the algorithm or keyid skip the record.
7999 */
8000 if (rdata.length != 5 || rdata.data[0] != signing->algorithm ||
8001 rdata.data[1] != ((signing->keyid >> 8) & 0xff) ||
8002 rdata.data[2] != (signing->keyid & 0xff))
8003 {
8004 have_rr = true;
8005 dns_rdata_reset(&rdata);
8006 continue;
8007 }
8008 /*
8009 * We have a match. If we were signing (!signing->deleteit)
8010 * and we already have a record indicating that we have
8011 * finished signing (rdata.data[4] != 0) then keep it.
8012 * Otherwise it needs to be deleted as we have removed all
8013 * the signatures (signing->deleteit), so any record indicating
8014 * completion is now out of date, or we have finished signing
8015 * with the new record so we no longer need to remember that
8016 * we need to sign the zone with the matching key across a
8017 * nameserver re-start.
8018 */
8019 if (!signing->deleteit && rdata.data[4] != 0) {
8020 seen_done = true;
8021 have_rr = true;
8022 } else {
8023 CHECK(update_one_rr(signing->db, version, diff,
8024 DNS_DIFFOP_DEL, &zone->origin,
8025 rdataset.ttl, &rdata));
8026 }
8027 dns_rdata_reset(&rdata);
8028 }
8029 if (result == ISC_R_NOMORE) {
8030 result = ISC_R_SUCCESS;
8031 }
8032 if (!signing->deleteit && !seen_done) {
8033 /*
8034 * If we were signing then we need to indicate that we have
8035 * finished signing the zone with this key. If it is already
8036 * there we don't need to add it a second time.
8037 */
8038 data[0] = signing->algorithm;
8039 data[1] = (signing->keyid >> 8) & 0xff;
8040 data[2] = signing->keyid & 0xff;
8041 data[3] = 0;
8042 data[4] = 1;
8043 rdata.length = sizeof(data);
8044 rdata.data = data;
8045 rdata.type = zone->privatetype;
8046 rdata.rdclass = dns_db_class(signing->db);
8047 CHECK(update_one_rr(signing->db, version, diff, DNS_DIFFOP_ADD,
8048 &zone->origin, rdataset.ttl, &rdata));
8049 } else if (!have_rr) {
8050 dns_name_t *origin = dns_db_origin(signing->db);
8051 /*
8052 * Rebuild the NSEC/NSEC3 record for the origin as we no
8053 * longer have any private records.
8054 */
8055 if (build_nsec3) {
8056 CHECK(dns_nsec3_addnsec3s(signing->db, version, origin,
8057 nsecttl, false, diff));
8058 }
8059 CHECK(updatesecure(signing->db, version, origin, nsecttl, true,
8060 diff));
8061 }
8062
8063 failure:
8064 if (dns_rdataset_isassociated(&rdataset)) {
8065 dns_rdataset_disassociate(&rdataset);
8066 }
8067 if (node != NULL) {
8068 dns_db_detachnode(signing->db, &node);
8069 }
8070 return (result);
8071 }
8072
8073 /*
8074 * Called from zone_nsec3chain() in order to update zone records indicating
8075 * processing status of given NSEC3 chain:
8076 *
8077 * - If the supplied dns_nsec3chain_t structure has been fully processed
8078 * (which is indicated by "active" being set to false):
8079 *
8080 * - remove all NSEC3PARAM records matching the relevant NSEC3 chain,
8081 *
8082 * - remove all private-type records containing NSEC3PARAM RDATA matching
8083 * the relevant NSEC3 chain.
8084 *
8085 * - If the supplied dns_nsec3chain_t structure has not been fully processed
8086 * (which is indicated by "active" being set to true), only remove the
8087 * NSEC3PARAM record which matches the relevant NSEC3 chain and has the
8088 * "flags" field set to 0.
8089 *
8090 * - If given NSEC3 chain is being added, add an NSEC3PARAM record contained
8091 * in the relevant private-type record, but with the "flags" field set to
8092 * 0, indicating that this NSEC3 chain is now complete for this zone.
8093 *
8094 * Note that this function is called at different processing stages for NSEC3
8095 * chain additions vs. removals and needs to handle all cases properly.
8096 */
8097 static isc_result_t
8098 fixup_nsec3param(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3chain_t *chain,
8099 bool active, dns_rdatatype_t privatetype, dns_diff_t *diff) {
8100 dns_dbnode_t *node = NULL;
8101 dns_name_t *name = dns_db_origin(db);
8102 dns_rdata_t rdata = DNS_RDATA_INIT;
8103 dns_rdataset_t rdataset;
8104 dns_rdata_nsec3param_t nsec3param;
8105 isc_result_t result;
8106 isc_buffer_t buffer;
8107 unsigned char parambuf[DNS_NSEC3PARAM_BUFFERSIZE];
8108 dns_ttl_t ttl = 0;
8109 bool nseconly = false, nsec3ok = false;
8110
8111 dns_rdataset_init(&rdataset);
8112
8113 result = dns_db_getoriginnode(db, &node);
8114 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8115 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param, 0,
8116 0, &rdataset, NULL);
8117 if (result == ISC_R_NOTFOUND) {
8118 goto try_private;
8119 }
8120 if (result != ISC_R_SUCCESS) {
8121 goto failure;
8122 }
8123
8124 /*
8125 * Preserve the existing ttl.
8126 */
8127 ttl = rdataset.ttl;
8128
8129 /*
8130 * Delete all NSEC3PARAM records which match that in nsec3chain.
8131 */
8132 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
8133 result = dns_rdataset_next(&rdataset))
8134 {
8135 dns_rdataset_current(&rdataset, &rdata);
8136 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
8137
8138 if (nsec3param.hash != chain->nsec3param.hash ||
8139 (active && nsec3param.flags != 0) ||
8140 nsec3param.iterations != chain->nsec3param.iterations ||
8141 nsec3param.salt_length != chain->nsec3param.salt_length ||
8142 memcmp(nsec3param.salt, chain->nsec3param.salt,
8143 nsec3param.salt_length))
8144 {
8145 dns_rdata_reset(&rdata);
8146 continue;
8147 }
8148
8149 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
8150 rdataset.ttl, &rdata));
8151 dns_rdata_reset(&rdata);
8152 }
8153 if (result != ISC_R_NOMORE) {
8154 goto failure;
8155 }
8156
8157 dns_rdataset_disassociate(&rdataset);
8158
8159 try_private:
8160
8161 if (active) {
8162 goto add;
8163 }
8164
8165 result = dns_nsec_nseconly(db, ver, &nseconly);
8166 nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
8167
8168 /*
8169 * Delete all private records which match that in nsec3chain.
8170 */
8171 result = dns_db_findrdataset(db, node, ver, privatetype, 0, 0,
8172 &rdataset, NULL);
8173 if (result == ISC_R_NOTFOUND) {
8174 goto add;
8175 }
8176 if (result != ISC_R_SUCCESS) {
8177 goto failure;
8178 }
8179
8180 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
8181 result = dns_rdataset_next(&rdataset))
8182 {
8183 dns_rdata_t private = DNS_RDATA_INIT;
8184 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
8185
8186 dns_rdataset_current(&rdataset, &private);
8187 if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
8188 sizeof(buf)))
8189 {
8190 continue;
8191 }
8192 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
8193
8194 if ((!nsec3ok &&
8195 (nsec3param.flags & DNS_NSEC3FLAG_INITIAL) != 0) ||
8196 nsec3param.hash != chain->nsec3param.hash ||
8197 nsec3param.iterations != chain->nsec3param.iterations ||
8198 nsec3param.salt_length != chain->nsec3param.salt_length ||
8199 memcmp(nsec3param.salt, chain->nsec3param.salt,
8200 nsec3param.salt_length))
8201 {
8202 dns_rdata_reset(&rdata);
8203 continue;
8204 }
8205
8206 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
8207 rdataset.ttl, &private));
8208 dns_rdata_reset(&rdata);
8209 }
8210 if (result != ISC_R_NOMORE) {
8211 goto failure;
8212 }
8213
8214 add:
8215 if ((chain->nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
8216 result = ISC_R_SUCCESS;
8217 goto failure;
8218 }
8219
8220 /*
8221 * Add a NSEC3PARAM record which matches that in nsec3chain but
8222 * with all flags bits cleared.
8223 *
8224 * Note: we do not clear chain->nsec3param.flags as this change
8225 * may be reversed.
8226 */
8227 isc_buffer_init(&buffer, ¶mbuf, sizeof(parambuf));
8228 CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db),
8229 dns_rdatatype_nsec3param, &chain->nsec3param,
8230 &buffer));
8231 rdata.data[1] = 0; /* Clear flag bits. */
8232 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, name, ttl, &rdata));
8233
8234 failure:
8235 dns_db_detachnode(db, &node);
8236 if (dns_rdataset_isassociated(&rdataset)) {
8237 dns_rdataset_disassociate(&rdataset);
8238 }
8239 return (result);
8240 }
8241
8242 static isc_result_t
8243 delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
8244 dns_name_t *name, dns_diff_t *diff) {
8245 dns_rdataset_t rdataset;
8246 isc_result_t result;
8247
8248 dns_rdataset_init(&rdataset);
8249
8250 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec, 0, 0,
8251 &rdataset, NULL);
8252 if (result == ISC_R_NOTFOUND) {
8253 return (ISC_R_SUCCESS);
8254 }
8255 if (result != ISC_R_SUCCESS) {
8256 return (result);
8257 }
8258 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
8259 result = dns_rdataset_next(&rdataset))
8260 {
8261 dns_rdata_t rdata = DNS_RDATA_INIT;
8262
8263 dns_rdataset_current(&rdataset, &rdata);
8264 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
8265 rdataset.ttl, &rdata));
8266 }
8267 if (result == ISC_R_NOMORE) {
8268 result = ISC_R_SUCCESS;
8269 }
8270 failure:
8271 dns_rdataset_disassociate(&rdataset);
8272 return (result);
8273 }
8274
8275 static isc_result_t
8276 deletematchingnsec3(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
8277 dns_name_t *name, const dns_rdata_nsec3param_t *param,
8278 dns_diff_t *diff) {
8279 dns_rdataset_t rdataset;
8280 dns_rdata_nsec3_t nsec3;
8281 isc_result_t result;
8282
8283 dns_rdataset_init(&rdataset);
8284 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3, 0, 0,
8285 &rdataset, NULL);
8286 if (result == ISC_R_NOTFOUND) {
8287 return (ISC_R_SUCCESS);
8288 }
8289 if (result != ISC_R_SUCCESS) {
8290 return (result);
8291 }
8292
8293 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
8294 result = dns_rdataset_next(&rdataset))
8295 {
8296 dns_rdata_t rdata = DNS_RDATA_INIT;
8297
8298 dns_rdataset_current(&rdataset, &rdata);
8299 CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
8300 if (nsec3.hash != param->hash ||
8301 nsec3.iterations != param->iterations ||
8302 nsec3.salt_length != param->salt_length ||
8303 memcmp(nsec3.salt, param->salt, nsec3.salt_length))
8304 {
8305 continue;
8306 }
8307 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
8308 rdataset.ttl, &rdata));
8309 }
8310 if (result == ISC_R_NOMORE) {
8311 result = ISC_R_SUCCESS;
8312 }
8313 failure:
8314 dns_rdataset_disassociate(&rdataset);
8315 return (result);
8316 }
8317
8318 static isc_result_t
8319 need_nsec_chain(dns_db_t *db, dns_dbversion_t *ver,
8320 const dns_rdata_nsec3param_t *param, bool *answer) {
8321 dns_dbnode_t *node = NULL;
8322 dns_rdata_t rdata = DNS_RDATA_INIT;
8323 dns_rdata_nsec3param_t myparam;
8324 dns_rdataset_t rdataset;
8325 isc_result_t result;
8326
8327 *answer = false;
8328
8329 result = dns_db_getoriginnode(db, &node);
8330 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8331
8332 dns_rdataset_init(&rdataset);
8333
8334 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec, 0, 0,
8335 &rdataset, NULL);
8336 if (result == ISC_R_SUCCESS) {
8337 dns_rdataset_disassociate(&rdataset);
8338 dns_db_detachnode(db, &node);
8339 return (result);
8340 }
8341 if (result != ISC_R_NOTFOUND) {
8342 dns_db_detachnode(db, &node);
8343 return (result);
8344 }
8345
8346 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param, 0,
8347 0, &rdataset, NULL);
8348 if (result == ISC_R_NOTFOUND) {
8349 *answer = true;
8350 dns_db_detachnode(db, &node);
8351 return (ISC_R_SUCCESS);
8352 }
8353 if (result != ISC_R_SUCCESS) {
8354 dns_db_detachnode(db, &node);
8355 return (result);
8356 }
8357
8358 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
8359 result = dns_rdataset_next(&rdataset))
8360 {
8361 dns_rdataset_current(&rdataset, &rdata);
8362 CHECK(dns_rdata_tostruct(&rdata, &myparam, NULL));
8363 dns_rdata_reset(&rdata);
8364 /*
8365 * Ignore any NSEC3PARAM removals.
8366 */
8367 if (NSEC3REMOVE(myparam.flags)) {
8368 continue;
8369 }
8370 /*
8371 * Ignore the chain that we are in the process of deleting.
8372 */
8373 if (myparam.hash == param->hash &&
8374 myparam.iterations == param->iterations &&
8375 myparam.salt_length == param->salt_length &&
8376 !memcmp(myparam.salt, param->salt, myparam.salt_length))
8377 {
8378 continue;
8379 }
8380 /*
8381 * Found an active NSEC3 chain.
8382 */
8383 break;
8384 }
8385 if (result == ISC_R_NOMORE) {
8386 *answer = true;
8387 result = ISC_R_SUCCESS;
8388 }
8389
8390 failure:
8391 if (dns_rdataset_isassociated(&rdataset)) {
8392 dns_rdataset_disassociate(&rdataset);
8393 }
8394 dns_db_detachnode(db, &node);
8395 return (result);
8396 }
8397
8398 /*%
8399 * Given a tuple which is part of a diff, return a pointer to the next tuple in
8400 * that diff which has the same name and type (or NULL if no such tuple is
8401 * found).
8402 */
8403 static dns_difftuple_t *
8404 find_next_matching_tuple(dns_difftuple_t *cur) {
8405 dns_difftuple_t *next = cur;
8406
8407 while ((next = ISC_LIST_NEXT(next, link)) != NULL) {
8408 if (cur->rdata.type == next->rdata.type &&
8409 dns_name_equal(&cur->name, &next->name))
8410 {
8411 return (next);
8412 }
8413 }
8414
8415 return (NULL);
8416 }
8417
8418 /*%
8419 * Remove all tuples with the same name and type as 'cur' from 'src' and append
8420 * them to 'dst'.
8421 */
8422 static void
8423 move_matching_tuples(dns_difftuple_t *cur, dns_diff_t *src, dns_diff_t *dst) {
8424 do {
8425 dns_difftuple_t *next = find_next_matching_tuple(cur);
8426 ISC_LIST_UNLINK(src->tuples, cur, link);
8427 dns_diff_appendminimal(dst, &cur);
8428 cur = next;
8429 } while (cur != NULL);
8430 }
8431
8432 /*%
8433 * Add/remove DNSSEC signatures for the list of "raw" zone changes supplied in
8434 * 'diff'. Gradually remove tuples from 'diff' and append them to 'zonediff'
8435 * along with tuples representing relevant signature changes.
8436 */
8437 isc_result_t
8438 dns__zone_updatesigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version,
8439 dst_key_t *zone_keys[], unsigned int nkeys,
8440 dns_zone_t *zone, isc_stdtime_t inception,
8441 isc_stdtime_t expire, isc_stdtime_t keyexpire,
8442 isc_stdtime_t now, bool check_ksk, bool keyset_kskonly,
8443 dns__zonediff_t *zonediff) {
8444 dns_difftuple_t *tuple;
8445 isc_result_t result;
8446
8447 while ((tuple = ISC_LIST_HEAD(diff->tuples)) != NULL) {
8448 isc_stdtime_t exp = expire;
8449
8450 if (keyexpire != 0 &&
8451 (tuple->rdata.type == dns_rdatatype_dnskey ||
8452 tuple->rdata.type == dns_rdatatype_cdnskey ||
8453 tuple->rdata.type == dns_rdatatype_cds))
8454 {
8455 exp = keyexpire;
8456 }
8457
8458 result = del_sigs(zone, db, version, &tuple->name,
8459 tuple->rdata.type, zonediff, zone_keys, nkeys,
8460 now, false);
8461 if (result != ISC_R_SUCCESS) {
8462 dns_zone_log(zone, ISC_LOG_ERROR,
8463 "dns__zone_updatesigs:del_sigs -> %s",
8464 dns_result_totext(result));
8465 return (result);
8466 }
8467 result = add_sigs(db, version, &tuple->name, zone,
8468 tuple->rdata.type, zonediff->diff, zone_keys,
8469 nkeys, zone->mctx, inception, exp, check_ksk,
8470 keyset_kskonly);
8471 if (result != ISC_R_SUCCESS) {
8472 dns_zone_log(zone, ISC_LOG_ERROR,
8473 "dns__zone_updatesigs:add_sigs -> %s",
8474 dns_result_totext(result));
8475 return (result);
8476 }
8477
8478 /*
8479 * Signature changes for all RRs with name tuple->name and type
8480 * tuple->rdata.type were appended to zonediff->diff. Now we
8481 * remove all the "raw" changes with the same name and type
8482 * from diff (so that they are not processed by this loop
8483 * again) and append them to zonediff so that they get applied.
8484 */
8485 move_matching_tuples(tuple, diff, zonediff->diff);
8486 }
8487 return (ISC_R_SUCCESS);
8488 }
8489
8490 /*
8491 * Incrementally build and sign a new NSEC3 chain using the parameters
8492 * requested.
8493 */
8494 static void
8495 zone_nsec3chain(dns_zone_t *zone) {
8496 const char *me = "zone_nsec3chain";
8497 dns_db_t *db = NULL;
8498 dns_dbnode_t *node = NULL;
8499 dns_dbversion_t *version = NULL;
8500 dns_diff_t _sig_diff;
8501 dns_diff_t nsec_diff;
8502 dns_diff_t nsec3_diff;
8503 dns_diff_t param_diff;
8504 dns__zonediff_t zonediff;
8505 dns_fixedname_t fixed;
8506 dns_fixedname_t nextfixed;
8507 dns_name_t *name, *nextname;
8508 dns_rdataset_t rdataset;
8509 dns_nsec3chain_t *nsec3chain = NULL, *nextnsec3chain;
8510 dns_nsec3chainlist_t cleanup;
8511 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
8512 int32_t signatures;
8513 bool check_ksk, keyset_kskonly;
8514 bool delegation;
8515 bool first;
8516 isc_result_t result;
8517 isc_stdtime_t now, inception, soaexpire, expire;
8518 uint32_t jitter, sigvalidityinterval, expiryinterval;
8519 unsigned int i;
8520 unsigned int nkeys = 0;
8521 uint32_t nodes;
8522 bool unsecure = false;
8523 bool seen_soa, seen_ns, seen_dname, seen_ds;
8524 bool seen_nsec, seen_nsec3, seen_rr;
8525 dns_rdatasetiter_t *iterator = NULL;
8526 bool buildnsecchain;
8527 bool updatensec = false;
8528 dns_rdatatype_t privatetype = zone->privatetype;
8529
8530 ENTER;
8531
8532 dns_rdataset_init(&rdataset);
8533 name = dns_fixedname_initname(&fixed);
8534 nextname = dns_fixedname_initname(&nextfixed);
8535 dns_diff_init(zone->mctx, ¶m_diff);
8536 dns_diff_init(zone->mctx, &nsec3_diff);
8537 dns_diff_init(zone->mctx, &nsec_diff);
8538 dns_diff_init(zone->mctx, &_sig_diff);
8539 zonediff_init(&zonediff, &_sig_diff);
8540 ISC_LIST_INIT(cleanup);
8541
8542 /*
8543 * Updates are disabled. Pause for 5 minutes.
8544 */
8545 if (zone->update_disabled) {
8546 result = ISC_R_FAILURE;
8547 goto failure;
8548 }
8549
8550 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8551 /*
8552 * This function is called when zone timer fires, after the latter gets
8553 * set by zone_addnsec3chain(). If the action triggering the call to
8554 * zone_addnsec3chain() is closely followed by a zone deletion request,
8555 * it might turn out that the timer thread will not be woken up until
8556 * after the zone is deleted by rmzone(), which calls dns_db_detach()
8557 * for zone->db, causing the latter to become NULL. Return immediately
8558 * if that happens.
8559 */
8560 if (zone->db != NULL) {
8561 dns_db_attach(zone->db, &db);
8562 }
8563 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8564 if (db == NULL) {
8565 return;
8566 }
8567
8568 result = dns_db_newversion(db, &version);
8569 if (result != ISC_R_SUCCESS) {
8570 dnssec_log(zone, ISC_LOG_ERROR,
8571 "zone_nsec3chain:dns_db_newversion -> %s",
8572 dns_result_totext(result));
8573 goto failure;
8574 }
8575
8576 isc_stdtime_get(&now);
8577
8578 result = dns__zone_findkeys(zone, db, version, now, zone->mctx,
8579 DNS_MAXZONEKEYS, zone_keys, &nkeys);
8580 if (result != ISC_R_SUCCESS) {
8581 dnssec_log(zone, ISC_LOG_ERROR,
8582 "zone_nsec3chain:dns__zone_findkeys -> %s",
8583 dns_result_totext(result));
8584 goto failure;
8585 }
8586
8587 sigvalidityinterval = dns_zone_getsigvalidityinterval(zone);
8588 inception = now - 3600; /* Allow for clock skew. */
8589 soaexpire = now + sigvalidityinterval;
8590 expiryinterval = dns_zone_getsigresigninginterval(zone);
8591 if (expiryinterval > sigvalidityinterval) {
8592 expiryinterval = sigvalidityinterval;
8593 } else {
8594 expiryinterval = sigvalidityinterval - expiryinterval;
8595 }
8596
8597 /*
8598 * Spread out signatures over time if they happen to be
8599 * clumped. We don't do this for each add_sigs() call as
8600 * we still want some clustering to occur.
8601 */
8602 if (sigvalidityinterval >= 3600U) {
8603 if (sigvalidityinterval > 7200U) {
8604 jitter = isc_random_uniform(expiryinterval);
8605 } else {
8606 jitter = isc_random_uniform(1200);
8607 }
8608 expire = soaexpire - jitter - 1;
8609 } else {
8610 expire = soaexpire - 1;
8611 }
8612
8613 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
8614 keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
8615
8616 /*
8617 * We keep pulling nodes off each iterator in turn until
8618 * we have no more nodes to pull off or we reach the limits
8619 * for this quantum.
8620 */
8621 nodes = zone->nodes;
8622 signatures = zone->signatures;
8623 LOCK_ZONE(zone);
8624 nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
8625 UNLOCK_ZONE(zone);
8626 first = true;
8627
8628 if (nsec3chain != NULL) {
8629 nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
8630 }
8631 /*
8632 * Generate new NSEC3 chains first.
8633 *
8634 * The following while loop iterates over nodes in the zone database,
8635 * updating the NSEC3 chain by calling dns_nsec3_addnsec3() for each of
8636 * them. Once all nodes are processed, the "delete_nsec" field is
8637 * consulted to check whether we are supposed to remove NSEC records
8638 * from the zone database; if so, the database iterator is reset to
8639 * point to the first node and the loop traverses all of them again,
8640 * this time removing NSEC records. If we hit a node which is obscured
8641 * by a delegation or a DNAME, nodes are skipped over until we find one
8642 * that is not obscured by the same obscuring name and then normal
8643 * processing is resumed.
8644 *
8645 * The above is repeated until all requested NSEC3 chain changes are
8646 * applied or when we reach the limits for this quantum, whichever
8647 * happens first.
8648 *
8649 * Note that the "signatures" variable is only used here to limit the
8650 * amount of work performed. Actual DNSSEC signatures are only
8651 * generated by dns__zone_updatesigs() calls later in this function.
8652 */
8653 while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
8654 dns_dbiterator_pause(nsec3chain->dbiterator);
8655
8656 LOCK_ZONE(zone);
8657 nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
8658
8659 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8660 if (nsec3chain->done || nsec3chain->db != zone->db) {
8661 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
8662 ISC_LIST_APPEND(cleanup, nsec3chain, link);
8663 }
8664 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8665 UNLOCK_ZONE(zone);
8666 if (ISC_LIST_TAIL(cleanup) == nsec3chain) {
8667 goto next_addchain;
8668 }
8669
8670 /*
8671 * Possible future db.
8672 */
8673 if (nsec3chain->db != db) {
8674 goto next_addchain;
8675 }
8676
8677 if (NSEC3REMOVE(nsec3chain->nsec3param.flags)) {
8678 goto next_addchain;
8679 }
8680
8681 dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
8682
8683 if (nsec3chain->delete_nsec) {
8684 delegation = false;
8685 dns_dbiterator_pause(nsec3chain->dbiterator);
8686 CHECK(delete_nsec(db, version, node, name, &nsec_diff));
8687 goto next_addnode;
8688 }
8689 /*
8690 * On the first pass we need to check if the current node
8691 * has not been obscured.
8692 */
8693 delegation = false;
8694 unsecure = false;
8695 if (first) {
8696 dns_fixedname_t ffound;
8697 dns_name_t *found;
8698 found = dns_fixedname_initname(&ffound);
8699 result = dns_db_find(
8700 db, name, version, dns_rdatatype_soa,
8701 DNS_DBFIND_NOWILD, 0, NULL, found, NULL, NULL);
8702 if ((result == DNS_R_DELEGATION ||
8703 result == DNS_R_DNAME) &&
8704 !dns_name_equal(name, found))
8705 {
8706 /*
8707 * Remember the obscuring name so that
8708 * we skip all obscured names.
8709 */
8710 dns_name_copynf(found, name);
8711 delegation = true;
8712 goto next_addnode;
8713 }
8714 }
8715
8716 /*
8717 * Check to see if this is a bottom of zone node.
8718 */
8719 result = dns_db_allrdatasets(db, node, version, 0, 0,
8720 &iterator);
8721 if (result == ISC_R_NOTFOUND) {
8722 /* Empty node? */
8723 goto next_addnode;
8724 }
8725 if (result != ISC_R_SUCCESS) {
8726 goto failure;
8727 }
8728
8729 seen_soa = seen_ns = seen_dname = seen_ds = seen_nsec = false;
8730 for (result = dns_rdatasetiter_first(iterator);
8731 result == ISC_R_SUCCESS;
8732 result = dns_rdatasetiter_next(iterator))
8733 {
8734 dns_rdatasetiter_current(iterator, &rdataset);
8735 INSIST(rdataset.type != dns_rdatatype_nsec3);
8736 if (rdataset.type == dns_rdatatype_soa) {
8737 seen_soa = true;
8738 } else if (rdataset.type == dns_rdatatype_ns) {
8739 seen_ns = true;
8740 } else if (rdataset.type == dns_rdatatype_dname) {
8741 seen_dname = true;
8742 } else if (rdataset.type == dns_rdatatype_ds) {
8743 seen_ds = true;
8744 } else if (rdataset.type == dns_rdatatype_nsec) {
8745 seen_nsec = true;
8746 }
8747 dns_rdataset_disassociate(&rdataset);
8748 }
8749 dns_rdatasetiter_destroy(&iterator);
8750 /*
8751 * Is there a NSEC chain than needs to be cleaned up?
8752 */
8753 if (seen_nsec) {
8754 nsec3chain->seen_nsec = true;
8755 }
8756 if (seen_ns && !seen_soa && !seen_ds) {
8757 unsecure = true;
8758 }
8759 if ((seen_ns && !seen_soa) || seen_dname) {
8760 delegation = true;
8761 }
8762
8763 /*
8764 * Process one node.
8765 */
8766 dns_dbiterator_pause(nsec3chain->dbiterator);
8767 result = dns_nsec3_addnsec3(
8768 db, version, name, &nsec3chain->nsec3param,
8769 zone_nsecttl(zone), unsecure, &nsec3_diff);
8770 if (result != ISC_R_SUCCESS) {
8771 dnssec_log(zone, ISC_LOG_ERROR,
8772 "zone_nsec3chain:"
8773 "dns_nsec3_addnsec3 -> %s",
8774 dns_result_totext(result));
8775 goto failure;
8776 }
8777
8778 /*
8779 * Treat each call to dns_nsec3_addnsec3() as if it's cost is
8780 * two signatures. Additionally there will, in general, be
8781 * two signature generated below.
8782 *
8783 * If we are only changing the optout flag the cost is half
8784 * that of the cost of generating a completely new chain.
8785 */
8786 signatures -= 4;
8787
8788 /*
8789 * Go onto next node.
8790 */
8791 next_addnode:
8792 first = false;
8793 dns_db_detachnode(db, &node);
8794 do {
8795 result = dns_dbiterator_next(nsec3chain->dbiterator);
8796
8797 if (result == ISC_R_NOMORE && nsec3chain->delete_nsec) {
8798 dns_dbiterator_pause(nsec3chain->dbiterator);
8799 CHECK(fixup_nsec3param(db, version, nsec3chain,
8800 false, privatetype,
8801 ¶m_diff));
8802 LOCK_ZONE(zone);
8803 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
8804 link);
8805 UNLOCK_ZONE(zone);
8806 ISC_LIST_APPEND(cleanup, nsec3chain, link);
8807 goto next_addchain;
8808 }
8809 if (result == ISC_R_NOMORE) {
8810 dns_dbiterator_pause(nsec3chain->dbiterator);
8811 if (nsec3chain->seen_nsec) {
8812 CHECK(fixup_nsec3param(
8813 db, version, nsec3chain, true,
8814 privatetype, ¶m_diff));
8815 nsec3chain->delete_nsec = true;
8816 goto same_addchain;
8817 }
8818 CHECK(fixup_nsec3param(db, version, nsec3chain,
8819 false, privatetype,
8820 ¶m_diff));
8821 LOCK_ZONE(zone);
8822 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
8823 link);
8824 UNLOCK_ZONE(zone);
8825 ISC_LIST_APPEND(cleanup, nsec3chain, link);
8826 goto next_addchain;
8827 } else if (result != ISC_R_SUCCESS) {
8828 dnssec_log(zone, ISC_LOG_ERROR,
8829 "zone_nsec3chain:"
8830 "dns_dbiterator_next -> %s",
8831 dns_result_totext(result));
8832 goto failure;
8833 } else if (delegation) {
8834 dns_dbiterator_current(nsec3chain->dbiterator,
8835 &node, nextname);
8836 dns_db_detachnode(db, &node);
8837 if (!dns_name_issubdomain(nextname, name)) {
8838 break;
8839 }
8840 } else {
8841 break;
8842 }
8843 } while (1);
8844 continue;
8845
8846 same_addchain:
8847 CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
8848 first = true;
8849 continue;
8850
8851 next_addchain:
8852 dns_dbiterator_pause(nsec3chain->dbiterator);
8853 nsec3chain = nextnsec3chain;
8854 first = true;
8855 if (nsec3chain != NULL) {
8856 nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
8857 }
8858 }
8859
8860 if (nsec3chain != NULL) {
8861 goto skip_removals;
8862 }
8863
8864 /*
8865 * Process removals.
8866 *
8867 * This is a counterpart of the above while loop which takes care of
8868 * removing an NSEC3 chain. It starts with determining whether the
8869 * zone needs to switch from NSEC3 to NSEC; if so, it first builds an
8870 * NSEC chain by iterating over all nodes in the zone database and only
8871 * then goes on to remove NSEC3 records be iterating over all nodes
8872 * again and calling deletematchingnsec3() for each of them; otherwise,
8873 * it starts removing NSEC3 records immediately. Rules for processing
8874 * obscured nodes and interrupting work are the same as for the while
8875 * loop above.
8876 */
8877 LOCK_ZONE(zone);
8878 nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
8879 UNLOCK_ZONE(zone);
8880 first = true;
8881 buildnsecchain = false;
8882 while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
8883 dns_dbiterator_pause(nsec3chain->dbiterator);
8884
8885 LOCK_ZONE(zone);
8886 nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
8887 UNLOCK_ZONE(zone);
8888
8889 if (nsec3chain->db != db) {
8890 goto next_removechain;
8891 }
8892
8893 if (!NSEC3REMOVE(nsec3chain->nsec3param.flags)) {
8894 goto next_removechain;
8895 }
8896
8897 /*
8898 * Work out if we need to build a NSEC chain as a consequence
8899 * of removing this NSEC3 chain.
8900 */
8901 if (first && !updatensec &&
8902 (nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_NONSEC) == 0)
8903 {
8904 result = need_nsec_chain(db, version,
8905 &nsec3chain->nsec3param,
8906 &buildnsecchain);
8907 if (result != ISC_R_SUCCESS) {
8908 dnssec_log(zone, ISC_LOG_ERROR,
8909 "zone_nsec3chain:"
8910 "need_nsec_chain -> %s",
8911 dns_result_totext(result));
8912 goto failure;
8913 }
8914 }
8915
8916 if (first) {
8917 dnssec_log(zone, ISC_LOG_DEBUG(3),
8918 "zone_nsec3chain:buildnsecchain = %u\n",
8919 buildnsecchain);
8920 }
8921
8922 dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
8923 dns_dbiterator_pause(nsec3chain->dbiterator);
8924 delegation = false;
8925
8926 if (!buildnsecchain) {
8927 /*
8928 * Delete the NSEC3PARAM record matching this chain.
8929 */
8930 if (first) {
8931 result = fixup_nsec3param(
8932 db, version, nsec3chain, true,
8933 privatetype, ¶m_diff);
8934 if (result != ISC_R_SUCCESS) {
8935 dnssec_log(zone, ISC_LOG_ERROR,
8936 "zone_nsec3chain:"
8937 "fixup_nsec3param -> %s",
8938 dns_result_totext(result));
8939 goto failure;
8940 }
8941 }
8942
8943 /*
8944 * Delete the NSEC3 records.
8945 */
8946 result = deletematchingnsec3(db, version, node, name,
8947 &nsec3chain->nsec3param,
8948 &nsec3_diff);
8949 if (result != ISC_R_SUCCESS) {
8950 dnssec_log(zone, ISC_LOG_ERROR,
8951 "zone_nsec3chain:"
8952 "deletematchingnsec3 -> %s",
8953 dns_result_totext(result));
8954 goto failure;
8955 }
8956 goto next_removenode;
8957 }
8958
8959 if (first) {
8960 dns_fixedname_t ffound;
8961 dns_name_t *found;
8962 found = dns_fixedname_initname(&ffound);
8963 result = dns_db_find(
8964 db, name, version, dns_rdatatype_soa,
8965 DNS_DBFIND_NOWILD, 0, NULL, found, NULL, NULL);
8966 if ((result == DNS_R_DELEGATION ||
8967 result == DNS_R_DNAME) &&
8968 !dns_name_equal(name, found))
8969 {
8970 /*
8971 * Remember the obscuring name so that
8972 * we skip all obscured names.
8973 */
8974 dns_name_copynf(found, name);
8975 delegation = true;
8976 goto next_removenode;
8977 }
8978 }
8979
8980 /*
8981 * Check to see if this is a bottom of zone node.
8982 */
8983 result = dns_db_allrdatasets(db, node, version, 0, 0,
8984 &iterator);
8985 if (result == ISC_R_NOTFOUND) {
8986 /* Empty node? */
8987 goto next_removenode;
8988 }
8989 if (result != ISC_R_SUCCESS) {
8990 goto failure;
8991 }
8992
8993 seen_soa = seen_ns = seen_dname = seen_nsec3 = seen_nsec =
8994 seen_rr = false;
8995 for (result = dns_rdatasetiter_first(iterator);
8996 result == ISC_R_SUCCESS;
8997 result = dns_rdatasetiter_next(iterator))
8998 {
8999 dns_rdatasetiter_current(iterator, &rdataset);
9000 if (rdataset.type == dns_rdatatype_soa) {
9001 seen_soa = true;
9002 } else if (rdataset.type == dns_rdatatype_ns) {
9003 seen_ns = true;
9004 } else if (rdataset.type == dns_rdatatype_dname) {
9005 seen_dname = true;
9006 } else if (rdataset.type == dns_rdatatype_nsec) {
9007 seen_nsec = true;
9008 } else if (rdataset.type == dns_rdatatype_nsec3) {
9009 seen_nsec3 = true;
9010 } else if (rdataset.type != dns_rdatatype_rrsig) {
9011 seen_rr = true;
9012 }
9013 dns_rdataset_disassociate(&rdataset);
9014 }
9015 dns_rdatasetiter_destroy(&iterator);
9016
9017 if (!seen_rr || seen_nsec3 || seen_nsec) {
9018 goto next_removenode;
9019 }
9020 if ((seen_ns && !seen_soa) || seen_dname) {
9021 delegation = true;
9022 }
9023
9024 /*
9025 * Add a NSEC record except at the origin.
9026 */
9027 if (!dns_name_equal(name, dns_db_origin(db))) {
9028 dns_dbiterator_pause(nsec3chain->dbiterator);
9029 CHECK(add_nsec(db, version, name, node,
9030 zone_nsecttl(zone), delegation,
9031 &nsec_diff));
9032 signatures--;
9033 }
9034
9035 next_removenode:
9036 first = false;
9037 dns_db_detachnode(db, &node);
9038 do {
9039 result = dns_dbiterator_next(nsec3chain->dbiterator);
9040 if (result == ISC_R_NOMORE && buildnsecchain) {
9041 /*
9042 * The NSEC chain should now be built.
9043 * We can now remove the NSEC3 chain.
9044 */
9045 updatensec = true;
9046 goto same_removechain;
9047 }
9048 if (result == ISC_R_NOMORE) {
9049 dns_dbiterator_pause(nsec3chain->dbiterator);
9050 LOCK_ZONE(zone);
9051 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
9052 link);
9053 UNLOCK_ZONE(zone);
9054 ISC_LIST_APPEND(cleanup, nsec3chain, link);
9055 result = fixup_nsec3param(
9056 db, version, nsec3chain, false,
9057 privatetype, ¶m_diff);
9058 if (result != ISC_R_SUCCESS) {
9059 dnssec_log(zone, ISC_LOG_ERROR,
9060 "zone_nsec3chain:"
9061 "fixup_nsec3param -> %s",
9062 dns_result_totext(result));
9063 goto failure;
9064 }
9065 goto next_removechain;
9066 } else if (result != ISC_R_SUCCESS) {
9067 dnssec_log(zone, ISC_LOG_ERROR,
9068 "zone_nsec3chain:"
9069 "dns_dbiterator_next -> %s",
9070 dns_result_totext(result));
9071 goto failure;
9072 } else if (delegation) {
9073 dns_dbiterator_current(nsec3chain->dbiterator,
9074 &node, nextname);
9075 dns_db_detachnode(db, &node);
9076 if (!dns_name_issubdomain(nextname, name)) {
9077 break;
9078 }
9079 } else {
9080 break;
9081 }
9082 } while (1);
9083 continue;
9084
9085 same_removechain:
9086 CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
9087 buildnsecchain = false;
9088 first = true;
9089 continue;
9090
9091 next_removechain:
9092 dns_dbiterator_pause(nsec3chain->dbiterator);
9093 nsec3chain = nextnsec3chain;
9094 first = true;
9095 }
9096
9097 skip_removals:
9098 /*
9099 * We may need to update the NSEC/NSEC3 records for the zone apex.
9100 */
9101 if (!ISC_LIST_EMPTY(param_diff.tuples)) {
9102 bool rebuild_nsec = false, rebuild_nsec3 = false;
9103 result = dns_db_getoriginnode(db, &node);
9104 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9105 result = dns_db_allrdatasets(db, node, version, 0, 0,
9106 &iterator);
9107 if (result != ISC_R_SUCCESS) {
9108 dnssec_log(zone, ISC_LOG_ERROR,
9109 "zone_nsec3chain:dns_db_allrdatasets -> %s",
9110 dns_result_totext(result));
9111 goto failure;
9112 }
9113 for (result = dns_rdatasetiter_first(iterator);
9114 result == ISC_R_SUCCESS;
9115 result = dns_rdatasetiter_next(iterator))
9116 {
9117 dns_rdatasetiter_current(iterator, &rdataset);
9118 if (rdataset.type == dns_rdatatype_nsec) {
9119 rebuild_nsec = true;
9120 } else if (rdataset.type == dns_rdatatype_nsec3param) {
9121 rebuild_nsec3 = true;
9122 }
9123 dns_rdataset_disassociate(&rdataset);
9124 }
9125 dns_rdatasetiter_destroy(&iterator);
9126 dns_db_detachnode(db, &node);
9127
9128 if (rebuild_nsec) {
9129 if (nsec3chain != NULL) {
9130 dns_dbiterator_pause(nsec3chain->dbiterator);
9131 }
9132
9133 result = updatesecure(db, version, &zone->origin,
9134 zone_nsecttl(zone), true,
9135 &nsec_diff);
9136 if (result != ISC_R_SUCCESS) {
9137 dnssec_log(zone, ISC_LOG_ERROR,
9138 "zone_nsec3chain:updatesecure -> %s",
9139 dns_result_totext(result));
9140 goto failure;
9141 }
9142 }
9143
9144 if (rebuild_nsec3) {
9145 if (nsec3chain != NULL) {
9146 dns_dbiterator_pause(nsec3chain->dbiterator);
9147 }
9148
9149 result = dns_nsec3_addnsec3s(
9150 db, version, dns_db_origin(db),
9151 zone_nsecttl(zone), false, &nsec3_diff);
9152 if (result != ISC_R_SUCCESS) {
9153 dnssec_log(zone, ISC_LOG_ERROR,
9154 "zone_nsec3chain:"
9155 "dns_nsec3_addnsec3s -> %s",
9156 dns_result_totext(result));
9157 goto failure;
9158 }
9159 }
9160 }
9161
9162 /*
9163 * Add / update signatures for the NSEC3 records.
9164 */
9165 if (nsec3chain != NULL) {
9166 dns_dbiterator_pause(nsec3chain->dbiterator);
9167 }
9168 result = dns__zone_updatesigs(&nsec3_diff, db, version, zone_keys,
9169 nkeys, zone, inception, expire, 0, now,
9170 check_ksk, keyset_kskonly, &zonediff);
9171 if (result != ISC_R_SUCCESS) {
9172 dnssec_log(zone, ISC_LOG_ERROR,
9173 "zone_nsec3chain:dns__zone_updatesigs -> %s",
9174 dns_result_totext(result));
9175 goto failure;
9176 }
9177
9178 /*
9179 * We have changed the NSEC3PARAM or private RRsets
9180 * above so we need to update the signatures.
9181 */
9182 result = dns__zone_updatesigs(¶m_diff, db, version, zone_keys,
9183 nkeys, zone, inception, expire, 0, now,
9184 check_ksk, keyset_kskonly, &zonediff);
9185 if (result != ISC_R_SUCCESS) {
9186 dnssec_log(zone, ISC_LOG_ERROR,
9187 "zone_nsec3chain:dns__zone_updatesigs -> %s",
9188 dns_result_totext(result));
9189 goto failure;
9190 }
9191
9192 if (updatensec) {
9193 result = updatesecure(db, version, &zone->origin,
9194 zone_nsecttl(zone), false, &nsec_diff);
9195 if (result != ISC_R_SUCCESS) {
9196 dnssec_log(zone, ISC_LOG_ERROR,
9197 "zone_nsec3chain:updatesecure -> %s",
9198 dns_result_totext(result));
9199 goto failure;
9200 }
9201 }
9202
9203 result = dns__zone_updatesigs(&nsec_diff, db, version, zone_keys, nkeys,
9204 zone, inception, expire, 0, now,
9205 check_ksk, keyset_kskonly, &zonediff);
9206 if (result != ISC_R_SUCCESS) {
9207 dnssec_log(zone, ISC_LOG_ERROR,
9208 "zone_nsec3chain:dns__zone_updatesigs -> %s",
9209 dns_result_totext(result));
9210 goto failure;
9211 }
9212
9213 /*
9214 * If we made no effective changes to the zone then we can just
9215 * cleanup otherwise we need to increment the serial.
9216 */
9217 if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
9218 /*
9219 * No need to call dns_db_closeversion() here as it is
9220 * called with commit = true below.
9221 */
9222 goto done;
9223 }
9224
9225 result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
9226 &zonediff, zone_keys, nkeys, now, false);
9227 if (result != ISC_R_SUCCESS) {
9228 dnssec_log(zone, ISC_LOG_ERROR,
9229 "zone_nsec3chain:del_sigs -> %s",
9230 dns_result_totext(result));
9231 goto failure;
9232 }
9233
9234 result = update_soa_serial(zone, db, version, zonediff.diff, zone->mctx,
9235 zone->updatemethod);
9236 if (result != ISC_R_SUCCESS) {
9237 dnssec_log(zone, ISC_LOG_ERROR,
9238 "zone_nsec3chain:update_soa_serial -> %s",
9239 dns_result_totext(result));
9240 goto failure;
9241 }
9242
9243 result = add_sigs(db, version, &zone->origin, zone, dns_rdatatype_soa,
9244 zonediff.diff, zone_keys, nkeys, zone->mctx,
9245 inception, soaexpire, check_ksk, keyset_kskonly);
9246 if (result != ISC_R_SUCCESS) {
9247 dnssec_log(zone, ISC_LOG_ERROR,
9248 "zone_nsec3chain:add_sigs -> %s",
9249 dns_result_totext(result));
9250 goto failure;
9251 }
9252
9253 /* Write changes to journal file. */
9254 CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_nsec3chain"));
9255
9256 LOCK_ZONE(zone);
9257 zone_needdump(zone, DNS_DUMP_DELAY);
9258 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
9259 UNLOCK_ZONE(zone);
9260
9261 done:
9262 /*
9263 * Pause all iterators so that dns_db_closeversion() can succeed.
9264 */
9265 LOCK_ZONE(zone);
9266 for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain); nsec3chain != NULL;
9267 nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
9268 {
9269 dns_dbiterator_pause(nsec3chain->dbiterator);
9270 }
9271 UNLOCK_ZONE(zone);
9272
9273 /*
9274 * Everything has succeeded. Commit the changes.
9275 * Unconditionally commit as zonediff.offline not checked above.
9276 */
9277 dns_db_closeversion(db, &version, true);
9278
9279 /*
9280 * Everything succeeded so we can clean these up now.
9281 */
9282 nsec3chain = ISC_LIST_HEAD(cleanup);
9283 while (nsec3chain != NULL) {
9284 ISC_LIST_UNLINK(cleanup, nsec3chain, link);
9285 dns_db_detach(&nsec3chain->db);
9286 dns_dbiterator_destroy(&nsec3chain->dbiterator);
9287 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
9288 nsec3chain = ISC_LIST_HEAD(cleanup);
9289 }
9290
9291 LOCK_ZONE(zone);
9292 set_resigntime(zone);
9293 UNLOCK_ZONE(zone);
9294
9295 failure:
9296 if (result != ISC_R_SUCCESS) {
9297 dnssec_log(zone, ISC_LOG_ERROR, "zone_nsec3chain: %s",
9298 dns_result_totext(result));
9299 }
9300
9301 /*
9302 * On error roll back the current nsec3chain.
9303 */
9304 if (result != ISC_R_SUCCESS && nsec3chain != NULL) {
9305 if (nsec3chain->done) {
9306 dns_db_detach(&nsec3chain->db);
9307 dns_dbiterator_destroy(&nsec3chain->dbiterator);
9308 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
9309 } else {
9310 result = dns_dbiterator_first(nsec3chain->dbiterator);
9311 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9312 dns_dbiterator_pause(nsec3chain->dbiterator);
9313 nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
9314 }
9315 }
9316
9317 /*
9318 * Rollback the cleanup list.
9319 */
9320 nsec3chain = ISC_LIST_TAIL(cleanup);
9321 while (nsec3chain != NULL) {
9322 ISC_LIST_UNLINK(cleanup, nsec3chain, link);
9323 if (nsec3chain->done) {
9324 dns_db_detach(&nsec3chain->db);
9325 dns_dbiterator_destroy(&nsec3chain->dbiterator);
9326 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
9327 } else {
9328 LOCK_ZONE(zone);
9329 ISC_LIST_PREPEND(zone->nsec3chain, nsec3chain, link);
9330 UNLOCK_ZONE(zone);
9331 result = dns_dbiterator_first(nsec3chain->dbiterator);
9332 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9333 dns_dbiterator_pause(nsec3chain->dbiterator);
9334 nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
9335 }
9336 nsec3chain = ISC_LIST_TAIL(cleanup);
9337 }
9338
9339 LOCK_ZONE(zone);
9340 for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain); nsec3chain != NULL;
9341 nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
9342 {
9343 dns_dbiterator_pause(nsec3chain->dbiterator);
9344 }
9345 UNLOCK_ZONE(zone);
9346
9347 dns_diff_clear(¶m_diff);
9348 dns_diff_clear(&nsec3_diff);
9349 dns_diff_clear(&nsec_diff);
9350 dns_diff_clear(&_sig_diff);
9351
9352 if (iterator != NULL) {
9353 dns_rdatasetiter_destroy(&iterator);
9354 }
9355
9356 for (i = 0; i < nkeys; i++) {
9357 dst_key_free(&zone_keys[i]);
9358 }
9359
9360 if (node != NULL) {
9361 dns_db_detachnode(db, &node);
9362 }
9363 if (version != NULL) {
9364 dns_db_closeversion(db, &version, false);
9365 dns_db_detach(&db);
9366 } else if (db != NULL) {
9367 dns_db_detach(&db);
9368 }
9369
9370 LOCK_ZONE(zone);
9371 if (ISC_LIST_HEAD(zone->nsec3chain) != NULL) {
9372 isc_interval_t interval;
9373 if (zone->update_disabled || result != ISC_R_SUCCESS) {
9374 isc_interval_set(&interval, 60, 0); /* 1 minute */
9375 } else {
9376 isc_interval_set(&interval, 0, 10000000); /* 10 ms */
9377 }
9378 isc_time_nowplusinterval(&zone->nsec3chaintime, &interval);
9379 } else {
9380 isc_time_settoepoch(&zone->nsec3chaintime);
9381 }
9382 UNLOCK_ZONE(zone);
9383
9384 INSIST(version == NULL);
9385 }
9386
9387 /*%
9388 * Delete all RRSIG records with the given algorithm and keyid.
9389 * Remove the NSEC record and RRSIGs if nkeys is zero.
9390 * If all remaining RRsets are signed with the given algorithm
9391 * set *has_algp to true.
9392 */
9393 static isc_result_t
9394 del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
9395 dns_dbnode_t *node, unsigned int nkeys, dns_secalg_t algorithm,
9396 uint16_t keyid, bool *has_algp, dns_diff_t *diff) {
9397 dns_rdata_rrsig_t rrsig;
9398 dns_rdataset_t rdataset;
9399 dns_rdatasetiter_t *iterator = NULL;
9400 isc_result_t result;
9401 bool alg_missed = false;
9402 bool alg_found = false;
9403
9404 char namebuf[DNS_NAME_FORMATSIZE];
9405 dns_name_format(name, namebuf, sizeof(namebuf));
9406
9407 result = dns_db_allrdatasets(db, node, version, 0, 0, &iterator);
9408 if (result != ISC_R_SUCCESS) {
9409 if (result == ISC_R_NOTFOUND) {
9410 result = ISC_R_SUCCESS;
9411 }
9412 return (result);
9413 }
9414
9415 dns_rdataset_init(&rdataset);
9416 for (result = dns_rdatasetiter_first(iterator); result == ISC_R_SUCCESS;
9417 result = dns_rdatasetiter_next(iterator))
9418 {
9419 bool has_alg = false;
9420 dns_rdatasetiter_current(iterator, &rdataset);
9421 if (nkeys == 0 && rdataset.type == dns_rdatatype_nsec) {
9422 for (result = dns_rdataset_first(&rdataset);
9423 result == ISC_R_SUCCESS;
9424 result = dns_rdataset_next(&rdataset))
9425 {
9426 dns_rdata_t rdata = DNS_RDATA_INIT;
9427 dns_rdataset_current(&rdataset, &rdata);
9428 CHECK(update_one_rr(db, version, diff,
9429 DNS_DIFFOP_DEL, name,
9430 rdataset.ttl, &rdata));
9431 }
9432 if (result != ISC_R_NOMORE) {
9433 goto failure;
9434 }
9435 dns_rdataset_disassociate(&rdataset);
9436 continue;
9437 }
9438 if (rdataset.type != dns_rdatatype_rrsig) {
9439 dns_rdataset_disassociate(&rdataset);
9440 continue;
9441 }
9442 for (result = dns_rdataset_first(&rdataset);
9443 result == ISC_R_SUCCESS;
9444 result = dns_rdataset_next(&rdataset))
9445 {
9446 dns_rdata_t rdata = DNS_RDATA_INIT;
9447 dns_rdataset_current(&rdataset, &rdata);
9448 CHECK(dns_rdata_tostruct(&rdata, &rrsig, NULL));
9449 if (nkeys != 0 && (rrsig.algorithm != algorithm ||
9450 rrsig.keyid != keyid))
9451 {
9452 if (rrsig.algorithm == algorithm) {
9453 has_alg = true;
9454 }
9455 continue;
9456 }
9457 CHECK(update_one_rr(db, version, diff,
9458 DNS_DIFFOP_DELRESIGN, name,
9459 rdataset.ttl, &rdata));
9460 }
9461 dns_rdataset_disassociate(&rdataset);
9462 if (result != ISC_R_NOMORE) {
9463 break;
9464 }
9465
9466 /*
9467 * After deleting, if there's still a signature for
9468 * 'algorithm', set alg_found; if not, set alg_missed.
9469 */
9470 if (has_alg) {
9471 alg_found = true;
9472 } else {
9473 alg_missed = true;
9474 }
9475 }
9476 if (result == ISC_R_NOMORE) {
9477 result = ISC_R_SUCCESS;
9478 }
9479
9480 /*
9481 * Set `has_algp` if the algorithm was found in every RRset:
9482 * i.e., found in at least one, and not missing from any.
9483 */
9484 *has_algp = (alg_found && !alg_missed);
9485 failure:
9486 if (dns_rdataset_isassociated(&rdataset)) {
9487 dns_rdataset_disassociate(&rdataset);
9488 }
9489 dns_rdatasetiter_destroy(&iterator);
9490 return (result);
9491 }
9492
9493 /*
9494 * Incrementally sign the zone using the keys requested.
9495 * Builds the NSEC chain if required.
9496 */
9497 static void
9498 zone_sign(dns_zone_t *zone) {
9499 const char *me = "zone_sign";
9500 dns_db_t *db = NULL;
9501 dns_dbnode_t *node = NULL;
9502 dns_dbversion_t *version = NULL;
9503 dns_diff_t _sig_diff;
9504 dns_diff_t post_diff;
9505 dns__zonediff_t zonediff;
9506 dns_fixedname_t fixed;
9507 dns_fixedname_t nextfixed;
9508 dns_kasp_t *kasp;
9509 dns_name_t *name, *nextname;
9510 dns_rdataset_t rdataset;
9511 dns_signing_t *signing, *nextsigning;
9512 dns_signinglist_t cleanup;
9513 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
9514 int32_t signatures;
9515 bool check_ksk, keyset_kskonly, is_ksk, is_zsk;
9516 bool with_ksk, with_zsk;
9517 bool commit = false;
9518 bool is_bottom_of_zone;
9519 bool build_nsec = false;
9520 bool build_nsec3 = false;
9521 bool use_kasp = false;
9522 bool first;
9523 isc_result_t result;
9524 isc_stdtime_t now, inception, soaexpire, expire;
9525 uint32_t jitter, sigvalidityinterval, expiryinterval;
9526 unsigned int i, j;
9527 unsigned int nkeys = 0;
9528 uint32_t nodes;
9529
9530 ENTER;
9531
9532 dns_rdataset_init(&rdataset);
9533 name = dns_fixedname_initname(&fixed);
9534 nextname = dns_fixedname_initname(&nextfixed);
9535 dns_diff_init(zone->mctx, &_sig_diff);
9536 dns_diff_init(zone->mctx, &post_diff);
9537 zonediff_init(&zonediff, &_sig_diff);
9538 ISC_LIST_INIT(cleanup);
9539
9540 /*
9541 * Updates are disabled. Pause for 1 minute.
9542 */
9543 if (zone->update_disabled) {
9544 result = ISC_R_FAILURE;
9545 goto cleanup;
9546 }
9547
9548 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9549 if (zone->db != NULL) {
9550 dns_db_attach(zone->db, &db);
9551 }
9552 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9553 if (db == NULL) {
9554 result = ISC_R_FAILURE;
9555 goto cleanup;
9556 }
9557
9558 result = dns_db_newversion(db, &version);
9559 if (result != ISC_R_SUCCESS) {
9560 dnssec_log(zone, ISC_LOG_ERROR,
9561 "zone_sign:dns_db_newversion -> %s",
9562 dns_result_totext(result));
9563 goto cleanup;
9564 }
9565
9566 isc_stdtime_get(&now);
9567
9568 result = dns__zone_findkeys(zone, db, version, now, zone->mctx,
9569 DNS_MAXZONEKEYS, zone_keys, &nkeys);
9570 if (result != ISC_R_SUCCESS) {
9571 dnssec_log(zone, ISC_LOG_ERROR,
9572 "zone_sign:dns__zone_findkeys -> %s",
9573 dns_result_totext(result));
9574 goto cleanup;
9575 }
9576
9577 kasp = dns_zone_getkasp(zone);
9578 sigvalidityinterval = dns_zone_getsigvalidityinterval(zone);
9579 inception = now - 3600; /* Allow for clock skew. */
9580 soaexpire = now + sigvalidityinterval;
9581 expiryinterval = dns_zone_getsigresigninginterval(zone);
9582 if (expiryinterval > sigvalidityinterval) {
9583 expiryinterval = sigvalidityinterval;
9584 } else {
9585 expiryinterval = sigvalidityinterval - expiryinterval;
9586 }
9587
9588 /*
9589 * Spread out signatures over time if they happen to be
9590 * clumped. We don't do this for each add_sigs() call as
9591 * we still want some clustering to occur.
9592 */
9593 if (sigvalidityinterval >= 3600U) {
9594 if (sigvalidityinterval > 7200U) {
9595 jitter = isc_random_uniform(expiryinterval);
9596 } else {
9597 jitter = isc_random_uniform(1200);
9598 }
9599 expire = soaexpire - jitter - 1;
9600 } else {
9601 expire = soaexpire - 1;
9602 }
9603
9604 /*
9605 * We keep pulling nodes off each iterator in turn until
9606 * we have no more nodes to pull off or we reach the limits
9607 * for this quantum.
9608 */
9609 nodes = zone->nodes;
9610 signatures = zone->signatures;
9611 signing = ISC_LIST_HEAD(zone->signing);
9612 first = true;
9613
9614 if (dns_zone_getkasp(zone) != NULL) {
9615 check_ksk = false;
9616 keyset_kskonly = true;
9617 use_kasp = true;
9618 } else {
9619 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
9620 keyset_kskonly = DNS_ZONE_OPTION(zone,
9621 DNS_ZONEOPT_DNSKEYKSKONLY);
9622 }
9623 dnssec_log(zone, ISC_LOG_DEBUG(3), "zone_sign:use kasp -> %s",
9624 use_kasp ? "yes" : "no");
9625
9626 /* Determine which type of chain to build */
9627 if (use_kasp) {
9628 build_nsec3 = dns_kasp_nsec3(kasp);
9629 build_nsec = !build_nsec3;
9630 } else {
9631 CHECK(dns_private_chains(db, version, zone->privatetype,
9632 &build_nsec, &build_nsec3));
9633 /* If neither chain is found, default to NSEC */
9634 if (!build_nsec && !build_nsec3) {
9635 build_nsec = true;
9636 }
9637 }
9638
9639 while (signing != NULL && nodes-- > 0 && signatures > 0) {
9640 bool has_alg = false;
9641
9642 dns_dbiterator_pause(signing->dbiterator);
9643 nextsigning = ISC_LIST_NEXT(signing, link);
9644
9645 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9646 if (signing->done || signing->db != zone->db) {
9647 /*
9648 * The zone has been reloaded. We will have to
9649 * created new signings as part of the reload
9650 * process so we can destroy this one.
9651 */
9652 ISC_LIST_UNLINK(zone->signing, signing, link);
9653 ISC_LIST_APPEND(cleanup, signing, link);
9654 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9655 goto next_signing;
9656 }
9657 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9658
9659 if (signing->db != db) {
9660 goto next_signing;
9661 }
9662
9663 is_bottom_of_zone = false;
9664
9665 if (first && signing->deleteit) {
9666 /*
9667 * Remove the key we are deleting from consideration.
9668 */
9669 for (i = 0, j = 0; i < nkeys; i++) {
9670 /*
9671 * Find the key we want to remove.
9672 */
9673 if (ALG(zone_keys[i]) == signing->algorithm &&
9674 dst_key_id(zone_keys[i]) == signing->keyid)
9675 {
9676 bool ksk = false;
9677 isc_result_t ret = dst_key_getbool(
9678 zone_keys[i], DST_BOOL_KSK,
9679 &ksk);
9680 if (ret != ISC_R_SUCCESS) {
9681 ksk = KSK(zone_keys[i]);
9682 }
9683 if (ksk) {
9684 dst_key_free(&zone_keys[i]);
9685 }
9686 continue;
9687 }
9688 zone_keys[j] = zone_keys[i];
9689 j++;
9690 }
9691 for (i = j; i < nkeys; i++) {
9692 zone_keys[i] = NULL;
9693 }
9694 nkeys = j;
9695 }
9696
9697 dns_dbiterator_current(signing->dbiterator, &node, name);
9698
9699 if (signing->deleteit) {
9700 dns_dbiterator_pause(signing->dbiterator);
9701 CHECK(del_sig(db, version, name, node, nkeys,
9702 signing->algorithm, signing->keyid,
9703 &has_alg, zonediff.diff));
9704 }
9705
9706 /*
9707 * On the first pass we need to check if the current node
9708 * has not been obscured.
9709 */
9710 if (first) {
9711 dns_fixedname_t ffound;
9712 dns_name_t *found;
9713 found = dns_fixedname_initname(&ffound);
9714 result = dns_db_find(
9715 db, name, version, dns_rdatatype_soa,
9716 DNS_DBFIND_NOWILD, 0, NULL, found, NULL, NULL);
9717 if ((result == DNS_R_DELEGATION ||
9718 result == DNS_R_DNAME) &&
9719 !dns_name_equal(name, found))
9720 {
9721 /*
9722 * Remember the obscuring name so that
9723 * we skip all obscured names.
9724 */
9725 dns_name_copynf(found, name);
9726 is_bottom_of_zone = true;
9727 goto next_node;
9728 }
9729 }
9730
9731 /*
9732 * Process one node.
9733 */
9734 with_ksk = false;
9735 with_zsk = false;
9736 dns_dbiterator_pause(signing->dbiterator);
9737
9738 CHECK(check_if_bottom_of_zone(db, node, version,
9739 &is_bottom_of_zone));
9740
9741 for (i = 0; !has_alg && i < nkeys; i++) {
9742 bool both = false;
9743
9744 /*
9745 * Find the keys we want to sign with.
9746 */
9747 if (!dst_key_isprivate(zone_keys[i])) {
9748 continue;
9749 }
9750 if (dst_key_inactive(zone_keys[i])) {
9751 continue;
9752 }
9753
9754 /*
9755 * When adding look for the specific key.
9756 */
9757 if (!signing->deleteit &&
9758 (dst_key_alg(zone_keys[i]) != signing->algorithm ||
9759 dst_key_id(zone_keys[i]) != signing->keyid))
9760 {
9761 continue;
9762 }
9763
9764 /*
9765 * When deleting make sure we are properly signed
9766 * with the algorithm that was being removed.
9767 */
9768 if (signing->deleteit &&
9769 ALG(zone_keys[i]) != signing->algorithm)
9770 {
9771 continue;
9772 }
9773
9774 /*
9775 * Do we do KSK processing?
9776 */
9777 if (check_ksk && !REVOKE(zone_keys[i])) {
9778 bool have_ksk, have_nonksk;
9779 if (KSK(zone_keys[i])) {
9780 have_ksk = true;
9781 have_nonksk = false;
9782 } else {
9783 have_ksk = false;
9784 have_nonksk = true;
9785 }
9786 for (j = 0; j < nkeys; j++) {
9787 if (j == i || (ALG(zone_keys[i]) !=
9788 ALG(zone_keys[j])))
9789 {
9790 continue;
9791 }
9792 /*
9793 * Don't consider inactive keys, however
9794 * the key may be temporary offline, so
9795 * do consider KSKs which private key
9796 * files are unavailable.
9797 */
9798 if (dst_key_inactive(zone_keys[j])) {
9799 continue;
9800 }
9801 if (REVOKE(zone_keys[j])) {
9802 continue;
9803 }
9804 if (KSK(zone_keys[j])) {
9805 have_ksk = true;
9806 } else if (dst_key_isprivate(
9807 zone_keys[j]))
9808 {
9809 have_nonksk = true;
9810 }
9811 both = have_ksk && have_nonksk;
9812 if (both) {
9813 break;
9814 }
9815 }
9816 }
9817 if (use_kasp) {
9818 /*
9819 * A dnssec-policy is found. Check what
9820 * RRsets this key can sign.
9821 */
9822 isc_result_t kresult;
9823 is_ksk = false;
9824 kresult = dst_key_getbool(
9825 zone_keys[i], DST_BOOL_KSK, &is_ksk);
9826 if (kresult != ISC_R_SUCCESS) {
9827 if (KSK(zone_keys[i])) {
9828 is_ksk = true;
9829 }
9830 }
9831
9832 is_zsk = false;
9833 kresult = dst_key_getbool(
9834 zone_keys[i], DST_BOOL_ZSK, &is_zsk);
9835 if (kresult != ISC_R_SUCCESS) {
9836 if (!KSK(zone_keys[i])) {
9837 is_zsk = true;
9838 }
9839 }
9840 /* Treat as if we have both KSK and ZSK. */
9841 both = true;
9842 } else if (both || REVOKE(zone_keys[i])) {
9843 is_ksk = KSK(zone_keys[i]);
9844 is_zsk = !KSK(zone_keys[i]);
9845 } else {
9846 is_ksk = false;
9847 is_zsk = true;
9848 }
9849
9850 /*
9851 * If deleting signatures, we need to ensure that
9852 * the RRset is still signed at least once by a
9853 * KSK and a ZSK.
9854 */
9855 if (signing->deleteit && is_zsk && with_zsk) {
9856 continue;
9857 }
9858
9859 if (signing->deleteit && is_ksk && with_ksk) {
9860 continue;
9861 }
9862
9863 CHECK(sign_a_node(
9864 db, zone, name, node, version, build_nsec3,
9865 build_nsec, zone_keys[i], inception, expire,
9866 zone_nsecttl(zone), is_ksk, is_zsk,
9867 (both && keyset_kskonly), is_bottom_of_zone,
9868 zonediff.diff, &signatures, zone->mctx));
9869 /*
9870 * If we are adding we are done. Look for other keys
9871 * of the same algorithm if deleting.
9872 */
9873 if (!signing->deleteit) {
9874 break;
9875 }
9876 if (is_zsk) {
9877 with_zsk = true;
9878 }
9879 if (is_ksk) {
9880 with_ksk = true;
9881 }
9882 }
9883
9884 /*
9885 * Go onto next node.
9886 */
9887 next_node:
9888 first = false;
9889 dns_db_detachnode(db, &node);
9890 do {
9891 result = dns_dbiterator_next(signing->dbiterator);
9892 if (result == ISC_R_NOMORE) {
9893 ISC_LIST_UNLINK(zone->signing, signing, link);
9894 ISC_LIST_APPEND(cleanup, signing, link);
9895 dns_dbiterator_pause(signing->dbiterator);
9896 if (nkeys != 0 && build_nsec) {
9897 /*
9898 * We have finished regenerating the
9899 * zone with a zone signing key.
9900 * The NSEC chain is now complete and
9901 * there is a full set of signatures
9902 * for the zone. We can now clear the
9903 * OPT bit from the NSEC record.
9904 */
9905 result = updatesecure(
9906 db, version, &zone->origin,
9907 zone_nsecttl(zone), false,
9908 &post_diff);
9909 if (result != ISC_R_SUCCESS) {
9910 dnssec_log(zone, ISC_LOG_ERROR,
9911 "updatesecure -> %s",
9912 dns_result_totext(
9913 result));
9914 goto cleanup;
9915 }
9916 }
9917 result = updatesignwithkey(
9918 zone, signing, version, build_nsec3,
9919 zone_nsecttl(zone), &post_diff);
9920 if (result != ISC_R_SUCCESS) {
9921 dnssec_log(zone, ISC_LOG_ERROR,
9922 "updatesignwithkey -> %s",
9923 dns_result_totext(result));
9924 goto cleanup;
9925 }
9926 build_nsec = false;
9927 goto next_signing;
9928 } else if (result != ISC_R_SUCCESS) {
9929 dnssec_log(zone, ISC_LOG_ERROR,
9930 "zone_sign:"
9931 "dns_dbiterator_next -> %s",
9932 dns_result_totext(result));
9933 goto cleanup;
9934 } else if (is_bottom_of_zone) {
9935 dns_dbiterator_current(signing->dbiterator,
9936 &node, nextname);
9937 dns_db_detachnode(db, &node);
9938 if (!dns_name_issubdomain(nextname, name)) {
9939 break;
9940 }
9941 } else {
9942 break;
9943 }
9944 } while (1);
9945 continue;
9946
9947 next_signing:
9948 dns_dbiterator_pause(signing->dbiterator);
9949 signing = nextsigning;
9950 first = true;
9951 }
9952
9953 if (ISC_LIST_HEAD(post_diff.tuples) != NULL) {
9954 result = dns__zone_updatesigs(&post_diff, db, version,
9955 zone_keys, nkeys, zone, inception,
9956 expire, 0, now, check_ksk,
9957 keyset_kskonly, &zonediff);
9958 if (result != ISC_R_SUCCESS) {
9959 dnssec_log(zone, ISC_LOG_ERROR,
9960 "zone_sign:dns__zone_updatesigs -> %s",
9961 dns_result_totext(result));
9962 goto cleanup;
9963 }
9964 }
9965
9966 /*
9967 * Have we changed anything?
9968 */
9969 if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
9970 if (zonediff.offline) {
9971 commit = true;
9972 }
9973 result = ISC_R_SUCCESS;
9974 goto pauseall;
9975 }
9976
9977 commit = true;
9978
9979 result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
9980 &zonediff, zone_keys, nkeys, now, false);
9981 if (result != ISC_R_SUCCESS) {
9982 dnssec_log(zone, ISC_LOG_ERROR, "zone_sign:del_sigs -> %s",
9983 dns_result_totext(result));
9984 goto cleanup;
9985 }
9986
9987 result = update_soa_serial(zone, db, version, zonediff.diff, zone->mctx,
9988 zone->updatemethod);
9989 if (result != ISC_R_SUCCESS) {
9990 dnssec_log(zone, ISC_LOG_ERROR,
9991 "zone_sign:update_soa_serial -> %s",
9992 dns_result_totext(result));
9993 goto cleanup;
9994 }
9995
9996 /*
9997 * Generate maximum life time signatures so that the above loop
9998 * termination is sensible.
9999 */
10000 result = add_sigs(db, version, &zone->origin, zone, dns_rdatatype_soa,
10001 zonediff.diff, zone_keys, nkeys, zone->mctx,
10002 inception, soaexpire, check_ksk, keyset_kskonly);
10003 if (result != ISC_R_SUCCESS) {
10004 dnssec_log(zone, ISC_LOG_ERROR, "zone_sign:add_sigs -> %s",
10005 dns_result_totext(result));
10006 goto cleanup;
10007 }
10008
10009 /*
10010 * Write changes to journal file.
10011 */
10012 CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_sign"));
10013
10014 pauseall:
10015 /*
10016 * Pause all iterators so that dns_db_closeversion() can succeed.
10017 */
10018 for (signing = ISC_LIST_HEAD(zone->signing); signing != NULL;
10019 signing = ISC_LIST_NEXT(signing, link))
10020 {
10021 dns_dbiterator_pause(signing->dbiterator);
10022 }
10023
10024 for (signing = ISC_LIST_HEAD(cleanup); signing != NULL;
10025 signing = ISC_LIST_NEXT(signing, link))
10026 {
10027 dns_dbiterator_pause(signing->dbiterator);
10028 }
10029
10030 /*
10031 * Everything has succeeded. Commit the changes.
10032 */
10033 dns_db_closeversion(db, &version, commit);
10034
10035 /*
10036 * Everything succeeded so we can clean these up now.
10037 */
10038 signing = ISC_LIST_HEAD(cleanup);
10039 while (signing != NULL) {
10040 ISC_LIST_UNLINK(cleanup, signing, link);
10041 dns_db_detach(&signing->db);
10042 dns_dbiterator_destroy(&signing->dbiterator);
10043 isc_mem_put(zone->mctx, signing, sizeof *signing);
10044 signing = ISC_LIST_HEAD(cleanup);
10045 }
10046
10047 LOCK_ZONE(zone);
10048 set_resigntime(zone);
10049 if (commit) {
10050 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
10051 zone_needdump(zone, DNS_DUMP_DELAY);
10052 }
10053 UNLOCK_ZONE(zone);
10054
10055 failure:
10056 if (result != ISC_R_SUCCESS) {
10057 dnssec_log(zone, ISC_LOG_ERROR, "zone_sign: failed: %s",
10058 dns_result_totext(result));
10059 }
10060
10061 cleanup:
10062 /*
10063 * Pause all dbiterators.
10064 */
10065 for (signing = ISC_LIST_HEAD(zone->signing); signing != NULL;
10066 signing = ISC_LIST_NEXT(signing, link))
10067 {
10068 dns_dbiterator_pause(signing->dbiterator);
10069 }
10070
10071 /*
10072 * Rollback the cleanup list.
10073 */
10074 signing = ISC_LIST_HEAD(cleanup);
10075 while (signing != NULL) {
10076 ISC_LIST_UNLINK(cleanup, signing, link);
10077 ISC_LIST_PREPEND(zone->signing, signing, link);
10078 dns_dbiterator_first(signing->dbiterator);
10079 dns_dbiterator_pause(signing->dbiterator);
10080 signing = ISC_LIST_HEAD(cleanup);
10081 }
10082
10083 dns_diff_clear(&_sig_diff);
10084
10085 for (i = 0; i < nkeys; i++) {
10086 dst_key_free(&zone_keys[i]);
10087 }
10088
10089 if (node != NULL) {
10090 dns_db_detachnode(db, &node);
10091 }
10092
10093 if (version != NULL) {
10094 dns_db_closeversion(db, &version, false);
10095 dns_db_detach(&db);
10096 } else if (db != NULL) {
10097 dns_db_detach(&db);
10098 }
10099
10100 LOCK_ZONE(zone);
10101 if (ISC_LIST_HEAD(zone->signing) != NULL) {
10102 isc_interval_t interval;
10103 if (zone->update_disabled || result != ISC_R_SUCCESS) {
10104 isc_interval_set(&interval, 60, 0); /* 1 minute */
10105 } else {
10106 isc_interval_set(&interval, 0, 10000000); /* 10 ms */
10107 }
10108 isc_time_nowplusinterval(&zone->signingtime, &interval);
10109 } else {
10110 isc_time_settoepoch(&zone->signingtime);
10111 }
10112 UNLOCK_ZONE(zone);
10113
10114 INSIST(version == NULL);
10115 }
10116
10117 static isc_result_t
10118 normalize_key(dns_rdata_t *rr, dns_rdata_t *target, unsigned char *data,
10119 int size) {
10120 dns_rdata_dnskey_t dnskey;
10121 dns_rdata_keydata_t keydata;
10122 isc_buffer_t buf;
10123 isc_result_t result;
10124
10125 dns_rdata_reset(target);
10126 isc_buffer_init(&buf, data, size);
10127
10128 switch (rr->type) {
10129 case dns_rdatatype_dnskey:
10130 result = dns_rdata_tostruct(rr, &dnskey, NULL);
10131 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10132 dnskey.flags &= ~DNS_KEYFLAG_REVOKE;
10133 dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
10134 &dnskey, &buf);
10135 break;
10136 case dns_rdatatype_keydata:
10137 result = dns_rdata_tostruct(rr, &keydata, NULL);
10138 if (result == ISC_R_UNEXPECTEDEND) {
10139 return (result);
10140 }
10141 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10142 dns_keydata_todnskey(&keydata, &dnskey, NULL);
10143 dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
10144 &dnskey, &buf);
10145 break;
10146 default:
10147 UNREACHABLE();
10148 }
10149 return (ISC_R_SUCCESS);
10150 }
10151
10152 /*
10153 * 'rdset' contains either a DNSKEY rdataset from the zone apex, or
10154 * a KEYDATA rdataset from the key zone.
10155 *
10156 * 'rr' contains either a DNSKEY record, or a KEYDATA record
10157 *
10158 * After normalizing keys to the same format (DNSKEY, with revoke bit
10159 * cleared), return true if a key that matches 'rr' is found in
10160 * 'rdset', or false if not.
10161 */
10162
10163 static bool
10164 matchkey(dns_rdataset_t *rdset, dns_rdata_t *rr) {
10165 unsigned char data1[4096], data2[4096];
10166 dns_rdata_t rdata, rdata1, rdata2;
10167 isc_result_t result;
10168
10169 dns_rdata_init(&rdata);
10170 dns_rdata_init(&rdata1);
10171 dns_rdata_init(&rdata2);
10172
10173 result = normalize_key(rr, &rdata1, data1, sizeof(data1));
10174 if (result != ISC_R_SUCCESS) {
10175 return (false);
10176 }
10177
10178 for (result = dns_rdataset_first(rdset); result == ISC_R_SUCCESS;
10179 result = dns_rdataset_next(rdset))
10180 {
10181 dns_rdata_reset(&rdata);
10182 dns_rdataset_current(rdset, &rdata);
10183 result = normalize_key(&rdata, &rdata2, data2, sizeof(data2));
10184 if (result != ISC_R_SUCCESS) {
10185 continue;
10186 }
10187 if (dns_rdata_compare(&rdata1, &rdata2) == 0) {
10188 return (true);
10189 }
10190 }
10191
10192 return (false);
10193 }
10194
10195 /*
10196 * Calculate the refresh interval for a keydata zone, per
10197 * RFC5011: MAX(1 hr,
10198 * MIN(15 days,
10199 * 1/2 * OrigTTL,
10200 * 1/2 * RRSigExpirationInterval))
10201 * or for retries: MAX(1 hr,
10202 * MIN(1 day,
10203 * 1/10 * OrigTTL,
10204 * 1/10 * RRSigExpirationInterval))
10205 */
10206 static isc_stdtime_t
10207 refresh_time(dns_keyfetch_t *kfetch, bool retry) {
10208 isc_result_t result;
10209 uint32_t t;
10210 dns_rdataset_t *rdset;
10211 dns_rdata_t sigrr = DNS_RDATA_INIT;
10212 dns_rdata_sig_t sig;
10213 isc_stdtime_t now;
10214
10215 isc_stdtime_get(&now);
10216
10217 if (dns_rdataset_isassociated(&kfetch->dnskeysigset)) {
10218 rdset = &kfetch->dnskeysigset;
10219 } else {
10220 return (now + dns_zone_mkey_hour);
10221 }
10222
10223 result = dns_rdataset_first(rdset);
10224 if (result != ISC_R_SUCCESS) {
10225 return (now + dns_zone_mkey_hour);
10226 }
10227
10228 dns_rdataset_current(rdset, &sigrr);
10229 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
10230 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10231
10232 if (!retry) {
10233 t = sig.originalttl / 2;
10234
10235 if (isc_serial_gt(sig.timeexpire, now)) {
10236 uint32_t exp = (sig.timeexpire - now) / 2;
10237 if (t > exp) {
10238 t = exp;
10239 }
10240 }
10241
10242 if (t > (15 * dns_zone_mkey_day)) {
10243 t = (15 * dns_zone_mkey_day);
10244 }
10245
10246 if (t < dns_zone_mkey_hour) {
10247 t = dns_zone_mkey_hour;
10248 }
10249 } else {
10250 t = sig.originalttl / 10;
10251
10252 if (isc_serial_gt(sig.timeexpire, now)) {
10253 uint32_t exp = (sig.timeexpire - now) / 10;
10254 if (t > exp) {
10255 t = exp;
10256 }
10257 }
10258
10259 if (t > dns_zone_mkey_day) {
10260 t = dns_zone_mkey_day;
10261 }
10262
10263 if (t < dns_zone_mkey_hour) {
10264 t = dns_zone_mkey_hour;
10265 }
10266 }
10267
10268 return (now + t);
10269 }
10270
10271 /*
10272 * This routine is called when no changes are needed in a KEYDATA
10273 * record except to simply update the refresh timer. Caller should
10274 * hold zone lock.
10275 */
10276 static isc_result_t
10277 minimal_update(dns_keyfetch_t *kfetch, dns_dbversion_t *ver, dns_diff_t *diff) {
10278 isc_result_t result;
10279 isc_buffer_t keyb;
10280 unsigned char key_buf[4096];
10281 dns_rdata_t rdata = DNS_RDATA_INIT;
10282 dns_rdata_keydata_t keydata;
10283 dns_name_t *name;
10284 dns_zone_t *zone = kfetch->zone;
10285 isc_stdtime_t now;
10286
10287 name = dns_fixedname_name(&kfetch->name);
10288 isc_stdtime_get(&now);
10289
10290 for (result = dns_rdataset_first(&kfetch->keydataset);
10291 result == ISC_R_SUCCESS;
10292 result = dns_rdataset_next(&kfetch->keydataset))
10293 {
10294 dns_rdata_reset(&rdata);
10295 dns_rdataset_current(&kfetch->keydataset, &rdata);
10296
10297 /* Delete old version */
10298 CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_DEL, name,
10299 0, &rdata));
10300
10301 /* Update refresh timer */
10302 result = dns_rdata_tostruct(&rdata, &keydata, NULL);
10303 if (result == ISC_R_UNEXPECTEDEND) {
10304 continue;
10305 }
10306 if (result != ISC_R_SUCCESS) {
10307 goto failure;
10308 }
10309 keydata.refresh = refresh_time(kfetch, true);
10310 set_refreshkeytimer(zone, &keydata, now, false);
10311
10312 dns_rdata_reset(&rdata);
10313 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10314 CHECK(dns_rdata_fromstruct(&rdata, zone->rdclass,
10315 dns_rdatatype_keydata, &keydata,
10316 &keyb));
10317
10318 /* Insert updated version */
10319 CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_ADD, name,
10320 0, &rdata));
10321 }
10322 result = ISC_R_SUCCESS;
10323 failure:
10324 return (result);
10325 }
10326
10327 /*
10328 * Verify that DNSKEY set is signed by the key specified in 'keydata'.
10329 */
10330 static bool
10331 revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) {
10332 isc_result_t result;
10333 dns_name_t *keyname;
10334 isc_mem_t *mctx;
10335 dns_rdata_t sigrr = DNS_RDATA_INIT;
10336 dns_rdata_t rr = DNS_RDATA_INIT;
10337 dns_rdata_rrsig_t sig;
10338 dns_rdata_dnskey_t dnskey;
10339 dst_key_t *dstkey = NULL;
10340 unsigned char key_buf[4096];
10341 isc_buffer_t keyb;
10342 bool answer = false;
10343
10344 REQUIRE(kfetch != NULL && keydata != NULL);
10345 REQUIRE(dns_rdataset_isassociated(&kfetch->dnskeysigset));
10346
10347 keyname = dns_fixedname_name(&kfetch->name);
10348 mctx = kfetch->zone->view->mctx;
10349
10350 /* Generate a key from keydata */
10351 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10352 dns_keydata_todnskey(keydata, &dnskey, NULL);
10353 dns_rdata_fromstruct(&rr, keydata->common.rdclass, dns_rdatatype_dnskey,
10354 &dnskey, &keyb);
10355 result = dns_dnssec_keyfromrdata(keyname, &rr, mctx, &dstkey);
10356 if (result != ISC_R_SUCCESS) {
10357 return (false);
10358 }
10359
10360 /* See if that key generated any of the signatures */
10361 for (result = dns_rdataset_first(&kfetch->dnskeysigset);
10362 result == ISC_R_SUCCESS;
10363 result = dns_rdataset_next(&kfetch->dnskeysigset))
10364 {
10365 dns_fixedname_t fixed;
10366 dns_fixedname_init(&fixed);
10367
10368 dns_rdata_reset(&sigrr);
10369 dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
10370 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
10371 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10372
10373 if (dst_key_alg(dstkey) == sig.algorithm &&
10374 dst_key_rid(dstkey) == sig.keyid)
10375 {
10376 result = dns_dnssec_verify(
10377 keyname, &kfetch->dnskeyset, dstkey, false, 0,
10378 mctx, &sigrr, dns_fixedname_name(&fixed));
10379
10380 dnssec_log(kfetch->zone, ISC_LOG_DEBUG(3),
10381 "Confirm revoked DNSKEY is self-signed: %s",
10382 dns_result_totext(result));
10383
10384 if (result == ISC_R_SUCCESS) {
10385 answer = true;
10386 break;
10387 }
10388 }
10389 }
10390
10391 dst_key_free(&dstkey);
10392 return (answer);
10393 }
10394
10395 /*
10396 * A DNSKEY set has been fetched from the zone apex of a zone whose trust
10397 * anchors are being managed; scan the keyset, and update the key zone and the
10398 * local trust anchors according to RFC5011.
10399 */
10400 static void
10401 keyfetch_done(isc_task_t *task, isc_event_t *event) {
10402 isc_result_t result, eresult;
10403 dns_fetchevent_t *devent;
10404 dns_keyfetch_t *kfetch;
10405 dns_zone_t *zone;
10406 isc_mem_t *mctx = NULL;
10407 dns_keytable_t *secroots = NULL;
10408 dns_dbversion_t *ver = NULL;
10409 dns_diff_t diff;
10410 bool alldone = false;
10411 bool commit = false;
10412 dns_name_t *keyname = NULL;
10413 dns_rdata_t sigrr = DNS_RDATA_INIT;
10414 dns_rdata_t dnskeyrr = DNS_RDATA_INIT;
10415 dns_rdata_t keydatarr = DNS_RDATA_INIT;
10416 dns_rdata_rrsig_t sig;
10417 dns_rdata_dnskey_t dnskey;
10418 dns_rdata_keydata_t keydata;
10419 bool initializing;
10420 char namebuf[DNS_NAME_FORMATSIZE];
10421 unsigned char key_buf[4096];
10422 isc_buffer_t keyb;
10423 dst_key_t *dstkey = NULL;
10424 isc_stdtime_t now;
10425 int pending = 0;
10426 bool secure = false, initial = false;
10427 bool free_needed;
10428 dns_keynode_t *keynode = NULL;
10429 dns_rdataset_t *dnskeys = NULL, *dnskeysigs = NULL;
10430 dns_rdataset_t *keydataset = NULL, dsset;
10431
10432 UNUSED(task);
10433 INSIST(event != NULL && event->ev_type == DNS_EVENT_FETCHDONE);
10434 INSIST(event->ev_arg != NULL);
10435
10436 kfetch = event->ev_arg;
10437 zone = kfetch->zone;
10438 mctx = kfetch->mctx;
10439 keyname = dns_fixedname_name(&kfetch->name);
10440 dnskeys = &kfetch->dnskeyset;
10441 dnskeysigs = &kfetch->dnskeysigset;
10442 keydataset = &kfetch->keydataset;
10443
10444 devent = (dns_fetchevent_t *)event;
10445 eresult = devent->result;
10446
10447 /* Free resources which are not of interest */
10448 if (devent->node != NULL) {
10449 dns_db_detachnode(devent->db, &devent->node);
10450 }
10451 if (devent->db != NULL) {
10452 dns_db_detach(&devent->db);
10453 }
10454 isc_event_free(&event);
10455 dns_resolver_destroyfetch(&kfetch->fetch);
10456
10457 LOCK_ZONE(zone);
10458 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || zone->view == NULL) {
10459 goto cleanup;
10460 }
10461
10462 isc_stdtime_get(&now);
10463 dns_name_format(keyname, namebuf, sizeof(namebuf));
10464
10465 result = dns_view_getsecroots(zone->view, &secroots);
10466 INSIST(result == ISC_R_SUCCESS);
10467
10468 dns_diff_init(mctx, &diff);
10469
10470 CHECK(dns_db_newversion(kfetch->db, &ver));
10471
10472 zone->refreshkeycount--;
10473 alldone = (zone->refreshkeycount == 0);
10474
10475 if (alldone) {
10476 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
10477 }
10478
10479 dnssec_log(zone, ISC_LOG_DEBUG(3),
10480 "Returned from key fetch in keyfetch_done() for '%s': %s",
10481 namebuf, dns_result_totext(eresult));
10482
10483 /* Fetch failed */
10484 if (eresult != ISC_R_SUCCESS || !dns_rdataset_isassociated(dnskeys)) {
10485 dnssec_log(zone, ISC_LOG_WARNING,
10486 "Unable to fetch DNSKEY set '%s': %s", namebuf,
10487 dns_result_totext(eresult));
10488 CHECK(minimal_update(kfetch, ver, &diff));
10489 goto done;
10490 }
10491
10492 /* No RRSIGs found */
10493 if (!dns_rdataset_isassociated(dnskeysigs)) {
10494 dnssec_log(zone, ISC_LOG_WARNING,
10495 "No DNSKEY RRSIGs found for '%s': %s", namebuf,
10496 dns_result_totext(eresult));
10497 CHECK(minimal_update(kfetch, ver, &diff));
10498 goto done;
10499 }
10500
10501 /*
10502 * Clear any cached trust level, as we need to run validation
10503 * over again; trusted keys might have changed.
10504 */
10505 dnskeys->trust = dnskeysigs->trust = dns_trust_none;
10506
10507 /* Look up the trust anchor */
10508 result = dns_keytable_find(secroots, keyname, &keynode);
10509 if (result != ISC_R_SUCCESS) {
10510 goto anchors_done;
10511 }
10512
10513 /*
10514 * If the keynode has a DS trust anchor, use it for verification.
10515 */
10516 dns_rdataset_init(&dsset);
10517 if (dns_keynode_dsset(keynode, &dsset)) {
10518 for (result = dns_rdataset_first(dnskeysigs);
10519 result == ISC_R_SUCCESS;
10520 result = dns_rdataset_next(dnskeysigs))
10521 {
10522 isc_result_t tresult;
10523 dns_rdata_t keyrdata = DNS_RDATA_INIT;
10524
10525 dns_rdata_reset(&sigrr);
10526 dns_rdataset_current(dnskeysigs, &sigrr);
10527 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
10528 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10529
10530 for (tresult = dns_rdataset_first(&dsset);
10531 tresult == ISC_R_SUCCESS;
10532 tresult = dns_rdataset_next(&dsset))
10533 {
10534 dns_rdata_t dsrdata = DNS_RDATA_INIT;
10535 dns_rdata_ds_t ds;
10536
10537 dns_rdata_reset(&dsrdata);
10538 dns_rdataset_current(&dsset, &dsrdata);
10539 tresult = dns_rdata_tostruct(&dsrdata, &ds,
10540 NULL);
10541 RUNTIME_CHECK(tresult == ISC_R_SUCCESS);
10542
10543 if (ds.key_tag != sig.keyid ||
10544 ds.algorithm != sig.algorithm)
10545 {
10546 continue;
10547 }
10548
10549 result = dns_dnssec_matchdskey(
10550 keyname, &dsrdata, dnskeys, &keyrdata);
10551 if (result == ISC_R_SUCCESS) {
10552 break;
10553 }
10554 }
10555
10556 if (tresult == ISC_R_NOMORE) {
10557 continue;
10558 }
10559
10560 result = dns_dnssec_keyfromrdata(keyname, &keyrdata,
10561 mctx, &dstkey);
10562 if (result != ISC_R_SUCCESS) {
10563 continue;
10564 }
10565
10566 result = dns_dnssec_verify(keyname, dnskeys, dstkey,
10567 false, 0, mctx, &sigrr,
10568 NULL);
10569 dst_key_free(&dstkey);
10570
10571 dnssec_log(zone, ISC_LOG_DEBUG(3),
10572 "Verifying DNSKEY set for zone "
10573 "'%s' using DS %d/%d: %s",
10574 namebuf, sig.keyid, sig.algorithm,
10575 dns_result_totext(result));
10576
10577 if (result == ISC_R_SUCCESS) {
10578 dnskeys->trust = dns_trust_secure;
10579 dnskeysigs->trust = dns_trust_secure;
10580 initial = dns_keynode_initial(keynode);
10581 dns_keynode_trust(keynode);
10582 secure = true;
10583 break;
10584 }
10585 }
10586 dns_rdataset_disassociate(&dsset);
10587 }
10588
10589 anchors_done:
10590 if (keynode != NULL) {
10591 dns_keytable_detachkeynode(secroots, &keynode);
10592 }
10593
10594 /*
10595 * If we were not able to verify the answer using the current
10596 * trusted keys then all we can do is look at any revoked keys.
10597 */
10598 if (!secure) {
10599 dnssec_log(zone, ISC_LOG_INFO,
10600 "DNSKEY set for zone '%s' could not be verified "
10601 "with current keys",
10602 namebuf);
10603 }
10604
10605 /*
10606 * First scan keydataset to find keys that are not in dnskeyset
10607 * - Missing keys which are not scheduled for removal,
10608 * log a warning
10609 * - Missing keys which are scheduled for removal and
10610 * the remove hold-down timer has completed should
10611 * be removed from the key zone
10612 * - Missing keys whose acceptance timers have not yet
10613 * completed, log a warning and reset the acceptance
10614 * timer to 30 days in the future
10615 * - All keys not being removed have their refresh timers
10616 * updated
10617 */
10618 initializing = true;
10619 for (result = dns_rdataset_first(keydataset); result == ISC_R_SUCCESS;
10620 result = dns_rdataset_next(keydataset))
10621 {
10622 dns_keytag_t keytag;
10623
10624 dns_rdata_reset(&keydatarr);
10625 dns_rdataset_current(keydataset, &keydatarr);
10626 result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
10627 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10628
10629 dns_keydata_todnskey(&keydata, &dnskey, NULL);
10630 result = compute_tag(keyname, &dnskey, mctx, &keytag);
10631 if (result != ISC_R_SUCCESS) {
10632 /*
10633 * Skip if we cannot compute the key tag.
10634 * This may happen if the algorithm is unsupported
10635 */
10636 dns_zone_log(zone, ISC_LOG_ERROR,
10637 "Cannot compute tag for key in zone %s: "
10638 "%s "
10639 "(skipping)",
10640 namebuf, dns_result_totext(result));
10641 continue;
10642 }
10643 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10644
10645 /*
10646 * If any keydata record has a nonzero add holddown, then
10647 * there was a pre-existing trust anchor for this domain;
10648 * that means we are *not* initializing it and shouldn't
10649 * automatically trust all the keys we find at the zone apex.
10650 */
10651 initializing = initializing && (keydata.addhd == 0);
10652
10653 if (!matchkey(dnskeys, &keydatarr)) {
10654 bool deletekey = false;
10655
10656 if (!secure) {
10657 if (keydata.removehd != 0 &&
10658 keydata.removehd <= now)
10659 {
10660 deletekey = true;
10661 }
10662 } else if (keydata.addhd == 0) {
10663 deletekey = true;
10664 } else if (keydata.addhd > now) {
10665 dnssec_log(zone, ISC_LOG_INFO,
10666 "Pending key %d for zone %s "
10667 "unexpectedly missing "
10668 "restarting 30-day acceptance "
10669 "timer",
10670 keytag, namebuf);
10671 if (keydata.addhd < now + dns_zone_mkey_month) {
10672 keydata.addhd = now +
10673 dns_zone_mkey_month;
10674 }
10675 keydata.refresh = refresh_time(kfetch, false);
10676 } else if (keydata.removehd == 0) {
10677 dnssec_log(zone, ISC_LOG_INFO,
10678 "Active key %d for zone %s "
10679 "unexpectedly missing",
10680 keytag, namebuf);
10681 keydata.refresh = now + dns_zone_mkey_hour;
10682 } else if (keydata.removehd <= now) {
10683 deletekey = true;
10684 dnssec_log(zone, ISC_LOG_INFO,
10685 "Revoked key %d for zone %s "
10686 "missing: deleting from "
10687 "managed keys database",
10688 keytag, namebuf);
10689 } else {
10690 keydata.refresh = refresh_time(kfetch, false);
10691 }
10692
10693 if (secure || deletekey) {
10694 /* Delete old version */
10695 CHECK(update_one_rr(kfetch->db, ver, &diff,
10696 DNS_DIFFOP_DEL, keyname, 0,
10697 &keydatarr));
10698 }
10699
10700 if (!secure || deletekey) {
10701 continue;
10702 }
10703
10704 dns_rdata_reset(&keydatarr);
10705 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10706 dns_rdata_fromstruct(&keydatarr, zone->rdclass,
10707 dns_rdatatype_keydata, &keydata,
10708 &keyb);
10709
10710 /* Insert updated version */
10711 CHECK(update_one_rr(kfetch->db, ver, &diff,
10712 DNS_DIFFOP_ADD, keyname, 0,
10713 &keydatarr));
10714
10715 set_refreshkeytimer(zone, &keydata, now, false);
10716 }
10717 }
10718
10719 /*
10720 * Next scan dnskeyset:
10721 * - If new keys are found (i.e., lacking a match in keydataset)
10722 * add them to the key zone and set the acceptance timer
10723 * to 30 days in the future (or to immediately if we've
10724 * determined that we're initializing the zone for the
10725 * first time)
10726 * - Previously-known keys that have been revoked
10727 * must be scheduled for removal from the key zone (or,
10728 * if they hadn't been accepted as trust anchors yet
10729 * anyway, removed at once)
10730 * - Previously-known unrevoked keys whose acceptance timers
10731 * have completed are promoted to trust anchors
10732 * - All keys not being removed have their refresh
10733 * timers updated
10734 */
10735 for (result = dns_rdataset_first(dnskeys); result == ISC_R_SUCCESS;
10736 result = dns_rdataset_next(dnskeys))
10737 {
10738 bool revoked = false;
10739 bool newkey = false;
10740 bool updatekey = false;
10741 bool deletekey = false;
10742 bool trustkey = false;
10743 dns_keytag_t keytag;
10744
10745 dns_rdata_reset(&dnskeyrr);
10746 dns_rdataset_current(dnskeys, &dnskeyrr);
10747 result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
10748 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10749
10750 /* Skip ZSK's */
10751 if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0) {
10752 continue;
10753 }
10754
10755 result = compute_tag(keyname, &dnskey, mctx, &keytag);
10756 if (result != ISC_R_SUCCESS) {
10757 /*
10758 * Skip if we cannot compute the key tag.
10759 * This may happen if the algorithm is unsupported
10760 */
10761 dns_zone_log(zone, ISC_LOG_ERROR,
10762 "Cannot compute tag for key in zone %s: "
10763 "%s "
10764 "(skipping)",
10765 namebuf, dns_result_totext(result));
10766 continue;
10767 }
10768 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10769
10770 revoked = ((dnskey.flags & DNS_KEYFLAG_REVOKE) != 0);
10771
10772 if (matchkey(keydataset, &dnskeyrr)) {
10773 dns_rdata_reset(&keydatarr);
10774 dns_rdataset_current(keydataset, &keydatarr);
10775 result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
10776 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10777
10778 if (revoked && revocable(kfetch, &keydata)) {
10779 if (keydata.addhd > now) {
10780 /*
10781 * Key wasn't trusted yet, and now
10782 * it's been revoked? Just remove it
10783 */
10784 deletekey = true;
10785 dnssec_log(zone, ISC_LOG_INFO,
10786 "Pending key %d for "
10787 "zone %s is now revoked: "
10788 "deleting from the "
10789 "managed keys database",
10790 keytag, namebuf);
10791 } else if (keydata.removehd == 0) {
10792 /*
10793 * Remove key from secroots.
10794 */
10795 dns_view_untrust(zone->view, keyname,
10796 &dnskey);
10797
10798 /* If initializing, delete now */
10799 if (keydata.addhd == 0) {
10800 deletekey = true;
10801 } else {
10802 keydata.removehd =
10803 now +
10804 dns_zone_mkey_month;
10805 keydata.flags |=
10806 DNS_KEYFLAG_REVOKE;
10807 }
10808
10809 dnssec_log(zone, ISC_LOG_INFO,
10810 "Trusted key %d for "
10811 "zone %s is now revoked",
10812 keytag, namebuf);
10813 } else if (keydata.removehd < now) {
10814 /* Scheduled for removal */
10815 deletekey = true;
10816
10817 dnssec_log(zone, ISC_LOG_INFO,
10818 "Revoked key %d for "
10819 "zone %s removal timer "
10820 "complete: deleting from "
10821 "the managed keys database",
10822 keytag, namebuf);
10823 }
10824 } else if (revoked && keydata.removehd == 0) {
10825 dnssec_log(zone, ISC_LOG_WARNING,
10826 "Active key %d for zone "
10827 "%s is revoked but "
10828 "did not self-sign; "
10829 "ignoring",
10830 keytag, namebuf);
10831 continue;
10832 } else if (secure) {
10833 if (keydata.removehd != 0) {
10834 /*
10835 * Key isn't revoked--but it
10836 * seems it used to be.
10837 * Remove it now and add it
10838 * back as if it were a fresh key,
10839 * with a 30-day acceptance timer.
10840 */
10841 deletekey = true;
10842 newkey = true;
10843 keydata.removehd = 0;
10844 keydata.addhd = now +
10845 dns_zone_mkey_month;
10846
10847 dnssec_log(zone, ISC_LOG_INFO,
10848 "Revoked key %d for "
10849 "zone %s has returned: "
10850 "starting 30-day "
10851 "acceptance timer",
10852 keytag, namebuf);
10853 } else if (keydata.addhd > now) {
10854 pending++;
10855 } else if (keydata.addhd == 0) {
10856 keydata.addhd = now;
10857 }
10858
10859 if (keydata.addhd <= now) {
10860 trustkey = true;
10861 dnssec_log(zone, ISC_LOG_INFO,
10862 "Key %d for zone %s "
10863 "is now trusted (%s)",
10864 keytag, namebuf,
10865 initial ? "initializing key "
10866 "verified"
10867 : "acceptance timer "
10868 "complete");
10869 }
10870 } else if (keydata.addhd > now) {
10871 /*
10872 * Not secure, and key is pending:
10873 * reset the acceptance timer
10874 */
10875 pending++;
10876 keydata.addhd = now + dns_zone_mkey_month;
10877 dnssec_log(zone, ISC_LOG_INFO,
10878 "Pending key %d "
10879 "for zone %s was "
10880 "not validated: restarting "
10881 "30-day acceptance timer",
10882 keytag, namebuf);
10883 }
10884
10885 if (!deletekey && !newkey) {
10886 updatekey = true;
10887 }
10888 } else if (secure) {
10889 /*
10890 * Key wasn't in the key zone but it's
10891 * revoked now anyway, so just skip it
10892 */
10893 if (revoked) {
10894 continue;
10895 }
10896
10897 /* Key wasn't in the key zone: add it */
10898 newkey = true;
10899
10900 if (initializing) {
10901 dnssec_log(zone, ISC_LOG_WARNING,
10902 "Initializing automatic trust "
10903 "anchor management for zone '%s'; "
10904 "DNSKEY ID %d is now trusted, "
10905 "waiving the normal 30-day "
10906 "waiting period.",
10907 namebuf, keytag);
10908 trustkey = true;
10909 } else {
10910 dnssec_log(zone, ISC_LOG_INFO,
10911 "New key %d observed "
10912 "for zone '%s': "
10913 "starting 30-day "
10914 "acceptance timer",
10915 keytag, namebuf);
10916 }
10917 } else {
10918 /*
10919 * No previously known key, and the key is not
10920 * secure, so skip it.
10921 */
10922 continue;
10923 }
10924
10925 /* Delete old version */
10926 if (deletekey || !newkey) {
10927 CHECK(update_one_rr(kfetch->db, ver, &diff,
10928 DNS_DIFFOP_DEL, keyname, 0,
10929 &keydatarr));
10930 }
10931
10932 if (updatekey) {
10933 /* Set refresh timer */
10934 keydata.refresh = refresh_time(kfetch, false);
10935 dns_rdata_reset(&keydatarr);
10936 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10937 dns_rdata_fromstruct(&keydatarr, zone->rdclass,
10938 dns_rdatatype_keydata, &keydata,
10939 &keyb);
10940
10941 /* Insert updated version */
10942 CHECK(update_one_rr(kfetch->db, ver, &diff,
10943 DNS_DIFFOP_ADD, keyname, 0,
10944 &keydatarr));
10945 } else if (newkey) {
10946 /* Convert DNSKEY to KEYDATA */
10947 result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
10948 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10949 dns_keydata_fromdnskey(&keydata, &dnskey, 0, 0, 0,
10950 NULL);
10951 keydata.addhd = initializing
10952 ? now
10953 : now + dns_zone_mkey_month;
10954 keydata.refresh = refresh_time(kfetch, false);
10955 dns_rdata_reset(&keydatarr);
10956 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10957 dns_rdata_fromstruct(&keydatarr, zone->rdclass,
10958 dns_rdatatype_keydata, &keydata,
10959 &keyb);
10960
10961 /* Insert into key zone */
10962 CHECK(update_one_rr(kfetch->db, ver, &diff,
10963 DNS_DIFFOP_ADD, keyname, 0,
10964 &keydatarr));
10965 }
10966
10967 if (trustkey) {
10968 /* Trust this key. */
10969 result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
10970 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10971 trust_key(zone, keyname, &dnskey, false);
10972 }
10973
10974 if (secure && !deletekey) {
10975 INSIST(newkey || updatekey);
10976 set_refreshkeytimer(zone, &keydata, now, false);
10977 }
10978 }
10979
10980 /*
10981 * RFC5011 says, "A trust point that has all of its trust anchors
10982 * revoked is considered deleted and is treated as if the trust
10983 * point was never configured." But if someone revoked their
10984 * active key before the standby was trusted, that would mean the
10985 * zone would suddenly be nonsecured. We avoid this by checking to
10986 * see if there's pending keydata. If so, we put a null key in
10987 * the security roots; then all queries to the zone will fail.
10988 */
10989 if (pending != 0) {
10990 fail_secure(zone, keyname);
10991 }
10992
10993 done:
10994 if (!ISC_LIST_EMPTY(diff.tuples)) {
10995 /* Write changes to journal file. */
10996 CHECK(update_soa_serial(zone, kfetch->db, ver, &diff, mctx,
10997 zone->updatemethod));
10998 CHECK(zone_journal(zone, &diff, NULL, "keyfetch_done"));
10999 commit = true;
11000
11001 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
11002 zone_needdump(zone, 30);
11003 } else if (result == ISC_R_NOMORE) {
11004 /*
11005 * If "updatekey" was true for all keys found in the DNSKEY
11006 * response and the previous update of those keys happened
11007 * during the same second (only possible if a key refresh was
11008 * externally triggered), it may happen that all relevant
11009 * update_one_rr() calls will return ISC_R_SUCCESS, but
11010 * diff.tuples will remain empty. Reset result to
11011 * ISC_R_SUCCESS to prevent a bogus warning from being logged.
11012 */
11013 result = ISC_R_SUCCESS;
11014 }
11015
11016 failure:
11017 if (result != ISC_R_SUCCESS) {
11018 dnssec_log(zone, ISC_LOG_ERROR,
11019 "error during managed-keys processing (%s): "
11020 "DNSSEC validation may be at risk",
11021 isc_result_totext(result));
11022 }
11023 dns_diff_clear(&diff);
11024 if (ver != NULL) {
11025 dns_db_closeversion(kfetch->db, &ver, commit);
11026 }
11027
11028 cleanup:
11029 dns_db_detach(&kfetch->db);
11030
11031 /* The zone must be managed */
11032 INSIST(kfetch->zone->task != NULL);
11033 isc_refcount_decrement(&zone->irefs);
11034
11035 if (dns_rdataset_isassociated(keydataset)) {
11036 dns_rdataset_disassociate(keydataset);
11037 }
11038 if (dns_rdataset_isassociated(dnskeys)) {
11039 dns_rdataset_disassociate(dnskeys);
11040 }
11041 if (dns_rdataset_isassociated(dnskeysigs)) {
11042 dns_rdataset_disassociate(dnskeysigs);
11043 }
11044
11045 dns_name_free(keyname, mctx);
11046 isc_mem_putanddetach(&kfetch->mctx, kfetch, sizeof(dns_keyfetch_t));
11047
11048 if (secroots != NULL) {
11049 dns_keytable_detach(&secroots);
11050 }
11051
11052 free_needed = exit_check(zone);
11053 UNLOCK_ZONE(zone);
11054
11055 if (free_needed) {
11056 zone_free(zone);
11057 }
11058
11059 INSIST(ver == NULL);
11060 }
11061
11062 static void
11063 retry_keyfetch(dns_keyfetch_t *kfetch, dns_name_t *kname) {
11064 isc_time_t timenow, timethen;
11065 dns_zone_t *zone = kfetch->zone;
11066 bool free_needed;
11067
11068 /*
11069 * Error during a key fetch; cancel and retry in an hour.
11070 */
11071 LOCK_ZONE(zone);
11072 zone->refreshkeycount--;
11073 isc_refcount_decrement(&zone->irefs);
11074 dns_db_detach(&kfetch->db);
11075 dns_rdataset_disassociate(&kfetch->keydataset);
11076 dns_name_free(kname, zone->mctx);
11077 isc_mem_putanddetach(&kfetch->mctx, kfetch, sizeof(*kfetch));
11078 dnssec_log(zone, ISC_LOG_WARNING,
11079 "Failed to create fetch for DNSKEY update");
11080
11081 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
11082 /* Don't really retry if we are exiting */
11083 char timebuf[80];
11084
11085 TIME_NOW(&timenow);
11086 DNS_ZONE_TIME_ADD(&timenow, dns_zone_mkey_hour, &timethen);
11087 zone->refreshkeytime = timethen;
11088 zone_settimer(zone, &timenow);
11089
11090 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
11091 dnssec_log(zone, ISC_LOG_DEBUG(1), "retry key refresh: %s",
11092 timebuf);
11093 }
11094
11095 free_needed = exit_check(zone);
11096 UNLOCK_ZONE(zone);
11097
11098 if (free_needed) {
11099 zone_free(zone);
11100 }
11101 }
11102
11103 static void
11104 do_keyfetch(isc_task_t *task, isc_event_t *event) {
11105 isc_result_t result;
11106 dns_keyfetch_t *kfetch = (dns_keyfetch_t *)event->ev_arg;
11107 dns_name_t *kname = dns_fixedname_name(&kfetch->name);
11108 dns_zone_t *zone = kfetch->zone;
11109
11110 UNUSED(task);
11111
11112 isc_event_free(&event);
11113
11114 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
11115 retry_keyfetch(kfetch, kname);
11116 return;
11117 }
11118
11119 /*
11120 * Use of DNS_FETCHOPT_NOCACHED is essential here. If it is not
11121 * set and the cache still holds a non-expired, validated version
11122 * of the RRset being queried for by the time the response is
11123 * received, the cached RRset will be passed to keyfetch_done()
11124 * instead of the one received in the response as the latter will
11125 * have a lower trust level due to not being validated until
11126 * keyfetch_done() is called.
11127 */
11128 result = dns_resolver_createfetch(
11129 zone->view->resolver, kname, dns_rdatatype_dnskey, NULL, NULL,
11130 NULL, NULL, 0,
11131 DNS_FETCHOPT_NOVALIDATE | DNS_FETCHOPT_UNSHARED |
11132 DNS_FETCHOPT_NOCACHED,
11133 0, NULL, zone->task, keyfetch_done, kfetch, &kfetch->dnskeyset,
11134 &kfetch->dnskeysigset, &kfetch->fetch);
11135
11136 if (result != ISC_R_SUCCESS) {
11137 retry_keyfetch(kfetch, kname);
11138 }
11139 }
11140
11141 /*
11142 * Refresh the data in the key zone. Initiate a fetch to look up
11143 * DNSKEY records at the trust anchor name.
11144 */
11145 static void
11146 zone_refreshkeys(dns_zone_t *zone) {
11147 const char me[] = "zone_refreshkeys";
11148 isc_result_t result;
11149 dns_rriterator_t rrit;
11150 dns_db_t *db = NULL;
11151 dns_dbversion_t *ver = NULL;
11152 dns_diff_t diff;
11153 dns_rdata_t rdata = DNS_RDATA_INIT;
11154 dns_rdata_keydata_t kd;
11155 isc_stdtime_t now;
11156 bool commit = false;
11157 bool fetching = false;
11158 bool timerset = false;
11159
11160 ENTER;
11161 REQUIRE(zone->db != NULL);
11162
11163 isc_stdtime_get(&now);
11164
11165 LOCK_ZONE(zone);
11166 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
11167 isc_time_settoepoch(&zone->refreshkeytime);
11168 UNLOCK_ZONE(zone);
11169 return;
11170 }
11171
11172 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11173 dns_db_attach(zone->db, &db);
11174 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11175
11176 dns_diff_init(zone->mctx, &diff);
11177
11178 CHECK(dns_db_newversion(db, &ver));
11179
11180 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESHING);
11181
11182 dns_rriterator_init(&rrit, db, ver, 0);
11183 for (result = dns_rriterator_first(&rrit); result == ISC_R_SUCCESS;
11184 result = dns_rriterator_nextrrset(&rrit))
11185 {
11186 isc_stdtime_t timer = 0xffffffff;
11187 dns_name_t *name = NULL, *kname = NULL;
11188 dns_rdataset_t *kdset = NULL;
11189 uint32_t ttl;
11190
11191 dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL);
11192 if (kdset == NULL || kdset->type != dns_rdatatype_keydata ||
11193 !dns_rdataset_isassociated(kdset))
11194 {
11195 continue;
11196 }
11197
11198 /*
11199 * Scan the stored keys looking for ones that need
11200 * removal or refreshing
11201 */
11202 for (result = dns_rdataset_first(kdset);
11203 result == ISC_R_SUCCESS; result = dns_rdataset_next(kdset))
11204 {
11205 dns_rdata_reset(&rdata);
11206 dns_rdataset_current(kdset, &rdata);
11207 result = dns_rdata_tostruct(&rdata, &kd, NULL);
11208 RUNTIME_CHECK(result == ISC_R_SUCCESS);
11209
11210 /* Removal timer expired? */
11211 if (kd.removehd != 0 && kd.removehd < now) {
11212 dns_rriterator_pause(&rrit);
11213 CHECK(update_one_rr(db, ver, &diff,
11214 DNS_DIFFOP_DEL, name, ttl,
11215 &rdata));
11216 continue;
11217 }
11218
11219 /* Acceptance timer expired? */
11220 if (kd.addhd <= now) {
11221 timer = kd.addhd;
11222 }
11223
11224 /* Or do we just need to refresh the keyset? */
11225 if (timer > kd.refresh) {
11226 timer = kd.refresh;
11227 }
11228
11229 dns_rriterator_pause(&rrit);
11230 set_refreshkeytimer(zone, &kd, now, false);
11231 timerset = true;
11232 }
11233
11234 if (timer > now) {
11235 continue;
11236 }
11237
11238 dns_rriterator_pause(&rrit);
11239
11240 #ifdef ENABLE_AFL
11241 if (!dns_fuzzing_resolver) {
11242 #endif /* ifdef ENABLE_AFL */
11243 dns_keyfetch_t *kfetch = NULL;
11244 isc_event_t *e;
11245
11246 kfetch = isc_mem_get(zone->mctx,
11247 sizeof(dns_keyfetch_t));
11248 *kfetch = (dns_keyfetch_t){ .zone = zone };
11249 isc_mem_attach(zone->mctx, &kfetch->mctx);
11250
11251 zone->refreshkeycount++;
11252 isc_refcount_increment0(&zone->irefs);
11253 kname = dns_fixedname_initname(&kfetch->name);
11254 dns_name_dup(name, zone->mctx, kname);
11255 dns_rdataset_init(&kfetch->dnskeyset);
11256 dns_rdataset_init(&kfetch->dnskeysigset);
11257 dns_rdataset_init(&kfetch->keydataset);
11258 dns_rdataset_clone(kdset, &kfetch->keydataset);
11259 dns_db_attach(db, &kfetch->db);
11260
11261 if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
11262 char namebuf[DNS_NAME_FORMATSIZE];
11263 dns_name_format(kname, namebuf,
11264 sizeof(namebuf));
11265 dnssec_log(zone, ISC_LOG_DEBUG(3),
11266 "Creating key fetch in "
11267 "zone_refreshkeys() for '%s'",
11268 namebuf);
11269 }
11270
11271 e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE,
11272 do_keyfetch, kfetch,
11273 sizeof(isc_event_t));
11274 isc_task_send(zone->task, &e);
11275 fetching = true;
11276 #ifdef ENABLE_AFL
11277 }
11278 #endif /* ifdef ENABLE_AFL */
11279 }
11280 if (!ISC_LIST_EMPTY(diff.tuples)) {
11281 CHECK(update_soa_serial(zone, db, ver, &diff, zone->mctx,
11282 zone->updatemethod));
11283 CHECK(zone_journal(zone, &diff, NULL, "zone_refreshkeys"));
11284 commit = true;
11285 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
11286 zone_needdump(zone, 30);
11287 }
11288
11289 failure:
11290 if (!timerset) {
11291 isc_time_settoepoch(&zone->refreshkeytime);
11292 }
11293
11294 if (!fetching) {
11295 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
11296 }
11297
11298 dns_diff_clear(&diff);
11299 if (ver != NULL) {
11300 dns_rriterator_destroy(&rrit);
11301 dns_db_closeversion(db, &ver, commit);
11302 }
11303 dns_db_detach(&db);
11304
11305 UNLOCK_ZONE(zone);
11306
11307 INSIST(ver == NULL);
11308 }
11309
11310 static void
11311 zone_maintenance(dns_zone_t *zone) {
11312 const char me[] = "zone_maintenance";
11313 isc_time_t now;
11314 isc_result_t result;
11315 bool dumping, load_pending, exiting, viewok;
11316 bool need_notify;
11317
11318 REQUIRE(DNS_ZONE_VALID(zone));
11319 ENTER;
11320
11321 /*
11322 * Are we pending load/reload, exiting, or unconfigured
11323 * (e.g. because of a syntax failure in the config file)?
11324 * If so, don't attempt maintenance.
11325 */
11326 LOCK_ZONE(zone);
11327 load_pending = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING);
11328 exiting = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING);
11329 viewok = (zone->view != NULL && zone->view->adb != NULL);
11330 UNLOCK_ZONE(zone);
11331
11332 if (load_pending || exiting || !viewok) {
11333 return;
11334 }
11335
11336 TIME_NOW(&now);
11337
11338 /*
11339 * Expire check.
11340 */
11341 switch (zone->type) {
11342 case dns_zone_redirect:
11343 if (zone->masters == NULL) {
11344 break;
11345 }
11346 FALLTHROUGH;
11347 case dns_zone_secondary:
11348 case dns_zone_mirror:
11349 case dns_zone_stub:
11350 LOCK_ZONE(zone);
11351 if (isc_time_compare(&now, &zone->expiretime) >= 0 &&
11352 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
11353 {
11354 zone_expire(zone);
11355 zone->refreshtime = now;
11356 }
11357 UNLOCK_ZONE(zone);
11358 break;
11359 default:
11360 break;
11361 }
11362
11363 /*
11364 * Up to date check.
11365 */
11366 switch (zone->type) {
11367 case dns_zone_redirect:
11368 if (zone->masters == NULL) {
11369 break;
11370 }
11371 FALLTHROUGH;
11372 case dns_zone_secondary:
11373 case dns_zone_mirror:
11374 case dns_zone_stub:
11375 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
11376 isc_time_compare(&now, &zone->refreshtime) >= 0)
11377 {
11378 dns_zone_refresh(zone);
11379 }
11380 break;
11381 default:
11382 break;
11383 }
11384
11385 /*
11386 * Secondaries send notifies before backing up to disk,
11387 * primaries after.
11388 */
11389 LOCK_ZONE(zone);
11390 need_notify = (zone->type == dns_zone_secondary ||
11391 zone->type == dns_zone_mirror) &&
11392 (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
11393 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY)) &&
11394 (isc_time_compare(&now, &zone->notifytime) >= 0);
11395 UNLOCK_ZONE(zone);
11396
11397 if (need_notify) {
11398 zone_notify(zone, &now);
11399 }
11400
11401 /*
11402 * Do we need to consolidate the backing store?
11403 */
11404 switch (zone->type) {
11405 case dns_zone_primary:
11406 case dns_zone_secondary:
11407 case dns_zone_mirror:
11408 case dns_zone_key:
11409 case dns_zone_redirect:
11410 case dns_zone_stub:
11411 LOCK_ZONE(zone);
11412 if (zone->masterfile != NULL &&
11413 isc_time_compare(&now, &zone->dumptime) >= 0 &&
11414 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
11415 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP))
11416 {
11417 dumping = was_dumping(zone);
11418 } else {
11419 dumping = true;
11420 }
11421 UNLOCK_ZONE(zone);
11422 if (!dumping) {
11423 result = zone_dump(zone, true); /* task locked */
11424 if (result != ISC_R_SUCCESS) {
11425 dns_zone_log(zone, ISC_LOG_WARNING,
11426 "dump failed: %s",
11427 dns_result_totext(result));
11428 }
11429 }
11430 break;
11431 default:
11432 break;
11433 }
11434
11435 /*
11436 * Master/redirect zones send notifies now, if needed
11437 */
11438 switch (zone->type) {
11439 case dns_zone_primary:
11440 case dns_zone_redirect:
11441 if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
11442 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY)) &&
11443 isc_time_compare(&now, &zone->notifytime) >= 0)
11444 {
11445 zone_notify(zone, &now);
11446 }
11447 default:
11448 break;
11449 }
11450
11451 /*
11452 * Do we need to refresh keys?
11453 */
11454 switch (zone->type) {
11455 case dns_zone_key:
11456 if (isc_time_compare(&now, &zone->refreshkeytime) >= 0) {
11457 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
11458 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING))
11459 {
11460 zone_refreshkeys(zone);
11461 }
11462 }
11463 break;
11464 case dns_zone_primary:
11465 if (!isc_time_isepoch(&zone->refreshkeytime) &&
11466 isc_time_compare(&now, &zone->refreshkeytime) >= 0 &&
11467 zone->rss_event == NULL)
11468 {
11469 zone_rekey(zone);
11470 }
11471 default:
11472 break;
11473 }
11474
11475 switch (zone->type) {
11476 case dns_zone_primary:
11477 case dns_zone_redirect:
11478 case dns_zone_secondary:
11479 /*
11480 * Do we need to sign/resign some RRsets?
11481 */
11482 if (zone->rss_event != NULL) {
11483 break;
11484 }
11485 if (!isc_time_isepoch(&zone->signingtime) &&
11486 isc_time_compare(&now, &zone->signingtime) >= 0)
11487 {
11488 zone_sign(zone);
11489 } else if (!isc_time_isepoch(&zone->resigntime) &&
11490 isc_time_compare(&now, &zone->resigntime) >= 0)
11491 {
11492 zone_resigninc(zone);
11493 } else if (!isc_time_isepoch(&zone->nsec3chaintime) &&
11494 isc_time_compare(&now, &zone->nsec3chaintime) >= 0)
11495 {
11496 zone_nsec3chain(zone);
11497 }
11498 /*
11499 * Do we need to issue a key expiry warning?
11500 */
11501 if (!isc_time_isepoch(&zone->keywarntime) &&
11502 isc_time_compare(&now, &zone->keywarntime) >= 0)
11503 {
11504 set_key_expiry_warning(zone, zone->key_expiry,
11505 isc_time_seconds(&now));
11506 }
11507 break;
11508
11509 default:
11510 break;
11511 }
11512 LOCK_ZONE(zone);
11513 zone_settimer(zone, &now);
11514 UNLOCK_ZONE(zone);
11515 }
11516
11517 void
11518 dns_zone_markdirty(dns_zone_t *zone) {
11519 uint32_t serial;
11520 isc_result_t result = ISC_R_SUCCESS;
11521 dns_zone_t *secure = NULL;
11522
11523 /*
11524 * Obtaining a lock on the zone->secure (see zone_send_secureserial)
11525 * could result in a deadlock due to a LOR so we will spin if we
11526 * can't obtain the both locks.
11527 */
11528 again:
11529 LOCK_ZONE(zone);
11530 if (zone->type == dns_zone_primary) {
11531 if (inline_raw(zone)) {
11532 unsigned int soacount;
11533 secure = zone->secure;
11534 INSIST(secure != zone);
11535 TRYLOCK_ZONE(result, secure);
11536 if (result != ISC_R_SUCCESS) {
11537 UNLOCK_ZONE(zone);
11538 secure = NULL;
11539 isc_thread_yield();
11540 goto again;
11541 }
11542
11543 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11544 if (zone->db != NULL) {
11545 result = zone_get_from_db(
11546 zone, zone->db, NULL, &soacount, NULL,
11547 &serial, NULL, NULL, NULL, NULL, NULL);
11548 } else {
11549 result = DNS_R_NOTLOADED;
11550 }
11551 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11552 if (result == ISC_R_SUCCESS && soacount > 0U) {
11553 zone_send_secureserial(zone, serial);
11554 }
11555 }
11556
11557 /* XXXMPA make separate call back */
11558 if (result == ISC_R_SUCCESS) {
11559 set_resigntime(zone);
11560 if (zone->task != NULL) {
11561 isc_time_t now;
11562 TIME_NOW(&now);
11563 zone_settimer(zone, &now);
11564 }
11565 }
11566 }
11567 if (secure != NULL) {
11568 UNLOCK_ZONE(secure);
11569 }
11570 zone_needdump(zone, DNS_DUMP_DELAY);
11571 UNLOCK_ZONE(zone);
11572 }
11573
11574 void
11575 dns_zone_expire(dns_zone_t *zone) {
11576 REQUIRE(DNS_ZONE_VALID(zone));
11577
11578 LOCK_ZONE(zone);
11579 zone_expire(zone);
11580 UNLOCK_ZONE(zone);
11581 }
11582
11583 static void
11584 zone_expire(dns_zone_t *zone) {
11585 dns_db_t *db = NULL;
11586
11587 /*
11588 * 'zone' locked by caller.
11589 */
11590
11591 REQUIRE(LOCKED_ZONE(zone));
11592
11593 dns_zone_log(zone, ISC_LOG_WARNING, "expired");
11594
11595 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXPIRED);
11596 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
11597 zone->retry = DNS_ZONE_DEFAULTRETRY;
11598 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
11599
11600 /*
11601 * An RPZ zone has expired; before unloading it, we must
11602 * first remove it from the RPZ summary database. The
11603 * easiest way to do this is "update" it with an empty
11604 * database so that the update callback synchronizes
11605 * the diff automatically.
11606 */
11607 if (zone->rpzs != NULL && zone->rpz_num != DNS_RPZ_INVALID_NUM) {
11608 isc_result_t result;
11609 dns_rpz_zone_t *rpz = zone->rpzs->zones[zone->rpz_num];
11610
11611 CHECK(dns_db_create(zone->mctx, "rbt", &zone->origin,
11612 dns_dbtype_zone, zone->rdclass, 0, NULL,
11613 &db));
11614 CHECK(dns_rpz_dbupdate_callback(db, rpz));
11615 dns_zone_log(zone, ISC_LOG_WARNING,
11616 "response-policy zone expired; "
11617 "policies unloaded");
11618 }
11619
11620 failure:
11621 if (db != NULL) {
11622 dns_db_detach(&db);
11623 }
11624
11625 zone_unload(zone);
11626 }
11627
11628 void
11629 dns_zone_refresh(dns_zone_t *zone) {
11630 isc_interval_t i;
11631 uint32_t oldflags;
11632 unsigned int j;
11633 isc_result_t result;
11634
11635 REQUIRE(DNS_ZONE_VALID(zone));
11636
11637 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
11638 return;
11639 }
11640
11641 /*
11642 * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation
11643 * in progress at a time.
11644 */
11645
11646 LOCK_ZONE(zone);
11647 oldflags = atomic_load(&zone->flags);
11648 if (zone->masterscnt == 0) {
11649 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOMASTERS);
11650 if ((oldflags & DNS_ZONEFLG_NOMASTERS) == 0) {
11651 dns_zone_log(zone, ISC_LOG_ERROR,
11652 "cannot refresh: no primaries");
11653 }
11654 goto unlock;
11655 }
11656 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
11657 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
11658 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
11659 if ((oldflags & (DNS_ZONEFLG_REFRESH | DNS_ZONEFLG_LOADING)) != 0) {
11660 goto unlock;
11661 }
11662
11663 /*
11664 * Set the next refresh time as if refresh check has failed.
11665 * Setting this to the retry time will do that. XXXMLG
11666 * If we are successful it will be reset using zone->refresh.
11667 */
11668 isc_interval_set(&i, zone->retry - isc_random_uniform(zone->retry / 4),
11669 0);
11670 result = isc_time_nowplusinterval(&zone->refreshtime, &i);
11671 if (result != ISC_R_SUCCESS) {
11672 dns_zone_log(zone, ISC_LOG_WARNING,
11673 "isc_time_nowplusinterval() failed: %s",
11674 dns_result_totext(result));
11675 }
11676
11677 /*
11678 * When lacking user-specified timer values from the SOA,
11679 * do exponential backoff of the retry time up to a
11680 * maximum of six hours.
11681 */
11682 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS)) {
11683 zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
11684 }
11685
11686 zone->curmaster = 0;
11687 for (j = 0; j < zone->masterscnt; j++) {
11688 zone->mastersok[j] = false;
11689 }
11690 /* initiate soa query */
11691 queue_soa_query(zone);
11692 unlock:
11693 UNLOCK_ZONE(zone);
11694 }
11695
11696 static isc_result_t
11697 zone_journal_rollforward(dns_zone_t *zone, dns_db_t *db, bool *needdump,
11698 bool *fixjournal) {
11699 dns_journal_t *journal = NULL;
11700 unsigned int options;
11701 isc_result_t result;
11702
11703 if (zone->type == dns_zone_primary &&
11704 (inline_secure(zone) ||
11705 (zone->update_acl != NULL || zone->ssutable != NULL)))
11706 {
11707 options = DNS_JOURNALOPT_RESIGN;
11708 } else {
11709 options = 0;
11710 }
11711
11712 result = dns_journal_open(zone->mctx, zone->journal, DNS_JOURNAL_READ,
11713 &journal);
11714 if (result == ISC_R_NOTFOUND) {
11715 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(3),
11716 "no journal file, but that's OK ");
11717 return (ISC_R_SUCCESS);
11718 } else if (result != ISC_R_SUCCESS) {
11719 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
11720 "journal open failed: %s",
11721 dns_result_totext(result));
11722 return (result);
11723 }
11724
11725 if (dns_journal_empty(journal)) {
11726 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
11727 "journal empty");
11728 dns_journal_destroy(&journal);
11729 return (ISC_R_SUCCESS);
11730 }
11731
11732 result = dns_journal_rollforward(journal, db, options);
11733 switch (result) {
11734 case ISC_R_SUCCESS:
11735 *needdump = true;
11736 FALLTHROUGH;
11737 case DNS_R_UPTODATE:
11738 if (dns_journal_recovered(journal)) {
11739 *fixjournal = true;
11740 dns_zone_logc(
11741 zone, DNS_LOGCATEGORY_ZONELOAD,
11742 ISC_LOG_DEBUG(1),
11743 "journal rollforward completed successfully "
11744 "using old journal format: %s",
11745 dns_result_totext(result));
11746 } else {
11747 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
11748 ISC_LOG_DEBUG(1),
11749 "journal rollforward completed "
11750 "successfully: %s",
11751 dns_result_totext(result));
11752 }
11753
11754 dns_journal_destroy(&journal);
11755 return (ISC_R_SUCCESS);
11756 case ISC_R_NOTFOUND:
11757 case ISC_R_RANGE:
11758 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
11759 "journal rollforward failed: journal out of sync "
11760 "with zone");
11761 dns_journal_destroy(&journal);
11762 return (result);
11763 default:
11764 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
11765 "journal rollforward failed: %s",
11766 dns_result_totext(result));
11767 dns_journal_destroy(&journal);
11768 return (result);
11769 }
11770 }
11771
11772 static void
11773 zone_journal_compact(dns_zone_t *zone, dns_db_t *db, uint32_t serial) {
11774 isc_result_t result;
11775 int32_t journalsize;
11776 dns_dbversion_t *ver = NULL;
11777 uint64_t dbsize;
11778 uint32_t options = 0;
11779
11780 INSIST(LOCKED_ZONE(zone));
11781 if (inline_raw(zone)) {
11782 INSIST(LOCKED_ZONE(zone->secure));
11783 }
11784
11785 journalsize = zone->journalsize;
11786 if (journalsize == -1) {
11787 journalsize = DNS_JOURNAL_SIZE_MAX;
11788 dns_db_currentversion(db, &ver);
11789 result = dns_db_getsize(db, ver, NULL, &dbsize);
11790 dns_db_closeversion(db, &ver, false);
11791 if (result != ISC_R_SUCCESS) {
11792 dns_zone_log(zone, ISC_LOG_ERROR,
11793 "zone_journal_compact: "
11794 "could not get zone size: %s",
11795 isc_result_totext(result));
11796 } else if (dbsize < DNS_JOURNAL_SIZE_MAX / 2) {
11797 journalsize = (int32_t)dbsize * 2;
11798 }
11799 }
11800 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FIXJOURNAL)) {
11801 options |= DNS_JOURNAL_COMPACTALL;
11802 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FIXJOURNAL);
11803 zone_debuglog(zone, "zone_journal_compact", 1,
11804 "repair full journal");
11805 } else {
11806 zone_debuglog(zone, "zone_journal_compact", 1,
11807 "target journal size %d", journalsize);
11808 }
11809 result = dns_journal_compact(zone->mctx, zone->journal, serial, options,
11810 journalsize);
11811 switch (result) {
11812 case ISC_R_SUCCESS:
11813 case ISC_R_NOSPACE:
11814 case ISC_R_NOTFOUND:
11815 dns_zone_log(zone, ISC_LOG_DEBUG(3), "dns_journal_compact: %s",
11816 dns_result_totext(result));
11817 break;
11818 default:
11819 dns_zone_log(zone, ISC_LOG_ERROR,
11820 "dns_journal_compact failed: %s",
11821 dns_result_totext(result));
11822 break;
11823 }
11824 }
11825
11826 isc_result_t
11827 dns_zone_flush(dns_zone_t *zone) {
11828 isc_result_t result = ISC_R_SUCCESS;
11829 bool dumping;
11830
11831 REQUIRE(DNS_ZONE_VALID(zone));
11832
11833 LOCK_ZONE(zone);
11834 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FLUSH);
11835 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
11836 zone->masterfile != NULL)
11837 {
11838 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
11839 result = ISC_R_ALREADYRUNNING;
11840 dumping = was_dumping(zone);
11841 } else {
11842 dumping = true;
11843 }
11844 UNLOCK_ZONE(zone);
11845 if (!dumping) {
11846 result = zone_dump(zone, true); /* Unknown task. */
11847 }
11848 return (result);
11849 }
11850
11851 isc_result_t
11852 dns_zone_dump(dns_zone_t *zone) {
11853 isc_result_t result = ISC_R_ALREADYRUNNING;
11854 bool dumping;
11855
11856 REQUIRE(DNS_ZONE_VALID(zone));
11857
11858 LOCK_ZONE(zone);
11859 dumping = was_dumping(zone);
11860 UNLOCK_ZONE(zone);
11861 if (!dumping) {
11862 result = zone_dump(zone, false); /* Unknown task. */
11863 }
11864 return (result);
11865 }
11866
11867 static void
11868 zone_needdump(dns_zone_t *zone, unsigned int delay) {
11869 const char me[] = "zone_needdump";
11870 isc_time_t dumptime;
11871 isc_time_t now;
11872
11873 /*
11874 * 'zone' locked by caller
11875 */
11876
11877 REQUIRE(DNS_ZONE_VALID(zone));
11878 REQUIRE(LOCKED_ZONE(zone));
11879 ENTER;
11880
11881 /*
11882 * Do we have a place to dump to and are we loaded?
11883 */
11884 if (zone->masterfile == NULL ||
11885 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
11886 {
11887 return;
11888 }
11889
11890 TIME_NOW(&now);
11891 /* add some noise */
11892 DNS_ZONE_JITTER_ADD(&now, delay, &dumptime);
11893
11894 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
11895 if (isc_time_isepoch(&zone->dumptime) ||
11896 isc_time_compare(&zone->dumptime, &dumptime) > 0)
11897 {
11898 zone->dumptime = dumptime;
11899 }
11900 if (zone->task != NULL) {
11901 zone_settimer(zone, &now);
11902 }
11903 }
11904
11905 static void
11906 dump_done(void *arg, isc_result_t result) {
11907 const char me[] = "dump_done";
11908 dns_zone_t *zone = arg;
11909 dns_zone_t *secure = NULL;
11910 dns_db_t *db;
11911 dns_dbversion_t *version;
11912 bool again = false;
11913 bool compact = false;
11914 uint32_t serial;
11915 isc_result_t tresult;
11916
11917 REQUIRE(DNS_ZONE_VALID(zone));
11918
11919 ENTER;
11920
11921 if (result == ISC_R_SUCCESS && zone->journal != NULL) {
11922 /*
11923 * We don't own these, zone->dctx must stay valid.
11924 */
11925 db = dns_dumpctx_db(zone->dctx);
11926 version = dns_dumpctx_version(zone->dctx);
11927 tresult = dns_db_getsoaserial(db, version, &serial);
11928
11929 /*
11930 * Handle lock order inversion.
11931 */
11932 again:
11933 LOCK_ZONE(zone);
11934 if (inline_raw(zone)) {
11935 secure = zone->secure;
11936 INSIST(secure != zone);
11937 TRYLOCK_ZONE(result, secure);
11938 if (result != ISC_R_SUCCESS) {
11939 UNLOCK_ZONE(zone);
11940 secure = NULL;
11941 isc_thread_yield();
11942 goto again;
11943 }
11944 }
11945
11946 /*
11947 * If there is a secure version of this zone
11948 * use its serial if it is less than ours.
11949 */
11950 if (tresult == ISC_R_SUCCESS && secure != NULL) {
11951 uint32_t sserial;
11952 isc_result_t mresult;
11953
11954 ZONEDB_LOCK(&secure->dblock, isc_rwlocktype_read);
11955 if (secure->db != NULL) {
11956 mresult = dns_db_getsoaserial(zone->secure->db,
11957 NULL, &sserial);
11958 if (mresult == ISC_R_SUCCESS &&
11959 isc_serial_lt(sserial, serial))
11960 {
11961 serial = sserial;
11962 }
11963 }
11964 ZONEDB_UNLOCK(&secure->dblock, isc_rwlocktype_read);
11965 }
11966 if (tresult == ISC_R_SUCCESS && zone->xfr == NULL) {
11967 dns_db_t *zdb = NULL;
11968 if (dns_zone_getdb(zone, &zdb) == ISC_R_SUCCESS) {
11969 zone_journal_compact(zone, zdb, serial);
11970 dns_db_detach(&zdb);
11971 }
11972 } else if (tresult == ISC_R_SUCCESS) {
11973 compact = true;
11974 zone->compact_serial = serial;
11975 }
11976 if (secure != NULL) {
11977 UNLOCK_ZONE(secure);
11978 }
11979 UNLOCK_ZONE(zone);
11980 }
11981
11982 LOCK_ZONE(zone);
11983 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
11984 if (compact) {
11985 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
11986 }
11987 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN)) {
11988 /*
11989 * If DNS_ZONEFLG_SHUTDOWN is set, all external references to
11990 * the zone are gone, which means it is in the process of being
11991 * cleaned up, so do not reschedule dumping.
11992 *
11993 * Detach from the raw version of the zone in case this
11994 * operation has been deferred in zone_shutdown().
11995 */
11996 if (zone->raw != NULL) {
11997 dns_zone_detach(&zone->raw);
11998 }
11999 if (result == ISC_R_SUCCESS) {
12000 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
12001 }
12002 } else if (result != ISC_R_SUCCESS && result != ISC_R_CANCELED) {
12003 /*
12004 * Try again in a short while.
12005 */
12006 zone_needdump(zone, DNS_DUMP_DELAY);
12007 } else if (result == ISC_R_SUCCESS &&
12008 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
12009 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
12010 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
12011 {
12012 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
12013 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
12014 isc_time_settoepoch(&zone->dumptime);
12015 again = true;
12016 } else if (result == ISC_R_SUCCESS) {
12017 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
12018 }
12019
12020 if (zone->dctx != NULL) {
12021 dns_dumpctx_detach(&zone->dctx);
12022 }
12023 zonemgr_putio(&zone->writeio);
12024 UNLOCK_ZONE(zone);
12025 if (again) {
12026 (void)zone_dump(zone, false);
12027 }
12028 dns_zone_idetach(&zone);
12029 }
12030
12031 static isc_result_t
12032 zone_dump(dns_zone_t *zone, bool compact) {
12033 const char me[] = "zone_dump";
12034 isc_result_t result;
12035 dns_dbversion_t *version = NULL;
12036 bool again;
12037 dns_db_t *db = NULL;
12038 char *masterfile = NULL;
12039 dns_masterformat_t masterformat = dns_masterformat_none;
12040
12041 /*
12042 * 'compact' MUST only be set if we are task locked.
12043 */
12044
12045 REQUIRE(DNS_ZONE_VALID(zone));
12046 ENTER;
12047
12048 redo:
12049 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
12050 if (zone->db != NULL) {
12051 dns_db_attach(zone->db, &db);
12052 }
12053 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12054 LOCK_ZONE(zone);
12055 if (zone->masterfile != NULL) {
12056 masterfile = isc_mem_strdup(zone->mctx, zone->masterfile);
12057 masterformat = zone->masterformat;
12058 }
12059 UNLOCK_ZONE(zone);
12060 if (db == NULL) {
12061 result = DNS_R_NOTLOADED;
12062 goto fail;
12063 }
12064 if (masterfile == NULL) {
12065 result = DNS_R_NOMASTERFILE;
12066 goto fail;
12067 }
12068
12069 if (compact && zone->type != dns_zone_stub) {
12070 dns_zone_t *dummy = NULL;
12071 LOCK_ZONE(zone);
12072 zone_iattach(zone, &dummy);
12073 result = zonemgr_getio(zone->zmgr, false, zone->task,
12074 zone_gotwritehandle, zone,
12075 &zone->writeio);
12076 if (result != ISC_R_SUCCESS) {
12077 zone_idetach(&dummy);
12078 } else {
12079 result = DNS_R_CONTINUE;
12080 }
12081 UNLOCK_ZONE(zone);
12082 } else {
12083 const dns_master_style_t *output_style;
12084
12085 dns_masterrawheader_t rawdata;
12086 dns_db_currentversion(db, &version);
12087 dns_master_initrawheader(&rawdata);
12088 if (inline_secure(zone)) {
12089 get_raw_serial(zone->raw, &rawdata);
12090 }
12091 if (zone->type == dns_zone_key) {
12092 output_style = &dns_master_style_keyzone;
12093 } else {
12094 output_style = &dns_master_style_default;
12095 }
12096 result = dns_master_dump(zone->mctx, db, version, output_style,
12097 masterfile, masterformat, &rawdata);
12098 dns_db_closeversion(db, &version, false);
12099 }
12100 fail:
12101 if (db != NULL) {
12102 dns_db_detach(&db);
12103 }
12104 if (masterfile != NULL) {
12105 isc_mem_free(zone->mctx, masterfile);
12106 }
12107 masterfile = NULL;
12108
12109 if (result == DNS_R_CONTINUE) {
12110 return (ISC_R_SUCCESS); /* XXXMPA */
12111 }
12112
12113 again = false;
12114 LOCK_ZONE(zone);
12115 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
12116 if (result != ISC_R_SUCCESS) {
12117 /*
12118 * Try again in a short while.
12119 */
12120 zone_needdump(zone, DNS_DUMP_DELAY);
12121 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
12122 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
12123 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
12124 {
12125 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
12126 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
12127 isc_time_settoepoch(&zone->dumptime);
12128 again = true;
12129 } else {
12130 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
12131 }
12132 UNLOCK_ZONE(zone);
12133 if (again) {
12134 goto redo;
12135 }
12136
12137 return (result);
12138 }
12139
12140 static isc_result_t
12141 dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style,
12142 dns_masterformat_t format, const uint32_t rawversion) {
12143 isc_result_t result;
12144 dns_dbversion_t *version = NULL;
12145 dns_db_t *db = NULL;
12146 dns_masterrawheader_t rawdata;
12147
12148 REQUIRE(DNS_ZONE_VALID(zone));
12149
12150 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
12151 if (zone->db != NULL) {
12152 dns_db_attach(zone->db, &db);
12153 }
12154 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12155 if (db == NULL) {
12156 return (DNS_R_NOTLOADED);
12157 }
12158
12159 dns_db_currentversion(db, &version);
12160 dns_master_initrawheader(&rawdata);
12161 if (rawversion == 0) {
12162 rawdata.flags |= DNS_MASTERRAW_COMPAT;
12163 } else if (inline_secure(zone)) {
12164 get_raw_serial(zone->raw, &rawdata);
12165 } else if (zone->sourceserialset) {
12166 rawdata.flags = DNS_MASTERRAW_SOURCESERIALSET;
12167 rawdata.sourceserial = zone->sourceserial;
12168 }
12169 result = dns_master_dumptostream(zone->mctx, db, version, style, format,
12170 &rawdata, fd);
12171 dns_db_closeversion(db, &version, false);
12172 dns_db_detach(&db);
12173 return (result);
12174 }
12175
12176 isc_result_t
12177 dns_zone_dumptostream(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
12178 const dns_master_style_t *style,
12179 const uint32_t rawversion) {
12180 return (dumptostream(zone, fd, style, format, rawversion));
12181 }
12182
12183 void
12184 dns_zone_unload(dns_zone_t *zone) {
12185 REQUIRE(DNS_ZONE_VALID(zone));
12186
12187 LOCK_ZONE(zone);
12188 zone_unload(zone);
12189 UNLOCK_ZONE(zone);
12190 }
12191
12192 static void
12193 notify_cancel(dns_zone_t *zone) {
12194 dns_notify_t *notify;
12195
12196 /*
12197 * 'zone' locked by caller.
12198 */
12199
12200 REQUIRE(LOCKED_ZONE(zone));
12201
12202 for (notify = ISC_LIST_HEAD(zone->notifies); notify != NULL;
12203 notify = ISC_LIST_NEXT(notify, link))
12204 {
12205 if (notify->find != NULL) {
12206 dns_adb_cancelfind(notify->find);
12207 }
12208 if (notify->request != NULL) {
12209 dns_request_cancel(notify->request);
12210 }
12211 }
12212 }
12213
12214 static void
12215 checkds_cancel(dns_zone_t *zone) {
12216 dns_checkds_t *checkds;
12217
12218 /*
12219 * 'zone' locked by caller.
12220 */
12221
12222 REQUIRE(LOCKED_ZONE(zone));
12223
12224 for (checkds = ISC_LIST_HEAD(zone->checkds_requests); checkds != NULL;
12225 checkds = ISC_LIST_NEXT(checkds, link))
12226 {
12227 if (checkds->request != NULL) {
12228 dns_request_cancel(checkds->request);
12229 }
12230 }
12231 }
12232
12233 static void
12234 forward_cancel(dns_zone_t *zone) {
12235 dns_forward_t *forward;
12236
12237 /*
12238 * 'zone' locked by caller.
12239 */
12240
12241 REQUIRE(LOCKED_ZONE(zone));
12242
12243 for (forward = ISC_LIST_HEAD(zone->forwards); forward != NULL;
12244 forward = ISC_LIST_NEXT(forward, link))
12245 {
12246 if (forward->request != NULL) {
12247 dns_request_cancel(forward->request);
12248 }
12249 }
12250 }
12251
12252 static void
12253 zone_unload(dns_zone_t *zone) {
12254 /*
12255 * 'zone' locked by caller.
12256 */
12257
12258 REQUIRE(LOCKED_ZONE(zone));
12259
12260 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
12261 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
12262 {
12263 if (zone->writeio != NULL) {
12264 zonemgr_cancelio(zone->writeio);
12265 }
12266
12267 if (zone->dctx != NULL) {
12268 dns_dumpctx_cancel(zone->dctx);
12269 }
12270 }
12271 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
12272 zone_detachdb(zone);
12273 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
12274 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
12275 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
12276
12277 if (zone->type == dns_zone_mirror) {
12278 dns_zone_log(zone, ISC_LOG_INFO,
12279 "mirror zone is no longer in use; "
12280 "reverting to normal recursion");
12281 }
12282 }
12283
12284 void
12285 dns_zone_setminrefreshtime(dns_zone_t *zone, uint32_t val) {
12286 REQUIRE(DNS_ZONE_VALID(zone));
12287 REQUIRE(val > 0);
12288
12289 zone->minrefresh = val;
12290 }
12291
12292 void
12293 dns_zone_setmaxrefreshtime(dns_zone_t *zone, uint32_t val) {
12294 REQUIRE(DNS_ZONE_VALID(zone));
12295 REQUIRE(val > 0);
12296
12297 zone->maxrefresh = val;
12298 }
12299
12300 void
12301 dns_zone_setminretrytime(dns_zone_t *zone, uint32_t val) {
12302 REQUIRE(DNS_ZONE_VALID(zone));
12303 REQUIRE(val > 0);
12304
12305 zone->minretry = val;
12306 }
12307
12308 void
12309 dns_zone_setmaxretrytime(dns_zone_t *zone, uint32_t val) {
12310 REQUIRE(DNS_ZONE_VALID(zone));
12311 REQUIRE(val > 0);
12312
12313 zone->maxretry = val;
12314 }
12315
12316 uint32_t
12317 dns_zone_getmaxrecords(dns_zone_t *zone) {
12318 REQUIRE(DNS_ZONE_VALID(zone));
12319
12320 return (zone->maxrecords);
12321 }
12322
12323 void
12324 dns_zone_setmaxrecords(dns_zone_t *zone, uint32_t val) {
12325 REQUIRE(DNS_ZONE_VALID(zone));
12326
12327 zone->maxrecords = val;
12328 }
12329
12330 static bool
12331 notify_isqueued(dns_zone_t *zone, unsigned int flags, dns_name_t *name,
12332 isc_sockaddr_t *addr, dns_tsigkey_t *key) {
12333 dns_notify_t *notify;
12334 dns_zonemgr_t *zmgr;
12335 isc_result_t result;
12336
12337 for (notify = ISC_LIST_HEAD(zone->notifies); notify != NULL;
12338 notify = ISC_LIST_NEXT(notify, link))
12339 {
12340 if (notify->request != NULL) {
12341 continue;
12342 }
12343 if (name != NULL && dns_name_dynamic(¬ify->ns) &&
12344 dns_name_equal(name, ¬ify->ns))
12345 {
12346 goto requeue;
12347 }
12348 if (addr != NULL && isc_sockaddr_equal(addr, ¬ify->dst) &&
12349 notify->key == key)
12350 {
12351 goto requeue;
12352 }
12353 }
12354 return (false);
12355
12356 requeue:
12357 /*
12358 * If we are enqueued on the startup ratelimiter and this is
12359 * not a startup notify, re-enqueue on the normal notify
12360 * ratelimiter.
12361 */
12362 if (notify->event != NULL && (flags & DNS_NOTIFY_STARTUP) == 0 &&
12363 (notify->flags & DNS_NOTIFY_STARTUP) != 0)
12364 {
12365 zmgr = notify->zone->zmgr;
12366 result = isc_ratelimiter_dequeue(zmgr->startupnotifyrl,
12367 notify->event);
12368 if (result != ISC_R_SUCCESS) {
12369 return (true);
12370 }
12371
12372 notify->flags &= ~DNS_NOTIFY_STARTUP;
12373 result = isc_ratelimiter_enqueue(notify->zone->zmgr->notifyrl,
12374 notify->zone->task,
12375 ¬ify->event);
12376 if (result != ISC_R_SUCCESS) {
12377 isc_event_free(¬ify->event);
12378 return (false);
12379 }
12380 }
12381
12382 return (true);
12383 }
12384
12385 static bool
12386 notify_isself(dns_zone_t *zone, isc_sockaddr_t *dst) {
12387 dns_tsigkey_t *key = NULL;
12388 isc_sockaddr_t src;
12389 isc_sockaddr_t any;
12390 bool isself;
12391 isc_netaddr_t dstaddr;
12392 isc_result_t result;
12393
12394 if (zone->view == NULL || zone->isself == NULL) {
12395 return (false);
12396 }
12397
12398 switch (isc_sockaddr_pf(dst)) {
12399 case PF_INET:
12400 src = zone->notifysrc4;
12401 isc_sockaddr_any(&any);
12402 break;
12403 case PF_INET6:
12404 src = zone->notifysrc6;
12405 isc_sockaddr_any6(&any);
12406 break;
12407 default:
12408 return (false);
12409 }
12410
12411 /*
12412 * When sending from any the kernel will assign a source address
12413 * that matches the destination address.
12414 */
12415 if (isc_sockaddr_eqaddr(&any, &src)) {
12416 src = *dst;
12417 }
12418
12419 isc_netaddr_fromsockaddr(&dstaddr, dst);
12420 result = dns_view_getpeertsig(zone->view, &dstaddr, &key);
12421 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
12422 return (false);
12423 }
12424 isself = (zone->isself)(zone->view, key, &src, dst, zone->rdclass,
12425 zone->isselfarg);
12426 if (key != NULL) {
12427 dns_tsigkey_detach(&key);
12428 }
12429 return (isself);
12430 }
12431
12432 static void
12433 notify_destroy(dns_notify_t *notify, bool locked) {
12434 isc_mem_t *mctx;
12435
12436 REQUIRE(DNS_NOTIFY_VALID(notify));
12437
12438 if (notify->zone != NULL) {
12439 if (!locked) {
12440 LOCK_ZONE(notify->zone);
12441 }
12442 REQUIRE(LOCKED_ZONE(notify->zone));
12443 if (ISC_LINK_LINKED(notify, link)) {
12444 ISC_LIST_UNLINK(notify->zone->notifies, notify, link);
12445 }
12446 if (!locked) {
12447 UNLOCK_ZONE(notify->zone);
12448 }
12449 if (locked) {
12450 zone_idetach(¬ify->zone);
12451 } else {
12452 dns_zone_idetach(¬ify->zone);
12453 }
12454 }
12455 if (notify->find != NULL) {
12456 dns_adb_destroyfind(¬ify->find);
12457 }
12458 if (notify->request != NULL) {
12459 dns_request_destroy(¬ify->request);
12460 }
12461 if (dns_name_dynamic(¬ify->ns)) {
12462 dns_name_free(¬ify->ns, notify->mctx);
12463 }
12464 if (notify->key != NULL) {
12465 dns_tsigkey_detach(¬ify->key);
12466 }
12467 mctx = notify->mctx;
12468 isc_mem_put(notify->mctx, notify, sizeof(*notify));
12469 isc_mem_detach(&mctx);
12470 }
12471
12472 static isc_result_t
12473 notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
12474 dns_notify_t *notify;
12475
12476 REQUIRE(notifyp != NULL && *notifyp == NULL);
12477
12478 notify = isc_mem_get(mctx, sizeof(*notify));
12479
12480 notify->mctx = NULL;
12481 isc_mem_attach(mctx, ¬ify->mctx);
12482 notify->flags = flags;
12483 notify->zone = NULL;
12484 notify->find = NULL;
12485 notify->request = NULL;
12486 notify->key = NULL;
12487 notify->event = NULL;
12488 isc_sockaddr_any(¬ify->dst);
12489 dns_name_init(¬ify->ns, NULL);
12490 ISC_LINK_INIT(notify, link);
12491 notify->magic = NOTIFY_MAGIC;
12492 *notifyp = notify;
12493 return (ISC_R_SUCCESS);
12494 }
12495
12496 /*
12497 * XXXAG should check for DNS_ZONEFLG_EXITING
12498 */
12499 static void
12500 process_adb_event(isc_task_t *task, isc_event_t *ev) {
12501 dns_notify_t *notify;
12502 isc_eventtype_t result;
12503
12504 UNUSED(task);
12505
12506 notify = ev->ev_arg;
12507 REQUIRE(DNS_NOTIFY_VALID(notify));
12508 INSIST(task == notify->zone->task);
12509 result = ev->ev_type;
12510 isc_event_free(&ev);
12511 if (result == DNS_EVENT_ADBMOREADDRESSES) {
12512 dns_adb_destroyfind(¬ify->find);
12513 notify_find_address(notify);
12514 return;
12515 }
12516 if (result == DNS_EVENT_ADBNOMOREADDRESSES) {
12517 LOCK_ZONE(notify->zone);
12518 notify_send(notify);
12519 UNLOCK_ZONE(notify->zone);
12520 }
12521 notify_destroy(notify, false);
12522 }
12523
12524 static void
12525 notify_find_address(dns_notify_t *notify) {
12526 isc_result_t result;
12527 unsigned int options;
12528
12529 REQUIRE(DNS_NOTIFY_VALID(notify));
12530 options = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_INET | DNS_ADBFIND_INET6 |
12531 DNS_ADBFIND_RETURNLAME;
12532
12533 if (notify->zone->view->adb == NULL) {
12534 goto destroy;
12535 }
12536
12537 result = dns_adb_createfind(
12538 notify->zone->view->adb, notify->zone->task, process_adb_event,
12539 notify, ¬ify->ns, dns_rootname, 0, options, 0, NULL,
12540 notify->zone->view->dstport, 0, NULL, ¬ify->find);
12541
12542 /* Something failed? */
12543 if (result != ISC_R_SUCCESS) {
12544 goto destroy;
12545 }
12546
12547 /* More addresses pending? */
12548 if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0) {
12549 return;
12550 }
12551
12552 /* We have as many addresses as we can get. */
12553 LOCK_ZONE(notify->zone);
12554 notify_send(notify);
12555 UNLOCK_ZONE(notify->zone);
12556
12557 destroy:
12558 notify_destroy(notify, false);
12559 }
12560
12561 static isc_result_t
12562 notify_send_queue(dns_notify_t *notify, bool startup) {
12563 isc_event_t *e;
12564 isc_result_t result;
12565
12566 INSIST(notify->event == NULL);
12567 e = isc_event_allocate(notify->mctx, NULL, DNS_EVENT_NOTIFYSENDTOADDR,
12568 notify_send_toaddr, notify, sizeof(isc_event_t));
12569 if (startup) {
12570 notify->event = e;
12571 }
12572 e->ev_arg = notify;
12573 e->ev_sender = NULL;
12574 result = isc_ratelimiter_enqueue(
12575 startup ? notify->zone->zmgr->startupnotifyrl
12576 : notify->zone->zmgr->notifyrl,
12577 notify->zone->task, &e);
12578 if (result != ISC_R_SUCCESS) {
12579 isc_event_free(&e);
12580 notify->event = NULL;
12581 }
12582 return (result);
12583 }
12584
12585 static void
12586 notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
12587 dns_notify_t *notify;
12588 isc_result_t result;
12589 dns_message_t *message = NULL;
12590 isc_netaddr_t dstip;
12591 dns_tsigkey_t *key = NULL;
12592 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
12593 isc_sockaddr_t src;
12594 unsigned int options, timeout;
12595 bool have_notifysource = false;
12596 bool have_notifydscp = false;
12597 isc_dscp_t dscp = -1;
12598
12599 notify = event->ev_arg;
12600 REQUIRE(DNS_NOTIFY_VALID(notify));
12601
12602 UNUSED(task);
12603
12604 LOCK_ZONE(notify->zone);
12605
12606 notify->event = NULL;
12607
12608 if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0) {
12609 result = ISC_R_CANCELED;
12610 goto cleanup;
12611 }
12612
12613 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
12614 DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) ||
12615 notify->zone->view->requestmgr == NULL || notify->zone->db == NULL)
12616 {
12617 result = ISC_R_CANCELED;
12618 goto cleanup;
12619 }
12620
12621 /*
12622 * The raw IPv4 address should also exist. Don't send to the
12623 * mapped form.
12624 */
12625 if (isc_sockaddr_pf(¬ify->dst) == PF_INET6 &&
12626 IN6_IS_ADDR_V4MAPPED(¬ify->dst.type.sin6.sin6_addr))
12627 {
12628 isc_sockaddr_format(¬ify->dst, addrbuf, sizeof(addrbuf));
12629 notify_log(notify->zone, ISC_LOG_DEBUG(3),
12630 "notify: ignoring IPv6 mapped IPV4 address: %s",
12631 addrbuf);
12632 result = ISC_R_CANCELED;
12633 goto cleanup;
12634 }
12635
12636 result = notify_createmessage(notify->zone, notify->flags, &message);
12637 if (result != ISC_R_SUCCESS) {
12638 goto cleanup;
12639 }
12640
12641 isc_sockaddr_format(¬ify->dst, addrbuf, sizeof(addrbuf));
12642 if (notify->key != NULL) {
12643 /* Transfer ownership of key */
12644 key = notify->key;
12645 notify->key = NULL;
12646 } else {
12647 isc_netaddr_fromsockaddr(&dstip, ¬ify->dst);
12648 result = dns_view_getpeertsig(notify->zone->view, &dstip, &key);
12649 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
12650 notify_log(notify->zone, ISC_LOG_ERROR,
12651 "NOTIFY to %s not sent. "
12652 "Peer TSIG key lookup failure.",
12653 addrbuf);
12654 goto cleanup_message;
12655 }
12656 }
12657
12658 if (key != NULL) {
12659 char namebuf[DNS_NAME_FORMATSIZE];
12660
12661 dns_name_format(&key->name, namebuf, sizeof(namebuf));
12662 notify_log(notify->zone, ISC_LOG_DEBUG(3),
12663 "sending notify to %s : TSIG (%s)", addrbuf,
12664 namebuf);
12665 } else {
12666 notify_log(notify->zone, ISC_LOG_DEBUG(3),
12667 "sending notify to %s", addrbuf);
12668 }
12669 options = 0;
12670 if (notify->zone->view->peers != NULL) {
12671 dns_peer_t *peer = NULL;
12672 bool usetcp = false;
12673 result = dns_peerlist_peerbyaddr(notify->zone->view->peers,
12674 &dstip, &peer);
12675 if (result == ISC_R_SUCCESS) {
12676 result = dns_peer_getnotifysource(peer, &src);
12677 if (result == ISC_R_SUCCESS) {
12678 have_notifysource = true;
12679 }
12680 dns_peer_getnotifydscp(peer, &dscp);
12681 if (dscp != -1) {
12682 have_notifydscp = true;
12683 }
12684 result = dns_peer_getforcetcp(peer, &usetcp);
12685 if (result == ISC_R_SUCCESS && usetcp) {
12686 options |= DNS_FETCHOPT_TCP;
12687 }
12688 }
12689 }
12690 switch (isc_sockaddr_pf(¬ify->dst)) {
12691 case PF_INET:
12692 if (!have_notifysource) {
12693 src = notify->zone->notifysrc4;
12694 }
12695 if (!have_notifydscp) {
12696 dscp = notify->zone->notifysrc4dscp;
12697 }
12698 break;
12699 case PF_INET6:
12700 if (!have_notifysource) {
12701 src = notify->zone->notifysrc6;
12702 }
12703 if (!have_notifydscp) {
12704 dscp = notify->zone->notifysrc6dscp;
12705 }
12706 break;
12707 default:
12708 result = ISC_R_NOTIMPLEMENTED;
12709 goto cleanup_key;
12710 }
12711 timeout = 15;
12712 if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY)) {
12713 timeout = 30;
12714 }
12715 result = dns_request_createvia(
12716 notify->zone->view->requestmgr, message, &src, ¬ify->dst,
12717 dscp, options, key, timeout * 3, timeout, 0, notify->zone->task,
12718 notify_done, notify, ¬ify->request);
12719 if (result == ISC_R_SUCCESS) {
12720 if (isc_sockaddr_pf(¬ify->dst) == AF_INET) {
12721 inc_stats(notify->zone,
12722 dns_zonestatscounter_notifyoutv4);
12723 } else {
12724 inc_stats(notify->zone,
12725 dns_zonestatscounter_notifyoutv6);
12726 }
12727 }
12728
12729 cleanup_key:
12730 if (key != NULL) {
12731 dns_tsigkey_detach(&key);
12732 }
12733 cleanup_message:
12734 dns_message_detach(&message);
12735 cleanup:
12736 UNLOCK_ZONE(notify->zone);
12737 isc_event_free(&event);
12738 if (result != ISC_R_SUCCESS) {
12739 notify_destroy(notify, false);
12740 }
12741 }
12742
12743 static void
12744 notify_send(dns_notify_t *notify) {
12745 dns_adbaddrinfo_t *ai;
12746 isc_sockaddr_t dst;
12747 isc_result_t result;
12748 dns_notify_t *newnotify = NULL;
12749 unsigned int flags;
12750 bool startup;
12751
12752 /*
12753 * Zone lock held by caller.
12754 */
12755 REQUIRE(DNS_NOTIFY_VALID(notify));
12756 REQUIRE(LOCKED_ZONE(notify->zone));
12757
12758 if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING)) {
12759 return;
12760 }
12761
12762 for (ai = ISC_LIST_HEAD(notify->find->list); ai != NULL;
12763 ai = ISC_LIST_NEXT(ai, publink))
12764 {
12765 dst = ai->sockaddr;
12766 if (notify_isqueued(notify->zone, notify->flags, NULL, &dst,
12767 NULL))
12768 {
12769 continue;
12770 }
12771 if (notify_isself(notify->zone, &dst)) {
12772 continue;
12773 }
12774 newnotify = NULL;
12775 flags = notify->flags & DNS_NOTIFY_NOSOA;
12776 result = notify_create(notify->mctx, flags, &newnotify);
12777 if (result != ISC_R_SUCCESS) {
12778 goto cleanup;
12779 }
12780 zone_iattach(notify->zone, &newnotify->zone);
12781 ISC_LIST_APPEND(newnotify->zone->notifies, newnotify, link);
12782 newnotify->dst = dst;
12783 startup = ((notify->flags & DNS_NOTIFY_STARTUP) != 0);
12784 result = notify_send_queue(newnotify, startup);
12785 if (result != ISC_R_SUCCESS) {
12786 goto cleanup;
12787 }
12788 newnotify = NULL;
12789 }
12790
12791 cleanup:
12792 if (newnotify != NULL) {
12793 notify_destroy(newnotify, true);
12794 }
12795 }
12796
12797 void
12798 dns_zone_notify(dns_zone_t *zone) {
12799 isc_time_t now;
12800
12801 REQUIRE(DNS_ZONE_VALID(zone));
12802
12803 LOCK_ZONE(zone);
12804 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
12805
12806 TIME_NOW(&now);
12807 zone_settimer(zone, &now);
12808 UNLOCK_ZONE(zone);
12809 }
12810
12811 static void
12812 zone_notify(dns_zone_t *zone, isc_time_t *now) {
12813 dns_dbnode_t *node = NULL;
12814 dns_db_t *zonedb = NULL;
12815 dns_dbversion_t *version = NULL;
12816 dns_name_t *origin = NULL;
12817 dns_name_t master;
12818 dns_rdata_ns_t ns;
12819 dns_rdata_soa_t soa;
12820 uint32_t serial;
12821 dns_rdata_t rdata = DNS_RDATA_INIT;
12822 dns_rdataset_t nsrdset;
12823 dns_rdataset_t soardset;
12824 isc_result_t result;
12825 unsigned int i;
12826 isc_sockaddr_t dst;
12827 bool isqueued;
12828 dns_notifytype_t notifytype;
12829 unsigned int flags = 0;
12830 bool loggednotify = false;
12831 bool startup;
12832
12833 REQUIRE(DNS_ZONE_VALID(zone));
12834
12835 LOCK_ZONE(zone);
12836 startup = !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
12837 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
12838 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY);
12839 notifytype = zone->notifytype;
12840 DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime);
12841 UNLOCK_ZONE(zone);
12842
12843 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
12844 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
12845 {
12846 return;
12847 }
12848
12849 if (notifytype == dns_notifytype_no) {
12850 return;
12851 }
12852
12853 if (notifytype == dns_notifytype_masteronly &&
12854 zone->type != dns_zone_primary)
12855 {
12856 return;
12857 }
12858
12859 origin = &zone->origin;
12860
12861 /*
12862 * If the zone is dialup we are done as we don't want to send
12863 * the current soa so as to force a refresh query.
12864 */
12865 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY)) {
12866 flags |= DNS_NOTIFY_NOSOA;
12867 }
12868
12869 /*
12870 * Record that this was a notify due to starting up.
12871 */
12872 if (startup) {
12873 flags |= DNS_NOTIFY_STARTUP;
12874 }
12875
12876 /*
12877 * Get SOA RRset.
12878 */
12879 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
12880 if (zone->db != NULL) {
12881 dns_db_attach(zone->db, &zonedb);
12882 }
12883 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12884 if (zonedb == NULL) {
12885 return;
12886 }
12887 dns_db_currentversion(zonedb, &version);
12888 result = dns_db_findnode(zonedb, origin, false, &node);
12889 if (result != ISC_R_SUCCESS) {
12890 goto cleanup1;
12891 }
12892
12893 dns_rdataset_init(&soardset);
12894 result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
12895 dns_rdatatype_none, 0, &soardset, NULL);
12896 if (result != ISC_R_SUCCESS) {
12897 goto cleanup2;
12898 }
12899
12900 /*
12901 * Find serial and master server's name.
12902 */
12903 dns_name_init(&master, NULL);
12904 result = dns_rdataset_first(&soardset);
12905 if (result != ISC_R_SUCCESS) {
12906 goto cleanup3;
12907 }
12908 dns_rdataset_current(&soardset, &rdata);
12909 result = dns_rdata_tostruct(&rdata, &soa, NULL);
12910 RUNTIME_CHECK(result == ISC_R_SUCCESS);
12911 dns_rdata_reset(&rdata);
12912 dns_name_dup(&soa.origin, zone->mctx, &master);
12913 serial = soa.serial;
12914 dns_rdataset_disassociate(&soardset);
12915
12916 /*
12917 * Enqueue notify requests for 'also-notify' servers.
12918 */
12919 LOCK_ZONE(zone);
12920 for (i = 0; i < zone->notifycnt; i++) {
12921 dns_tsigkey_t *key = NULL;
12922 dns_notify_t *notify = NULL;
12923
12924 if ((zone->notifykeynames != NULL) &&
12925 (zone->notifykeynames[i] != NULL))
12926 {
12927 dns_view_t *view = dns_zone_getview(zone);
12928 dns_name_t *keyname = zone->notifykeynames[i];
12929 (void)dns_view_gettsig(view, keyname, &key);
12930 }
12931
12932 dst = zone->notify[i];
12933 if (notify_isqueued(zone, flags, NULL, &dst, key)) {
12934 if (key != NULL) {
12935 dns_tsigkey_detach(&key);
12936 }
12937 continue;
12938 }
12939
12940 result = notify_create(zone->mctx, flags, ¬ify);
12941 if (result != ISC_R_SUCCESS) {
12942 if (key != NULL) {
12943 dns_tsigkey_detach(&key);
12944 }
12945 continue;
12946 }
12947
12948 zone_iattach(zone, ¬ify->zone);
12949 notify->dst = dst;
12950
12951 INSIST(notify->key == NULL);
12952
12953 if (key != NULL) {
12954 notify->key = key;
12955 key = NULL;
12956 }
12957
12958 ISC_LIST_APPEND(zone->notifies, notify, link);
12959 result = notify_send_queue(notify, startup);
12960 if (result != ISC_R_SUCCESS) {
12961 notify_destroy(notify, true);
12962 }
12963 if (!loggednotify) {
12964 notify_log(zone, ISC_LOG_INFO,
12965 "sending notifies (serial %u)", serial);
12966 loggednotify = true;
12967 }
12968 }
12969 UNLOCK_ZONE(zone);
12970
12971 if (notifytype == dns_notifytype_explicit) {
12972 goto cleanup3;
12973 }
12974
12975 /*
12976 * Process NS RRset to generate notifies.
12977 */
12978
12979 dns_rdataset_init(&nsrdset);
12980 result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_ns,
12981 dns_rdatatype_none, 0, &nsrdset, NULL);
12982 if (result != ISC_R_SUCCESS) {
12983 goto cleanup3;
12984 }
12985
12986 result = dns_rdataset_first(&nsrdset);
12987 while (result == ISC_R_SUCCESS) {
12988 dns_notify_t *notify = NULL;
12989
12990 dns_rdataset_current(&nsrdset, &rdata);
12991 result = dns_rdata_tostruct(&rdata, &ns, NULL);
12992 RUNTIME_CHECK(result == ISC_R_SUCCESS);
12993 dns_rdata_reset(&rdata);
12994 /*
12995 * Don't notify the master server unless explicitly
12996 * configured to do so.
12997 */
12998 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOTIFYTOSOA) &&
12999 dns_name_compare(&master, &ns.name) == 0)
13000 {
13001 result = dns_rdataset_next(&nsrdset);
13002 continue;
13003 }
13004
13005 if (!loggednotify) {
13006 notify_log(zone, ISC_LOG_INFO,
13007 "sending notifies (serial %u)", serial);
13008 loggednotify = true;
13009 }
13010
13011 LOCK_ZONE(zone);
13012 isqueued = notify_isqueued(zone, flags, &ns.name, NULL, NULL);
13013 UNLOCK_ZONE(zone);
13014 if (isqueued) {
13015 result = dns_rdataset_next(&nsrdset);
13016 continue;
13017 }
13018 result = notify_create(zone->mctx, flags, ¬ify);
13019 if (result != ISC_R_SUCCESS) {
13020 continue;
13021 }
13022 dns_zone_iattach(zone, ¬ify->zone);
13023 dns_name_dup(&ns.name, zone->mctx, ¬ify->ns);
13024 LOCK_ZONE(zone);
13025 ISC_LIST_APPEND(zone->notifies, notify, link);
13026 UNLOCK_ZONE(zone);
13027 notify_find_address(notify);
13028 result = dns_rdataset_next(&nsrdset);
13029 }
13030 dns_rdataset_disassociate(&nsrdset);
13031
13032 cleanup3:
13033 if (dns_name_dynamic(&master)) {
13034 dns_name_free(&master, zone->mctx);
13035 }
13036 cleanup2:
13037 dns_db_detachnode(zonedb, &node);
13038 cleanup1:
13039 dns_db_closeversion(zonedb, &version, false);
13040 dns_db_detach(&zonedb);
13041 }
13042
13043 /***
13044 *** Private
13045 ***/
13046 static isc_result_t
13047 create_query(dns_zone_t *zone, dns_rdatatype_t rdtype, dns_name_t *name,
13048 dns_message_t **messagep) {
13049 dns_message_t *message = NULL;
13050 dns_name_t *qname = NULL;
13051 dns_rdataset_t *qrdataset = NULL;
13052 isc_result_t result;
13053
13054 dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER, &message);
13055
13056 message->opcode = dns_opcode_query;
13057 message->rdclass = zone->rdclass;
13058
13059 result = dns_message_gettempname(message, &qname);
13060 if (result != ISC_R_SUCCESS) {
13061 goto cleanup;
13062 }
13063
13064 result = dns_message_gettemprdataset(message, &qrdataset);
13065 if (result != ISC_R_SUCCESS) {
13066 goto cleanup;
13067 }
13068
13069 /*
13070 * Make question.
13071 */
13072 dns_name_clone(name, qname);
13073 dns_rdataset_makequestion(qrdataset, zone->rdclass, rdtype);
13074 ISC_LIST_APPEND(qname->list, qrdataset, link);
13075 dns_message_addname(message, qname, DNS_SECTION_QUESTION);
13076
13077 *messagep = message;
13078 return (ISC_R_SUCCESS);
13079
13080 cleanup:
13081 if (qname != NULL) {
13082 dns_message_puttempname(message, &qname);
13083 }
13084 if (qrdataset != NULL) {
13085 dns_message_puttemprdataset(message, &qrdataset);
13086 }
13087 dns_message_detach(&message);
13088 return (result);
13089 }
13090
13091 static isc_result_t
13092 add_opt(dns_message_t *message, uint16_t udpsize, bool reqnsid,
13093 bool reqexpire) {
13094 isc_result_t result;
13095 dns_rdataset_t *rdataset = NULL;
13096 dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS];
13097 int count = 0;
13098
13099 /* Set EDNS options if applicable. */
13100 if (reqnsid) {
13101 INSIST(count < DNS_EDNSOPTIONS);
13102 ednsopts[count].code = DNS_OPT_NSID;
13103 ednsopts[count].length = 0;
13104 ednsopts[count].value = NULL;
13105 count++;
13106 }
13107 if (reqexpire) {
13108 INSIST(count < DNS_EDNSOPTIONS);
13109 ednsopts[count].code = DNS_OPT_EXPIRE;
13110 ednsopts[count].length = 0;
13111 ednsopts[count].value = NULL;
13112 count++;
13113 }
13114 result = dns_message_buildopt(message, &rdataset, 0, udpsize, 0,
13115 ednsopts, count);
13116 if (result != ISC_R_SUCCESS) {
13117 return (result);
13118 }
13119
13120 return (dns_message_setopt(message, rdataset));
13121 }
13122
13123 /*
13124 * Called when stub zone update is finished.
13125 * Update zone refresh, retry, expire values accordingly with
13126 * SOA received from master, sync database to file, restart
13127 * zone management timer.
13128 */
13129 static void
13130 stub_finish_zone_update(dns_stub_t *stub, isc_time_t now) {
13131 uint32_t refresh, retry, expire;
13132 isc_result_t result;
13133 isc_interval_t i;
13134 unsigned int soacount;
13135 dns_zone_t *zone = stub->zone;
13136
13137 /*
13138 * Tidy up.
13139 */
13140 dns_db_closeversion(stub->db, &stub->version, true);
13141 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
13142 if (zone->db == NULL) {
13143 zone_attachdb(zone, stub->db);
13144 }
13145 result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL, NULL,
13146 &refresh, &retry, &expire, NULL, NULL);
13147 if (result == ISC_R_SUCCESS && soacount > 0U) {
13148 zone->refresh = RANGE(refresh, zone->minrefresh,
13149 zone->maxrefresh);
13150 zone->retry = RANGE(retry, zone->minretry, zone->maxretry);
13151 zone->expire = RANGE(expire, zone->refresh + zone->retry,
13152 DNS_MAX_EXPIRE);
13153 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
13154 }
13155 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
13156 dns_db_detach(&stub->db);
13157
13158 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
13159 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
13160 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
13161 isc_interval_set(&i, zone->expire, 0);
13162 DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
13163
13164 if (zone->masterfile != NULL) {
13165 zone_needdump(zone, 0);
13166 }
13167
13168 zone_settimer(zone, &now);
13169 }
13170
13171 /*
13172 * Process answers for A and AAAA queries when
13173 * resolving nameserver addresses for which glue
13174 * was missing in a previous answer for a NS query.
13175 */
13176 static void
13177 stub_glue_response_cb(isc_task_t *task, isc_event_t *event) {
13178 const char me[] = "stub_glue_response_cb";
13179 dns_requestevent_t *revent = (dns_requestevent_t *)event;
13180 dns_stub_t *stub = NULL;
13181 dns_message_t *msg = NULL;
13182 dns_zone_t *zone = NULL;
13183 char master[ISC_SOCKADDR_FORMATSIZE];
13184 char source[ISC_SOCKADDR_FORMATSIZE];
13185 uint32_t addr_count, cnamecnt;
13186 isc_result_t result;
13187 isc_time_t now;
13188 struct stub_glue_request *request;
13189 struct stub_cb_args *cb_args;
13190 dns_rdataset_t *addr_rdataset = NULL;
13191 dns_dbnode_t *node = NULL;
13192
13193 UNUSED(task);
13194
13195 request = revent->ev_arg;
13196 cb_args = request->args;
13197 stub = cb_args->stub;
13198 INSIST(DNS_STUB_VALID(stub));
13199
13200 zone = stub->zone;
13201
13202 ENTER;
13203
13204 TIME_NOW(&now);
13205
13206 LOCK_ZONE(zone);
13207
13208 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
13209 zone_debuglog(zone, me, 1, "exiting");
13210 goto cleanup;
13211 }
13212
13213 isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
13214 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
13215
13216 if (revent->result != ISC_R_SUCCESS) {
13217 dns_zonemgr_unreachableadd(zone->zmgr, &zone->masteraddr,
13218 &zone->sourceaddr, &now);
13219 dns_zone_log(zone, ISC_LOG_INFO,
13220 "could not refresh stub from master %s"
13221 " (source %s): %s",
13222 master, source, dns_result_totext(revent->result));
13223 goto cleanup;
13224 }
13225
13226 dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
13227 result = dns_request_getresponse(revent->request, msg, 0);
13228 if (result != ISC_R_SUCCESS) {
13229 dns_zone_log(zone, ISC_LOG_INFO,
13230 "refreshing stub: unable to parse response (%s)",
13231 isc_result_totext(result));
13232 goto cleanup;
13233 }
13234
13235 /*
13236 * Unexpected opcode.
13237 */
13238 if (msg->opcode != dns_opcode_query) {
13239 char opcode[128];
13240 isc_buffer_t rb;
13241
13242 isc_buffer_init(&rb, opcode, sizeof(opcode));
13243 (void)dns_opcode_totext(msg->opcode, &rb);
13244
13245 dns_zone_log(zone, ISC_LOG_INFO,
13246 "refreshing stub: "
13247 "unexpected opcode (%.*s) from %s (source %s)",
13248 (int)rb.used, opcode, master, source);
13249 goto cleanup;
13250 }
13251
13252 /*
13253 * Unexpected rcode.
13254 */
13255 if (msg->rcode != dns_rcode_noerror) {
13256 char rcode[128];
13257 isc_buffer_t rb;
13258
13259 isc_buffer_init(&rb, rcode, sizeof(rcode));
13260 (void)dns_rcode_totext(msg->rcode, &rb);
13261
13262 dns_zone_log(zone, ISC_LOG_INFO,
13263 "refreshing stub: "
13264 "unexpected rcode (%.*s) from %s (source %s)",
13265 (int)rb.used, rcode, master, source);
13266 goto cleanup;
13267 }
13268
13269 /*
13270 * We need complete messages.
13271 */
13272 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
13273 if (dns_request_usedtcp(revent->request)) {
13274 dns_zone_log(zone, ISC_LOG_INFO,
13275 "refreshing stub: truncated TCP "
13276 "response from master %s (source %s)",
13277 master, source);
13278 }
13279 goto cleanup;
13280 }
13281
13282 /*
13283 * If non-auth log.
13284 */
13285 if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
13286 dns_zone_log(zone, ISC_LOG_INFO,
13287 "refreshing stub: "
13288 "non-authoritative answer from "
13289 "master %s (source %s)",
13290 master, source);
13291 goto cleanup;
13292 }
13293
13294 /*
13295 * Sanity checks.
13296 */
13297 cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
13298 addr_count = message_count(msg, DNS_SECTION_ANSWER,
13299 request->ipv4 ? dns_rdatatype_a
13300 : dns_rdatatype_aaaa);
13301
13302 if (cnamecnt != 0) {
13303 dns_zone_log(zone, ISC_LOG_INFO,
13304 "refreshing stub: unexpected CNAME response "
13305 "from master %s (source %s)",
13306 master, source);
13307 goto cleanup;
13308 }
13309
13310 if (addr_count == 0) {
13311 dns_zone_log(zone, ISC_LOG_INFO,
13312 "refreshing stub: no %s records in response "
13313 "from master %s (source %s)",
13314 request->ipv4 ? "A" : "AAAA", master, source);
13315 goto cleanup;
13316 }
13317 /*
13318 * Extract A or AAAA RRset from message.
13319 */
13320 result = dns_message_findname(msg, DNS_SECTION_ANSWER, &request->name,
13321 request->ipv4 ? dns_rdatatype_a
13322 : dns_rdatatype_aaaa,
13323 dns_rdatatype_none, NULL, &addr_rdataset);
13324 if (result != ISC_R_SUCCESS) {
13325 if (result != DNS_R_NXDOMAIN && result != DNS_R_NXRRSET) {
13326 char namebuf[DNS_NAME_FORMATSIZE];
13327 dns_name_format(&request->name, namebuf,
13328 sizeof(namebuf));
13329 dns_zone_log(
13330 zone, ISC_LOG_INFO,
13331 "refreshing stub: dns_message_findname(%s/%s) "
13332 "failed (%s)",
13333 namebuf, request->ipv4 ? "A" : "AAAA",
13334 isc_result_totext(result));
13335 }
13336 goto cleanup;
13337 }
13338
13339 result = dns_db_findnode(stub->db, &request->name, true, &node);
13340 if (result != ISC_R_SUCCESS) {
13341 dns_zone_log(zone, ISC_LOG_INFO,
13342 "refreshing stub: "
13343 "dns_db_findnode() failed: %s",
13344 dns_result_totext(result));
13345 goto cleanup;
13346 }
13347
13348 result = dns_db_addrdataset(stub->db, node, stub->version, 0,
13349 addr_rdataset, 0, NULL);
13350 if (result != ISC_R_SUCCESS) {
13351 dns_zone_log(zone, ISC_LOG_INFO,
13352 "refreshing stub: "
13353 "dns_db_addrdataset() failed: %s",
13354 dns_result_totext(result));
13355 }
13356 dns_db_detachnode(stub->db, &node);
13357
13358 cleanup:
13359 if (msg != NULL) {
13360 dns_message_detach(&msg);
13361 }
13362 isc_event_free(&event);
13363 dns_name_free(&request->name, zone->mctx);
13364 dns_request_destroy(&request->request);
13365 isc_mem_put(zone->mctx, request, sizeof(*request));
13366
13367 /* If last request, release all related resources */
13368 if (atomic_fetch_sub_release(&stub->pending_requests, 1) == 1) {
13369 isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
13370 stub_finish_zone_update(stub, now);
13371 UNLOCK_ZONE(zone);
13372 stub->magic = 0;
13373 dns_zone_idetach(&stub->zone);
13374 INSIST(stub->db == NULL);
13375 INSIST(stub->version == NULL);
13376 isc_mem_put(stub->mctx, stub, sizeof(*stub));
13377 } else {
13378 UNLOCK_ZONE(zone);
13379 }
13380 }
13381
13382 /*
13383 * Create and send an A or AAAA query to the master
13384 * server of the stub zone given.
13385 */
13386 static isc_result_t
13387 stub_request_nameserver_address(struct stub_cb_args *args, bool ipv4,
13388 const dns_name_t *name) {
13389 dns_message_t *message = NULL;
13390 dns_zone_t *zone;
13391 isc_result_t result;
13392 struct stub_glue_request *request;
13393
13394 zone = args->stub->zone;
13395 request = isc_mem_get(zone->mctx, sizeof(*request));
13396 request->request = NULL;
13397 request->args = args;
13398 request->name = (dns_name_t)DNS_NAME_INITEMPTY;
13399 request->ipv4 = ipv4;
13400 dns_name_dup(name, zone->mctx, &request->name);
13401
13402 result = create_query(zone, ipv4 ? dns_rdatatype_a : dns_rdatatype_aaaa,
13403 &request->name, &message);
13404 INSIST(result == ISC_R_SUCCESS);
13405
13406 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
13407 result = add_opt(message, args->udpsize, args->reqnsid, false);
13408 if (result != ISC_R_SUCCESS) {
13409 zone_debuglog(zone, "stub_send_query", 1,
13410 "unable to add opt record: %s",
13411 dns_result_totext(result));
13412 goto fail;
13413 }
13414 }
13415
13416 atomic_fetch_add_release(&args->stub->pending_requests, 1);
13417
13418 result = dns_request_createvia(
13419 zone->view->requestmgr, message, &zone->sourceaddr,
13420 &zone->masteraddr, args->dscp, DNS_REQUESTOPT_TCP,
13421 args->tsig_key, args->timeout * 3, args->timeout, 0, zone->task,
13422 stub_glue_response_cb, request, &request->request);
13423
13424 if (result != ISC_R_SUCCESS) {
13425 INSIST(atomic_fetch_sub_release(&args->stub->pending_requests,
13426 1) > 1);
13427 zone_debuglog(zone, "stub_send_query", 1,
13428 "dns_request_createvia() failed: %s",
13429 dns_result_totext(result));
13430 goto fail;
13431 }
13432
13433 dns_message_detach(&message);
13434
13435 return (ISC_R_SUCCESS);
13436
13437 fail:
13438 dns_name_free(&request->name, zone->mctx);
13439 isc_mem_put(zone->mctx, request, sizeof(*request));
13440
13441 if (message != NULL) {
13442 dns_message_detach(&message);
13443 }
13444
13445 return (result);
13446 }
13447
13448 static isc_result_t
13449 save_nsrrset(dns_message_t *message, dns_name_t *name,
13450 struct stub_cb_args *cb_args, dns_db_t *db,
13451 dns_dbversion_t *version) {
13452 dns_rdataset_t *nsrdataset = NULL;
13453 dns_rdataset_t *rdataset = NULL;
13454 dns_dbnode_t *node = NULL;
13455 dns_rdata_ns_t ns;
13456 isc_result_t result;
13457 dns_rdata_t rdata = DNS_RDATA_INIT;
13458 bool has_glue = false;
13459 dns_name_t *ns_name;
13460 /*
13461 * List of NS entries in answer, keep names that will be used
13462 * to resolve missing A/AAAA glue for each entry.
13463 */
13464 dns_namelist_t ns_list;
13465 ISC_LIST_INIT(ns_list);
13466
13467 /*
13468 * Extract NS RRset from message.
13469 */
13470 result = dns_message_findname(message, DNS_SECTION_ANSWER, name,
13471 dns_rdatatype_ns, dns_rdatatype_none,
13472 NULL, &nsrdataset);
13473 if (result != ISC_R_SUCCESS) {
13474 goto done;
13475 }
13476
13477 /*
13478 * Add NS rdataset.
13479 */
13480 result = dns_db_findnode(db, name, true, &node);
13481 if (result != ISC_R_SUCCESS) {
13482 goto done;
13483 }
13484 result = dns_db_addrdataset(db, node, version, 0, nsrdataset, 0, NULL);
13485 dns_db_detachnode(db, &node);
13486 if (result != ISC_R_SUCCESS) {
13487 goto done;
13488 }
13489 /*
13490 * Add glue rdatasets.
13491 */
13492 for (result = dns_rdataset_first(nsrdataset); result == ISC_R_SUCCESS;
13493 result = dns_rdataset_next(nsrdataset))
13494 {
13495 dns_rdataset_current(nsrdataset, &rdata);
13496 result = dns_rdata_tostruct(&rdata, &ns, NULL);
13497 RUNTIME_CHECK(result == ISC_R_SUCCESS);
13498 dns_rdata_reset(&rdata);
13499
13500 if (!dns_name_issubdomain(&ns.name, name)) {
13501 continue;
13502 }
13503 rdataset = NULL;
13504 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
13505 &ns.name, dns_rdatatype_aaaa,
13506 dns_rdatatype_none, NULL,
13507 &rdataset);
13508 if (result == ISC_R_SUCCESS) {
13509 has_glue = true;
13510 result = dns_db_findnode(db, &ns.name, true, &node);
13511 if (result != ISC_R_SUCCESS) {
13512 goto done;
13513 }
13514 result = dns_db_addrdataset(db, node, version, 0,
13515 rdataset, 0, NULL);
13516 dns_db_detachnode(db, &node);
13517 if (result != ISC_R_SUCCESS) {
13518 goto done;
13519 }
13520 }
13521
13522 rdataset = NULL;
13523 result = dns_message_findname(
13524 message, DNS_SECTION_ADDITIONAL, &ns.name,
13525 dns_rdatatype_a, dns_rdatatype_none, NULL, &rdataset);
13526 if (result == ISC_R_SUCCESS) {
13527 has_glue = true;
13528 result = dns_db_findnode(db, &ns.name, true, &node);
13529 if (result != ISC_R_SUCCESS) {
13530 goto done;
13531 }
13532 result = dns_db_addrdataset(db, node, version, 0,
13533 rdataset, 0, NULL);
13534 dns_db_detachnode(db, &node);
13535 if (result != ISC_R_SUCCESS) {
13536 goto done;
13537 }
13538 }
13539
13540 /*
13541 * If no glue is found so far, we add the name to the list to
13542 * resolve the A/AAAA glue later. If any glue is found in any
13543 * iteration step, this list will be discarded and only the glue
13544 * provided in this message will be used.
13545 */
13546 if (!has_glue && dns_name_issubdomain(&ns.name, name)) {
13547 dns_name_t *tmp_name;
13548 tmp_name = isc_mem_get(cb_args->stub->mctx,
13549 sizeof(*tmp_name));
13550 dns_name_init(tmp_name, NULL);
13551 dns_name_dup(&ns.name, cb_args->stub->mctx, tmp_name);
13552 ISC_LIST_APPEND(ns_list, tmp_name, link);
13553 }
13554 }
13555
13556 if (result != ISC_R_NOMORE) {
13557 goto done;
13558 }
13559
13560 /*
13561 * If no glue records were found, we attempt to resolve A/AAAA
13562 * for each NS entry found in the answer.
13563 */
13564 if (!has_glue) {
13565 for (ns_name = ISC_LIST_HEAD(ns_list); ns_name != NULL;
13566 ns_name = ISC_LIST_NEXT(ns_name, link))
13567 {
13568 /*
13569 * Resolve NS IPv4 address/A.
13570 */
13571 result = stub_request_nameserver_address(cb_args, true,
13572 ns_name);
13573 if (result != ISC_R_SUCCESS) {
13574 goto done;
13575 }
13576 /*
13577 * Resolve NS IPv6 address/AAAA.
13578 */
13579 result = stub_request_nameserver_address(cb_args, false,
13580 ns_name);
13581 if (result != ISC_R_SUCCESS) {
13582 goto done;
13583 }
13584 }
13585 }
13586
13587 result = ISC_R_SUCCESS;
13588
13589 done:
13590 while ((ns_name = ISC_LIST_HEAD(ns_list)) != NULL) {
13591 ISC_LIST_UNLINK(ns_list, ns_name, link);
13592 dns_name_free(ns_name, cb_args->stub->mctx);
13593 isc_mem_put(cb_args->stub->mctx, ns_name, sizeof(*ns_name));
13594 }
13595 return (result);
13596 }
13597
13598 static void
13599 stub_callback(isc_task_t *task, isc_event_t *event) {
13600 const char me[] = "stub_callback";
13601 dns_requestevent_t *revent = (dns_requestevent_t *)event;
13602 dns_stub_t *stub = NULL;
13603 dns_message_t *msg = NULL;
13604 dns_zone_t *zone = NULL;
13605 char master[ISC_SOCKADDR_FORMATSIZE];
13606 char source[ISC_SOCKADDR_FORMATSIZE];
13607 uint32_t nscnt, cnamecnt;
13608 isc_result_t result;
13609 isc_time_t now;
13610 bool exiting = false;
13611 unsigned int j;
13612 struct stub_cb_args *cb_args;
13613
13614 cb_args = revent->ev_arg;
13615 stub = cb_args->stub;
13616 INSIST(DNS_STUB_VALID(stub));
13617
13618 UNUSED(task);
13619
13620 zone = stub->zone;
13621
13622 ENTER;
13623
13624 TIME_NOW(&now);
13625
13626 LOCK_ZONE(zone);
13627
13628 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
13629 zone_debuglog(zone, me, 1, "exiting");
13630 exiting = true;
13631 goto next_master;
13632 }
13633
13634 isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
13635 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
13636
13637 if (revent->result != ISC_R_SUCCESS) {
13638 if (revent->result == ISC_R_TIMEDOUT &&
13639 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS))
13640 {
13641 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
13642 dns_zone_log(zone, ISC_LOG_DEBUG(1),
13643 "refreshing stub: timeout retrying "
13644 " without EDNS master %s (source %s)",
13645 master, source);
13646 goto same_master;
13647 }
13648 dns_zonemgr_unreachableadd(zone->zmgr, &zone->masteraddr,
13649 &zone->sourceaddr, &now);
13650 dns_zone_log(zone, ISC_LOG_INFO,
13651 "could not refresh stub from master %s"
13652 " (source %s): %s",
13653 master, source, dns_result_totext(revent->result));
13654 goto next_master;
13655 }
13656
13657 dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
13658
13659 result = dns_request_getresponse(revent->request, msg, 0);
13660 if (result != ISC_R_SUCCESS) {
13661 goto next_master;
13662 }
13663
13664 /*
13665 * Unexpected opcode.
13666 */
13667 if (msg->opcode != dns_opcode_query) {
13668 char opcode[128];
13669 isc_buffer_t rb;
13670
13671 isc_buffer_init(&rb, opcode, sizeof(opcode));
13672 (void)dns_opcode_totext(msg->opcode, &rb);
13673
13674 dns_zone_log(zone, ISC_LOG_INFO,
13675 "refreshing stub: "
13676 "unexpected opcode (%.*s) from %s (source %s)",
13677 (int)rb.used, opcode, master, source);
13678 goto next_master;
13679 }
13680
13681 /*
13682 * Unexpected rcode.
13683 */
13684 if (msg->rcode != dns_rcode_noerror) {
13685 char rcode[128];
13686 isc_buffer_t rb;
13687
13688 isc_buffer_init(&rb, rcode, sizeof(rcode));
13689 (void)dns_rcode_totext(msg->rcode, &rb);
13690
13691 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
13692 (msg->rcode == dns_rcode_servfail ||
13693 msg->rcode == dns_rcode_notimp ||
13694 msg->rcode == dns_rcode_formerr))
13695 {
13696 dns_zone_log(zone, ISC_LOG_DEBUG(1),
13697 "refreshing stub: rcode (%.*s) retrying "
13698 "without EDNS master %s (source %s)",
13699 (int)rb.used, rcode, master, source);
13700 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
13701 goto same_master;
13702 }
13703
13704 dns_zone_log(zone, ISC_LOG_INFO,
13705 "refreshing stub: "
13706 "unexpected rcode (%.*s) from %s (source %s)",
13707 (int)rb.used, rcode, master, source);
13708 goto next_master;
13709 }
13710
13711 /*
13712 * We need complete messages.
13713 */
13714 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
13715 if (dns_request_usedtcp(revent->request)) {
13716 dns_zone_log(zone, ISC_LOG_INFO,
13717 "refreshing stub: truncated TCP "
13718 "response from master %s (source %s)",
13719 master, source);
13720 goto next_master;
13721 }
13722 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
13723 goto same_master;
13724 }
13725
13726 /*
13727 * If non-auth log and next master.
13728 */
13729 if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
13730 dns_zone_log(zone, ISC_LOG_INFO,
13731 "refreshing stub: "
13732 "non-authoritative answer from "
13733 "master %s (source %s)",
13734 master, source);
13735 goto next_master;
13736 }
13737
13738 /*
13739 * Sanity checks.
13740 */
13741 cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
13742 nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns);
13743
13744 if (cnamecnt != 0) {
13745 dns_zone_log(zone, ISC_LOG_INFO,
13746 "refreshing stub: unexpected CNAME response "
13747 "from master %s (source %s)",
13748 master, source);
13749 goto next_master;
13750 }
13751
13752 if (nscnt == 0) {
13753 dns_zone_log(zone, ISC_LOG_INFO,
13754 "refreshing stub: no NS records in response "
13755 "from master %s (source %s)",
13756 master, source);
13757 goto next_master;
13758 }
13759
13760 atomic_fetch_add(&stub->pending_requests, 1);
13761
13762 /*
13763 * Save answer.
13764 */
13765 result = save_nsrrset(msg, &zone->origin, cb_args, stub->db,
13766 stub->version);
13767 if (result != ISC_R_SUCCESS) {
13768 dns_zone_log(zone, ISC_LOG_INFO,
13769 "refreshing stub: unable to save NS records "
13770 "from master %s (source %s)",
13771 master, source);
13772 goto next_master;
13773 }
13774
13775 dns_message_detach(&msg);
13776 isc_event_free(&event);
13777 dns_request_destroy(&zone->request);
13778
13779 /*
13780 * Check to see if there are no outstanding requests and
13781 * finish off if that is so.
13782 */
13783 if (atomic_fetch_sub(&stub->pending_requests, 1) == 1) {
13784 isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
13785 stub_finish_zone_update(stub, now);
13786 goto free_stub;
13787 }
13788
13789 UNLOCK_ZONE(zone);
13790 return;
13791
13792 next_master:
13793 isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
13794 if (stub->version != NULL) {
13795 dns_db_closeversion(stub->db, &stub->version, false);
13796 }
13797 if (stub->db != NULL) {
13798 dns_db_detach(&stub->db);
13799 }
13800 if (msg != NULL) {
13801 dns_message_detach(&msg);
13802 }
13803 isc_event_free(&event);
13804 dns_request_destroy(&zone->request);
13805 /*
13806 * Skip to next failed / untried master.
13807 */
13808 do {
13809 zone->curmaster++;
13810 } while (zone->curmaster < zone->masterscnt &&
13811 zone->mastersok[zone->curmaster]);
13812 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
13813 if (exiting || zone->curmaster >= zone->masterscnt) {
13814 bool done = true;
13815 if (!exiting &&
13816 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
13817 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
13818 {
13819 /*
13820 * Did we get a good answer from all the primaries?
13821 */
13822 for (j = 0; j < zone->masterscnt; j++) {
13823 if (!zone->mastersok[j]) {
13824 {
13825 done = false;
13826 break;
13827 }
13828 }
13829 }
13830 } else {
13831 done = true;
13832 }
13833 if (!done) {
13834 zone->curmaster = 0;
13835 /*
13836 * Find the next failed master.
13837 */
13838 while (zone->curmaster < zone->masterscnt &&
13839 zone->mastersok[zone->curmaster])
13840 {
13841 zone->curmaster++;
13842 }
13843 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
13844 } else {
13845 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
13846
13847 zone_settimer(zone, &now);
13848 goto free_stub;
13849 }
13850 }
13851 queue_soa_query(zone);
13852 goto free_stub;
13853
13854 same_master:
13855 isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
13856 if (msg != NULL) {
13857 dns_message_detach(&msg);
13858 }
13859 isc_event_free(&event);
13860 dns_request_destroy(&zone->request);
13861 ns_query(zone, NULL, stub);
13862 UNLOCK_ZONE(zone);
13863 goto done;
13864
13865 free_stub:
13866 UNLOCK_ZONE(zone);
13867 stub->magic = 0;
13868 dns_zone_idetach(&stub->zone);
13869 INSIST(stub->db == NULL);
13870 INSIST(stub->version == NULL);
13871 isc_mem_put(stub->mctx, stub, sizeof(*stub));
13872
13873 done:
13874 INSIST(event == NULL);
13875 return;
13876 }
13877
13878 /*
13879 * Get the EDNS EXPIRE option from the response and if it exists trim
13880 * expire to be not more than it.
13881 */
13882 static void
13883 get_edns_expire(dns_zone_t *zone, dns_message_t *message, uint32_t *expirep) {
13884 isc_result_t result;
13885 uint32_t expire;
13886 dns_rdata_t rdata = DNS_RDATA_INIT;
13887 isc_buffer_t optbuf;
13888 uint16_t optcode;
13889 uint16_t optlen;
13890
13891 REQUIRE(expirep != NULL);
13892 REQUIRE(message != NULL);
13893
13894 if (message->opt == NULL) {
13895 return;
13896 }
13897
13898 result = dns_rdataset_first(message->opt);
13899 if (result == ISC_R_SUCCESS) {
13900 dns_rdataset_current(message->opt, &rdata);
13901 isc_buffer_init(&optbuf, rdata.data, rdata.length);
13902 isc_buffer_add(&optbuf, rdata.length);
13903 while (isc_buffer_remaininglength(&optbuf) >= 4) {
13904 optcode = isc_buffer_getuint16(&optbuf);
13905 optlen = isc_buffer_getuint16(&optbuf);
13906 /*
13907 * A EDNS EXPIRE response has a length of 4.
13908 */
13909 if (optcode != DNS_OPT_EXPIRE || optlen != 4) {
13910 isc_buffer_forward(&optbuf, optlen);
13911 continue;
13912 }
13913 expire = isc_buffer_getuint32(&optbuf);
13914 dns_zone_log(zone, ISC_LOG_DEBUG(1),
13915 "got EDNS EXPIRE of %u", expire);
13916 /*
13917 * Trim *expirep?
13918 */
13919 if (expire < *expirep) {
13920 *expirep = expire;
13921 }
13922 break;
13923 }
13924 }
13925 }
13926
13927 /*
13928 * Set the file modification time zone->expire seconds before expiretime.
13929 */
13930 static void
13931 setmodtime(dns_zone_t *zone, isc_time_t *expiretime) {
13932 isc_result_t result;
13933 isc_time_t when;
13934 isc_interval_t i;
13935
13936 isc_interval_set(&i, zone->expire, 0);
13937 result = isc_time_subtract(expiretime, &i, &when);
13938 if (result != ISC_R_SUCCESS) {
13939 return;
13940 }
13941
13942 result = ISC_R_FAILURE;
13943 if (zone->journal != NULL) {
13944 result = isc_file_settime(zone->journal, &when);
13945 }
13946 if (result == ISC_R_SUCCESS &&
13947 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
13948 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
13949 {
13950 result = isc_file_settime(zone->masterfile, &when);
13951 } else if (result != ISC_R_SUCCESS) {
13952 result = isc_file_settime(zone->masterfile, &when);
13953 }
13954
13955 /*
13956 * Someone removed the file from underneath us!
13957 */
13958 if (result == ISC_R_FILENOTFOUND) {
13959 zone_needdump(zone, DNS_DUMP_DELAY);
13960 } else if (result != ISC_R_SUCCESS) {
13961 dns_zone_log(zone, ISC_LOG_ERROR,
13962 "refresh: could not set "
13963 "file modification time of '%s': %s",
13964 zone->masterfile, dns_result_totext(result));
13965 }
13966 }
13967
13968 /*
13969 * An SOA query has finished (successfully or not).
13970 */
13971 static void
13972 refresh_callback(isc_task_t *task, isc_event_t *event) {
13973 const char me[] = "refresh_callback";
13974 dns_requestevent_t *revent = (dns_requestevent_t *)event;
13975 dns_zone_t *zone;
13976 dns_message_t *msg = NULL;
13977 uint32_t soacnt, cnamecnt, soacount, nscount;
13978 isc_time_t now;
13979 char master[ISC_SOCKADDR_FORMATSIZE];
13980 char source[ISC_SOCKADDR_FORMATSIZE];
13981 dns_rdataset_t *rdataset = NULL;
13982 dns_rdata_t rdata = DNS_RDATA_INIT;
13983 dns_rdata_soa_t soa;
13984 isc_result_t result;
13985 uint32_t serial, oldserial = 0;
13986 unsigned int j;
13987 bool do_queue_xfrin = false;
13988
13989 zone = revent->ev_arg;
13990 INSIST(DNS_ZONE_VALID(zone));
13991
13992 UNUSED(task);
13993
13994 ENTER;
13995
13996 TIME_NOW(&now);
13997
13998 LOCK_ZONE(zone);
13999
14000 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
14001 isc_event_free(&event);
14002 dns_request_destroy(&zone->request);
14003 goto detach;
14004 }
14005
14006 /*
14007 * if timeout log and next master;
14008 */
14009
14010 isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
14011 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
14012
14013 if (revent->result != ISC_R_SUCCESS) {
14014 if (revent->result == ISC_R_TIMEDOUT &&
14015 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS))
14016 {
14017 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
14018 dns_zone_log(zone, ISC_LOG_DEBUG(1),
14019 "refresh: timeout retrying without EDNS "
14020 "master %s (source %s)",
14021 master, source);
14022 goto same_master;
14023 }
14024 if (revent->result == ISC_R_TIMEDOUT &&
14025 !dns_request_usedtcp(revent->request))
14026 {
14027 dns_zone_log(zone, ISC_LOG_INFO,
14028 "refresh: retry limit for "
14029 "master %s exceeded (source %s)",
14030 master, source);
14031 /* Try with slave with TCP. */
14032 if ((zone->type == dns_zone_secondary ||
14033 zone->type == dns_zone_mirror ||
14034 zone->type == dns_zone_redirect) &&
14035 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH))
14036 {
14037 if (!dns_zonemgr_unreachable(
14038 zone->zmgr, &zone->masteraddr,
14039 &zone->sourceaddr, &now))
14040 {
14041 DNS_ZONE_SETFLAG(
14042 zone,
14043 DNS_ZONEFLG_SOABEFOREAXFR);
14044 goto tcp_transfer;
14045 }
14046 dns_zone_log(zone, ISC_LOG_DEBUG(1),
14047 "refresh: skipped tcp fallback "
14048 "as master %s (source %s) is "
14049 "unreachable (cached)",
14050 master, source);
14051 }
14052 } else {
14053 dns_zone_log(zone, ISC_LOG_INFO,
14054 "refresh: failure trying master "
14055 "%s (source %s): %s",
14056 master, source,
14057 dns_result_totext(revent->result));
14058 }
14059 goto next_master;
14060 }
14061
14062 dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
14063 result = dns_request_getresponse(revent->request, msg, 0);
14064 if (result != ISC_R_SUCCESS) {
14065 dns_zone_log(zone, ISC_LOG_INFO,
14066 "refresh: failure trying master "
14067 "%s (source %s): %s",
14068 master, source, dns_result_totext(result));
14069 goto next_master;
14070 }
14071
14072 /*
14073 * Unexpected opcode.
14074 */
14075 if (msg->opcode != dns_opcode_query) {
14076 char opcode[128];
14077 isc_buffer_t rb;
14078
14079 isc_buffer_init(&rb, opcode, sizeof(opcode));
14080 (void)dns_opcode_totext(msg->opcode, &rb);
14081
14082 dns_zone_log(zone, ISC_LOG_INFO,
14083 "refresh: "
14084 "unexpected opcode (%.*s) from %s (source %s)",
14085 (int)rb.used, opcode, master, source);
14086 goto next_master;
14087 }
14088
14089 /*
14090 * Unexpected rcode.
14091 */
14092 if (msg->rcode != dns_rcode_noerror) {
14093 char rcode[128];
14094 isc_buffer_t rb;
14095
14096 isc_buffer_init(&rb, rcode, sizeof(rcode));
14097 (void)dns_rcode_totext(msg->rcode, &rb);
14098
14099 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
14100 (msg->rcode == dns_rcode_servfail ||
14101 msg->rcode == dns_rcode_notimp ||
14102 msg->rcode == dns_rcode_formerr))
14103 {
14104 dns_zone_log(zone, ISC_LOG_DEBUG(1),
14105 "refresh: rcode (%.*s) retrying without "
14106 "EDNS master %s (source %s)",
14107 (int)rb.used, rcode, master, source);
14108 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
14109 goto same_master;
14110 }
14111 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
14112 msg->rcode == dns_rcode_badvers)
14113 {
14114 dns_zone_log(zone, ISC_LOG_DEBUG(1),
14115 "refresh: rcode (%.*s) retrying without "
14116 "EDNS EXPIRE OPTION master %s (source %s)",
14117 (int)rb.used, rcode, master, source);
14118 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
14119 goto same_master;
14120 }
14121 dns_zone_log(zone, ISC_LOG_INFO,
14122 "refresh: unexpected rcode (%.*s) from "
14123 "master %s (source %s)",
14124 (int)rb.used, rcode, master, source);
14125 /*
14126 * Perhaps AXFR/IXFR is allowed even if SOA queries aren't.
14127 */
14128 if (msg->rcode == dns_rcode_refused &&
14129 (zone->type == dns_zone_secondary ||
14130 zone->type == dns_zone_mirror ||
14131 zone->type == dns_zone_redirect))
14132 {
14133 goto tcp_transfer;
14134 }
14135 goto next_master;
14136 }
14137
14138 /*
14139 * If truncated punt to zone transfer which will query again.
14140 */
14141 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
14142 if (zone->type == dns_zone_secondary ||
14143 zone->type == dns_zone_mirror ||
14144 zone->type == dns_zone_redirect)
14145 {
14146 dns_zone_log(zone, ISC_LOG_INFO,
14147 "refresh: truncated UDP answer, "
14148 "initiating TCP zone xfer "
14149 "for master %s (source %s)",
14150 master, source);
14151 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
14152 goto tcp_transfer;
14153 } else {
14154 INSIST(zone->type == dns_zone_stub);
14155 if (dns_request_usedtcp(revent->request)) {
14156 dns_zone_log(zone, ISC_LOG_INFO,
14157 "refresh: truncated TCP response "
14158 "from master %s (source %s)",
14159 master, source);
14160 goto next_master;
14161 }
14162 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
14163 goto same_master;
14164 }
14165 }
14166
14167 /*
14168 * if non-auth log and next master;
14169 */
14170 if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
14171 dns_zone_log(zone, ISC_LOG_INFO,
14172 "refresh: non-authoritative answer from "
14173 "master %s (source %s)",
14174 master, source);
14175 goto next_master;
14176 }
14177
14178 cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
14179 soacnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_soa);
14180 nscount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_ns);
14181 soacount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_soa);
14182
14183 /*
14184 * There should not be a CNAME record at top of zone.
14185 */
14186 if (cnamecnt != 0) {
14187 dns_zone_log(zone, ISC_LOG_INFO,
14188 "refresh: CNAME at top of zone "
14189 "in master %s (source %s)",
14190 master, source);
14191 goto next_master;
14192 }
14193
14194 /*
14195 * if referral log and next master;
14196 */
14197 if (soacnt == 0 && soacount == 0 && nscount != 0) {
14198 dns_zone_log(zone, ISC_LOG_INFO,
14199 "refresh: referral response "
14200 "from master %s (source %s)",
14201 master, source);
14202 goto next_master;
14203 }
14204
14205 /*
14206 * if nodata log and next master;
14207 */
14208 if (soacnt == 0 && (nscount == 0 || soacount != 0)) {
14209 dns_zone_log(zone, ISC_LOG_INFO,
14210 "refresh: NODATA response "
14211 "from master %s (source %s)",
14212 master, source);
14213 goto next_master;
14214 }
14215
14216 /*
14217 * Only one soa at top of zone.
14218 */
14219 if (soacnt != 1) {
14220 dns_zone_log(zone, ISC_LOG_INFO,
14221 "refresh: answer SOA count (%d) != 1 "
14222 "from master %s (source %s)",
14223 soacnt, master, source);
14224 goto next_master;
14225 }
14226
14227 /*
14228 * Extract serial
14229 */
14230 rdataset = NULL;
14231 result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin,
14232 dns_rdatatype_soa, dns_rdatatype_none,
14233 NULL, &rdataset);
14234 if (result != ISC_R_SUCCESS) {
14235 dns_zone_log(zone, ISC_LOG_INFO,
14236 "refresh: unable to get SOA record "
14237 "from master %s (source %s)",
14238 master, source);
14239 goto next_master;
14240 }
14241
14242 result = dns_rdataset_first(rdataset);
14243 if (result != ISC_R_SUCCESS) {
14244 dns_zone_log(zone, ISC_LOG_INFO,
14245 "refresh: dns_rdataset_first() failed");
14246 goto next_master;
14247 }
14248
14249 dns_rdataset_current(rdataset, &rdata);
14250 result = dns_rdata_tostruct(&rdata, &soa, NULL);
14251 RUNTIME_CHECK(result == ISC_R_SUCCESS);
14252
14253 serial = soa.serial;
14254 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
14255 unsigned int dbsoacount;
14256 result = zone_get_from_db(zone, zone->db, NULL, &dbsoacount,
14257 NULL, &oldserial, NULL, NULL, NULL,
14258 NULL, NULL);
14259 RUNTIME_CHECK(result == ISC_R_SUCCESS);
14260 RUNTIME_CHECK(dbsoacount > 0U);
14261 zone_debuglog(zone, me, 1, "serial: new %u, old %u", serial,
14262 oldserial);
14263 } else {
14264 zone_debuglog(zone, me, 1, "serial: new %u, old not loaded",
14265 serial);
14266 }
14267
14268 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
14269 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
14270 isc_serial_gt(serial, oldserial))
14271 {
14272 if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
14273 &zone->sourceaddr, &now))
14274 {
14275 dns_zone_log(zone, ISC_LOG_INFO,
14276 "refresh: skipping %s as master %s "
14277 "(source %s) is unreachable (cached)",
14278 (zone->type == dns_zone_secondary ||
14279 zone->type == dns_zone_mirror ||
14280 zone->type == dns_zone_redirect)
14281 ? "zone transfer"
14282 : "NS query",
14283 master, source);
14284 goto next_master;
14285 }
14286 tcp_transfer:
14287 isc_event_free(&event);
14288 dns_request_destroy(&zone->request);
14289 if (zone->type == dns_zone_secondary ||
14290 zone->type == dns_zone_mirror ||
14291 zone->type == dns_zone_redirect)
14292 {
14293 do_queue_xfrin = true;
14294 } else {
14295 INSIST(zone->type == dns_zone_stub);
14296 ns_query(zone, rdataset, NULL);
14297 }
14298 if (msg != NULL) {
14299 dns_message_detach(&msg);
14300 }
14301 } else if (isc_serial_eq(soa.serial, oldserial)) {
14302 isc_time_t expiretime;
14303 uint32_t expire;
14304
14305 /*
14306 * Compute the new expire time based on this response.
14307 */
14308 expire = zone->expire;
14309 get_edns_expire(zone, msg, &expire);
14310 DNS_ZONE_TIME_ADD(&now, expire, &expiretime);
14311
14312 /*
14313 * Has the expire time improved?
14314 */
14315 if (isc_time_compare(&expiretime, &zone->expiretime) > 0) {
14316 zone->expiretime = expiretime;
14317 if (zone->masterfile != NULL) {
14318 setmodtime(zone, &expiretime);
14319 }
14320 }
14321
14322 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
14323 zone->mastersok[zone->curmaster] = true;
14324 goto next_master;
14325 } else {
14326 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER)) {
14327 dns_zone_log(zone, ISC_LOG_INFO,
14328 "serial number (%u) "
14329 "received from master %s < ours (%u)",
14330 soa.serial, master, oldserial);
14331 } else {
14332 zone_debuglog(zone, me, 1, "ahead");
14333 }
14334 zone->mastersok[zone->curmaster] = true;
14335 goto next_master;
14336 }
14337 if (msg != NULL) {
14338 dns_message_detach(&msg);
14339 }
14340 goto detach;
14341
14342 next_master:
14343 if (msg != NULL) {
14344 dns_message_detach(&msg);
14345 }
14346 isc_event_free(&event);
14347 dns_request_destroy(&zone->request);
14348 /*
14349 * Skip to next failed / untried master.
14350 */
14351 do {
14352 zone->curmaster++;
14353 } while (zone->curmaster < zone->masterscnt &&
14354 zone->mastersok[zone->curmaster]);
14355 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
14356 if (zone->curmaster >= zone->masterscnt) {
14357 bool done = true;
14358 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
14359 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
14360 {
14361 /*
14362 * Did we get a good answer from all the primaries?
14363 */
14364 for (j = 0; j < zone->masterscnt; j++) {
14365 if (!zone->mastersok[j]) {
14366 {
14367 done = false;
14368 break;
14369 }
14370 }
14371 }
14372 } else {
14373 done = true;
14374 }
14375 if (!done) {
14376 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
14377 zone->curmaster = 0;
14378 /*
14379 * Find the next failed master.
14380 */
14381 while (zone->curmaster < zone->masterscnt &&
14382 zone->mastersok[zone->curmaster])
14383 {
14384 zone->curmaster++;
14385 }
14386 goto requeue;
14387 }
14388 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
14389 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
14390 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
14391 zone->refreshtime = now;
14392 }
14393 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
14394 zone_settimer(zone, &now);
14395 goto detach;
14396 }
14397
14398 requeue:
14399 queue_soa_query(zone);
14400 goto detach;
14401
14402 same_master:
14403 if (msg != NULL) {
14404 dns_message_detach(&msg);
14405 }
14406 isc_event_free(&event);
14407 dns_request_destroy(&zone->request);
14408 queue_soa_query(zone);
14409
14410 detach:
14411 UNLOCK_ZONE(zone);
14412 if (do_queue_xfrin) {
14413 queue_xfrin(zone);
14414 }
14415 dns_zone_idetach(&zone);
14416 return;
14417 }
14418
14419 static void
14420 queue_soa_query(dns_zone_t *zone) {
14421 const char me[] = "queue_soa_query";
14422 isc_event_t *e;
14423 dns_zone_t *dummy = NULL;
14424 isc_result_t result;
14425
14426 ENTER;
14427 /*
14428 * Locked by caller
14429 */
14430 REQUIRE(LOCKED_ZONE(zone));
14431
14432 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
14433 cancel_refresh(zone);
14434 return;
14435 }
14436
14437 e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE, soa_query,
14438 zone, sizeof(isc_event_t));
14439
14440 /*
14441 * Attach so that we won't clean up
14442 * until the event is delivered.
14443 */
14444 zone_iattach(zone, &dummy);
14445
14446 e->ev_arg = zone;
14447 e->ev_sender = NULL;
14448 result = isc_ratelimiter_enqueue(zone->zmgr->refreshrl, zone->task, &e);
14449 if (result != ISC_R_SUCCESS) {
14450 zone_idetach(&dummy);
14451 isc_event_free(&e);
14452 cancel_refresh(zone);
14453 }
14454 }
14455
14456 static void
14457 soa_query(isc_task_t *task, isc_event_t *event) {
14458 const char me[] = "soa_query";
14459 isc_result_t result = ISC_R_FAILURE;
14460 dns_message_t *message = NULL;
14461 dns_zone_t *zone = event->ev_arg;
14462 dns_zone_t *dummy = NULL;
14463 isc_netaddr_t masterip;
14464 dns_tsigkey_t *key = NULL;
14465 uint32_t options;
14466 bool cancel = true;
14467 int timeout;
14468 bool have_xfrsource, have_xfrdscp, reqnsid, reqexpire;
14469 uint16_t udpsize = SEND_BUFFER_SIZE;
14470 isc_dscp_t dscp = -1;
14471
14472 REQUIRE(DNS_ZONE_VALID(zone));
14473
14474 UNUSED(task);
14475
14476 ENTER;
14477
14478 LOCK_ZONE(zone);
14479 if (((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) ||
14480 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
14481 zone->view->requestmgr == NULL)
14482 {
14483 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
14484 cancel = false;
14485 }
14486 goto cleanup;
14487 }
14488
14489 again:
14490 result = create_query(zone, dns_rdatatype_soa, &zone->origin, &message);
14491 if (result != ISC_R_SUCCESS) {
14492 goto cleanup;
14493 }
14494
14495 INSIST(zone->masterscnt > 0);
14496 INSIST(zone->curmaster < zone->masterscnt);
14497
14498 zone->masteraddr = zone->masters[zone->curmaster];
14499
14500 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
14501 /*
14502 * First, look for a tsig key in the master statement, then
14503 * try for a server key.
14504 */
14505 if ((zone->masterkeynames != NULL) &&
14506 (zone->masterkeynames[zone->curmaster] != NULL))
14507 {
14508 dns_view_t *view = dns_zone_getview(zone);
14509 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
14510 result = dns_view_gettsig(view, keyname, &key);
14511 if (result != ISC_R_SUCCESS) {
14512 char namebuf[DNS_NAME_FORMATSIZE];
14513 dns_name_format(keyname, namebuf, sizeof(namebuf));
14514 dns_zone_log(zone, ISC_LOG_ERROR,
14515 "unable to find key: %s", namebuf);
14516 goto skip_master;
14517 }
14518 }
14519 if (key == NULL) {
14520 result = dns_view_getpeertsig(zone->view, &masterip, &key);
14521 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
14522 char addrbuf[ISC_NETADDR_FORMATSIZE];
14523 isc_netaddr_format(&masterip, addrbuf, sizeof(addrbuf));
14524 dns_zone_log(zone, ISC_LOG_ERROR,
14525 "unable to find TSIG key for %s", addrbuf);
14526 goto skip_master;
14527 }
14528 }
14529
14530 options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ? DNS_REQUESTOPT_TCP
14531 : 0;
14532 have_xfrsource = have_xfrdscp = false;
14533 reqnsid = zone->view->requestnsid;
14534 reqexpire = zone->requestexpire;
14535 if (zone->view->peers != NULL) {
14536 dns_peer_t *peer = NULL;
14537 bool edns, usetcp;
14538 result = dns_peerlist_peerbyaddr(zone->view->peers, &masterip,
14539 &peer);
14540 if (result == ISC_R_SUCCESS) {
14541 result = dns_peer_getsupportedns(peer, &edns);
14542 if (result == ISC_R_SUCCESS && !edns) {
14543 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
14544 }
14545 result = dns_peer_gettransfersource(peer,
14546 &zone->sourceaddr);
14547 if (result == ISC_R_SUCCESS) {
14548 have_xfrsource = true;
14549 }
14550 (void)dns_peer_gettransferdscp(peer, &dscp);
14551 if (dscp != -1) {
14552 have_xfrdscp = true;
14553 }
14554 if (zone->view->resolver != NULL) {
14555 udpsize = dns_resolver_getudpsize(
14556 zone->view->resolver);
14557 }
14558 (void)dns_peer_getudpsize(peer, &udpsize);
14559 (void)dns_peer_getrequestnsid(peer, &reqnsid);
14560 (void)dns_peer_getrequestexpire(peer, &reqexpire);
14561 result = dns_peer_getforcetcp(peer, &usetcp);
14562 if (result == ISC_R_SUCCESS && usetcp) {
14563 options |= DNS_REQUESTOPT_TCP;
14564 }
14565 }
14566 }
14567
14568 switch (isc_sockaddr_pf(&zone->masteraddr)) {
14569 case PF_INET:
14570 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
14571 if (isc_sockaddr_equal(&zone->altxfrsource4,
14572 &zone->xfrsource4))
14573 {
14574 goto skip_master;
14575 }
14576 zone->sourceaddr = zone->altxfrsource4;
14577 if (!have_xfrdscp) {
14578 dscp = zone->altxfrsource4dscp;
14579 }
14580 } else if (!have_xfrsource) {
14581 zone->sourceaddr = zone->xfrsource4;
14582 if (!have_xfrdscp) {
14583 dscp = zone->xfrsource4dscp;
14584 }
14585 }
14586 break;
14587 case PF_INET6:
14588 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
14589 if (isc_sockaddr_equal(&zone->altxfrsource6,
14590 &zone->xfrsource6))
14591 {
14592 goto skip_master;
14593 }
14594 zone->sourceaddr = zone->altxfrsource6;
14595 if (!have_xfrdscp) {
14596 dscp = zone->altxfrsource6dscp;
14597 }
14598 } else if (!have_xfrsource) {
14599 zone->sourceaddr = zone->xfrsource6;
14600 if (!have_xfrdscp) {
14601 dscp = zone->xfrsource6dscp;
14602 }
14603 }
14604 break;
14605 default:
14606 result = ISC_R_NOTIMPLEMENTED;
14607 goto cleanup;
14608 }
14609
14610 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
14611 result = add_opt(message, udpsize, reqnsid, reqexpire);
14612 if (result != ISC_R_SUCCESS) {
14613 zone_debuglog(zone, me, 1,
14614 "unable to add opt record: %s",
14615 dns_result_totext(result));
14616 }
14617 }
14618
14619 zone_iattach(zone, &dummy);
14620 timeout = 15;
14621 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH)) {
14622 timeout = 30;
14623 }
14624 result = dns_request_createvia(
14625 zone->view->requestmgr, message, &zone->sourceaddr,
14626 &zone->masteraddr, dscp, options, key, timeout * 3, timeout, 0,
14627 zone->task, refresh_callback, zone, &zone->request);
14628 if (result != ISC_R_SUCCESS) {
14629 zone_idetach(&dummy);
14630 zone_debuglog(zone, me, 1,
14631 "dns_request_createvia4() failed: %s",
14632 dns_result_totext(result));
14633 goto skip_master;
14634 } else {
14635 if (isc_sockaddr_pf(&zone->masteraddr) == PF_INET) {
14636 inc_stats(zone, dns_zonestatscounter_soaoutv4);
14637 } else {
14638 inc_stats(zone, dns_zonestatscounter_soaoutv6);
14639 }
14640 }
14641 cancel = false;
14642
14643 cleanup:
14644 if (key != NULL) {
14645 dns_tsigkey_detach(&key);
14646 }
14647 if (result != ISC_R_SUCCESS) {
14648 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
14649 }
14650 if (message != NULL) {
14651 dns_message_detach(&message);
14652 }
14653 if (cancel) {
14654 cancel_refresh(zone);
14655 }
14656 isc_event_free(&event);
14657 UNLOCK_ZONE(zone);
14658 dns_zone_idetach(&zone);
14659 return;
14660
14661 skip_master:
14662 if (key != NULL) {
14663 dns_tsigkey_detach(&key);
14664 }
14665 dns_message_detach(&message);
14666 /*
14667 * Skip to next failed / untried master.
14668 */
14669 do {
14670 zone->curmaster++;
14671 } while (zone->curmaster < zone->masterscnt &&
14672 zone->mastersok[zone->curmaster]);
14673 if (zone->curmaster < zone->masterscnt) {
14674 goto again;
14675 }
14676 zone->curmaster = 0;
14677 goto cleanup;
14678 }
14679
14680 static void
14681 ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
14682 const char me[] = "ns_query";
14683 isc_result_t result;
14684 dns_message_t *message = NULL;
14685 isc_netaddr_t masterip;
14686 dns_tsigkey_t *key = NULL;
14687 dns_dbnode_t *node = NULL;
14688 int timeout;
14689 bool have_xfrsource = false, have_xfrdscp = false;
14690 bool reqnsid;
14691 uint16_t udpsize = SEND_BUFFER_SIZE;
14692 isc_dscp_t dscp = -1;
14693 struct stub_cb_args *cb_args;
14694
14695 REQUIRE(DNS_ZONE_VALID(zone));
14696 REQUIRE(LOCKED_ZONE(zone));
14697 REQUIRE((soardataset != NULL && stub == NULL) ||
14698 (soardataset == NULL && stub != NULL));
14699 REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
14700
14701 ENTER;
14702
14703 if (stub == NULL) {
14704 stub = isc_mem_get(zone->mctx, sizeof(*stub));
14705 stub->magic = STUB_MAGIC;
14706 stub->mctx = zone->mctx;
14707 stub->zone = NULL;
14708 stub->db = NULL;
14709 stub->version = NULL;
14710 atomic_init(&stub->pending_requests, 0);
14711
14712 /*
14713 * Attach so that the zone won't disappear from under us.
14714 */
14715 zone_iattach(zone, &stub->zone);
14716
14717 /*
14718 * If a db exists we will update it, otherwise we create a
14719 * new one and attach it to the zone once we have the NS
14720 * RRset and glue.
14721 */
14722 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
14723 if (zone->db != NULL) {
14724 dns_db_attach(zone->db, &stub->db);
14725 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
14726 } else {
14727 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
14728
14729 INSIST(zone->db_argc >= 1);
14730 result = dns_db_create(zone->mctx, zone->db_argv[0],
14731 &zone->origin, dns_dbtype_stub,
14732 zone->rdclass, zone->db_argc - 1,
14733 zone->db_argv + 1, &stub->db);
14734 if (result != ISC_R_SUCCESS) {
14735 dns_zone_log(zone, ISC_LOG_ERROR,
14736 "refreshing stub: "
14737 "could not create "
14738 "database: %s",
14739 dns_result_totext(result));
14740 goto cleanup;
14741 }
14742 dns_db_settask(stub->db, zone->task);
14743 }
14744
14745 result = dns_db_newversion(stub->db, &stub->version);
14746 if (result != ISC_R_SUCCESS) {
14747 dns_zone_log(zone, ISC_LOG_INFO,
14748 "refreshing stub: "
14749 "dns_db_newversion() failed: %s",
14750 dns_result_totext(result));
14751 goto cleanup;
14752 }
14753
14754 /*
14755 * Update SOA record.
14756 */
14757 result = dns_db_findnode(stub->db, &zone->origin, true, &node);
14758 if (result != ISC_R_SUCCESS) {
14759 dns_zone_log(zone, ISC_LOG_INFO,
14760 "refreshing stub: "
14761 "dns_db_findnode() failed: %s",
14762 dns_result_totext(result));
14763 goto cleanup;
14764 }
14765
14766 result = dns_db_addrdataset(stub->db, node, stub->version, 0,
14767 soardataset, 0, NULL);
14768 dns_db_detachnode(stub->db, &node);
14769 if (result != ISC_R_SUCCESS) {
14770 dns_zone_log(zone, ISC_LOG_INFO,
14771 "refreshing stub: "
14772 "dns_db_addrdataset() failed: %s",
14773 dns_result_totext(result));
14774 goto cleanup;
14775 }
14776 }
14777
14778 /*
14779 * XXX Optimisation: Create message when zone is setup and reuse.
14780 */
14781 result = create_query(zone, dns_rdatatype_ns, &zone->origin, &message);
14782 INSIST(result == ISC_R_SUCCESS);
14783
14784 INSIST(zone->masterscnt > 0);
14785 INSIST(zone->curmaster < zone->masterscnt);
14786 zone->masteraddr = zone->masters[zone->curmaster];
14787
14788 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
14789 /*
14790 * First, look for a tsig key in the master statement, then
14791 * try for a server key.
14792 */
14793 if ((zone->masterkeynames != NULL) &&
14794 (zone->masterkeynames[zone->curmaster] != NULL))
14795 {
14796 dns_view_t *view = dns_zone_getview(zone);
14797 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
14798 result = dns_view_gettsig(view, keyname, &key);
14799 if (result != ISC_R_SUCCESS) {
14800 char namebuf[DNS_NAME_FORMATSIZE];
14801 dns_name_format(keyname, namebuf, sizeof(namebuf));
14802 dns_zone_log(zone, ISC_LOG_ERROR,
14803 "unable to find key: %s", namebuf);
14804 }
14805 }
14806 if (key == NULL) {
14807 (void)dns_view_getpeertsig(zone->view, &masterip, &key);
14808 }
14809
14810 reqnsid = zone->view->requestnsid;
14811 if (zone->view->peers != NULL) {
14812 dns_peer_t *peer = NULL;
14813 bool edns;
14814 result = dns_peerlist_peerbyaddr(zone->view->peers, &masterip,
14815 &peer);
14816 if (result == ISC_R_SUCCESS) {
14817 result = dns_peer_getsupportedns(peer, &edns);
14818 if (result == ISC_R_SUCCESS && !edns) {
14819 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
14820 }
14821 result = dns_peer_gettransfersource(peer,
14822 &zone->sourceaddr);
14823 if (result == ISC_R_SUCCESS) {
14824 have_xfrsource = true;
14825 }
14826 result = dns_peer_gettransferdscp(peer, &dscp);
14827 if (result == ISC_R_SUCCESS && dscp != -1) {
14828 have_xfrdscp = true;
14829 }
14830 if (zone->view->resolver != NULL) {
14831 udpsize = dns_resolver_getudpsize(
14832 zone->view->resolver);
14833 }
14834 (void)dns_peer_getudpsize(peer, &udpsize);
14835 (void)dns_peer_getrequestnsid(peer, &reqnsid);
14836 }
14837 }
14838 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
14839 result = add_opt(message, udpsize, reqnsid, false);
14840 if (result != ISC_R_SUCCESS) {
14841 zone_debuglog(zone, me, 1,
14842 "unable to add opt record: %s",
14843 dns_result_totext(result));
14844 }
14845 }
14846
14847 /*
14848 * Always use TCP so that we shouldn't truncate in additional section.
14849 */
14850 switch (isc_sockaddr_pf(&zone->masteraddr)) {
14851 case PF_INET:
14852 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
14853 zone->sourceaddr = zone->altxfrsource4;
14854 if (!have_xfrdscp) {
14855 dscp = zone->altxfrsource4dscp;
14856 }
14857 } else if (!have_xfrsource) {
14858 zone->sourceaddr = zone->xfrsource4;
14859 if (!have_xfrdscp) {
14860 dscp = zone->xfrsource4dscp;
14861 }
14862 }
14863 break;
14864 case PF_INET6:
14865 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
14866 zone->sourceaddr = zone->altxfrsource6;
14867 if (!have_xfrdscp) {
14868 dscp = zone->altxfrsource6dscp;
14869 }
14870 } else if (!have_xfrsource) {
14871 zone->sourceaddr = zone->xfrsource6;
14872 if (!have_xfrdscp) {
14873 dscp = zone->xfrsource6dscp;
14874 }
14875 }
14876 break;
14877 default:
14878 result = ISC_R_NOTIMPLEMENTED;
14879 POST(result);
14880 goto cleanup;
14881 }
14882 timeout = 15;
14883 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH)) {
14884 timeout = 30;
14885 }
14886
14887 /*
14888 * Save request parameters so we can reuse them later on
14889 * for resolving missing glue A/AAAA records.
14890 */
14891 cb_args = isc_mem_get(zone->mctx, sizeof(*cb_args));
14892 cb_args->stub = stub;
14893 cb_args->tsig_key = key;
14894 cb_args->dscp = dscp;
14895 cb_args->udpsize = udpsize;
14896 cb_args->timeout = timeout;
14897 cb_args->reqnsid = reqnsid;
14898
14899 result = dns_request_createvia(
14900 zone->view->requestmgr, message, &zone->sourceaddr,
14901 &zone->masteraddr, dscp, DNS_REQUESTOPT_TCP, key, timeout * 3,
14902 timeout, 0, zone->task, stub_callback, cb_args, &zone->request);
14903 if (result != ISC_R_SUCCESS) {
14904 zone_debuglog(zone, me, 1, "dns_request_createvia() failed: %s",
14905 dns_result_totext(result));
14906 goto cleanup;
14907 }
14908 dns_message_detach(&message);
14909 goto unlock;
14910
14911 cleanup:
14912 cancel_refresh(zone);
14913 stub->magic = 0;
14914 if (stub->version != NULL) {
14915 dns_db_closeversion(stub->db, &stub->version, false);
14916 }
14917 if (stub->db != NULL) {
14918 dns_db_detach(&stub->db);
14919 }
14920 if (stub->zone != NULL) {
14921 zone_idetach(&stub->zone);
14922 }
14923 isc_mem_put(stub->mctx, stub, sizeof(*stub));
14924 if (message != NULL) {
14925 dns_message_detach(&message);
14926 }
14927 unlock:
14928 if (key != NULL) {
14929 dns_tsigkey_detach(&key);
14930 }
14931 return;
14932 }
14933
14934 /*
14935 * Shut the zone down.
14936 */
14937 static void
14938 zone_shutdown(isc_task_t *task, isc_event_t *event) {
14939 dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
14940 bool free_needed, linked = false;
14941 dns_zone_t *raw = NULL, *secure = NULL;
14942
14943 UNUSED(task);
14944 REQUIRE(DNS_ZONE_VALID(zone));
14945 INSIST(event->ev_type == DNS_EVENT_ZONECONTROL);
14946 INSIST(isc_refcount_current(&zone->erefs) == 0);
14947
14948 zone_debuglog(zone, "zone_shutdown", 3, "shutting down");
14949
14950 /*
14951 * If we were waiting for xfrin quota, step out of
14952 * the queue.
14953 * If there's no zone manager, we can't be waiting for the
14954 * xfrin quota
14955 */
14956 if (zone->zmgr != NULL) {
14957 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
14958 if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
14959 ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone,
14960 statelink);
14961 linked = true;
14962 zone->statelist = NULL;
14963 }
14964 if (zone->statelist == &zone->zmgr->xfrin_in_progress) {
14965 ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone,
14966 statelink);
14967 zone->statelist = NULL;
14968 zmgr_resume_xfrs(zone->zmgr, false);
14969 }
14970 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
14971 }
14972
14973 /*
14974 * In task context, no locking required. See zone_xfrdone().
14975 */
14976 if (zone->xfr != NULL) {
14977 dns_xfrin_shutdown(zone->xfr);
14978 }
14979
14980 /* Safe to release the zone now */
14981 if (zone->zmgr != NULL) {
14982 dns_zonemgr_releasezone(zone->zmgr, zone);
14983 }
14984
14985 LOCK_ZONE(zone);
14986 INSIST(zone != zone->raw);
14987 if (linked) {
14988 isc_refcount_decrement(&zone->irefs);
14989 }
14990 if (zone->request != NULL) {
14991 dns_request_cancel(zone->request);
14992 }
14993
14994 if (zone->readio != NULL) {
14995 zonemgr_cancelio(zone->readio);
14996 }
14997
14998 if (zone->lctx != NULL) {
14999 dns_loadctx_cancel(zone->lctx);
15000 }
15001
15002 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
15003 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
15004 {
15005 if (zone->writeio != NULL) {
15006 zonemgr_cancelio(zone->writeio);
15007 }
15008
15009 if (zone->dctx != NULL) {
15010 dns_dumpctx_cancel(zone->dctx);
15011 }
15012 }
15013
15014 checkds_cancel(zone);
15015
15016 notify_cancel(zone);
15017
15018 forward_cancel(zone);
15019
15020 if (zone->timer != NULL) {
15021 isc_timer_detach(&zone->timer);
15022 isc_refcount_decrement(&zone->irefs);
15023 }
15024
15025 /*
15026 * We have now canceled everything set the flag to allow exit_check()
15027 * to succeed. We must not unlock between setting this flag and
15028 * calling exit_check().
15029 */
15030 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN);
15031 free_needed = exit_check(zone);
15032 /*
15033 * If a dump is in progress for the secure zone, defer detaching from
15034 * the raw zone as it may prevent the unsigned serial number from being
15035 * stored in the raw-format dump of the secure zone. In this scenario,
15036 * dump_done() takes care of cleaning up the zone->raw reference.
15037 */
15038 if (inline_secure(zone) && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
15039 raw = zone->raw;
15040 zone->raw = NULL;
15041 }
15042 if (inline_raw(zone)) {
15043 secure = zone->secure;
15044 zone->secure = NULL;
15045 }
15046 UNLOCK_ZONE(zone);
15047 if (raw != NULL) {
15048 dns_zone_detach(&raw);
15049 }
15050 if (secure != NULL) {
15051 dns_zone_idetach(&secure);
15052 }
15053 if (free_needed) {
15054 zone_free(zone);
15055 }
15056 }
15057
15058 static void
15059 zone_timer(isc_task_t *task, isc_event_t *event) {
15060 const char me[] = "zone_timer";
15061 dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
15062
15063 UNUSED(task);
15064 REQUIRE(DNS_ZONE_VALID(zone));
15065
15066 ENTER;
15067
15068 zone_maintenance(zone);
15069
15070 isc_event_free(&event);
15071 }
15072
15073 static void
15074 zone_settimer(dns_zone_t *zone, isc_time_t *now) {
15075 const char me[] = "zone_settimer";
15076 isc_time_t next;
15077 isc_result_t result;
15078
15079 REQUIRE(DNS_ZONE_VALID(zone));
15080 REQUIRE(LOCKED_ZONE(zone));
15081 ENTER;
15082
15083 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
15084 return;
15085 }
15086
15087 isc_time_settoepoch(&next);
15088
15089 switch (zone->type) {
15090 case dns_zone_redirect:
15091 if (zone->masters != NULL) {
15092 goto treat_as_slave;
15093 }
15094 FALLTHROUGH;
15095 case dns_zone_primary:
15096 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
15097 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))
15098 {
15099 next = zone->notifytime;
15100 }
15101 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
15102 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
15103 {
15104 INSIST(!isc_time_isepoch(&zone->dumptime));
15105 if (isc_time_isepoch(&next) ||
15106 isc_time_compare(&zone->dumptime, &next) < 0)
15107 {
15108 next = zone->dumptime;
15109 }
15110 }
15111 if (zone->type == dns_zone_redirect) {
15112 break;
15113 }
15114 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING) &&
15115 !isc_time_isepoch(&zone->refreshkeytime))
15116 {
15117 if (isc_time_isepoch(&next) ||
15118 isc_time_compare(&zone->refreshkeytime, &next) < 0)
15119 {
15120 next = zone->refreshkeytime;
15121 }
15122 }
15123 if (!isc_time_isepoch(&zone->resigntime)) {
15124 if (isc_time_isepoch(&next) ||
15125 isc_time_compare(&zone->resigntime, &next) < 0)
15126 {
15127 next = zone->resigntime;
15128 }
15129 }
15130 if (!isc_time_isepoch(&zone->keywarntime)) {
15131 if (isc_time_isepoch(&next) ||
15132 isc_time_compare(&zone->keywarntime, &next) < 0)
15133 {
15134 next = zone->keywarntime;
15135 }
15136 }
15137 if (!isc_time_isepoch(&zone->signingtime)) {
15138 if (isc_time_isepoch(&next) ||
15139 isc_time_compare(&zone->signingtime, &next) < 0)
15140 {
15141 next = zone->signingtime;
15142 }
15143 }
15144 if (!isc_time_isepoch(&zone->nsec3chaintime)) {
15145 if (isc_time_isepoch(&next) ||
15146 isc_time_compare(&zone->nsec3chaintime, &next) < 0)
15147 {
15148 next = zone->nsec3chaintime;
15149 }
15150 }
15151 break;
15152
15153 case dns_zone_secondary:
15154 case dns_zone_mirror:
15155 treat_as_slave:
15156 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
15157 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))
15158 {
15159 next = zone->notifytime;
15160 }
15161 FALLTHROUGH;
15162 case dns_zone_stub:
15163 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) &&
15164 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOMASTERS) &&
15165 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH) &&
15166 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING) &&
15167 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING) &&
15168 !isc_time_isepoch(&zone->refreshtime) &&
15169 (isc_time_isepoch(&next) ||
15170 isc_time_compare(&zone->refreshtime, &next) < 0))
15171 {
15172 next = zone->refreshtime;
15173 }
15174 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
15175 !isc_time_isepoch(&zone->expiretime))
15176 {
15177 if (isc_time_isepoch(&next) ||
15178 isc_time_compare(&zone->expiretime, &next) < 0)
15179 {
15180 next = zone->expiretime;
15181 }
15182 }
15183 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
15184 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
15185 {
15186 INSIST(!isc_time_isepoch(&zone->dumptime));
15187 if (isc_time_isepoch(&next) ||
15188 isc_time_compare(&zone->dumptime, &next) < 0)
15189 {
15190 next = zone->dumptime;
15191 }
15192 }
15193 break;
15194
15195 case dns_zone_key:
15196 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
15197 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
15198 {
15199 INSIST(!isc_time_isepoch(&zone->dumptime));
15200 if (isc_time_isepoch(&next) ||
15201 isc_time_compare(&zone->dumptime, &next) < 0)
15202 {
15203 next = zone->dumptime;
15204 }
15205 }
15206 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
15207 if (isc_time_isepoch(&next) ||
15208 (!isc_time_isepoch(&zone->refreshkeytime) &&
15209 isc_time_compare(&zone->refreshkeytime, &next) <
15210 0))
15211 {
15212 next = zone->refreshkeytime;
15213 }
15214 }
15215 break;
15216
15217 default:
15218 break;
15219 }
15220
15221 if (isc_time_isepoch(&next)) {
15222 zone_debuglog(zone, me, 10, "settimer inactive");
15223 result = isc_timer_reset(zone->timer, isc_timertype_inactive,
15224 NULL, NULL, true);
15225 if (result != ISC_R_SUCCESS) {
15226 dns_zone_log(zone, ISC_LOG_ERROR,
15227 "could not deactivate zone timer: %s",
15228 isc_result_totext(result));
15229 }
15230 } else {
15231 if (isc_time_compare(&next, now) <= 0) {
15232 next = *now;
15233 }
15234 result = isc_timer_reset(zone->timer, isc_timertype_once, &next,
15235 NULL, true);
15236 if (result != ISC_R_SUCCESS) {
15237 dns_zone_log(zone, ISC_LOG_ERROR,
15238 "could not reset zone timer: %s",
15239 isc_result_totext(result));
15240 }
15241 }
15242 }
15243
15244 static void
15245 cancel_refresh(dns_zone_t *zone) {
15246 const char me[] = "cancel_refresh";
15247 isc_time_t now;
15248
15249 /*
15250 * 'zone' locked by caller.
15251 */
15252
15253 REQUIRE(DNS_ZONE_VALID(zone));
15254 REQUIRE(LOCKED_ZONE(zone));
15255
15256 ENTER;
15257
15258 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
15259 TIME_NOW(&now);
15260 zone_settimer(zone, &now);
15261 }
15262
15263 static isc_result_t
15264 notify_createmessage(dns_zone_t *zone, unsigned int flags,
15265 dns_message_t **messagep) {
15266 dns_db_t *zonedb = NULL;
15267 dns_dbnode_t *node = NULL;
15268 dns_dbversion_t *version = NULL;
15269 dns_message_t *message = NULL;
15270 dns_rdataset_t rdataset;
15271 dns_rdata_t rdata = DNS_RDATA_INIT;
15272
15273 dns_name_t *tempname = NULL;
15274 dns_rdata_t *temprdata = NULL;
15275 dns_rdatalist_t *temprdatalist = NULL;
15276 dns_rdataset_t *temprdataset = NULL;
15277
15278 isc_result_t result;
15279 isc_region_t r;
15280 isc_buffer_t *b = NULL;
15281
15282 REQUIRE(DNS_ZONE_VALID(zone));
15283 REQUIRE(messagep != NULL && *messagep == NULL);
15284
15285 dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER, &message);
15286
15287 message->opcode = dns_opcode_notify;
15288 message->flags |= DNS_MESSAGEFLAG_AA;
15289 message->rdclass = zone->rdclass;
15290
15291 result = dns_message_gettempname(message, &tempname);
15292 if (result != ISC_R_SUCCESS) {
15293 goto cleanup;
15294 }
15295
15296 result = dns_message_gettemprdataset(message, &temprdataset);
15297 if (result != ISC_R_SUCCESS) {
15298 goto cleanup;
15299 }
15300
15301 /*
15302 * Make question.
15303 */
15304 dns_name_clone(&zone->origin, tempname);
15305 dns_rdataset_makequestion(temprdataset, zone->rdclass,
15306 dns_rdatatype_soa);
15307 ISC_LIST_APPEND(tempname->list, temprdataset, link);
15308 dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
15309 tempname = NULL;
15310 temprdataset = NULL;
15311
15312 if ((flags & DNS_NOTIFY_NOSOA) != 0) {
15313 goto done;
15314 }
15315
15316 result = dns_message_gettempname(message, &tempname);
15317 if (result != ISC_R_SUCCESS) {
15318 goto soa_cleanup;
15319 }
15320 result = dns_message_gettemprdata(message, &temprdata);
15321 if (result != ISC_R_SUCCESS) {
15322 goto soa_cleanup;
15323 }
15324 result = dns_message_gettemprdataset(message, &temprdataset);
15325 if (result != ISC_R_SUCCESS) {
15326 goto soa_cleanup;
15327 }
15328 result = dns_message_gettemprdatalist(message, &temprdatalist);
15329 if (result != ISC_R_SUCCESS) {
15330 goto soa_cleanup;
15331 }
15332
15333 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
15334 INSIST(zone->db != NULL); /* XXXJT: is this assumption correct? */
15335 dns_db_attach(zone->db, &zonedb);
15336 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
15337
15338 dns_name_clone(&zone->origin, tempname);
15339 dns_db_currentversion(zonedb, &version);
15340 result = dns_db_findnode(zonedb, tempname, false, &node);
15341 if (result != ISC_R_SUCCESS) {
15342 goto soa_cleanup;
15343 }
15344
15345 dns_rdataset_init(&rdataset);
15346 result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
15347 dns_rdatatype_none, 0, &rdataset, NULL);
15348 if (result != ISC_R_SUCCESS) {
15349 goto soa_cleanup;
15350 }
15351 result = dns_rdataset_first(&rdataset);
15352 if (result != ISC_R_SUCCESS) {
15353 goto soa_cleanup;
15354 }
15355 dns_rdataset_current(&rdataset, &rdata);
15356 dns_rdata_toregion(&rdata, &r);
15357 isc_buffer_allocate(zone->mctx, &b, r.length);
15358 isc_buffer_putmem(b, r.base, r.length);
15359 isc_buffer_usedregion(b, &r);
15360 dns_rdata_init(temprdata);
15361 dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r);
15362 dns_message_takebuffer(message, &b);
15363 result = dns_rdataset_next(&rdataset);
15364 dns_rdataset_disassociate(&rdataset);
15365 if (result != ISC_R_NOMORE) {
15366 goto soa_cleanup;
15367 }
15368 temprdatalist->rdclass = rdata.rdclass;
15369 temprdatalist->type = rdata.type;
15370 temprdatalist->ttl = rdataset.ttl;
15371 ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link);
15372
15373 result = dns_rdatalist_tordataset(temprdatalist, temprdataset);
15374 if (result != ISC_R_SUCCESS) {
15375 goto soa_cleanup;
15376 }
15377
15378 ISC_LIST_APPEND(tempname->list, temprdataset, link);
15379 dns_message_addname(message, tempname, DNS_SECTION_ANSWER);
15380 temprdatalist = NULL;
15381 temprdataset = NULL;
15382 temprdata = NULL;
15383 tempname = NULL;
15384
15385 soa_cleanup:
15386 if (node != NULL) {
15387 dns_db_detachnode(zonedb, &node);
15388 }
15389 if (version != NULL) {
15390 dns_db_closeversion(zonedb, &version, false);
15391 }
15392 if (zonedb != NULL) {
15393 dns_db_detach(&zonedb);
15394 }
15395 if (tempname != NULL) {
15396 dns_message_puttempname(message, &tempname);
15397 }
15398 if (temprdata != NULL) {
15399 dns_message_puttemprdata(message, &temprdata);
15400 }
15401 if (temprdataset != NULL) {
15402 dns_message_puttemprdataset(message, &temprdataset);
15403 }
15404 if (temprdatalist != NULL) {
15405 dns_message_puttemprdatalist(message, &temprdatalist);
15406 }
15407
15408 done:
15409 *messagep = message;
15410 return (ISC_R_SUCCESS);
15411
15412 cleanup:
15413 if (tempname != NULL) {
15414 dns_message_puttempname(message, &tempname);
15415 }
15416 if (temprdataset != NULL) {
15417 dns_message_puttemprdataset(message, &temprdataset);
15418 }
15419 dns_message_detach(&message);
15420 return (result);
15421 }
15422
15423 isc_result_t
15424 dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
15425 isc_sockaddr_t *to, dns_message_t *msg) {
15426 unsigned int i;
15427 dns_rdata_soa_t soa;
15428 dns_rdataset_t *rdataset = NULL;
15429 dns_rdata_t rdata = DNS_RDATA_INIT;
15430 isc_result_t result;
15431 char fromtext[ISC_SOCKADDR_FORMATSIZE];
15432 int match = 0;
15433 isc_netaddr_t netaddr;
15434 uint32_t serial = 0;
15435 bool have_serial = false;
15436 dns_tsigkey_t *tsigkey;
15437 const dns_name_t *tsig;
15438
15439 REQUIRE(DNS_ZONE_VALID(zone));
15440
15441 /*
15442 * If type != T_SOA return DNS_R_NOTIMP. We don't yet support
15443 * ROLLOVER.
15444 *
15445 * SOA: RFC1996
15446 * Check that 'from' is a valid notify source, (zone->masters).
15447 * Return DNS_R_REFUSED if not.
15448 *
15449 * If the notify message contains a serial number check it
15450 * against the zones serial and return if <= current serial
15451 *
15452 * If a refresh check is progress, if so just record the
15453 * fact we received a NOTIFY and from where and return.
15454 * We will perform a new refresh check when the current one
15455 * completes. Return ISC_R_SUCCESS.
15456 *
15457 * Otherwise initiate a refresh check using 'from' as the
15458 * first address to check. Return ISC_R_SUCCESS.
15459 */
15460
15461 isc_sockaddr_format(from, fromtext, sizeof(fromtext));
15462
15463 /*
15464 * Notify messages are processed by the raw zone.
15465 */
15466 LOCK_ZONE(zone);
15467 INSIST(zone != zone->raw);
15468 if (inline_secure(zone)) {
15469 result = dns_zone_notifyreceive(zone->raw, from, to, msg);
15470 UNLOCK_ZONE(zone);
15471 return (result);
15472 }
15473 /*
15474 * We only handle NOTIFY (SOA) at the present.
15475 */
15476 if (isc_sockaddr_pf(from) == PF_INET) {
15477 inc_stats(zone, dns_zonestatscounter_notifyinv4);
15478 } else {
15479 inc_stats(zone, dns_zonestatscounter_notifyinv6);
15480 }
15481 if (msg->counts[DNS_SECTION_QUESTION] == 0 ||
15482 dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin,
15483 dns_rdatatype_soa, dns_rdatatype_none, NULL,
15484 NULL) != ISC_R_SUCCESS)
15485 {
15486 UNLOCK_ZONE(zone);
15487 if (msg->counts[DNS_SECTION_QUESTION] == 0) {
15488 dns_zone_log(zone, ISC_LOG_NOTICE,
15489 "NOTIFY with no "
15490 "question section from: %s",
15491 fromtext);
15492 return (DNS_R_FORMERR);
15493 }
15494 dns_zone_log(zone, ISC_LOG_NOTICE,
15495 "NOTIFY zone does not match");
15496 return (DNS_R_NOTIMP);
15497 }
15498
15499 /*
15500 * If we are a master zone just succeed.
15501 */
15502 if (zone->type == dns_zone_primary) {
15503 UNLOCK_ZONE(zone);
15504 return (ISC_R_SUCCESS);
15505 }
15506
15507 isc_netaddr_fromsockaddr(&netaddr, from);
15508 for (i = 0; i < zone->masterscnt; i++) {
15509 if (isc_sockaddr_eqaddr(from, &zone->masters[i])) {
15510 break;
15511 }
15512 if (zone->view->aclenv.match_mapped &&
15513 IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) &&
15514 isc_sockaddr_pf(&zone->masters[i]) == AF_INET)
15515 {
15516 isc_netaddr_t na1, na2;
15517 isc_netaddr_fromv4mapped(&na1, &netaddr);
15518 isc_netaddr_fromsockaddr(&na2, &zone->masters[i]);
15519 if (isc_netaddr_equal(&na1, &na2)) {
15520 break;
15521 }
15522 }
15523 }
15524
15525 /*
15526 * Accept notify requests from non masters if they are on
15527 * 'zone->notify_acl'.
15528 */
15529 tsigkey = dns_message_gettsigkey(msg);
15530 tsig = dns_tsigkey_identity(tsigkey);
15531 if (i >= zone->masterscnt && zone->notify_acl != NULL &&
15532 (dns_acl_match(&netaddr, tsig, zone->notify_acl,
15533 &zone->view->aclenv, &match,
15534 NULL) == ISC_R_SUCCESS) &&
15535 match > 0)
15536 {
15537 /* Accept notify. */
15538 } else if (i >= zone->masterscnt) {
15539 UNLOCK_ZONE(zone);
15540 dns_zone_log(zone, ISC_LOG_INFO,
15541 "refused notify from non-master: %s", fromtext);
15542 inc_stats(zone, dns_zonestatscounter_notifyrej);
15543 return (DNS_R_REFUSED);
15544 }
15545
15546 /*
15547 * If the zone is loaded and there are answers check the serial
15548 * to see if we need to do a refresh. Do not worry about this
15549 * check if we are a dialup zone as we use the notify request
15550 * to trigger a refresh check.
15551 */
15552 if (msg->counts[DNS_SECTION_ANSWER] > 0 &&
15553 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
15554 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH))
15555 {
15556 result = dns_message_findname(
15557 msg, DNS_SECTION_ANSWER, &zone->origin,
15558 dns_rdatatype_soa, dns_rdatatype_none, NULL, &rdataset);
15559 if (result == ISC_R_SUCCESS) {
15560 result = dns_rdataset_first(rdataset);
15561 }
15562 if (result == ISC_R_SUCCESS) {
15563 uint32_t oldserial;
15564 unsigned int soacount;
15565
15566 dns_rdataset_current(rdataset, &rdata);
15567 result = dns_rdata_tostruct(&rdata, &soa, NULL);
15568 RUNTIME_CHECK(result == ISC_R_SUCCESS);
15569 serial = soa.serial;
15570 have_serial = true;
15571 /*
15572 * The following should safely be performed without DB
15573 * lock and succeed in this context.
15574 */
15575 result = zone_get_from_db(zone, zone->db, NULL,
15576 &soacount, NULL, &oldserial,
15577 NULL, NULL, NULL, NULL, NULL);
15578 RUNTIME_CHECK(result == ISC_R_SUCCESS);
15579 RUNTIME_CHECK(soacount > 0U);
15580 if (isc_serial_le(serial, oldserial)) {
15581 dns_zone_log(zone, ISC_LOG_INFO,
15582 "notify from %s: "
15583 "zone is up to date",
15584 fromtext);
15585 UNLOCK_ZONE(zone);
15586 return (ISC_R_SUCCESS);
15587 }
15588 }
15589 }
15590
15591 /*
15592 * If we got this far and there was a refresh in progress just
15593 * let it complete. Record where we got the notify from so we
15594 * can perform a refresh check when the current one completes
15595 */
15596 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
15597 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
15598 zone->notifyfrom = *from;
15599 UNLOCK_ZONE(zone);
15600 if (have_serial) {
15601 dns_zone_log(zone, ISC_LOG_INFO,
15602 "notify from %s: serial %u: refresh in "
15603 "progress, refresh check queued",
15604 fromtext, serial);
15605 } else {
15606 dns_zone_log(zone, ISC_LOG_INFO,
15607 "notify from %s: refresh in progress, "
15608 "refresh check queued",
15609 fromtext);
15610 }
15611 return (ISC_R_SUCCESS);
15612 }
15613 if (have_serial) {
15614 dns_zone_log(zone, ISC_LOG_INFO, "notify from %s: serial %u",
15615 fromtext, serial);
15616 } else {
15617 dns_zone_log(zone, ISC_LOG_INFO, "notify from %s: no serial",
15618 fromtext);
15619 }
15620 zone->notifyfrom = *from;
15621 UNLOCK_ZONE(zone);
15622
15623 if (to != NULL) {
15624 dns_zonemgr_unreachabledel(zone->zmgr, from, to);
15625 }
15626 dns_zone_refresh(zone);
15627 return (ISC_R_SUCCESS);
15628 }
15629
15630 void
15631 dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
15632 REQUIRE(DNS_ZONE_VALID(zone));
15633
15634 LOCK_ZONE(zone);
15635 if (zone->notify_acl != NULL) {
15636 dns_acl_detach(&zone->notify_acl);
15637 }
15638 dns_acl_attach(acl, &zone->notify_acl);
15639 UNLOCK_ZONE(zone);
15640 }
15641
15642 void
15643 dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
15644 REQUIRE(DNS_ZONE_VALID(zone));
15645
15646 LOCK_ZONE(zone);
15647 if (zone->query_acl != NULL) {
15648 dns_acl_detach(&zone->query_acl);
15649 }
15650 dns_acl_attach(acl, &zone->query_acl);
15651 UNLOCK_ZONE(zone);
15652 }
15653
15654 void
15655 dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl) {
15656 REQUIRE(DNS_ZONE_VALID(zone));
15657
15658 LOCK_ZONE(zone);
15659 if (zone->queryon_acl != NULL) {
15660 dns_acl_detach(&zone->queryon_acl);
15661 }
15662 dns_acl_attach(acl, &zone->queryon_acl);
15663 UNLOCK_ZONE(zone);
15664 }
15665
15666 void
15667 dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
15668 REQUIRE(DNS_ZONE_VALID(zone));
15669
15670 LOCK_ZONE(zone);
15671 if (zone->update_acl != NULL) {
15672 dns_acl_detach(&zone->update_acl);
15673 }
15674 dns_acl_attach(acl, &zone->update_acl);
15675 UNLOCK_ZONE(zone);
15676 }
15677
15678 void
15679 dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
15680 REQUIRE(DNS_ZONE_VALID(zone));
15681
15682 LOCK_ZONE(zone);
15683 if (zone->forward_acl != NULL) {
15684 dns_acl_detach(&zone->forward_acl);
15685 }
15686 dns_acl_attach(acl, &zone->forward_acl);
15687 UNLOCK_ZONE(zone);
15688 }
15689
15690 void
15691 dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
15692 REQUIRE(DNS_ZONE_VALID(zone));
15693
15694 LOCK_ZONE(zone);
15695 if (zone->xfr_acl != NULL) {
15696 dns_acl_detach(&zone->xfr_acl);
15697 }
15698 dns_acl_attach(acl, &zone->xfr_acl);
15699 UNLOCK_ZONE(zone);
15700 }
15701
15702 dns_acl_t *
15703 dns_zone_getnotifyacl(dns_zone_t *zone) {
15704 REQUIRE(DNS_ZONE_VALID(zone));
15705
15706 return (zone->notify_acl);
15707 }
15708
15709 dns_acl_t *
15710 dns_zone_getqueryacl(dns_zone_t *zone) {
15711 REQUIRE(DNS_ZONE_VALID(zone));
15712
15713 return (zone->query_acl);
15714 }
15715
15716 dns_acl_t *
15717 dns_zone_getqueryonacl(dns_zone_t *zone) {
15718 REQUIRE(DNS_ZONE_VALID(zone));
15719
15720 return (zone->queryon_acl);
15721 }
15722
15723 dns_acl_t *
15724 dns_zone_getupdateacl(dns_zone_t *zone) {
15725 REQUIRE(DNS_ZONE_VALID(zone));
15726
15727 return (zone->update_acl);
15728 }
15729
15730 dns_acl_t *
15731 dns_zone_getforwardacl(dns_zone_t *zone) {
15732 REQUIRE(DNS_ZONE_VALID(zone));
15733
15734 return (zone->forward_acl);
15735 }
15736
15737 dns_acl_t *
15738 dns_zone_getxfracl(dns_zone_t *zone) {
15739 REQUIRE(DNS_ZONE_VALID(zone));
15740
15741 return (zone->xfr_acl);
15742 }
15743
15744 void
15745 dns_zone_clearupdateacl(dns_zone_t *zone) {
15746 REQUIRE(DNS_ZONE_VALID(zone));
15747
15748 LOCK_ZONE(zone);
15749 if (zone->update_acl != NULL) {
15750 dns_acl_detach(&zone->update_acl);
15751 }
15752 UNLOCK_ZONE(zone);
15753 }
15754
15755 void
15756 dns_zone_clearforwardacl(dns_zone_t *zone) {
15757 REQUIRE(DNS_ZONE_VALID(zone));
15758
15759 LOCK_ZONE(zone);
15760 if (zone->forward_acl != NULL) {
15761 dns_acl_detach(&zone->forward_acl);
15762 }
15763 UNLOCK_ZONE(zone);
15764 }
15765
15766 void
15767 dns_zone_clearnotifyacl(dns_zone_t *zone) {
15768 REQUIRE(DNS_ZONE_VALID(zone));
15769
15770 LOCK_ZONE(zone);
15771 if (zone->notify_acl != NULL) {
15772 dns_acl_detach(&zone->notify_acl);
15773 }
15774 UNLOCK_ZONE(zone);
15775 }
15776
15777 void
15778 dns_zone_clearqueryacl(dns_zone_t *zone) {
15779 REQUIRE(DNS_ZONE_VALID(zone));
15780
15781 LOCK_ZONE(zone);
15782 if (zone->query_acl != NULL) {
15783 dns_acl_detach(&zone->query_acl);
15784 }
15785 UNLOCK_ZONE(zone);
15786 }
15787
15788 void
15789 dns_zone_clearqueryonacl(dns_zone_t *zone) {
15790 REQUIRE(DNS_ZONE_VALID(zone));
15791
15792 LOCK_ZONE(zone);
15793 if (zone->queryon_acl != NULL) {
15794 dns_acl_detach(&zone->queryon_acl);
15795 }
15796 UNLOCK_ZONE(zone);
15797 }
15798
15799 void
15800 dns_zone_clearxfracl(dns_zone_t *zone) {
15801 REQUIRE(DNS_ZONE_VALID(zone));
15802
15803 LOCK_ZONE(zone);
15804 if (zone->xfr_acl != NULL) {
15805 dns_acl_detach(&zone->xfr_acl);
15806 }
15807 UNLOCK_ZONE(zone);
15808 }
15809
15810 bool
15811 dns_zone_getupdatedisabled(dns_zone_t *zone) {
15812 REQUIRE(DNS_ZONE_VALID(zone));
15813 return (zone->update_disabled);
15814 }
15815
15816 void
15817 dns_zone_setupdatedisabled(dns_zone_t *zone, bool state) {
15818 REQUIRE(DNS_ZONE_VALID(zone));
15819 zone->update_disabled = state;
15820 }
15821
15822 bool
15823 dns_zone_getzeronosoattl(dns_zone_t *zone) {
15824 REQUIRE(DNS_ZONE_VALID(zone));
15825 return (zone->zero_no_soa_ttl);
15826 }
15827
15828 void
15829 dns_zone_setzeronosoattl(dns_zone_t *zone, bool state) {
15830 REQUIRE(DNS_ZONE_VALID(zone));
15831 zone->zero_no_soa_ttl = state;
15832 }
15833
15834 void
15835 dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
15836 REQUIRE(DNS_ZONE_VALID(zone));
15837
15838 zone->check_names = severity;
15839 }
15840
15841 dns_severity_t
15842 dns_zone_getchecknames(dns_zone_t *zone) {
15843 REQUIRE(DNS_ZONE_VALID(zone));
15844
15845 return (zone->check_names);
15846 }
15847
15848 void
15849 dns_zone_setjournalsize(dns_zone_t *zone, int32_t size) {
15850 REQUIRE(DNS_ZONE_VALID(zone));
15851
15852 zone->journalsize = size;
15853 }
15854
15855 int32_t
15856 dns_zone_getjournalsize(dns_zone_t *zone) {
15857 REQUIRE(DNS_ZONE_VALID(zone));
15858
15859 return (zone->journalsize);
15860 }
15861
15862 static void
15863 zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) {
15864 isc_result_t result = ISC_R_FAILURE;
15865 isc_buffer_t buffer;
15866
15867 REQUIRE(buf != NULL);
15868 REQUIRE(length > 1U);
15869
15870 /*
15871 * Leave space for terminating '\0'.
15872 */
15873 isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
15874 if (zone->type != dns_zone_redirect && zone->type != dns_zone_key) {
15875 if (dns_name_dynamic(&zone->origin)) {
15876 result = dns_name_totext(&zone->origin, true, &buffer);
15877 }
15878 if (result != ISC_R_SUCCESS &&
15879 isc_buffer_availablelength(&buffer) >=
15880 (sizeof("<UNKNOWN>") - 1))
15881 {
15882 isc_buffer_putstr(&buffer, "<UNKNOWN>");
15883 }
15884
15885 if (isc_buffer_availablelength(&buffer) > 0) {
15886 isc_buffer_putstr(&buffer, "/");
15887 }
15888 (void)dns_rdataclass_totext(zone->rdclass, &buffer);
15889 }
15890
15891 if (zone->view != NULL && strcmp(zone->view->name, "_bind") != 0 &&
15892 strcmp(zone->view->name, "_default") != 0 &&
15893 strlen(zone->view->name) < isc_buffer_availablelength(&buffer))
15894 {
15895 isc_buffer_putstr(&buffer, "/");
15896 isc_buffer_putstr(&buffer, zone->view->name);
15897 }
15898 if (inline_secure(zone) && 9U < isc_buffer_availablelength(&buffer)) {
15899 isc_buffer_putstr(&buffer, " (signed)");
15900 }
15901 if (inline_raw(zone) && 11U < isc_buffer_availablelength(&buffer)) {
15902 isc_buffer_putstr(&buffer, " (unsigned)");
15903 }
15904
15905 buf[isc_buffer_usedlength(&buffer)] = '\0';
15906 }
15907
15908 static void
15909 zone_name_tostr(dns_zone_t *zone, char *buf, size_t length) {
15910 isc_result_t result = ISC_R_FAILURE;
15911 isc_buffer_t buffer;
15912
15913 REQUIRE(buf != NULL);
15914 REQUIRE(length > 1U);
15915
15916 /*
15917 * Leave space for terminating '\0'.
15918 */
15919 isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
15920 if (dns_name_dynamic(&zone->origin)) {
15921 result = dns_name_totext(&zone->origin, true, &buffer);
15922 }
15923 if (result != ISC_R_SUCCESS &&
15924 isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
15925 {
15926 isc_buffer_putstr(&buffer, "<UNKNOWN>");
15927 }
15928
15929 buf[isc_buffer_usedlength(&buffer)] = '\0';
15930 }
15931
15932 static void
15933 zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length) {
15934 isc_buffer_t buffer;
15935
15936 REQUIRE(buf != NULL);
15937 REQUIRE(length > 1U);
15938
15939 /*
15940 * Leave space for terminating '\0'.
15941 */
15942 isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
15943 (void)dns_rdataclass_totext(zone->rdclass, &buffer);
15944
15945 buf[isc_buffer_usedlength(&buffer)] = '\0';
15946 }
15947
15948 static void
15949 zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length) {
15950 isc_buffer_t buffer;
15951
15952 REQUIRE(buf != NULL);
15953 REQUIRE(length > 1U);
15954
15955 /*
15956 * Leave space for terminating '\0'.
15957 */
15958 isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
15959
15960 if (zone->view == NULL) {
15961 isc_buffer_putstr(&buffer, "_none");
15962 } else if (strlen(zone->view->name) <
15963 isc_buffer_availablelength(&buffer))
15964 {
15965 isc_buffer_putstr(&buffer, zone->view->name);
15966 } else {
15967 isc_buffer_putstr(&buffer, "_toolong");
15968 }
15969
15970 buf[isc_buffer_usedlength(&buffer)] = '\0';
15971 }
15972
15973 void
15974 dns_zone_name(dns_zone_t *zone, char *buf, size_t length) {
15975 REQUIRE(DNS_ZONE_VALID(zone));
15976 REQUIRE(buf != NULL);
15977
15978 LOCK_ZONE(zone);
15979 zone_namerd_tostr(zone, buf, length);
15980 UNLOCK_ZONE(zone);
15981 }
15982
15983 void
15984 dns_zone_nameonly(dns_zone_t *zone, char *buf, size_t length) {
15985 REQUIRE(DNS_ZONE_VALID(zone));
15986 REQUIRE(buf != NULL);
15987 zone_name_tostr(zone, buf, length);
15988 }
15989
15990 void
15991 dns_zone_logv(dns_zone_t *zone, isc_logcategory_t *category, int level,
15992 const char *prefix, const char *fmt, va_list ap) {
15993 char message[4096];
15994 const char *zstr;
15995
15996 REQUIRE(DNS_ZONE_VALID(zone));
15997
15998 if (!isc_log_wouldlog(dns_lctx, level)) {
15999 return;
16000 }
16001
16002 vsnprintf(message, sizeof(message), fmt, ap);
16003
16004 switch (zone->type) {
16005 case dns_zone_key:
16006 zstr = "managed-keys-zone";
16007 break;
16008 case dns_zone_redirect:
16009 zstr = "redirect-zone";
16010 break;
16011 default:
16012 zstr = "zone ";
16013 }
16014
16015 isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE, level,
16016 "%s%s%s%s: %s", (prefix != NULL ? prefix : ""),
16017 (prefix != NULL ? ": " : ""), zstr, zone->strnamerd,
16018 message);
16019 }
16020
16021 static void
16022 notify_log(dns_zone_t *zone, int level, const char *fmt, ...) {
16023 va_list ap;
16024
16025 va_start(ap, fmt);
16026 dns_zone_logv(zone, DNS_LOGCATEGORY_NOTIFY, level, NULL, fmt, ap);
16027 va_end(ap);
16028 }
16029
16030 void
16031 dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category, int level,
16032 const char *fmt, ...) {
16033 va_list ap;
16034
16035 va_start(ap, fmt);
16036 dns_zone_logv(zone, category, level, NULL, fmt, ap);
16037 va_end(ap);
16038 }
16039
16040 void
16041 dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) {
16042 va_list ap;
16043
16044 va_start(ap, fmt);
16045 dns_zone_logv(zone, DNS_LOGCATEGORY_GENERAL, level, NULL, fmt, ap);
16046 va_end(ap);
16047 }
16048
16049 static void
16050 zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel, const char *fmt,
16051 ...) {
16052 int level = ISC_LOG_DEBUG(debuglevel);
16053 va_list ap;
16054
16055 va_start(ap, fmt);
16056 dns_zone_logv(zone, DNS_LOGCATEGORY_GENERAL, level, me, fmt, ap);
16057 va_end(ap);
16058 }
16059
16060 static void
16061 dnssec_log(dns_zone_t *zone, int level, const char *fmt, ...) {
16062 va_list ap;
16063
16064 va_start(ap, fmt);
16065 dns_zone_logv(zone, DNS_LOGCATEGORY_DNSSEC, level, NULL, fmt, ap);
16066 va_end(ap);
16067 }
16068
16069 static int
16070 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type) {
16071 isc_result_t result;
16072 dns_name_t *name;
16073 dns_rdataset_t *curr;
16074 int count = 0;
16075
16076 result = dns_message_firstname(msg, section);
16077 while (result == ISC_R_SUCCESS) {
16078 name = NULL;
16079 dns_message_currentname(msg, section, &name);
16080
16081 for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
16082 curr = ISC_LIST_PREV(curr, link))
16083 {
16084 if (curr->type == type) {
16085 count++;
16086 }
16087 }
16088 result = dns_message_nextname(msg, section);
16089 }
16090
16091 return (count);
16092 }
16093
16094 void
16095 dns_zone_setmaxxfrin(dns_zone_t *zone, uint32_t maxxfrin) {
16096 REQUIRE(DNS_ZONE_VALID(zone));
16097
16098 zone->maxxfrin = maxxfrin;
16099 }
16100
16101 uint32_t
16102 dns_zone_getmaxxfrin(dns_zone_t *zone) {
16103 REQUIRE(DNS_ZONE_VALID(zone));
16104
16105 return (zone->maxxfrin);
16106 }
16107
16108 void
16109 dns_zone_setmaxxfrout(dns_zone_t *zone, uint32_t maxxfrout) {
16110 REQUIRE(DNS_ZONE_VALID(zone));
16111 zone->maxxfrout = maxxfrout;
16112 }
16113
16114 uint32_t
16115 dns_zone_getmaxxfrout(dns_zone_t *zone) {
16116 REQUIRE(DNS_ZONE_VALID(zone));
16117
16118 return (zone->maxxfrout);
16119 }
16120
16121 dns_zonetype_t
16122 dns_zone_gettype(dns_zone_t *zone) {
16123 REQUIRE(DNS_ZONE_VALID(zone));
16124
16125 return (zone->type);
16126 }
16127
16128 const char *
16129 dns_zonetype_name(dns_zonetype_t type) {
16130 switch (type) {
16131 case dns_zone_none:
16132 return ("none");
16133 case dns_zone_primary:
16134 return ("primary");
16135 case dns_zone_secondary:
16136 return ("secondary");
16137 case dns_zone_mirror:
16138 return ("mirror");
16139 case dns_zone_stub:
16140 return ("stub");
16141 case dns_zone_staticstub:
16142 return ("static-stub");
16143 case dns_zone_key:
16144 return ("key");
16145 case dns_zone_dlz:
16146 return ("dlz");
16147 case dns_zone_redirect:
16148 return ("redirect");
16149 default:
16150 return ("unknown");
16151 }
16152 }
16153
16154 dns_zonetype_t
16155 dns_zone_getredirecttype(dns_zone_t *zone) {
16156 REQUIRE(DNS_ZONE_VALID(zone));
16157 REQUIRE(zone->type == dns_zone_redirect);
16158
16159 return (zone->masters == NULL ? dns_zone_primary : dns_zone_secondary);
16160 }
16161
16162 dns_name_t *
16163 dns_zone_getorigin(dns_zone_t *zone) {
16164 REQUIRE(DNS_ZONE_VALID(zone));
16165
16166 return (&zone->origin);
16167 }
16168
16169 void
16170 dns_zone_settask(dns_zone_t *zone, isc_task_t *task) {
16171 REQUIRE(DNS_ZONE_VALID(zone));
16172
16173 LOCK_ZONE(zone);
16174 if (zone->task != NULL) {
16175 isc_task_detach(&zone->task);
16176 }
16177 isc_task_attach(task, &zone->task);
16178 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
16179 if (zone->db != NULL) {
16180 dns_db_settask(zone->db, zone->task);
16181 }
16182 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
16183 UNLOCK_ZONE(zone);
16184 }
16185
16186 void
16187 dns_zone_gettask(dns_zone_t *zone, isc_task_t **target) {
16188 REQUIRE(DNS_ZONE_VALID(zone));
16189 isc_task_attach(zone->task, target);
16190 }
16191
16192 void
16193 dns_zone_setidlein(dns_zone_t *zone, uint32_t idlein) {
16194 REQUIRE(DNS_ZONE_VALID(zone));
16195
16196 if (idlein == 0) {
16197 idlein = DNS_DEFAULT_IDLEIN;
16198 }
16199 zone->idlein = idlein;
16200 }
16201
16202 uint32_t
16203 dns_zone_getidlein(dns_zone_t *zone) {
16204 REQUIRE(DNS_ZONE_VALID(zone));
16205
16206 return (zone->idlein);
16207 }
16208
16209 void
16210 dns_zone_setidleout(dns_zone_t *zone, uint32_t idleout) {
16211 REQUIRE(DNS_ZONE_VALID(zone));
16212
16213 zone->idleout = idleout;
16214 }
16215
16216 uint32_t
16217 dns_zone_getidleout(dns_zone_t *zone) {
16218 REQUIRE(DNS_ZONE_VALID(zone));
16219
16220 return (zone->idleout);
16221 }
16222
16223 static void
16224 notify_done(isc_task_t *task, isc_event_t *event) {
16225 dns_requestevent_t *revent = (dns_requestevent_t *)event;
16226 dns_notify_t *notify;
16227 isc_result_t result;
16228 dns_message_t *message = NULL;
16229 isc_buffer_t buf;
16230 char rcode[128];
16231 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
16232
16233 UNUSED(task);
16234
16235 notify = event->ev_arg;
16236 REQUIRE(DNS_NOTIFY_VALID(notify));
16237 INSIST(task == notify->zone->task);
16238
16239 isc_buffer_init(&buf, rcode, sizeof(rcode));
16240 isc_sockaddr_format(¬ify->dst, addrbuf, sizeof(addrbuf));
16241 dns_message_create(notify->zone->mctx, DNS_MESSAGE_INTENTPARSE,
16242 &message);
16243
16244 result = revent->result;
16245 if (result == ISC_R_SUCCESS) {
16246 result =
16247 dns_request_getresponse(revent->request, message,
16248 DNS_MESSAGEPARSE_PRESERVEORDER);
16249 }
16250 if (result == ISC_R_SUCCESS) {
16251 result = dns_rcode_totext(message->rcode, &buf);
16252 }
16253 if (result == ISC_R_SUCCESS) {
16254 notify_log(notify->zone, ISC_LOG_DEBUG(3),
16255 "notify response from %s: %.*s", addrbuf,
16256 (int)buf.used, rcode);
16257 } else {
16258 notify_log(notify->zone, ISC_LOG_DEBUG(2),
16259 "notify to %s failed: %s", addrbuf,
16260 dns_result_totext(result));
16261 }
16262
16263 /*
16264 * Old bind's return formerr if they see a soa record. Retry w/o
16265 * the soa if we see a formerr and had sent a SOA.
16266 */
16267 isc_event_free(&event);
16268 if (message->rcode == dns_rcode_formerr &&
16269 (notify->flags & DNS_NOTIFY_NOSOA) == 0)
16270 {
16271 bool startup;
16272
16273 notify->flags |= DNS_NOTIFY_NOSOA;
16274 dns_request_destroy(¬ify->request);
16275 startup = (notify->flags & DNS_NOTIFY_STARTUP);
16276 result = notify_send_queue(notify, startup);
16277 if (result != ISC_R_SUCCESS) {
16278 notify_destroy(notify, false);
16279 }
16280 } else {
16281 if (result == ISC_R_TIMEDOUT) {
16282 notify_log(notify->zone, ISC_LOG_DEBUG(1),
16283 "notify to %s: retries exceeded", addrbuf);
16284 }
16285 notify_destroy(notify, false);
16286 }
16287 dns_message_detach(&message);
16288 }
16289
16290 struct secure_event {
16291 isc_event_t e;
16292 dns_db_t *db;
16293 uint32_t serial;
16294 };
16295
16296 static void
16297 update_log_cb(void *arg, dns_zone_t *zone, int level, const char *message) {
16298 UNUSED(arg);
16299 dns_zone_log(zone, level, "%s", message);
16300 }
16301
16302 static isc_result_t
16303 sync_secure_journal(dns_zone_t *zone, dns_zone_t *raw, dns_journal_t *journal,
16304 uint32_t start, uint32_t end, dns_difftuple_t **soatuplep,
16305 dns_diff_t *diff) {
16306 isc_result_t result;
16307 dns_difftuple_t *tuple = NULL;
16308 dns_diffop_t op = DNS_DIFFOP_ADD;
16309 int n_soa = 0;
16310
16311 REQUIRE(soatuplep != NULL);
16312
16313 if (start == end) {
16314 return (DNS_R_UNCHANGED);
16315 }
16316
16317 CHECK(dns_journal_iter_init(journal, start, end, NULL));
16318 for (result = dns_journal_first_rr(journal); result == ISC_R_SUCCESS;
16319 result = dns_journal_next_rr(journal))
16320 {
16321 dns_name_t *name = NULL;
16322 uint32_t ttl;
16323 dns_rdata_t *rdata = NULL;
16324 dns_journal_current_rr(journal, &name, &ttl, &rdata);
16325
16326 if (rdata->type == dns_rdatatype_soa) {
16327 n_soa++;
16328 if (n_soa == 2) {
16329 /*
16330 * Save the latest raw SOA record.
16331 */
16332 if (*soatuplep != NULL) {
16333 dns_difftuple_free(soatuplep);
16334 }
16335 CHECK(dns_difftuple_create(
16336 diff->mctx, DNS_DIFFOP_ADD, name, ttl,
16337 rdata, soatuplep));
16338 }
16339 if (n_soa == 3) {
16340 n_soa = 1;
16341 }
16342 continue;
16343 }
16344
16345 /* Sanity. */
16346 if (n_soa == 0) {
16347 dns_zone_log(raw, ISC_LOG_ERROR,
16348 "corrupt journal file: '%s'\n",
16349 raw->journal);
16350 return (ISC_R_FAILURE);
16351 }
16352
16353 if (zone->privatetype != 0 && rdata->type == zone->privatetype)
16354 {
16355 continue;
16356 }
16357
16358 if (rdata->type == dns_rdatatype_nsec ||
16359 rdata->type == dns_rdatatype_rrsig ||
16360 rdata->type == dns_rdatatype_nsec3 ||
16361 rdata->type == dns_rdatatype_dnskey ||
16362 rdata->type == dns_rdatatype_nsec3param)
16363 {
16364 continue;
16365 }
16366
16367 op = (n_soa == 1) ? DNS_DIFFOP_DEL : DNS_DIFFOP_ADD;
16368
16369 CHECK(dns_difftuple_create(diff->mctx, op, name, ttl, rdata,
16370 &tuple));
16371 dns_diff_appendminimal(diff, &tuple);
16372 }
16373 if (result == ISC_R_NOMORE) {
16374 result = ISC_R_SUCCESS;
16375 }
16376
16377 failure:
16378 return (result);
16379 }
16380
16381 static isc_result_t
16382 sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb,
16383 dns_dbversion_t *secver, dns_difftuple_t **soatuple,
16384 dns_diff_t *diff) {
16385 isc_result_t result;
16386 dns_db_t *rawdb = NULL;
16387 dns_dbversion_t *rawver = NULL;
16388 dns_difftuple_t *tuple = NULL, *next;
16389 dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
16390 dns_rdata_soa_t oldsoa, newsoa;
16391
16392 REQUIRE(DNS_ZONE_VALID(seczone));
16393 REQUIRE(soatuple != NULL && *soatuple == NULL);
16394
16395 if (!seczone->sourceserialset) {
16396 return (DNS_R_UNCHANGED);
16397 }
16398
16399 dns_db_attach(raw->db, &rawdb);
16400 dns_db_currentversion(rawdb, &rawver);
16401 result = dns_db_diffx(diff, rawdb, rawver, secdb, secver, NULL);
16402 dns_db_closeversion(rawdb, &rawver, false);
16403 dns_db_detach(&rawdb);
16404
16405 if (result != ISC_R_SUCCESS) {
16406 return (result);
16407 }
16408
16409 for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL; tuple = next) {
16410 next = ISC_LIST_NEXT(tuple, link);
16411 if (tuple->rdata.type == dns_rdatatype_nsec ||
16412 tuple->rdata.type == dns_rdatatype_rrsig ||
16413 tuple->rdata.type == dns_rdatatype_dnskey ||
16414 tuple->rdata.type == dns_rdatatype_nsec3 ||
16415 tuple->rdata.type == dns_rdatatype_nsec3param)
16416 {
16417 ISC_LIST_UNLINK(diff->tuples, tuple, link);
16418 dns_difftuple_free(&tuple);
16419 continue;
16420 }
16421 if (tuple->rdata.type == dns_rdatatype_soa) {
16422 if (tuple->op == DNS_DIFFOP_DEL) {
16423 INSIST(oldtuple == NULL);
16424 oldtuple = tuple;
16425 }
16426 if (tuple->op == DNS_DIFFOP_ADD) {
16427 INSIST(newtuple == NULL);
16428 newtuple = tuple;
16429 }
16430 }
16431 }
16432
16433 if (oldtuple != NULL && newtuple != NULL) {
16434 result = dns_rdata_tostruct(&oldtuple->rdata, &oldsoa, NULL);
16435 RUNTIME_CHECK(result == ISC_R_SUCCESS);
16436
16437 result = dns_rdata_tostruct(&newtuple->rdata, &newsoa, NULL);
16438 RUNTIME_CHECK(result == ISC_R_SUCCESS);
16439
16440 /*
16441 * If the SOA records are the same except for the serial
16442 * remove them from the diff.
16443 */
16444 if (oldtuple->ttl == newtuple->ttl &&
16445 oldsoa.refresh == newsoa.refresh &&
16446 oldsoa.retry == newsoa.retry &&
16447 oldsoa.minimum == newsoa.minimum &&
16448 oldsoa.expire == newsoa.expire &&
16449 dns_name_equal(&oldsoa.origin, &newsoa.origin) &&
16450 dns_name_equal(&oldsoa.contact, &newsoa.contact))
16451 {
16452 ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
16453 dns_difftuple_free(&oldtuple);
16454 ISC_LIST_UNLINK(diff->tuples, newtuple, link);
16455 dns_difftuple_free(&newtuple);
16456 }
16457 }
16458
16459 if (ISC_LIST_EMPTY(diff->tuples)) {
16460 return (DNS_R_UNCHANGED);
16461 }
16462
16463 /*
16464 * If there are still SOA records in the diff they can now be removed
16465 * saving the new SOA record.
16466 */
16467 if (oldtuple != NULL) {
16468 ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
16469 dns_difftuple_free(&oldtuple);
16470 }
16471
16472 if (newtuple != NULL) {
16473 ISC_LIST_UNLINK(diff->tuples, newtuple, link);
16474 *soatuple = newtuple;
16475 }
16476
16477 return (ISC_R_SUCCESS);
16478 }
16479
16480 static void
16481 receive_secure_serial(isc_task_t *task, isc_event_t *event) {
16482 static char me[] = "receive_secure_serial";
16483 isc_result_t result = ISC_R_SUCCESS;
16484 dns_journal_t *rjournal = NULL;
16485 dns_journal_t *sjournal = NULL;
16486 uint32_t start, end;
16487 dns_zone_t *zone;
16488 dns_difftuple_t *tuple = NULL, *soatuple = NULL;
16489 dns_update_log_t log = { update_log_cb, NULL };
16490 uint32_t newserial = 0, desired = 0;
16491 isc_time_t timenow;
16492 int level = ISC_LOG_ERROR;
16493
16494 UNUSED(task);
16495
16496 zone = event->ev_arg;
16497 end = ((struct secure_event *)event)->serial;
16498
16499 ENTER;
16500
16501 LOCK_ZONE(zone);
16502
16503 /*
16504 * If we are already processing a receive secure serial event
16505 * for the zone, just queue the new one and exit.
16506 */
16507 if (zone->rss_event != NULL && zone->rss_event != event) {
16508 ISC_LIST_APPEND(zone->rss_events, event, ev_link);
16509 UNLOCK_ZONE(zone);
16510 return;
16511 }
16512
16513 nextevent:
16514 if (zone->rss_event != NULL) {
16515 INSIST(zone->rss_event == event);
16516 UNLOCK_ZONE(zone);
16517 } else {
16518 zone->rss_event = event;
16519 dns_diff_init(zone->mctx, &zone->rss_diff);
16520
16521 /*
16522 * zone->db may be NULL, if the load from disk failed.
16523 */
16524 result = ISC_R_SUCCESS;
16525 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
16526 if (zone->db != NULL) {
16527 dns_db_attach(zone->db, &zone->rss_db);
16528 } else {
16529 result = ISC_R_FAILURE;
16530 }
16531 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
16532
16533 if (result == ISC_R_SUCCESS && zone->raw != NULL) {
16534 dns_zone_attach(zone->raw, &zone->rss_raw);
16535 } else {
16536 result = ISC_R_FAILURE;
16537 }
16538
16539 UNLOCK_ZONE(zone);
16540
16541 CHECK(result);
16542
16543 /*
16544 * We first attempt to sync the raw zone to the secure zone
16545 * by using the raw zone's journal, applying all the deltas
16546 * from the latest source-serial of the secure zone up to
16547 * the current serial number of the raw zone.
16548 *
16549 * If that fails, then we'll fall back to a direct comparison
16550 * between raw and secure zones.
16551 */
16552 CHECK(dns_journal_open(zone->rss_raw->mctx,
16553 zone->rss_raw->journal,
16554 DNS_JOURNAL_WRITE, &rjournal));
16555
16556 result = dns_journal_open(zone->mctx, zone->journal,
16557 DNS_JOURNAL_READ, &sjournal);
16558 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
16559 goto failure;
16560 }
16561
16562 if (!dns_journal_get_sourceserial(rjournal, &start)) {
16563 start = dns_journal_first_serial(rjournal);
16564 dns_journal_set_sourceserial(rjournal, start);
16565 }
16566 if (sjournal != NULL) {
16567 uint32_t serial;
16568 /*
16569 * We read the secure journal first, if that
16570 * exists use its value provided it is greater
16571 * that from the raw journal.
16572 */
16573 if (dns_journal_get_sourceserial(sjournal, &serial)) {
16574 if (isc_serial_gt(serial, start)) {
16575 start = serial;
16576 }
16577 }
16578 dns_journal_destroy(&sjournal);
16579 }
16580
16581 dns_db_currentversion(zone->rss_db, &zone->rss_oldver);
16582 CHECK(dns_db_newversion(zone->rss_db, &zone->rss_newver));
16583
16584 /*
16585 * Try to apply diffs from the raw zone's journal to the secure
16586 * zone. If that fails, we recover by syncing up the databases
16587 * directly.
16588 */
16589 result = sync_secure_journal(zone, zone->rss_raw, rjournal,
16590 start, end, &soatuple,
16591 &zone->rss_diff);
16592 if (result == DNS_R_UNCHANGED) {
16593 level = ISC_LOG_INFO;
16594 goto failure;
16595 } else if (result != ISC_R_SUCCESS) {
16596 CHECK(sync_secure_db(zone, zone->rss_raw, zone->rss_db,
16597 zone->rss_oldver, &soatuple,
16598 &zone->rss_diff));
16599 }
16600
16601 CHECK(dns_diff_apply(&zone->rss_diff, zone->rss_db,
16602 zone->rss_newver));
16603
16604 if (soatuple != NULL) {
16605 uint32_t oldserial;
16606
16607 CHECK(dns_db_createsoatuple(
16608 zone->rss_db, zone->rss_oldver,
16609 zone->rss_diff.mctx, DNS_DIFFOP_DEL, &tuple));
16610 oldserial = dns_soa_getserial(&tuple->rdata);
16611 newserial = desired =
16612 dns_soa_getserial(&soatuple->rdata);
16613 if (!isc_serial_gt(newserial, oldserial)) {
16614 newserial = oldserial + 1;
16615 if (newserial == 0) {
16616 newserial++;
16617 }
16618 dns_soa_setserial(newserial, &soatuple->rdata);
16619 }
16620 CHECK(do_one_tuple(&tuple, zone->rss_db,
16621 zone->rss_newver, &zone->rss_diff));
16622 CHECK(do_one_tuple(&soatuple, zone->rss_db,
16623 zone->rss_newver, &zone->rss_diff));
16624 } else {
16625 CHECK(update_soa_serial(zone, zone->rss_db,
16626 zone->rss_newver,
16627 &zone->rss_diff, zone->mctx,
16628 zone->updatemethod));
16629 }
16630 }
16631 result = dns_update_signaturesinc(
16632 &log, zone, zone->rss_db, zone->rss_oldver, zone->rss_newver,
16633 &zone->rss_diff, zone->sigvalidityinterval, &zone->rss_state);
16634 if (result == DNS_R_CONTINUE) {
16635 if (rjournal != NULL) {
16636 dns_journal_destroy(&rjournal);
16637 }
16638 isc_task_send(task, &event);
16639 return;
16640 }
16641 /*
16642 * If something went wrong while trying to update the secure zone and
16643 * the latter was already signed before, do not apply raw zone deltas
16644 * to it as that would break existing DNSSEC signatures. However, if
16645 * the secure zone was not yet signed (e.g. because no signing keys
16646 * were created for it), commence applying raw zone deltas to it so
16647 * that contents of the raw zone and the secure zone are kept in sync.
16648 */
16649 if (result != ISC_R_SUCCESS && dns_db_issecure(zone->rss_db)) {
16650 goto failure;
16651 }
16652
16653 if (rjournal == NULL) {
16654 CHECK(dns_journal_open(zone->rss_raw->mctx,
16655 zone->rss_raw->journal,
16656 DNS_JOURNAL_WRITE, &rjournal));
16657 }
16658 CHECK(zone_journal(zone, &zone->rss_diff, &end,
16659 "receive_secure_serial"));
16660
16661 dns_journal_set_sourceserial(rjournal, end);
16662 dns_journal_commit(rjournal);
16663
16664 LOCK_ZONE(zone);
16665 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
16666
16667 zone->sourceserial = end;
16668 zone->sourceserialset = true;
16669 zone_needdump(zone, DNS_DUMP_DELAY);
16670
16671 /*
16672 * Set resign time to make sure it is set to the earliest
16673 * signature expiration.
16674 */
16675 set_resigntime(zone);
16676 TIME_NOW(&timenow);
16677 zone_settimer(zone, &timenow);
16678 UNLOCK_ZONE(zone);
16679
16680 dns_db_closeversion(zone->rss_db, &zone->rss_oldver, false);
16681 dns_db_closeversion(zone->rss_db, &zone->rss_newver, true);
16682
16683 if (newserial != 0) {
16684 dns_zone_log(zone, ISC_LOG_INFO, "serial %u (unsigned %u)",
16685 newserial, desired);
16686 }
16687
16688 failure:
16689 isc_event_free(&zone->rss_event);
16690 event = ISC_LIST_HEAD(zone->rss_events);
16691
16692 if (zone->rss_raw != NULL) {
16693 dns_zone_detach(&zone->rss_raw);
16694 }
16695 if (result != ISC_R_SUCCESS) {
16696 LOCK_ZONE(zone);
16697 set_resigntime(zone);
16698 TIME_NOW(&timenow);
16699 zone_settimer(zone, &timenow);
16700 UNLOCK_ZONE(zone);
16701 dns_zone_log(zone, level, "receive_secure_serial: %s",
16702 dns_result_totext(result));
16703 }
16704 if (tuple != NULL) {
16705 dns_difftuple_free(&tuple);
16706 }
16707 if (soatuple != NULL) {
16708 dns_difftuple_free(&soatuple);
16709 }
16710 if (zone->rss_db != NULL) {
16711 if (zone->rss_oldver != NULL) {
16712 dns_db_closeversion(zone->rss_db, &zone->rss_oldver,
16713 false);
16714 }
16715 if (zone->rss_newver != NULL) {
16716 dns_db_closeversion(zone->rss_db, &zone->rss_newver,
16717 false);
16718 }
16719 dns_db_detach(&zone->rss_db);
16720 }
16721 INSIST(zone->rss_oldver == NULL);
16722 INSIST(zone->rss_newver == NULL);
16723 if (rjournal != NULL) {
16724 dns_journal_destroy(&rjournal);
16725 }
16726 dns_diff_clear(&zone->rss_diff);
16727
16728 if (event != NULL) {
16729 LOCK_ZONE(zone);
16730 isc_refcount_decrement(&zone->irefs);
16731 ISC_LIST_UNLINK(zone->rss_events, event, ev_link);
16732 goto nextevent;
16733 }
16734
16735 event = ISC_LIST_HEAD(zone->rss_post);
16736 while (event != NULL) {
16737 ISC_LIST_UNLINK(zone->rss_post, event, ev_link);
16738 rss_post(zone, event);
16739 event = ISC_LIST_HEAD(zone->rss_post);
16740 }
16741
16742 dns_zone_idetach(&zone);
16743 }
16744
16745 static isc_result_t
16746 zone_send_secureserial(dns_zone_t *zone, uint32_t serial) {
16747 isc_event_t *e;
16748 dns_zone_t *dummy = NULL;
16749
16750 e = isc_event_allocate(zone->secure->mctx, zone,
16751 DNS_EVENT_ZONESECURESERIAL,
16752 receive_secure_serial, zone->secure,
16753 sizeof(struct secure_event));
16754 ((struct secure_event *)e)->serial = serial;
16755 INSIST(LOCKED_ZONE(zone->secure));
16756 zone_iattach(zone->secure, &dummy);
16757 isc_task_send(zone->secure->task, &e);
16758
16759 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
16760 return (ISC_R_SUCCESS);
16761 }
16762
16763 static isc_result_t
16764 checkandaddsoa(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
16765 dns_rdataset_t *rdataset, uint32_t oldserial) {
16766 dns_rdata_soa_t soa;
16767 dns_rdata_t rdata = DNS_RDATA_INIT;
16768 dns_rdatalist_t temprdatalist;
16769 dns_rdataset_t temprdataset;
16770 isc_buffer_t b;
16771 isc_result_t result;
16772 unsigned char buf[DNS_SOA_BUFFERSIZE];
16773 dns_fixedname_t fixed;
16774 dns_name_t *name;
16775
16776 result = dns_rdataset_first(rdataset);
16777 RUNTIME_CHECK(result == ISC_R_SUCCESS);
16778 dns_rdataset_current(rdataset, &rdata);
16779 result = dns_rdata_tostruct(&rdata, &soa, NULL);
16780 RUNTIME_CHECK(result == ISC_R_SUCCESS);
16781
16782 if (isc_serial_gt(soa.serial, oldserial)) {
16783 return (dns_db_addrdataset(db, node, version, 0, rdataset, 0,
16784 NULL));
16785 }
16786 /*
16787 * Always bump the serial.
16788 */
16789 oldserial++;
16790 if (oldserial == 0) {
16791 oldserial++;
16792 }
16793 soa.serial = oldserial;
16794
16795 /*
16796 * Construct a replacement rdataset.
16797 */
16798 dns_rdata_reset(&rdata);
16799 isc_buffer_init(&b, buf, sizeof(buf));
16800 result = dns_rdata_fromstruct(&rdata, rdataset->rdclass,
16801 dns_rdatatype_soa, &soa, &b);
16802 RUNTIME_CHECK(result == ISC_R_SUCCESS);
16803 dns_rdatalist_init(&temprdatalist);
16804 temprdatalist.rdclass = rdata.rdclass;
16805 temprdatalist.type = rdata.type;
16806 temprdatalist.ttl = rdataset->ttl;
16807 ISC_LIST_APPEND(temprdatalist.rdata, &rdata, link);
16808
16809 dns_rdataset_init(&temprdataset);
16810 result = dns_rdatalist_tordataset(&temprdatalist, &temprdataset);
16811 RUNTIME_CHECK(result == ISC_R_SUCCESS);
16812
16813 name = dns_fixedname_initname(&fixed);
16814 result = dns_db_nodefullname(db, node, name);
16815 RUNTIME_CHECK(result == ISC_R_SUCCESS);
16816 dns_rdataset_getownercase(rdataset, name);
16817 dns_rdataset_setownercase(&temprdataset, name);
16818 return (dns_db_addrdataset(db, node, version, 0, &temprdataset, 0,
16819 NULL));
16820 }
16821
16822 /*
16823 * This function should populate an nsec3paramlist_t with the
16824 * nsecparam_t data from a zone.
16825 */
16826 static isc_result_t
16827 save_nsec3param(dns_zone_t *zone, nsec3paramlist_t *nsec3list) {
16828 isc_result_t result;
16829 dns_dbnode_t *node = NULL;
16830 dns_rdataset_t rdataset, prdataset;
16831 dns_dbversion_t *version = NULL;
16832 nsec3param_t *nsec3param = NULL;
16833 nsec3param_t *nsec3p = NULL;
16834 nsec3param_t *next;
16835 dns_db_t *db = NULL;
16836 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
16837
16838 REQUIRE(DNS_ZONE_VALID(zone));
16839 REQUIRE(nsec3list != NULL);
16840 REQUIRE(ISC_LIST_EMPTY(*nsec3list));
16841
16842 dns_rdataset_init(&rdataset);
16843 dns_rdataset_init(&prdataset);
16844
16845 dns_db_attach(zone->db, &db);
16846 CHECK(dns_db_getoriginnode(db, &node));
16847
16848 dns_db_currentversion(db, &version);
16849 result = dns_db_findrdataset(db, node, version,
16850 dns_rdatatype_nsec3param,
16851 dns_rdatatype_none, 0, &rdataset, NULL);
16852
16853 if (result != ISC_R_SUCCESS) {
16854 goto getprivate;
16855 }
16856
16857 /*
16858 * Walk nsec3param rdataset making a list of parameters (note that
16859 * multiple simultaneous nsec3 chains are annoyingly legal -- this
16860 * is why we use an nsec3list, even though we will usually only
16861 * have one).
16862 */
16863 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
16864 result = dns_rdataset_next(&rdataset))
16865 {
16866 dns_rdata_t rdata = DNS_RDATA_INIT;
16867 dns_rdata_t private = DNS_RDATA_INIT;
16868
16869 dns_rdataset_current(&rdataset, &rdata);
16870 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
16871 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
16872 "looping through nsec3param data");
16873 nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
16874 ISC_LINK_INIT(nsec3param, link);
16875
16876 /*
16877 * now transfer the data from the rdata to
16878 * the nsec3param
16879 */
16880 dns_nsec3param_toprivate(&rdata, &private, zone->privatetype,
16881 nsec3param->data,
16882 sizeof(nsec3param->data));
16883 nsec3param->length = private.length;
16884 ISC_LIST_APPEND(*nsec3list, nsec3param, link);
16885 }
16886
16887 getprivate:
16888 result = dns_db_findrdataset(db, node, version, zone->privatetype,
16889 dns_rdatatype_none, 0, &prdataset, NULL);
16890 if (result != ISC_R_SUCCESS) {
16891 goto done;
16892 }
16893
16894 /*
16895 * walk private type records, converting them to nsec3 parameters
16896 * using dns_nsec3param_fromprivate(), do the right thing based on
16897 * CREATE and REMOVE flags
16898 */
16899 for (result = dns_rdataset_first(&prdataset); result == ISC_R_SUCCESS;
16900 result = dns_rdataset_next(&prdataset))
16901 {
16902 dns_rdata_t rdata = DNS_RDATA_INIT;
16903 dns_rdata_t private = DNS_RDATA_INIT;
16904
16905 dns_rdataset_current(&prdataset, &private);
16906 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
16907 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
16908 "looping through nsec3param private data");
16909
16910 /*
16911 * Do we have a valid private record?
16912 */
16913 if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
16914 sizeof(buf)))
16915 {
16916 continue;
16917 }
16918
16919 /*
16920 * Remove any NSEC3PARAM records scheduled to be removed.
16921 */
16922 if (NSEC3REMOVE(rdata.data[1])) {
16923 /*
16924 * Zero out the flags.
16925 */
16926 rdata.data[1] = 0;
16927
16928 for (nsec3p = ISC_LIST_HEAD(*nsec3list); nsec3p != NULL;
16929 nsec3p = next)
16930 {
16931 next = ISC_LIST_NEXT(nsec3p, link);
16932
16933 if (nsec3p->length == rdata.length + 1 &&
16934 memcmp(rdata.data, nsec3p->data + 1,
16935 nsec3p->length - 1) == 0)
16936 {
16937 ISC_LIST_UNLINK(*nsec3list, nsec3p,
16938 link);
16939 isc_mem_put(zone->mctx, nsec3p,
16940 sizeof(nsec3param_t));
16941 }
16942 }
16943 continue;
16944 }
16945
16946 nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
16947 ISC_LINK_INIT(nsec3param, link);
16948
16949 /*
16950 * Copy the remaining private records so the nsec/nsec3
16951 * chain gets created.
16952 */
16953 INSIST(private.length <= sizeof(nsec3param->data));
16954 memmove(nsec3param->data, private.data, private.length);
16955 nsec3param->length = private.length;
16956 ISC_LIST_APPEND(*nsec3list, nsec3param, link);
16957 }
16958
16959 done:
16960 if (result == ISC_R_NOMORE || result == ISC_R_NOTFOUND) {
16961 result = ISC_R_SUCCESS;
16962 }
16963
16964 failure:
16965 if (node != NULL) {
16966 dns_db_detachnode(db, &node);
16967 }
16968 if (version != NULL) {
16969 dns_db_closeversion(db, &version, false);
16970 }
16971 if (db != NULL) {
16972 dns_db_detach(&db);
16973 }
16974 if (dns_rdataset_isassociated(&rdataset)) {
16975 dns_rdataset_disassociate(&rdataset);
16976 }
16977 if (dns_rdataset_isassociated(&prdataset)) {
16978 dns_rdataset_disassociate(&prdataset);
16979 }
16980 return (result);
16981 }
16982
16983 /*
16984 * Populate new zone db with private type records found by save_nsec3param().
16985 */
16986 static isc_result_t
16987 restore_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
16988 nsec3paramlist_t *nsec3list) {
16989 isc_result_t result = ISC_R_SUCCESS;
16990 dns_diff_t diff;
16991 dns_rdata_t rdata;
16992 nsec3param_t *nsec3p = NULL;
16993 nsec3param_t *next;
16994
16995 REQUIRE(DNS_ZONE_VALID(zone));
16996 REQUIRE(!ISC_LIST_EMPTY(*nsec3list));
16997
16998 dns_diff_init(zone->mctx, &diff);
16999
17000 /*
17001 * Loop through the list of private-type records, set the INITIAL
17002 * and CREATE flags, and the add the record to the apex of the tree
17003 * in db.
17004 */
17005 for (nsec3p = ISC_LIST_HEAD(*nsec3list); nsec3p != NULL; nsec3p = next)
17006 {
17007 next = ISC_LIST_NEXT(nsec3p, link);
17008 dns_rdata_init(&rdata);
17009 nsec3p->data[2] = DNS_NSEC3FLAG_CREATE | DNS_NSEC3FLAG_INITIAL;
17010 rdata.length = nsec3p->length;
17011 rdata.data = nsec3p->data;
17012 rdata.type = zone->privatetype;
17013 rdata.rdclass = zone->rdclass;
17014 result = update_one_rr(db, version, &diff, DNS_DIFFOP_ADD,
17015 &zone->origin, 0, &rdata);
17016 if (result != ISC_R_SUCCESS) {
17017 break;
17018 }
17019 }
17020
17021 dns_diff_clear(&diff);
17022 return (result);
17023 }
17024
17025 static isc_result_t
17026 copy_non_dnssec_records(dns_db_t *db, dns_db_t *version, dns_db_t *rawdb,
17027 dns_dbiterator_t *dbiterator, unsigned int *oldserial) {
17028 dns_dbnode_t *rawnode = NULL, *node = NULL;
17029 dns_fixedname_t fixed;
17030 dns_name_t *name = dns_fixedname_initname(&fixed);
17031 dns_rdataset_t rdataset;
17032 dns_rdatasetiter_t *rdsit = NULL;
17033 isc_result_t result;
17034
17035 result = dns_dbiterator_current(dbiterator, &rawnode, name);
17036 if (result != ISC_R_SUCCESS) {
17037 return (ISC_R_SUCCESS);
17038 }
17039
17040 dns_dbiterator_pause(dbiterator);
17041
17042 result = dns_db_findnode(db, name, true, &node);
17043 if (result != ISC_R_SUCCESS) {
17044 goto cleanup;
17045 }
17046
17047 result = dns_db_allrdatasets(rawdb, rawnode, NULL, 0, 0, &rdsit);
17048 if (result != ISC_R_SUCCESS) {
17049 goto cleanup;
17050 }
17051
17052 dns_rdataset_init(&rdataset);
17053
17054 for (result = dns_rdatasetiter_first(rdsit); result == ISC_R_SUCCESS;
17055 result = dns_rdatasetiter_next(rdsit))
17056 {
17057 dns_rdatasetiter_current(rdsit, &rdataset);
17058 if (rdataset.type == dns_rdatatype_nsec ||
17059 rdataset.type == dns_rdatatype_rrsig ||
17060 rdataset.type == dns_rdatatype_nsec3 ||
17061 rdataset.type == dns_rdatatype_dnskey ||
17062 rdataset.type == dns_rdatatype_nsec3param)
17063 {
17064 dns_rdataset_disassociate(&rdataset);
17065 continue;
17066 }
17067 if (rdataset.type == dns_rdatatype_soa && oldserial != NULL) {
17068 result = checkandaddsoa(db, node, version, &rdataset,
17069 *oldserial);
17070 } else {
17071 result = dns_db_addrdataset(db, node, version, 0,
17072 &rdataset, 0, NULL);
17073 }
17074 dns_rdataset_disassociate(&rdataset);
17075 if (result != ISC_R_SUCCESS) {
17076 goto cleanup;
17077 }
17078 }
17079 if (result == ISC_R_NOMORE) {
17080 result = ISC_R_SUCCESS;
17081 }
17082
17083 cleanup:
17084 if (rdsit != NULL) {
17085 dns_rdatasetiter_destroy(&rdsit);
17086 }
17087 if (rawnode) {
17088 dns_db_detachnode(rawdb, &rawnode);
17089 }
17090 if (node) {
17091 dns_db_detachnode(db, &node);
17092 }
17093 return (result);
17094 }
17095
17096 static void
17097 receive_secure_db(isc_task_t *task, isc_event_t *event) {
17098 isc_result_t result;
17099 dns_zone_t *zone;
17100 dns_db_t *rawdb, *db = NULL;
17101 dns_dbiterator_t *dbiterator = NULL;
17102 dns_dbversion_t *version = NULL;
17103 isc_time_t loadtime;
17104 unsigned int oldserial = 0, *oldserialp = NULL;
17105 nsec3paramlist_t nsec3list;
17106 isc_event_t *setnsec3param_event;
17107 dns_zone_t *dummy;
17108
17109 UNUSED(task);
17110
17111 ISC_LIST_INIT(nsec3list);
17112
17113 zone = event->ev_arg;
17114 rawdb = ((struct secure_event *)event)->db;
17115 isc_event_free(&event);
17116
17117 LOCK_ZONE(zone);
17118 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || !inline_secure(zone)) {
17119 result = ISC_R_SHUTTINGDOWN;
17120 goto failure;
17121 }
17122
17123 TIME_NOW(&loadtime);
17124 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
17125 if (zone->db != NULL) {
17126 result = dns_db_getsoaserial(zone->db, NULL, &oldserial);
17127 if (result == ISC_R_SUCCESS) {
17128 oldserialp = &oldserial;
17129 }
17130
17131 /*
17132 * assemble nsec3parameters from the old zone, and set a flag
17133 * if any are found
17134 */
17135 result = save_nsec3param(zone, &nsec3list);
17136 if (result != ISC_R_SUCCESS) {
17137 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17138 goto failure;
17139 }
17140 }
17141 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17142
17143 result = dns_db_create(zone->mctx, zone->db_argv[0], &zone->origin,
17144 dns_dbtype_zone, zone->rdclass,
17145 zone->db_argc - 1, zone->db_argv + 1, &db);
17146 if (result != ISC_R_SUCCESS) {
17147 goto failure;
17148 }
17149
17150 result = dns_db_setgluecachestats(db, zone->gluecachestats);
17151 if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) {
17152 goto failure;
17153 }
17154
17155 result = dns_db_newversion(db, &version);
17156 if (result != ISC_R_SUCCESS) {
17157 goto failure;
17158 }
17159
17160 result = dns_db_createiterator(rawdb, 0, &dbiterator);
17161 if (result != ISC_R_SUCCESS) {
17162 goto failure;
17163 }
17164
17165 for (result = dns_dbiterator_first(dbiterator); result == ISC_R_SUCCESS;
17166 result = dns_dbiterator_next(dbiterator))
17167 {
17168 result = copy_non_dnssec_records(db, version, rawdb, dbiterator,
17169 oldserialp);
17170 if (result != ISC_R_SUCCESS) {
17171 goto failure;
17172 }
17173 }
17174 dns_dbiterator_destroy(&dbiterator);
17175 if (result != ISC_R_NOMORE) {
17176 goto failure;
17177 }
17178
17179 /*
17180 * Call restore_nsec3param() to create private-type records from
17181 * the old nsec3 parameters and insert them into db
17182 */
17183 if (!ISC_LIST_EMPTY(nsec3list)) {
17184 result = restore_nsec3param(zone, db, version, &nsec3list);
17185 if (result != ISC_R_SUCCESS) {
17186 goto failure;
17187 }
17188 }
17189
17190 dns_db_closeversion(db, &version, true);
17191
17192 /*
17193 * Lock hierarchy: zmgr, zone, raw.
17194 */
17195 INSIST(zone != zone->raw);
17196 LOCK_ZONE(zone->raw);
17197 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
17198 result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
17199 zone_needdump(zone, 0); /* XXXMPA */
17200 UNLOCK_ZONE(zone->raw);
17201
17202 /*
17203 * Process any queued NSEC3PARAM change requests.
17204 */
17205 while (!ISC_LIST_EMPTY(zone->setnsec3param_queue)) {
17206 setnsec3param_event = ISC_LIST_HEAD(zone->setnsec3param_queue);
17207 ISC_LIST_UNLINK(zone->setnsec3param_queue, setnsec3param_event,
17208 ev_link);
17209 dummy = NULL;
17210 zone_iattach(zone, &dummy);
17211 isc_task_send(zone->task, &setnsec3param_event);
17212 }
17213
17214 failure:
17215 UNLOCK_ZONE(zone);
17216 if (dbiterator != NULL) {
17217 dns_dbiterator_destroy(&dbiterator);
17218 }
17219 if (result != ISC_R_SUCCESS) {
17220 dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_db: %s",
17221 dns_result_totext(result));
17222 }
17223
17224 while (!ISC_LIST_EMPTY(nsec3list)) {
17225 nsec3param_t *nsec3p;
17226 nsec3p = ISC_LIST_HEAD(nsec3list);
17227 ISC_LIST_UNLINK(nsec3list, nsec3p, link);
17228 isc_mem_put(zone->mctx, nsec3p, sizeof(nsec3param_t));
17229 }
17230 if (db != NULL) {
17231 if (version != NULL) {
17232 dns_db_closeversion(db, &version, false);
17233 }
17234 dns_db_detach(&db);
17235 }
17236 dns_db_detach(&rawdb);
17237 dns_zone_idetach(&zone);
17238
17239 INSIST(version == NULL);
17240 }
17241
17242 static isc_result_t
17243 zone_send_securedb(dns_zone_t *zone, dns_db_t *db) {
17244 isc_event_t *e;
17245 dns_db_t *dummy = NULL;
17246 dns_zone_t *secure = NULL;
17247
17248 e = isc_event_allocate(zone->secure->mctx, zone, DNS_EVENT_ZONESECUREDB,
17249 receive_secure_db, zone->secure,
17250 sizeof(struct secure_event));
17251 dns_db_attach(db, &dummy);
17252 ((struct secure_event *)e)->db = dummy;
17253 INSIST(LOCKED_ZONE(zone->secure));
17254 zone_iattach(zone->secure, &secure);
17255 isc_task_send(zone->secure->task, &e);
17256 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
17257 return (ISC_R_SUCCESS);
17258 }
17259
17260 isc_result_t
17261 dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump) {
17262 isc_result_t result;
17263 dns_zone_t *secure = NULL;
17264
17265 REQUIRE(DNS_ZONE_VALID(zone));
17266 again:
17267 LOCK_ZONE(zone);
17268 if (inline_raw(zone)) {
17269 secure = zone->secure;
17270 INSIST(secure != zone);
17271 TRYLOCK_ZONE(result, secure);
17272 if (result != ISC_R_SUCCESS) {
17273 UNLOCK_ZONE(zone);
17274 secure = NULL;
17275 isc_thread_yield();
17276 goto again;
17277 }
17278 }
17279 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
17280 result = zone_replacedb(zone, db, dump);
17281 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
17282 if (secure != NULL) {
17283 UNLOCK_ZONE(secure);
17284 }
17285 UNLOCK_ZONE(zone);
17286 return (result);
17287 }
17288
17289 static isc_result_t
17290 zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump) {
17291 dns_dbversion_t *ver;
17292 isc_result_t result;
17293 unsigned int soacount = 0;
17294 unsigned int nscount = 0;
17295
17296 /*
17297 * 'zone' and 'zone->db' locked by caller.
17298 */
17299 REQUIRE(DNS_ZONE_VALID(zone));
17300 REQUIRE(LOCKED_ZONE(zone));
17301 if (inline_raw(zone)) {
17302 REQUIRE(LOCKED_ZONE(zone->secure));
17303 }
17304
17305 result = zone_get_from_db(zone, db, &nscount, &soacount, NULL, NULL,
17306 NULL, NULL, NULL, NULL, NULL);
17307 if (result == ISC_R_SUCCESS) {
17308 if (soacount != 1) {
17309 dns_zone_log(zone, ISC_LOG_ERROR, "has %d SOA records",
17310 soacount);
17311 result = DNS_R_BADZONE;
17312 }
17313 if (nscount == 0 && zone->type != dns_zone_key) {
17314 dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records");
17315 result = DNS_R_BADZONE;
17316 }
17317 if (result != ISC_R_SUCCESS) {
17318 return (result);
17319 }
17320 } else {
17321 dns_zone_log(zone, ISC_LOG_ERROR,
17322 "retrieving SOA and NS records failed: %s",
17323 dns_result_totext(result));
17324 return (result);
17325 }
17326
17327 result = check_nsec3param(zone, db);
17328 if (result != ISC_R_SUCCESS) {
17329 return (result);
17330 }
17331
17332 ver = NULL;
17333 dns_db_currentversion(db, &ver);
17334
17335 /*
17336 * The initial version of a slave zone is always dumped;
17337 * subsequent versions may be journaled instead if this
17338 * is enabled in the configuration.
17339 */
17340 if (zone->db != NULL && zone->journal != NULL &&
17341 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
17342 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER))
17343 {
17344 uint32_t serial, oldserial;
17345
17346 dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
17347
17348 result = dns_db_getsoaserial(db, ver, &serial);
17349 if (result != ISC_R_SUCCESS) {
17350 dns_zone_log(zone, ISC_LOG_ERROR,
17351 "ixfr-from-differences: unable to get "
17352 "new serial");
17353 goto fail;
17354 }
17355
17356 /*
17357 * This is checked in zone_postload() for master zones.
17358 */
17359 result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL,
17360 &oldserial, NULL, NULL, NULL, NULL,
17361 NULL);
17362 RUNTIME_CHECK(result == ISC_R_SUCCESS);
17363 RUNTIME_CHECK(soacount > 0U);
17364 if ((zone->type == dns_zone_secondary ||
17365 (zone->type == dns_zone_redirect &&
17366 zone->masters != NULL)) &&
17367 !isc_serial_gt(serial, oldserial))
17368 {
17369 uint32_t serialmin, serialmax;
17370 serialmin = (oldserial + 1) & 0xffffffffU;
17371 serialmax = (oldserial + 0x7fffffffU) & 0xffffffffU;
17372 dns_zone_log(zone, ISC_LOG_ERROR,
17373 "ixfr-from-differences: failed: "
17374 "new serial (%u) out of range [%u - %u]",
17375 serial, serialmin, serialmax);
17376 result = ISC_R_RANGE;
17377 goto fail;
17378 }
17379
17380 result = dns_db_diff(zone->mctx, db, ver, zone->db, NULL,
17381 zone->journal);
17382 if (result != ISC_R_SUCCESS) {
17383 char strbuf[ISC_STRERRORSIZE];
17384 strerror_r(errno, strbuf, sizeof(strbuf));
17385 dns_zone_log(zone, ISC_LOG_ERROR,
17386 "ixfr-from-differences: failed: "
17387 "%s",
17388 strbuf);
17389 goto fallback;
17390 }
17391 if (dump) {
17392 zone_needdump(zone, DNS_DUMP_DELAY);
17393 } else {
17394 zone_journal_compact(zone, zone->db, serial);
17395 }
17396 if (zone->type == dns_zone_primary && inline_raw(zone)) {
17397 zone_send_secureserial(zone, serial);
17398 }
17399 } else {
17400 fallback:
17401 if (dump && zone->masterfile != NULL) {
17402 /*
17403 * If DNS_ZONEFLG_FORCEXFER was set we don't want
17404 * to keep the old masterfile.
17405 */
17406 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) &&
17407 remove(zone->masterfile) < 0 && errno != ENOENT)
17408 {
17409 char strbuf[ISC_STRERRORSIZE];
17410 strerror_r(errno, strbuf, sizeof(strbuf));
17411 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
17412 DNS_LOGMODULE_ZONE,
17413 ISC_LOG_WARNING,
17414 "unable to remove masterfile "
17415 "'%s': '%s'",
17416 zone->masterfile, strbuf);
17417 }
17418 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0) {
17419 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NODELAY);
17420 } else {
17421 zone_needdump(zone, 0);
17422 }
17423 }
17424 if (dump && zone->journal != NULL) {
17425 /*
17426 * The in-memory database just changed, and
17427 * because 'dump' is set, it didn't change by
17428 * being loaded from disk. Also, we have not
17429 * journaled diffs for this change.
17430 * Therefore, the on-disk journal is missing
17431 * the deltas for this change. Since it can
17432 * no longer be used to bring the zone
17433 * up-to-date, it is useless and should be
17434 * removed.
17435 */
17436 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
17437 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
17438 "removing journal file");
17439 if (remove(zone->journal) < 0 && errno != ENOENT) {
17440 char strbuf[ISC_STRERRORSIZE];
17441 strerror_r(errno, strbuf, sizeof(strbuf));
17442 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
17443 DNS_LOGMODULE_ZONE,
17444 ISC_LOG_WARNING,
17445 "unable to remove journal "
17446 "'%s': '%s'",
17447 zone->journal, strbuf);
17448 }
17449 }
17450
17451 if (inline_raw(zone)) {
17452 zone_send_securedb(zone, db);
17453 }
17454 }
17455
17456 dns_db_closeversion(db, &ver, false);
17457
17458 dns_zone_log(zone, ISC_LOG_DEBUG(3), "replacing zone database");
17459
17460 if (zone->db != NULL) {
17461 zone_detachdb(zone);
17462 }
17463 zone_attachdb(zone, db);
17464 dns_db_settask(zone->db, zone->task);
17465 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED | DNS_ZONEFLG_NEEDNOTIFY);
17466 return (ISC_R_SUCCESS);
17467
17468 fail:
17469 dns_db_closeversion(db, &ver, false);
17470 return (result);
17471 }
17472
17473 /* The caller must hold the dblock as a writer. */
17474 static void
17475 zone_attachdb(dns_zone_t *zone, dns_db_t *db) {
17476 REQUIRE(zone->db == NULL && db != NULL);
17477
17478 dns_db_attach(db, &zone->db);
17479 }
17480
17481 /* The caller must hold the dblock as a writer. */
17482 static void
17483 zone_detachdb(dns_zone_t *zone) {
17484 REQUIRE(zone->db != NULL);
17485
17486 dns_zone_rpz_disable_db(zone, zone->db);
17487 dns_zone_catz_disable_db(zone, zone->db);
17488 dns_db_detach(&zone->db);
17489 }
17490
17491 static void
17492 zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
17493 isc_time_t now;
17494 bool again = false;
17495 unsigned int soacount;
17496 unsigned int nscount;
17497 uint32_t serial, refresh, retry, expire, minimum, soattl;
17498 isc_result_t xfrresult = result;
17499 bool free_needed;
17500 dns_zone_t *secure = NULL;
17501
17502 REQUIRE(DNS_ZONE_VALID(zone));
17503
17504 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(1),
17505 "zone transfer finished: %s", dns_result_totext(result));
17506
17507 /*
17508 * Obtaining a lock on the zone->secure (see zone_send_secureserial)
17509 * could result in a deadlock due to a LOR so we will spin if we
17510 * can't obtain the both locks.
17511 */
17512 again:
17513 LOCK_ZONE(zone);
17514 if (inline_raw(zone)) {
17515 secure = zone->secure;
17516 INSIST(secure != zone);
17517 TRYLOCK_ZONE(result, secure);
17518 if (result != ISC_R_SUCCESS) {
17519 UNLOCK_ZONE(zone);
17520 secure = NULL;
17521 isc_thread_yield();
17522 goto again;
17523 }
17524 }
17525
17526 INSIST(DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH));
17527 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
17528 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
17529
17530 TIME_NOW(&now);
17531 switch (xfrresult) {
17532 case ISC_R_SUCCESS:
17533 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
17534 FALLTHROUGH;
17535 case DNS_R_UPTODATE:
17536 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FORCEXFER);
17537 /*
17538 * Has the zone expired underneath us?
17539 */
17540 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
17541 if (zone->db == NULL) {
17542 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17543 goto same_master;
17544 }
17545
17546 /*
17547 * Update the zone structure's data from the actual
17548 * SOA received.
17549 */
17550 nscount = 0;
17551 soacount = 0;
17552 INSIST(zone->db != NULL);
17553 result = zone_get_from_db(zone, zone->db, &nscount, &soacount,
17554 &soattl, &serial, &refresh, &retry,
17555 &expire, &minimum, NULL);
17556 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17557 if (result == ISC_R_SUCCESS) {
17558 if (soacount != 1) {
17559 dns_zone_log(zone, ISC_LOG_ERROR,
17560 "transferred zone "
17561 "has %d SOA records",
17562 soacount);
17563 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
17564 {
17565 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
17566 zone->retry = DNS_ZONE_DEFAULTRETRY;
17567 }
17568 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
17569 zone_unload(zone);
17570 goto next_master;
17571 }
17572 if (nscount == 0) {
17573 dns_zone_log(zone, ISC_LOG_ERROR,
17574 "transferred zone "
17575 "has no NS records");
17576 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
17577 {
17578 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
17579 zone->retry = DNS_ZONE_DEFAULTRETRY;
17580 }
17581 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
17582 zone_unload(zone);
17583 goto next_master;
17584 }
17585 zone->refresh = RANGE(refresh, zone->minrefresh,
17586 zone->maxrefresh);
17587 zone->retry = RANGE(retry, zone->minretry,
17588 zone->maxretry);
17589 zone->expire = RANGE(expire,
17590 zone->refresh + zone->retry,
17591 DNS_MAX_EXPIRE);
17592 zone->soattl = soattl;
17593 zone->minimum = minimum;
17594 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
17595 }
17596
17597 /*
17598 * Set our next update/expire times.
17599 */
17600 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
17601 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
17602 zone->refreshtime = now;
17603 DNS_ZONE_TIME_ADD(&now, zone->expire,
17604 &zone->expiretime);
17605 } else {
17606 DNS_ZONE_JITTER_ADD(&now, zone->refresh,
17607 &zone->refreshtime);
17608 DNS_ZONE_TIME_ADD(&now, zone->expire,
17609 &zone->expiretime);
17610 }
17611 if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS) {
17612 char buf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
17613 if (zone->tsigkey != NULL) {
17614 char namebuf[DNS_NAME_FORMATSIZE];
17615 dns_name_format(&zone->tsigkey->name, namebuf,
17616 sizeof(namebuf));
17617 snprintf(buf, sizeof(buf), ": TSIG '%s'",
17618 namebuf);
17619 } else {
17620 buf[0] = '\0';
17621 }
17622 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
17623 ISC_LOG_INFO, "transferred serial %u%s",
17624 serial, buf);
17625 if (inline_raw(zone)) {
17626 zone_send_secureserial(zone, serial);
17627 }
17628 }
17629
17630 /*
17631 * This is not necessary if we just performed a AXFR
17632 * however it is necessary for an IXFR / UPTODATE and
17633 * won't hurt with an AXFR.
17634 */
17635 if (zone->masterfile != NULL || zone->journal != NULL) {
17636 unsigned int delay = DNS_DUMP_DELAY;
17637
17638 result = ISC_R_FAILURE;
17639 if (zone->journal != NULL) {
17640 result = isc_file_settime(zone->journal, &now);
17641 }
17642 if (result != ISC_R_SUCCESS && zone->masterfile != NULL)
17643 {
17644 result = isc_file_settime(zone->masterfile,
17645 &now);
17646 }
17647
17648 if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NODELAY) != 0) ||
17649 result == ISC_R_FILENOTFOUND)
17650 {
17651 delay = 0;
17652 }
17653
17654 if ((result == ISC_R_SUCCESS ||
17655 result == ISC_R_FILENOTFOUND) &&
17656 zone->masterfile != NULL)
17657 {
17658 zone_needdump(zone, delay);
17659 } else if (result != ISC_R_SUCCESS) {
17660 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
17661 ISC_LOG_ERROR,
17662 "transfer: could not set file "
17663 "modification time of '%s': %s",
17664 zone->masterfile,
17665 dns_result_totext(result));
17666 }
17667 }
17668 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NODELAY);
17669 inc_stats(zone, dns_zonestatscounter_xfrsuccess);
17670 break;
17671
17672 case DNS_R_BADIXFR:
17673 /* Force retry with AXFR. */
17674 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOIXFR);
17675 goto same_master;
17676
17677 case DNS_R_TOOMANYRECORDS:
17678 case DNS_R_VERIFYFAILURE:
17679 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
17680 inc_stats(zone, dns_zonestatscounter_xfrfail);
17681 break;
17682
17683 default:
17684 next_master:
17685 /*
17686 * Skip to next failed / untried master.
17687 */
17688 do {
17689 zone->curmaster++;
17690 } while (zone->curmaster < zone->masterscnt &&
17691 zone->mastersok[zone->curmaster]);
17692 same_master:
17693 if (zone->curmaster >= zone->masterscnt) {
17694 zone->curmaster = 0;
17695 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
17696 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
17697 {
17698 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
17699 DNS_ZONE_SETFLAG(zone,
17700 DNS_ZONEFLG_USEALTXFRSRC);
17701 while (zone->curmaster < zone->masterscnt &&
17702 zone->mastersok[zone->curmaster])
17703 {
17704 zone->curmaster++;
17705 }
17706 again = true;
17707 } else {
17708 DNS_ZONE_CLRFLAG(zone,
17709 DNS_ZONEFLG_USEALTXFRSRC);
17710 }
17711 } else {
17712 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
17713 again = true;
17714 }
17715 inc_stats(zone, dns_zonestatscounter_xfrfail);
17716 break;
17717 }
17718 zone_settimer(zone, &now);
17719
17720 /*
17721 * If creating the transfer object failed, zone->xfr is NULL.
17722 * Otherwise, we are called as the done callback of a zone
17723 * transfer object that just entered its shutting-down
17724 * state. Since we are no longer responsible for shutting
17725 * it down, we can detach our reference.
17726 */
17727 if (zone->xfr != NULL) {
17728 dns_xfrin_detach(&zone->xfr);
17729 }
17730
17731 if (zone->tsigkey != NULL) {
17732 dns_tsigkey_detach(&zone->tsigkey);
17733 }
17734
17735 /*
17736 * Handle any deferred journal compaction.
17737 */
17738 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDCOMPACT)) {
17739 dns_db_t *db = NULL;
17740 if (dns_zone_getdb(zone, &db) == ISC_R_SUCCESS) {
17741 zone_journal_compact(zone, db, zone->compact_serial);
17742 dns_db_detach(&db);
17743 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
17744 }
17745 }
17746
17747 if (secure != NULL) {
17748 UNLOCK_ZONE(secure);
17749 }
17750 /*
17751 * This transfer finishing freed up a transfer quota slot.
17752 * Let any other zones waiting for quota have it.
17753 */
17754 if (zone->zmgr != NULL &&
17755 zone->statelist == &zone->zmgr->xfrin_in_progress)
17756 {
17757 UNLOCK_ZONE(zone);
17758 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
17759 ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
17760 zone->statelist = NULL;
17761 zmgr_resume_xfrs(zone->zmgr, false);
17762 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
17763 LOCK_ZONE(zone);
17764 }
17765
17766 /*
17767 * Retry with a different server if necessary.
17768 */
17769 if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
17770 queue_soa_query(zone);
17771 }
17772
17773 isc_refcount_decrement(&zone->irefs);
17774 free_needed = exit_check(zone);
17775 UNLOCK_ZONE(zone);
17776 if (free_needed) {
17777 zone_free(zone);
17778 }
17779 }
17780
17781 static void
17782 zone_loaddone(void *arg, isc_result_t result) {
17783 static char me[] = "zone_loaddone";
17784 dns_load_t *load = arg;
17785 dns_zone_t *zone;
17786 isc_result_t tresult;
17787 dns_zone_t *secure = NULL;
17788
17789 REQUIRE(DNS_LOAD_VALID(load));
17790 zone = load->zone;
17791
17792 ENTER;
17793
17794 /*
17795 * If zone loading failed, remove the update db callbacks prior
17796 * to calling the list of callbacks in the zone load structure.
17797 */
17798 if (result != ISC_R_SUCCESS) {
17799 dns_zone_rpz_disable_db(zone, load->db);
17800 dns_zone_catz_disable_db(zone, load->db);
17801 }
17802
17803 tresult = dns_db_endload(load->db, &load->callbacks);
17804 if (tresult != ISC_R_SUCCESS &&
17805 (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
17806 {
17807 result = tresult;
17808 }
17809
17810 /*
17811 * Lock hierarchy: zmgr, zone, raw.
17812 */
17813 again:
17814 LOCK_ZONE(zone);
17815 INSIST(zone != zone->raw);
17816 if (inline_secure(zone)) {
17817 LOCK_ZONE(zone->raw);
17818 } else if (inline_raw(zone)) {
17819 secure = zone->secure;
17820 TRYLOCK_ZONE(tresult, secure);
17821 if (tresult != ISC_R_SUCCESS) {
17822 UNLOCK_ZONE(zone);
17823 secure = NULL;
17824 isc_thread_yield();
17825 goto again;
17826 }
17827 }
17828 (void)zone_postload(zone, load->db, load->loadtime, result);
17829 zonemgr_putio(&zone->readio);
17830 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADING);
17831 zone_idetach(&load->callbacks.zone);
17832 /*
17833 * Leave the zone frozen if the reload fails.
17834 */
17835 if ((result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) &&
17836 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_THAW))
17837 {
17838 zone->update_disabled = false;
17839 }
17840 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_THAW);
17841 if (inline_secure(zone)) {
17842 UNLOCK_ZONE(zone->raw);
17843 } else if (secure != NULL) {
17844 UNLOCK_ZONE(secure);
17845 }
17846 UNLOCK_ZONE(zone);
17847
17848 load->magic = 0;
17849 dns_db_detach(&load->db);
17850 if (load->zone->lctx != NULL) {
17851 dns_loadctx_detach(&load->zone->lctx);
17852 }
17853 dns_zone_idetach(&load->zone);
17854 isc_mem_putanddetach(&load->mctx, load, sizeof(*load));
17855 }
17856
17857 void
17858 dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) {
17859 REQUIRE(DNS_ZONE_VALID(zone));
17860 REQUIRE(table != NULL);
17861 REQUIRE(*table == NULL);
17862
17863 LOCK_ZONE(zone);
17864 if (zone->ssutable != NULL) {
17865 dns_ssutable_attach(zone->ssutable, table);
17866 }
17867 UNLOCK_ZONE(zone);
17868 }
17869
17870 void
17871 dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
17872 REQUIRE(DNS_ZONE_VALID(zone));
17873
17874 LOCK_ZONE(zone);
17875 if (zone->ssutable != NULL) {
17876 dns_ssutable_detach(&zone->ssutable);
17877 }
17878 if (table != NULL) {
17879 dns_ssutable_attach(table, &zone->ssutable);
17880 }
17881 UNLOCK_ZONE(zone);
17882 }
17883
17884 void
17885 dns_zone_setsigvalidityinterval(dns_zone_t *zone, uint32_t interval) {
17886 REQUIRE(DNS_ZONE_VALID(zone));
17887
17888 zone->sigvalidityinterval = interval;
17889 }
17890
17891 uint32_t
17892 dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
17893 REQUIRE(DNS_ZONE_VALID(zone));
17894
17895 return (zone->sigvalidityinterval);
17896 }
17897
17898 void
17899 dns_zone_setkeyvalidityinterval(dns_zone_t *zone, uint32_t interval) {
17900 REQUIRE(DNS_ZONE_VALID(zone));
17901
17902 zone->keyvalidityinterval = interval;
17903 }
17904
17905 uint32_t
17906 dns_zone_getkeyvalidityinterval(dns_zone_t *zone) {
17907 REQUIRE(DNS_ZONE_VALID(zone));
17908
17909 return (zone->keyvalidityinterval);
17910 }
17911
17912 void
17913 dns_zone_setsigresigninginterval(dns_zone_t *zone, uint32_t interval) {
17914 isc_time_t now;
17915
17916 REQUIRE(DNS_ZONE_VALID(zone));
17917
17918 LOCK_ZONE(zone);
17919 zone->sigresigninginterval = interval;
17920 set_resigntime(zone);
17921 if (zone->task != NULL) {
17922 TIME_NOW(&now);
17923 zone_settimer(zone, &now);
17924 }
17925 UNLOCK_ZONE(zone);
17926 }
17927
17928 uint32_t
17929 dns_zone_getsigresigninginterval(dns_zone_t *zone) {
17930 REQUIRE(DNS_ZONE_VALID(zone));
17931
17932 return (zone->sigresigninginterval);
17933 }
17934
17935 static void
17936 queue_xfrin(dns_zone_t *zone) {
17937 const char me[] = "queue_xfrin";
17938 isc_result_t result;
17939 dns_zonemgr_t *zmgr = zone->zmgr;
17940
17941 ENTER;
17942
17943 INSIST(zone->statelist == NULL);
17944
17945 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
17946 ISC_LIST_APPEND(zmgr->waiting_for_xfrin, zone, statelink);
17947 isc_refcount_increment0(&zone->irefs);
17948 zone->statelist = &zmgr->waiting_for_xfrin;
17949 result = zmgr_start_xfrin_ifquota(zmgr, zone);
17950 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
17951
17952 if (result == ISC_R_QUOTA) {
17953 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
17954 "zone transfer deferred due to quota");
17955 } else if (result != ISC_R_SUCCESS) {
17956 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
17957 "starting zone transfer: %s",
17958 isc_result_totext(result));
17959 }
17960 }
17961
17962 /*
17963 * This event callback is called when a zone has received
17964 * any necessary zone transfer quota. This is the time
17965 * to go ahead and start the transfer.
17966 */
17967 static void
17968 got_transfer_quota(isc_task_t *task, isc_event_t *event) {
17969 isc_result_t result = ISC_R_SUCCESS;
17970 dns_peer_t *peer = NULL;
17971 char master[ISC_SOCKADDR_FORMATSIZE];
17972 char source[ISC_SOCKADDR_FORMATSIZE];
17973 dns_rdatatype_t xfrtype;
17974 dns_zone_t *zone = event->ev_arg;
17975 isc_netaddr_t masterip;
17976 isc_sockaddr_t sourceaddr;
17977 isc_sockaddr_t masteraddr;
17978 isc_time_t now;
17979 const char *soa_before = "";
17980 isc_dscp_t dscp = -1;
17981 bool loaded;
17982
17983 UNUSED(task);
17984
17985 INSIST(task == zone->task);
17986
17987 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
17988 result = ISC_R_CANCELED;
17989 goto cleanup;
17990 }
17991
17992 TIME_NOW(&now);
17993
17994 isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
17995 if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
17996 &zone->sourceaddr, &now))
17997 {
17998 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
17999 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
18000 "got_transfer_quota: skipping zone transfer as "
18001 "master %s (source %s) is unreachable (cached)",
18002 master, source);
18003 result = ISC_R_CANCELED;
18004 goto cleanup;
18005 }
18006
18007 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
18008 (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
18009
18010 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR)) {
18011 soa_before = "SOA before ";
18012 }
18013 /*
18014 * Decide whether we should request IXFR or AXFR.
18015 */
18016 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
18017 loaded = (zone->db != NULL);
18018 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
18019
18020 if (!loaded) {
18021 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(1),
18022 "no database exists yet, requesting AXFR of "
18023 "initial version from %s",
18024 master);
18025 xfrtype = dns_rdatatype_axfr;
18026 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
18027 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(1),
18028 "forced reload, requesting AXFR of "
18029 "initial version from %s",
18030 master);
18031 xfrtype = dns_rdatatype_axfr;
18032 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOIXFR)) {
18033 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(1),
18034 "retrying with AXFR from %s due to "
18035 "previous IXFR failure",
18036 master);
18037 xfrtype = dns_rdatatype_axfr;
18038 LOCK_ZONE(zone);
18039 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOIXFR);
18040 UNLOCK_ZONE(zone);
18041 } else {
18042 bool use_ixfr = true;
18043 if (peer != NULL) {
18044 result = dns_peer_getrequestixfr(peer, &use_ixfr);
18045 }
18046 if (peer == NULL || result != ISC_R_SUCCESS) {
18047 use_ixfr = zone->requestixfr;
18048 }
18049 if (!use_ixfr) {
18050 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
18051 ISC_LOG_DEBUG(1),
18052 "IXFR disabled, "
18053 "requesting %sAXFR from %s",
18054 soa_before, master);
18055 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR)) {
18056 xfrtype = dns_rdatatype_soa;
18057 } else {
18058 xfrtype = dns_rdatatype_axfr;
18059 }
18060 } else {
18061 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
18062 ISC_LOG_DEBUG(1),
18063 "requesting IXFR from %s", master);
18064 xfrtype = dns_rdatatype_ixfr;
18065 }
18066 }
18067
18068 /*
18069 * Determine if we should attempt to sign the request with TSIG.
18070 */
18071 result = ISC_R_NOTFOUND;
18072
18073 /*
18074 * First, look for a tsig key in the master statement, then
18075 * try for a server key.
18076 */
18077 if ((zone->masterkeynames != NULL) &&
18078 (zone->masterkeynames[zone->curmaster] != NULL))
18079 {
18080 dns_view_t *view = dns_zone_getview(zone);
18081 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
18082 result = dns_view_gettsig(view, keyname, &zone->tsigkey);
18083 }
18084 if (zone->tsigkey == NULL) {
18085 result = dns_view_getpeertsig(zone->view, &masterip,
18086 &zone->tsigkey);
18087 }
18088
18089 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
18090 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
18091 "could not get TSIG key for zone transfer: %s",
18092 isc_result_totext(result));
18093 }
18094
18095 if (zone->masterdscps != NULL) {
18096 dscp = zone->masterdscps[zone->curmaster];
18097 }
18098
18099 LOCK_ZONE(zone);
18100 masteraddr = zone->masteraddr;
18101 sourceaddr = zone->sourceaddr;
18102 switch (isc_sockaddr_pf(&masteraddr)) {
18103 case PF_INET:
18104 if (dscp == -1) {
18105 dscp = zone->xfrsource4dscp;
18106 }
18107 break;
18108 case PF_INET6:
18109 if (dscp == -1) {
18110 dscp = zone->xfrsource6dscp;
18111 }
18112 break;
18113 default:
18114 UNREACHABLE();
18115 }
18116 UNLOCK_ZONE(zone);
18117 INSIST(isc_sockaddr_pf(&masteraddr) == isc_sockaddr_pf(&sourceaddr));
18118 result = dns_xfrin_create(zone, xfrtype, &masteraddr, &sourceaddr, dscp,
18119 zone->tsigkey, zone->mctx,
18120 zone->zmgr->timermgr, zone->zmgr->socketmgr,
18121 zone->task, zone_xfrdone, &zone->xfr);
18122 if (result == ISC_R_SUCCESS) {
18123 LOCK_ZONE(zone);
18124 if (xfrtype == dns_rdatatype_axfr) {
18125 if (isc_sockaddr_pf(&masteraddr) == PF_INET) {
18126 inc_stats(zone, dns_zonestatscounter_axfrreqv4);
18127 } else {
18128 inc_stats(zone, dns_zonestatscounter_axfrreqv6);
18129 }
18130 } else if (xfrtype == dns_rdatatype_ixfr) {
18131 if (isc_sockaddr_pf(&masteraddr) == PF_INET) {
18132 inc_stats(zone, dns_zonestatscounter_ixfrreqv4);
18133 } else {
18134 inc_stats(zone, dns_zonestatscounter_ixfrreqv6);
18135 }
18136 }
18137 UNLOCK_ZONE(zone);
18138 }
18139 cleanup:
18140 /*
18141 * Any failure in this function is handled like a failed
18142 * zone transfer. This ensures that we get removed from
18143 * zmgr->xfrin_in_progress.
18144 */
18145 if (result != ISC_R_SUCCESS) {
18146 zone_xfrdone(zone, result);
18147 }
18148
18149 isc_event_free(&event);
18150 }
18151
18152 /*
18153 * Update forwarding support.
18154 */
18155
18156 static void
18157 forward_destroy(dns_forward_t *forward) {
18158 forward->magic = 0;
18159 if (forward->request != NULL) {
18160 dns_request_destroy(&forward->request);
18161 }
18162 if (forward->msgbuf != NULL) {
18163 isc_buffer_free(&forward->msgbuf);
18164 }
18165 if (forward->zone != NULL) {
18166 LOCK(&forward->zone->lock);
18167 if (ISC_LINK_LINKED(forward, link)) {
18168 ISC_LIST_UNLINK(forward->zone->forwards, forward, link);
18169 }
18170 UNLOCK(&forward->zone->lock);
18171 dns_zone_idetach(&forward->zone);
18172 }
18173 isc_mem_putanddetach(&forward->mctx, forward, sizeof(*forward));
18174 }
18175
18176 static isc_result_t
18177 sendtomaster(dns_forward_t *forward) {
18178 isc_result_t result;
18179 isc_sockaddr_t src;
18180 isc_dscp_t dscp = -1;
18181
18182 LOCK_ZONE(forward->zone);
18183
18184 if (DNS_ZONE_FLAG(forward->zone, DNS_ZONEFLG_EXITING)) {
18185 UNLOCK_ZONE(forward->zone);
18186 return (ISC_R_CANCELED);
18187 }
18188
18189 if (forward->which >= forward->zone->masterscnt) {
18190 UNLOCK_ZONE(forward->zone);
18191 return (ISC_R_NOMORE);
18192 }
18193
18194 forward->addr = forward->zone->masters[forward->which];
18195 /*
18196 * Always use TCP regardless of whether the original update
18197 * used TCP.
18198 * XXX The timeout may but a bit small if we are far down a
18199 * transfer graph and the master has to try several masters.
18200 */
18201 switch (isc_sockaddr_pf(&forward->addr)) {
18202 case PF_INET:
18203 src = forward->zone->xfrsource4;
18204 dscp = forward->zone->xfrsource4dscp;
18205 break;
18206 case PF_INET6:
18207 src = forward->zone->xfrsource6;
18208 dscp = forward->zone->xfrsource6dscp;
18209 break;
18210 default:
18211 result = ISC_R_NOTIMPLEMENTED;
18212 goto unlock;
18213 }
18214 result = dns_request_createraw(forward->zone->view->requestmgr,
18215 forward->msgbuf, &src, &forward->addr,
18216 dscp, forward->options, 15 /* XXX */, 0,
18217 0, forward->zone->task, forward_callback,
18218 forward, &forward->request);
18219 if (result == ISC_R_SUCCESS) {
18220 if (!ISC_LINK_LINKED(forward, link)) {
18221 ISC_LIST_APPEND(forward->zone->forwards, forward, link);
18222 }
18223 }
18224
18225 unlock:
18226 UNLOCK_ZONE(forward->zone);
18227 return (result);
18228 }
18229
18230 static void
18231 forward_callback(isc_task_t *task, isc_event_t *event) {
18232 const char me[] = "forward_callback";
18233 dns_requestevent_t *revent = (dns_requestevent_t *)event;
18234 dns_message_t *msg = NULL;
18235 char master[ISC_SOCKADDR_FORMATSIZE];
18236 isc_result_t result;
18237 dns_forward_t *forward;
18238 dns_zone_t *zone;
18239
18240 UNUSED(task);
18241
18242 forward = revent->ev_arg;
18243 INSIST(DNS_FORWARD_VALID(forward));
18244 zone = forward->zone;
18245 INSIST(DNS_ZONE_VALID(zone));
18246
18247 ENTER;
18248
18249 isc_sockaddr_format(&forward->addr, master, sizeof(master));
18250
18251 if (revent->result != ISC_R_SUCCESS) {
18252 dns_zone_log(zone, ISC_LOG_INFO,
18253 "could not forward dynamic update to %s: %s",
18254 master, dns_result_totext(revent->result));
18255 goto next_master;
18256 }
18257
18258 dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
18259
18260 result = dns_request_getresponse(revent->request, msg,
18261 DNS_MESSAGEPARSE_PRESERVEORDER |
18262 DNS_MESSAGEPARSE_CLONEBUFFER);
18263 if (result != ISC_R_SUCCESS) {
18264 goto next_master;
18265 }
18266
18267 /*
18268 * Unexpected opcode.
18269 */
18270 if (msg->opcode != dns_opcode_update) {
18271 char opcode[128];
18272 isc_buffer_t rb;
18273
18274 isc_buffer_init(&rb, opcode, sizeof(opcode));
18275 (void)dns_opcode_totext(msg->opcode, &rb);
18276
18277 dns_zone_log(zone, ISC_LOG_INFO,
18278 "forwarding dynamic update: "
18279 "unexpected opcode (%.*s) from %s",
18280 (int)rb.used, opcode, master);
18281 goto next_master;
18282 }
18283
18284 switch (msg->rcode) {
18285 /*
18286 * Pass these rcodes back to client.
18287 */
18288 case dns_rcode_noerror:
18289 case dns_rcode_yxdomain:
18290 case dns_rcode_yxrrset:
18291 case dns_rcode_nxrrset:
18292 case dns_rcode_refused:
18293 case dns_rcode_nxdomain: {
18294 char rcode[128];
18295 isc_buffer_t rb;
18296
18297 isc_buffer_init(&rb, rcode, sizeof(rcode));
18298 (void)dns_rcode_totext(msg->rcode, &rb);
18299 dns_zone_log(zone, ISC_LOG_INFO,
18300 "forwarded dynamic update: "
18301 "master %s returned: %.*s",
18302 master, (int)rb.used, rcode);
18303 break;
18304 }
18305
18306 /* These should not occur if the primaries/zone are valid. */
18307 case dns_rcode_notzone:
18308 case dns_rcode_notauth: {
18309 char rcode[128];
18310 isc_buffer_t rb;
18311
18312 isc_buffer_init(&rb, rcode, sizeof(rcode));
18313 (void)dns_rcode_totext(msg->rcode, &rb);
18314 dns_zone_log(zone, ISC_LOG_WARNING,
18315 "forwarding dynamic update: "
18316 "unexpected response: master %s returned: %.*s",
18317 master, (int)rb.used, rcode);
18318 goto next_master;
18319 }
18320
18321 /* Try another server for these rcodes. */
18322 case dns_rcode_formerr:
18323 case dns_rcode_servfail:
18324 case dns_rcode_notimp:
18325 case dns_rcode_badvers:
18326 default:
18327 goto next_master;
18328 }
18329
18330 /* call callback */
18331 (forward->callback)(forward->callback_arg, ISC_R_SUCCESS, msg);
18332 msg = NULL;
18333 dns_request_destroy(&forward->request);
18334 forward_destroy(forward);
18335 isc_event_free(&event);
18336 return;
18337
18338 next_master:
18339 if (msg != NULL) {
18340 dns_message_detach(&msg);
18341 }
18342 isc_event_free(&event);
18343 forward->which++;
18344 dns_request_destroy(&forward->request);
18345 result = sendtomaster(forward);
18346 if (result != ISC_R_SUCCESS) {
18347 /* call callback */
18348 dns_zone_log(zone, ISC_LOG_DEBUG(3),
18349 "exhausted dynamic update forwarder list");
18350 (forward->callback)(forward->callback_arg, result, NULL);
18351 forward_destroy(forward);
18352 }
18353 }
18354
18355 isc_result_t
18356 dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
18357 dns_updatecallback_t callback, void *callback_arg) {
18358 dns_forward_t *forward;
18359 isc_result_t result;
18360 isc_region_t *mr;
18361
18362 REQUIRE(DNS_ZONE_VALID(zone));
18363 REQUIRE(msg != NULL);
18364 REQUIRE(callback != NULL);
18365
18366 forward = isc_mem_get(zone->mctx, sizeof(*forward));
18367
18368 forward->request = NULL;
18369 forward->zone = NULL;
18370 forward->msgbuf = NULL;
18371 forward->which = 0;
18372 forward->mctx = 0;
18373 forward->callback = callback;
18374 forward->callback_arg = callback_arg;
18375 ISC_LINK_INIT(forward, link);
18376 forward->magic = FORWARD_MAGIC;
18377 forward->options = DNS_REQUESTOPT_TCP;
18378 /*
18379 * If we have a SIG(0) signed message we need to preserve the
18380 * query id as that is included in the SIG(0) computation.
18381 */
18382 if (msg->sig0 != NULL) {
18383 forward->options |= DNS_REQUESTOPT_FIXEDID;
18384 }
18385
18386 mr = dns_message_getrawmessage(msg);
18387 if (mr == NULL) {
18388 result = ISC_R_UNEXPECTEDEND;
18389 goto cleanup;
18390 }
18391
18392 isc_buffer_allocate(zone->mctx, &forward->msgbuf, mr->length);
18393 result = isc_buffer_copyregion(forward->msgbuf, mr);
18394 if (result != ISC_R_SUCCESS) {
18395 goto cleanup;
18396 }
18397
18398 isc_mem_attach(zone->mctx, &forward->mctx);
18399 dns_zone_iattach(zone, &forward->zone);
18400 result = sendtomaster(forward);
18401
18402 cleanup:
18403 if (result != ISC_R_SUCCESS) {
18404 forward_destroy(forward);
18405 }
18406 return (result);
18407 }
18408
18409 isc_result_t
18410 dns_zone_next(dns_zone_t *zone, dns_zone_t **next) {
18411 REQUIRE(DNS_ZONE_VALID(zone));
18412 REQUIRE(next != NULL && *next == NULL);
18413
18414 *next = ISC_LIST_NEXT(zone, link);
18415 if (*next == NULL) {
18416 return (ISC_R_NOMORE);
18417 } else {
18418 return (ISC_R_SUCCESS);
18419 }
18420 }
18421
18422 isc_result_t
18423 dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) {
18424 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18425 REQUIRE(first != NULL && *first == NULL);
18426
18427 *first = ISC_LIST_HEAD(zmgr->zones);
18428 if (*first == NULL) {
18429 return (ISC_R_NOMORE);
18430 } else {
18431 return (ISC_R_SUCCESS);
18432 }
18433 }
18434
18435 /***
18436 *** Zone manager.
18437 ***/
18438
18439 #define KEYMGMT_OVERCOMMIT 3
18440 #define KEYMGMT_BITS_MIN 2U
18441 #define KEYMGMT_BITS_MAX 32U
18442
18443 /*
18444 * WMM: Static hash functions copied from lib/dns/rbtdb.c. Should be moved to
18445 * lib/isc/hash.c when we refactor the hash table code.
18446 */
18447 #define GOLDEN_RATIO_32 0x61C88647
18448 #define HASHSIZE(bits) (UINT64_C(1) << (bits))
18449
18450 static uint32_t
18451 hash_index(uint32_t val, uint32_t bits) {
18452 return (val * GOLDEN_RATIO_32 >> (32 - bits));
18453 }
18454
18455 static uint32_t
18456 hash_bits_grow(uint32_t bits, uint32_t count) {
18457 uint32_t newbits = bits;
18458 while (count >= HASHSIZE(newbits) && newbits < KEYMGMT_BITS_MAX) {
18459 newbits++;
18460 }
18461 return (newbits);
18462 }
18463
18464 static uint32_t
18465 hash_bits_shrink(uint32_t bits, uint32_t count) {
18466 uint32_t newbits = bits;
18467 while (count <= HASHSIZE(newbits) && newbits > KEYMGMT_BITS_MIN) {
18468 newbits--;
18469 }
18470 return (newbits);
18471 }
18472
18473 static void
18474 zonemgr_keymgmt_init(dns_zonemgr_t *zmgr) {
18475 dns_keymgmt_t *mgmt = isc_mem_get(zmgr->mctx, sizeof(*mgmt));
18476 uint32_t size;
18477
18478 *mgmt = (dns_keymgmt_t){
18479 .bits = KEYMGMT_BITS_MIN,
18480 };
18481 isc_mem_attach(zmgr->mctx, &mgmt->mctx);
18482 isc_rwlock_init(&mgmt->lock, 0, 0);
18483
18484 size = HASHSIZE(mgmt->bits);
18485 mgmt->table = isc_mem_get(mgmt->mctx, sizeof(*mgmt->table) * size);
18486 memset(mgmt->table, 0, size * sizeof(mgmt->table[0]));
18487
18488 atomic_init(&mgmt->count, 0);
18489 mgmt->magic = KEYMGMT_MAGIC;
18490
18491 zmgr->keymgmt = mgmt;
18492 }
18493
18494 static void
18495 zonemgr_keymgmt_destroy(dns_zonemgr_t *zmgr) {
18496 dns_keymgmt_t *mgmt = zmgr->keymgmt;
18497 uint32_t size;
18498
18499 REQUIRE(DNS_KEYMGMT_VALID(mgmt));
18500
18501 size = HASHSIZE(mgmt->bits);
18502
18503 RWLOCK(&mgmt->lock, isc_rwlocktype_write);
18504 INSIST(mgmt->count == 0);
18505 RWUNLOCK(&mgmt->lock, isc_rwlocktype_write);
18506
18507 mgmt->magic = 0;
18508 isc_rwlock_destroy(&mgmt->lock);
18509 isc_mem_put(mgmt->mctx, mgmt->table, size * sizeof(mgmt->table[0]));
18510 isc_mem_putanddetach(&mgmt->mctx, mgmt, sizeof(dns_keymgmt_t));
18511 }
18512
18513 static void
18514 zonemgr_keymgmt_resize(dns_zonemgr_t *zmgr) {
18515 dns_keyfileio_t **newtable;
18516 dns_keymgmt_t *mgmt = zmgr->keymgmt;
18517 uint32_t bits, newbits, count, size, newsize;
18518 bool grow;
18519
18520 REQUIRE(DNS_KEYMGMT_VALID(mgmt));
18521
18522 RWLOCK(&mgmt->lock, isc_rwlocktype_read);
18523 count = atomic_load_relaxed(&mgmt->count);
18524 bits = mgmt->bits;
18525 RWUNLOCK(&mgmt->lock, isc_rwlocktype_read);
18526
18527 size = HASHSIZE(bits);
18528 INSIST(size > 0);
18529
18530 if (count >= (size * KEYMGMT_OVERCOMMIT)) {
18531 grow = true;
18532 } else if (count < (size / 2)) {
18533 grow = false;
18534 } else {
18535 /* No need to resize. */
18536 return;
18537 }
18538
18539 if (grow) {
18540 newbits = hash_bits_grow(bits, count);
18541 } else {
18542 newbits = hash_bits_shrink(bits, count);
18543 }
18544
18545 if (newbits == bits) {
18546 /*
18547 * Bit values may stay the same if maximum or minimum is
18548 * reached.
18549 */
18550 return;
18551 }
18552
18553 newsize = HASHSIZE(newbits);
18554 INSIST(newsize > 0);
18555
18556 RWLOCK(&mgmt->lock, isc_rwlocktype_write);
18557
18558 newtable = isc_mem_get(mgmt->mctx, sizeof(dns_keyfileio_t *) * newsize);
18559 memset(newtable, 0, sizeof(dns_keyfileio_t *) * newsize);
18560
18561 for (unsigned int i = 0; i < size; i++) {
18562 dns_keyfileio_t *kfio, *next;
18563 for (kfio = mgmt->table[i]; kfio != NULL; kfio = next) {
18564 uint32_t hash = hash_index(kfio->hashval, newbits);
18565 next = kfio->next;
18566 kfio->next = newtable[hash];
18567 newtable[hash] = kfio;
18568 }
18569 mgmt->table[i] = NULL;
18570 }
18571
18572 isc_mem_put(mgmt->mctx, mgmt->table, sizeof(*mgmt->table) * size);
18573 mgmt->bits = newbits;
18574 mgmt->table = newtable;
18575
18576 RWUNLOCK(&mgmt->lock, isc_rwlocktype_write);
18577 }
18578
18579 static void
18580 zonemgr_keymgmt_add(dns_zonemgr_t *zmgr, dns_zone_t *zone,
18581 dns_keyfileio_t **added) {
18582 dns_keymgmt_t *mgmt = zmgr->keymgmt;
18583 uint32_t hashval, hash;
18584 dns_keyfileio_t *kfio, *next;
18585
18586 REQUIRE(DNS_KEYMGMT_VALID(mgmt));
18587 REQUIRE(added != NULL && *added == NULL);
18588
18589 RWLOCK(&mgmt->lock, isc_rwlocktype_write);
18590
18591 hashval = dns_name_hash(&zone->origin, false);
18592 hash = hash_index(hashval, mgmt->bits);
18593
18594 for (kfio = mgmt->table[hash]; kfio != NULL; kfio = next) {
18595 next = kfio->next;
18596 if (dns_name_equal(kfio->name, &zone->origin)) {
18597 /* Already in table, increment the counter. */
18598 isc_refcount_increment(&kfio->references);
18599 break;
18600 }
18601 }
18602
18603 if (kfio == NULL) {
18604 /* No entry found, add it. */
18605 kfio = isc_mem_get(mgmt->mctx, sizeof(*kfio));
18606 *kfio = (dns_keyfileio_t){
18607 .hashval = hashval,
18608 .next = mgmt->table[hash],
18609 .magic = KEYFILEIO_MAGIC,
18610 };
18611
18612 isc_refcount_init(&kfio->references, 1);
18613
18614 kfio->name = dns_fixedname_initname(&kfio->fname);
18615 dns_name_copynf(&zone->origin, kfio->name);
18616
18617 isc_mutex_init(&kfio->lock);
18618
18619 mgmt->table[hash] = kfio;
18620
18621 atomic_fetch_add_relaxed(&mgmt->count, 1);
18622 }
18623
18624 RWUNLOCK(&mgmt->lock, isc_rwlocktype_write);
18625
18626 *added = kfio;
18627
18628 /*
18629 * Call resize, that function will also check if resize is necessary.
18630 */
18631 zonemgr_keymgmt_resize(zmgr);
18632 }
18633
18634 static void
18635 zonemgr_keymgmt_delete(dns_zonemgr_t *zmgr, dns_zone_t *zone,
18636 dns_keyfileio_t **deleted) {
18637 dns_keymgmt_t *mgmt = zmgr->keymgmt;
18638 uint32_t hashval, hash;
18639 dns_keyfileio_t *kfio, *prev, *next;
18640
18641 REQUIRE(DNS_KEYMGMT_VALID(mgmt));
18642 REQUIRE(deleted != NULL && DNS_KEYFILEIO_VALID(*deleted));
18643
18644 RWLOCK(&mgmt->lock, isc_rwlocktype_write);
18645
18646 hashval = dns_name_hash(&zone->origin, false);
18647 hash = hash_index(hashval, mgmt->bits);
18648
18649 prev = NULL;
18650 for (kfio = mgmt->table[hash]; kfio != NULL; kfio = next) {
18651 next = kfio->next;
18652 if (dns_name_equal(kfio->name, &zone->origin)) {
18653 INSIST(kfio == *deleted);
18654 *deleted = NULL;
18655
18656 if (isc_refcount_decrement(&kfio->references) == 1) {
18657 if (prev == NULL) {
18658 mgmt->table[hash] = kfio->next;
18659 } else {
18660 prev->next = kfio->next;
18661 }
18662
18663 isc_refcount_destroy(&kfio->references);
18664 isc_mutex_destroy(&kfio->lock);
18665 isc_mem_put(mgmt->mctx, kfio, sizeof(*kfio));
18666
18667 atomic_fetch_sub_relaxed(&mgmt->count, 1);
18668 }
18669 break;
18670 }
18671
18672 prev = kfio;
18673 }
18674
18675 RWUNLOCK(&mgmt->lock, isc_rwlocktype_write);
18676
18677 /*
18678 * Call resize, that function will also check if resize is necessary.
18679 */
18680 zonemgr_keymgmt_resize(zmgr);
18681 }
18682
18683 isc_result_t
18684 dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
18685 isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
18686 dns_zonemgr_t **zmgrp) {
18687 dns_zonemgr_t *zmgr;
18688 isc_result_t result;
18689
18690 zmgr = isc_mem_get(mctx, sizeof(*zmgr));
18691 zmgr->mctx = NULL;
18692 isc_refcount_init(&zmgr->refs, 1);
18693 isc_mem_attach(mctx, &zmgr->mctx);
18694 zmgr->taskmgr = taskmgr;
18695 zmgr->timermgr = timermgr;
18696 zmgr->socketmgr = socketmgr;
18697 zmgr->zonetasks = NULL;
18698 zmgr->loadtasks = NULL;
18699 zmgr->mctxpool = NULL;
18700 zmgr->task = NULL;
18701 zmgr->checkdsrl = NULL;
18702 zmgr->notifyrl = NULL;
18703 zmgr->refreshrl = NULL;
18704 zmgr->startupnotifyrl = NULL;
18705 zmgr->startuprefreshrl = NULL;
18706 ISC_LIST_INIT(zmgr->zones);
18707 ISC_LIST_INIT(zmgr->waiting_for_xfrin);
18708 ISC_LIST_INIT(zmgr->xfrin_in_progress);
18709 memset(zmgr->unreachable, 0, sizeof(zmgr->unreachable));
18710 for (size_t i = 0; i < UNREACH_CACHE_SIZE; i++) {
18711 atomic_init(&zmgr->unreachable[i].expire, 0);
18712 }
18713 isc_rwlock_init(&zmgr->rwlock, 0, 0);
18714
18715 zmgr->transfersin = 10;
18716 zmgr->transfersperns = 2;
18717
18718 /* Unreachable lock. */
18719 isc_rwlock_init(&zmgr->urlock, 0, 0);
18720
18721 /* Create a single task for queueing of SOA queries. */
18722 result = isc_task_create(taskmgr, 1, &zmgr->task);
18723 if (result != ISC_R_SUCCESS) {
18724 goto free_urlock;
18725 }
18726
18727 isc_task_setname(zmgr->task, "zmgr", zmgr);
18728 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
18729 &zmgr->checkdsrl);
18730 if (result != ISC_R_SUCCESS) {
18731 goto free_task;
18732 }
18733
18734 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
18735 &zmgr->notifyrl);
18736 if (result != ISC_R_SUCCESS) {
18737 goto free_checkdsrl;
18738 }
18739
18740 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
18741 &zmgr->refreshrl);
18742 if (result != ISC_R_SUCCESS) {
18743 goto free_notifyrl;
18744 }
18745
18746 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
18747 &zmgr->startupnotifyrl);
18748 if (result != ISC_R_SUCCESS) {
18749 goto free_refreshrl;
18750 }
18751
18752 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
18753 &zmgr->startuprefreshrl);
18754 if (result != ISC_R_SUCCESS) {
18755 goto free_startupnotifyrl;
18756 }
18757
18758 /* Key file I/O locks. */
18759 zonemgr_keymgmt_init(zmgr);
18760
18761 /* Default to 20 refresh queries / notifies / checkds per second. */
18762 setrl(zmgr->checkdsrl, &zmgr->checkdsrate, 20);
18763 setrl(zmgr->notifyrl, &zmgr->notifyrate, 20);
18764 setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, 20);
18765 setrl(zmgr->refreshrl, &zmgr->serialqueryrate, 20);
18766 setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, 20);
18767 isc_ratelimiter_setpushpop(zmgr->startupnotifyrl, true);
18768 isc_ratelimiter_setpushpop(zmgr->startuprefreshrl, true);
18769
18770 zmgr->iolimit = 1;
18771 zmgr->ioactive = 0;
18772 ISC_LIST_INIT(zmgr->high);
18773 ISC_LIST_INIT(zmgr->low);
18774
18775 isc_mutex_init(&zmgr->iolock);
18776
18777 zmgr->magic = ZONEMGR_MAGIC;
18778
18779 *zmgrp = zmgr;
18780 return (ISC_R_SUCCESS);
18781
18782 #if 0
18783 free_iolock:
18784 isc_mutex_destroy(&zmgr->iolock);
18785 #endif /* if 0 */
18786 free_startupnotifyrl:
18787 isc_ratelimiter_detach(&zmgr->startupnotifyrl);
18788 free_refreshrl:
18789 isc_ratelimiter_detach(&zmgr->refreshrl);
18790 free_notifyrl:
18791 isc_ratelimiter_detach(&zmgr->notifyrl);
18792 free_checkdsrl:
18793 isc_ratelimiter_detach(&zmgr->checkdsrl);
18794 free_task:
18795 isc_task_detach(&zmgr->task);
18796 free_urlock:
18797 isc_rwlock_destroy(&zmgr->urlock);
18798 isc_rwlock_destroy(&zmgr->rwlock);
18799 isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
18800 isc_mem_detach(&mctx);
18801 return (result);
18802 }
18803
18804 isc_result_t
18805 dns_zonemgr_createzone(dns_zonemgr_t *zmgr, dns_zone_t **zonep) {
18806 isc_result_t result;
18807 isc_mem_t *mctx = NULL;
18808 dns_zone_t *zone = NULL;
18809 void *item;
18810
18811 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18812 REQUIRE(zonep != NULL && *zonep == NULL);
18813
18814 if (zmgr->mctxpool == NULL) {
18815 return (ISC_R_FAILURE);
18816 }
18817
18818 item = isc_pool_get(zmgr->mctxpool);
18819 if (item == NULL) {
18820 return (ISC_R_FAILURE);
18821 }
18822
18823 isc_mem_attach((isc_mem_t *)item, &mctx);
18824 result = dns_zone_create(&zone, mctx);
18825 isc_mem_detach(&mctx);
18826
18827 if (result == ISC_R_SUCCESS) {
18828 *zonep = zone;
18829 }
18830
18831 return (result);
18832 }
18833
18834 isc_result_t
18835 dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
18836 isc_result_t result;
18837
18838 REQUIRE(DNS_ZONE_VALID(zone));
18839 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18840
18841 if (zmgr->zonetasks == NULL) {
18842 return (ISC_R_FAILURE);
18843 }
18844
18845 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18846 LOCK_ZONE(zone);
18847 REQUIRE(zone->task == NULL);
18848 REQUIRE(zone->timer == NULL);
18849 REQUIRE(zone->zmgr == NULL);
18850
18851 isc_taskpool_gettask(zmgr->zonetasks, &zone->task);
18852 isc_taskpool_gettask(zmgr->loadtasks, &zone->loadtask);
18853
18854 /*
18855 * Set the task name. The tag will arbitrarily point to one
18856 * of the zones sharing the task (in practice, the one
18857 * to be managed last).
18858 */
18859 isc_task_setname(zone->task, "zone", zone);
18860 isc_task_setname(zone->loadtask, "loadzone", zone);
18861
18862 result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive, NULL,
18863 NULL, zone->task, zone_timer, zone,
18864 &zone->timer);
18865
18866 if (result != ISC_R_SUCCESS) {
18867 goto cleanup_tasks;
18868 }
18869
18870 /*
18871 * The timer "holds" a iref.
18872 */
18873 isc_refcount_increment0(&zone->irefs);
18874
18875 zonemgr_keymgmt_add(zmgr, zone, &zone->kfio);
18876 INSIST(zone->kfio != NULL);
18877
18878 ISC_LIST_APPEND(zmgr->zones, zone, link);
18879 zone->zmgr = zmgr;
18880 isc_refcount_increment(&zmgr->refs);
18881
18882 goto unlock;
18883
18884 cleanup_tasks:
18885 isc_task_detach(&zone->loadtask);
18886 isc_task_detach(&zone->task);
18887
18888 unlock:
18889 UNLOCK_ZONE(zone);
18890 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18891 return (result);
18892 }
18893
18894 void
18895 dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
18896 REQUIRE(DNS_ZONE_VALID(zone));
18897 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18898 REQUIRE(zone->zmgr == zmgr);
18899
18900 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18901 LOCK_ZONE(zone);
18902
18903 ISC_LIST_UNLINK(zmgr->zones, zone, link);
18904
18905 if (zone->kfio != NULL) {
18906 zonemgr_keymgmt_delete(zmgr, zone, &zone->kfio);
18907 ENSURE(zone->kfio == NULL);
18908 }
18909
18910 /* Detach below, outside of the write lock. */
18911 zone->zmgr = NULL;
18912
18913 UNLOCK_ZONE(zone);
18914 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18915
18916 dns_zonemgr_detach(&zmgr);
18917 }
18918
18919 void
18920 dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) {
18921 REQUIRE(DNS_ZONEMGR_VALID(source));
18922 REQUIRE(target != NULL && *target == NULL);
18923
18924 isc_refcount_increment(&source->refs);
18925
18926 *target = source;
18927 }
18928
18929 void
18930 dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
18931 dns_zonemgr_t *zmgr;
18932
18933 REQUIRE(zmgrp != NULL);
18934 zmgr = *zmgrp;
18935 *zmgrp = NULL;
18936 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18937
18938 if (isc_refcount_decrement(&zmgr->refs) == 1) {
18939 zonemgr_free(zmgr);
18940 }
18941 }
18942
18943 isc_result_t
18944 dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
18945 dns_zone_t *p;
18946
18947 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18948
18949 RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
18950 for (p = ISC_LIST_HEAD(zmgr->zones); p != NULL;
18951 p = ISC_LIST_NEXT(p, link))
18952 {
18953 dns_zone_maintenance(p);
18954 }
18955 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
18956
18957 /*
18958 * Recent configuration changes may have increased the
18959 * amount of available transfers quota. Make sure any
18960 * transfers currently blocked on quota get started if
18961 * possible.
18962 */
18963 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18964 zmgr_resume_xfrs(zmgr, true);
18965 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18966 return (ISC_R_SUCCESS);
18967 }
18968
18969 void
18970 dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) {
18971 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18972
18973 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18974 zmgr_resume_xfrs(zmgr, true);
18975 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18976 }
18977
18978 void
18979 dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
18980 dns_zone_t *zone;
18981
18982 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18983
18984 isc_ratelimiter_shutdown(zmgr->checkdsrl);
18985 isc_ratelimiter_shutdown(zmgr->notifyrl);
18986 isc_ratelimiter_shutdown(zmgr->refreshrl);
18987 isc_ratelimiter_shutdown(zmgr->startupnotifyrl);
18988 isc_ratelimiter_shutdown(zmgr->startuprefreshrl);
18989
18990 if (zmgr->task != NULL) {
18991 isc_task_destroy(&zmgr->task);
18992 }
18993 if (zmgr->zonetasks != NULL) {
18994 isc_taskpool_destroy(&zmgr->zonetasks);
18995 }
18996 if (zmgr->loadtasks != NULL) {
18997 isc_taskpool_destroy(&zmgr->loadtasks);
18998 }
18999 if (zmgr->mctxpool != NULL) {
19000 isc_pool_destroy(&zmgr->mctxpool);
19001 }
19002
19003 RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
19004 for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
19005 zone = ISC_LIST_NEXT(zone, link))
19006 {
19007 LOCK_ZONE(zone);
19008 forward_cancel(zone);
19009 UNLOCK_ZONE(zone);
19010 }
19011 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
19012 }
19013
19014 static isc_result_t
19015 mctxinit(void **target, void *arg) {
19016 isc_mem_t *mctx = NULL;
19017
19018 UNUSED(arg);
19019
19020 REQUIRE(target != NULL && *target == NULL);
19021
19022 isc_mem_create(&mctx);
19023 isc_mem_setname(mctx, "zonemgr-pool", NULL);
19024
19025 *target = mctx;
19026 return (ISC_R_SUCCESS);
19027 }
19028
19029 static void
19030 mctxfree(void **target) {
19031 isc_mem_t *mctx = *(isc_mem_t **)target;
19032 isc_mem_detach(&mctx);
19033 *target = NULL;
19034 }
19035
19036 #define ZONES_PER_TASK 100
19037 #define ZONES_PER_MCTX 1000
19038
19039 isc_result_t
19040 dns_zonemgr_setsize(dns_zonemgr_t *zmgr, int num_zones) {
19041 isc_result_t result;
19042 int ntasks = num_zones / ZONES_PER_TASK;
19043 int nmctx = num_zones / ZONES_PER_MCTX;
19044 isc_taskpool_t *pool = NULL;
19045 isc_pool_t *mctxpool = NULL;
19046
19047 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19048
19049 /*
19050 * For anything fewer than 1000 zones we use 10 tasks in
19051 * the task pools. More than that, and we'll scale at one
19052 * task per 100 zones. Similarly, for anything smaller than
19053 * 2000 zones we use 2 memory contexts, then scale at 1:1000.
19054 */
19055 if (ntasks < 10) {
19056 ntasks = 10;
19057 }
19058 if (nmctx < 2) {
19059 nmctx = 2;
19060 }
19061
19062 /* Create or resize the zone task pools. */
19063 if (zmgr->zonetasks == NULL) {
19064 result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx, ntasks,
19065 2, false, &pool);
19066 } else {
19067 result = isc_taskpool_expand(&zmgr->zonetasks, ntasks, false,
19068 &pool);
19069 }
19070
19071 if (result == ISC_R_SUCCESS) {
19072 zmgr->zonetasks = pool;
19073 }
19074
19075 pool = NULL;
19076 if (zmgr->loadtasks == NULL) {
19077 result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx, ntasks,
19078 2, true, &pool);
19079 } else {
19080 result = isc_taskpool_expand(&zmgr->loadtasks, ntasks, true,
19081 &pool);
19082 }
19083
19084 if (result == ISC_R_SUCCESS) {
19085 zmgr->loadtasks = pool;
19086 }
19087
19088 /* Create or resize the zone memory context pool. */
19089 if (zmgr->mctxpool == NULL) {
19090 result = isc_pool_create(zmgr->mctx, nmctx, mctxfree, mctxinit,
19091 NULL, &mctxpool);
19092 } else {
19093 result = isc_pool_expand(&zmgr->mctxpool, nmctx, &mctxpool);
19094 }
19095
19096 if (result == ISC_R_SUCCESS) {
19097 zmgr->mctxpool = mctxpool;
19098 }
19099
19100 return (result);
19101 }
19102
19103 static void
19104 zonemgr_free(dns_zonemgr_t *zmgr) {
19105 isc_mem_t *mctx;
19106
19107 INSIST(ISC_LIST_EMPTY(zmgr->zones));
19108
19109 zmgr->magic = 0;
19110
19111 isc_refcount_destroy(&zmgr->refs);
19112 isc_mutex_destroy(&zmgr->iolock);
19113 isc_ratelimiter_detach(&zmgr->checkdsrl);
19114 isc_ratelimiter_detach(&zmgr->notifyrl);
19115 isc_ratelimiter_detach(&zmgr->refreshrl);
19116 isc_ratelimiter_detach(&zmgr->startupnotifyrl);
19117 isc_ratelimiter_detach(&zmgr->startuprefreshrl);
19118
19119 isc_rwlock_destroy(&zmgr->urlock);
19120 isc_rwlock_destroy(&zmgr->rwlock);
19121
19122 zonemgr_keymgmt_destroy(zmgr);
19123
19124 mctx = zmgr->mctx;
19125 isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
19126 isc_mem_detach(&mctx);
19127 }
19128
19129 void
19130 dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, uint32_t value) {
19131 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19132
19133 zmgr->transfersin = value;
19134 }
19135
19136 uint32_t
19137 dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) {
19138 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19139
19140 return (zmgr->transfersin);
19141 }
19142
19143 void
19144 dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, uint32_t value) {
19145 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19146
19147 zmgr->transfersperns = value;
19148 }
19149
19150 uint32_t
19151 dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr) {
19152 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19153
19154 return (zmgr->transfersperns);
19155 }
19156
19157 isc_taskmgr_t *
19158 dns_zonemgr_gettaskmgr(dns_zonemgr_t *zmgr) {
19159 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19160
19161 return (zmgr->taskmgr);
19162 }
19163
19164 /*
19165 * Try to start a new incoming zone transfer to fill a quota
19166 * slot that was just vacated.
19167 *
19168 * Requires:
19169 * The zone manager is locked by the caller.
19170 */
19171 static void
19172 zmgr_resume_xfrs(dns_zonemgr_t *zmgr, bool multi) {
19173 dns_zone_t *zone;
19174 dns_zone_t *next;
19175
19176 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin); zone != NULL;
19177 zone = next)
19178 {
19179 isc_result_t result;
19180 next = ISC_LIST_NEXT(zone, statelink);
19181 result = zmgr_start_xfrin_ifquota(zmgr, zone);
19182 if (result == ISC_R_SUCCESS) {
19183 if (multi) {
19184 continue;
19185 }
19186 /*
19187 * We successfully filled the slot. We're done.
19188 */
19189 break;
19190 } else if (result == ISC_R_QUOTA) {
19191 /*
19192 * Not enough quota. This is probably the per-server
19193 * quota, because we usually get called when a unit of
19194 * global quota has just been freed. Try the next
19195 * zone, it may succeed if it uses another master.
19196 */
19197 continue;
19198 } else {
19199 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
19200 ISC_LOG_DEBUG(1),
19201 "starting zone transfer: %s",
19202 isc_result_totext(result));
19203 break;
19204 }
19205 }
19206 }
19207
19208 /*
19209 * Try to start an incoming zone transfer for 'zone', quota permitting.
19210 *
19211 * Requires:
19212 * The zone manager is locked by the caller.
19213 *
19214 * Returns:
19215 * ISC_R_SUCCESS There was enough quota and we attempted to
19216 * start a transfer. zone_xfrdone() has been or will
19217 * be called.
19218 * ISC_R_QUOTA Not enough quota.
19219 * Others Failure.
19220 */
19221 static isc_result_t
19222 zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
19223 dns_peer_t *peer = NULL;
19224 isc_netaddr_t masterip;
19225 uint32_t nxfrsin, nxfrsperns;
19226 dns_zone_t *x;
19227 uint32_t maxtransfersin, maxtransfersperns;
19228 isc_event_t *e;
19229
19230 /*
19231 * If we are exiting just pretend we got quota so the zone will
19232 * be cleaned up in the zone's task context.
19233 */
19234 LOCK_ZONE(zone);
19235 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
19236 UNLOCK_ZONE(zone);
19237 goto gotquota;
19238 }
19239
19240 /*
19241 * Find any configured information about the server we'd
19242 * like to transfer this zone from.
19243 */
19244 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
19245 (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
19246 UNLOCK_ZONE(zone);
19247
19248 /*
19249 * Determine the total maximum number of simultaneous
19250 * transfers allowed, and the maximum for this specific
19251 * master.
19252 */
19253 maxtransfersin = zmgr->transfersin;
19254 maxtransfersperns = zmgr->transfersperns;
19255 if (peer != NULL) {
19256 (void)dns_peer_gettransfers(peer, &maxtransfersperns);
19257 }
19258
19259 /*
19260 * Count the total number of transfers that are in progress,
19261 * and the number of transfers in progress from this master.
19262 * We linearly scan a list of all transfers; if this turns
19263 * out to be too slow, we could hash on the master address.
19264 */
19265 nxfrsin = nxfrsperns = 0;
19266 for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress); x != NULL;
19267 x = ISC_LIST_NEXT(x, statelink))
19268 {
19269 isc_netaddr_t xip;
19270
19271 LOCK_ZONE(x);
19272 isc_netaddr_fromsockaddr(&xip, &x->masteraddr);
19273 UNLOCK_ZONE(x);
19274
19275 nxfrsin++;
19276 if (isc_netaddr_equal(&xip, &masterip)) {
19277 nxfrsperns++;
19278 }
19279 }
19280
19281 /* Enforce quota. */
19282 if (nxfrsin >= maxtransfersin) {
19283 return (ISC_R_QUOTA);
19284 }
19285
19286 if (nxfrsperns >= maxtransfersperns) {
19287 return (ISC_R_QUOTA);
19288 }
19289
19290 gotquota:
19291 /*
19292 * We have sufficient quota. Move the zone to the "xfrin_in_progress"
19293 * list and send it an event to let it start the actual transfer in the
19294 * context of its own task.
19295 */
19296 e = isc_event_allocate(zmgr->mctx, zmgr, DNS_EVENT_ZONESTARTXFRIN,
19297 got_transfer_quota, zone, sizeof(isc_event_t));
19298
19299 LOCK_ZONE(zone);
19300 INSIST(zone->statelist == &zmgr->waiting_for_xfrin);
19301 ISC_LIST_UNLINK(zmgr->waiting_for_xfrin, zone, statelink);
19302 ISC_LIST_APPEND(zmgr->xfrin_in_progress, zone, statelink);
19303 zone->statelist = &zmgr->xfrin_in_progress;
19304 isc_task_send(zone->task, &e);
19305 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
19306 "Transfer started.");
19307 UNLOCK_ZONE(zone);
19308
19309 return (ISC_R_SUCCESS);
19310 }
19311
19312 void
19313 dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, uint32_t iolimit) {
19314 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19315 REQUIRE(iolimit > 0);
19316
19317 zmgr->iolimit = iolimit;
19318 }
19319
19320 uint32_t
19321 dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr) {
19322 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19323
19324 return (zmgr->iolimit);
19325 }
19326
19327 /*
19328 * Get permission to request a file handle from the OS.
19329 * An event will be sent to action when one is available.
19330 * There are two queues available (high and low), the high
19331 * queue will be serviced before the low one.
19332 *
19333 * zonemgr_putio() must be called after the event is delivered to
19334 * 'action'.
19335 */
19336
19337 static isc_result_t
19338 zonemgr_getio(dns_zonemgr_t *zmgr, bool high, isc_task_t *task,
19339 isc_taskaction_t action, void *arg, dns_io_t **iop) {
19340 dns_io_t *io;
19341 bool queue;
19342
19343 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19344 REQUIRE(iop != NULL && *iop == NULL);
19345
19346 io = isc_mem_get(zmgr->mctx, sizeof(*io));
19347
19348 io->event = isc_event_allocate(zmgr->mctx, task, DNS_EVENT_IOREADY,
19349 action, arg, sizeof(*io->event));
19350
19351 io->zmgr = zmgr;
19352 io->high = high;
19353 io->task = NULL;
19354 isc_task_attach(task, &io->task);
19355 ISC_LINK_INIT(io, link);
19356 io->magic = IO_MAGIC;
19357
19358 LOCK(&zmgr->iolock);
19359 zmgr->ioactive++;
19360 queue = (zmgr->ioactive > zmgr->iolimit);
19361 if (queue) {
19362 if (io->high) {
19363 ISC_LIST_APPEND(zmgr->high, io, link);
19364 } else {
19365 ISC_LIST_APPEND(zmgr->low, io, link);
19366 }
19367 }
19368 UNLOCK(&zmgr->iolock);
19369 *iop = io;
19370
19371 if (!queue) {
19372 isc_task_send(io->task, &io->event);
19373 }
19374 return (ISC_R_SUCCESS);
19375 }
19376
19377 static void
19378 zonemgr_putio(dns_io_t **iop) {
19379 dns_io_t *io;
19380 dns_io_t *next;
19381 dns_zonemgr_t *zmgr;
19382
19383 REQUIRE(iop != NULL);
19384 io = *iop;
19385 *iop = NULL;
19386 REQUIRE(DNS_IO_VALID(io));
19387
19388 INSIST(!ISC_LINK_LINKED(io, link));
19389 INSIST(io->event == NULL);
19390
19391 zmgr = io->zmgr;
19392 isc_task_detach(&io->task);
19393 io->magic = 0;
19394 isc_mem_put(zmgr->mctx, io, sizeof(*io));
19395
19396 LOCK(&zmgr->iolock);
19397 INSIST(zmgr->ioactive > 0);
19398 zmgr->ioactive--;
19399 next = HEAD(zmgr->high);
19400 if (next == NULL) {
19401 next = HEAD(zmgr->low);
19402 }
19403 if (next != NULL) {
19404 if (next->high) {
19405 ISC_LIST_UNLINK(zmgr->high, next, link);
19406 } else {
19407 ISC_LIST_UNLINK(zmgr->low, next, link);
19408 }
19409 INSIST(next->event != NULL);
19410 }
19411 UNLOCK(&zmgr->iolock);
19412 if (next != NULL) {
19413 isc_task_send(next->task, &next->event);
19414 }
19415 }
19416
19417 static void
19418 zonemgr_cancelio(dns_io_t *io) {
19419 bool send_event = false;
19420
19421 REQUIRE(DNS_IO_VALID(io));
19422
19423 /*
19424 * If we are queued to be run then dequeue.
19425 */
19426 LOCK(&io->zmgr->iolock);
19427 if (ISC_LINK_LINKED(io, link)) {
19428 if (io->high) {
19429 ISC_LIST_UNLINK(io->zmgr->high, io, link);
19430 } else {
19431 ISC_LIST_UNLINK(io->zmgr->low, io, link);
19432 }
19433
19434 send_event = true;
19435 INSIST(io->event != NULL);
19436 }
19437 UNLOCK(&io->zmgr->iolock);
19438 if (send_event) {
19439 io->event->ev_attributes |= ISC_EVENTATTR_CANCELED;
19440 isc_task_send(io->task, &io->event);
19441 }
19442 }
19443
19444 static void
19445 zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
19446 char *buf;
19447 int buflen;
19448 isc_result_t result;
19449
19450 buflen = strlen(path) + strlen(templat) + 2;
19451
19452 buf = isc_mem_get(zone->mctx, buflen);
19453
19454 result = isc_file_template(path, templat, buf, buflen);
19455 if (result != ISC_R_SUCCESS) {
19456 goto cleanup;
19457 }
19458
19459 result = isc_file_renameunique(path, buf);
19460 if (result != ISC_R_SUCCESS) {
19461 goto cleanup;
19462 }
19463
19464 dns_zone_log(zone, ISC_LOG_WARNING,
19465 "unable to load from '%s'; "
19466 "renaming file to '%s' for failure analysis and "
19467 "retransferring.",
19468 path, buf);
19469
19470 cleanup:
19471 isc_mem_put(zone->mctx, buf, buflen);
19472 }
19473
19474 static void
19475 setrl(isc_ratelimiter_t *rl, unsigned int *rate, unsigned int value) {
19476 isc_interval_t interval;
19477 uint32_t s, ns;
19478 uint32_t pertic;
19479 isc_result_t result;
19480
19481 if (value == 0) {
19482 value = 1;
19483 }
19484
19485 if (value == 1) {
19486 s = 1;
19487 ns = 0;
19488 pertic = 1;
19489 } else if (value <= 10) {
19490 s = 0;
19491 ns = 1000000000 / value;
19492 pertic = 1;
19493 } else {
19494 s = 0;
19495 ns = (1000000000 / value) * 10;
19496 pertic = 10;
19497 }
19498
19499 isc_interval_set(&interval, s, ns);
19500
19501 result = isc_ratelimiter_setinterval(rl, &interval);
19502 RUNTIME_CHECK(result == ISC_R_SUCCESS);
19503 isc_ratelimiter_setpertic(rl, pertic);
19504
19505 *rate = value;
19506 }
19507
19508 void
19509 dns_zonemgr_setcheckdsrate(dns_zonemgr_t *zmgr, unsigned int value) {
19510 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19511
19512 setrl(zmgr->checkdsrl, &zmgr->checkdsrate, value);
19513 }
19514
19515 void
19516 dns_zonemgr_setnotifyrate(dns_zonemgr_t *zmgr, unsigned int value) {
19517 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19518
19519 setrl(zmgr->notifyrl, &zmgr->notifyrate, value);
19520 }
19521
19522 void
19523 dns_zonemgr_setstartupnotifyrate(dns_zonemgr_t *zmgr, unsigned int value) {
19524 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19525
19526 setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, value);
19527 }
19528
19529 void
19530 dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) {
19531 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19532
19533 setrl(zmgr->refreshrl, &zmgr->serialqueryrate, value);
19534 /* XXXMPA separate out once we have the code to support this. */
19535 setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, value);
19536 }
19537
19538 unsigned int
19539 dns_zonemgr_getnotifyrate(dns_zonemgr_t *zmgr) {
19540 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19541
19542 return (zmgr->notifyrate);
19543 }
19544
19545 unsigned int
19546 dns_zonemgr_getstartupnotifyrate(dns_zonemgr_t *zmgr) {
19547 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19548
19549 return (zmgr->startupnotifyrate);
19550 }
19551
19552 unsigned int
19553 dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
19554 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19555
19556 return (zmgr->serialqueryrate);
19557 }
19558
19559 bool
19560 dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
19561 isc_sockaddr_t *local, isc_time_t *now) {
19562 unsigned int i;
19563 uint32_t seconds = isc_time_seconds(now);
19564 uint32_t count = 0;
19565
19566 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19567
19568 RWLOCK(&zmgr->urlock, isc_rwlocktype_read);
19569 for (i = 0; i < UNREACH_CACHE_SIZE; i++) {
19570 if (atomic_load(&zmgr->unreachable[i].expire) >= seconds &&
19571 isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
19572 isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
19573 {
19574 atomic_store_relaxed(&zmgr->unreachable[i].last,
19575 seconds);
19576 count = zmgr->unreachable[i].count;
19577 break;
19578 }
19579 }
19580 RWUNLOCK(&zmgr->urlock, isc_rwlocktype_read);
19581 return (i < UNREACH_CACHE_SIZE && count > 1U);
19582 }
19583
19584 void
19585 dns_zonemgr_unreachabledel(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
19586 isc_sockaddr_t *local) {
19587 unsigned int i;
19588 char master[ISC_SOCKADDR_FORMATSIZE];
19589 char source[ISC_SOCKADDR_FORMATSIZE];
19590
19591 isc_sockaddr_format(remote, master, sizeof(master));
19592 isc_sockaddr_format(local, source, sizeof(source));
19593
19594 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19595
19596 RWLOCK(&zmgr->urlock, isc_rwlocktype_read);
19597 for (i = 0; i < UNREACH_CACHE_SIZE; i++) {
19598 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
19599 isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
19600 {
19601 atomic_store_relaxed(&zmgr->unreachable[i].expire, 0);
19602 break;
19603 }
19604 }
19605 RWUNLOCK(&zmgr->urlock, isc_rwlocktype_read);
19606 }
19607
19608 void
19609 dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
19610 isc_sockaddr_t *local, isc_time_t *now) {
19611 uint32_t seconds = isc_time_seconds(now);
19612 uint32_t expire = 0, last = seconds;
19613 unsigned int slot = UNREACH_CACHE_SIZE, oldest = 0;
19614 bool update_entry = true;
19615 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19616
19617 RWLOCK(&zmgr->urlock, isc_rwlocktype_write);
19618 for (unsigned int i = 0; i < UNREACH_CACHE_SIZE; i++) {
19619 /* Existing entry? */
19620 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
19621 isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
19622 {
19623 update_entry = false;
19624 slot = i;
19625 expire = atomic_load_relaxed(
19626 &zmgr->unreachable[i].expire);
19627 break;
19628 }
19629 /* Pick first empty slot? */
19630 if (atomic_load_relaxed(&zmgr->unreachable[i].expire) < seconds)
19631 {
19632 slot = i;
19633 break;
19634 }
19635 /* The worst case, least recently used slot? */
19636 if (atomic_load_relaxed(&zmgr->unreachable[i].last) < last) {
19637 last = atomic_load_relaxed(&zmgr->unreachable[i].last);
19638 oldest = i;
19639 }
19640 }
19641
19642 /* We haven't found any existing or free slots, use the oldest */
19643 if (slot == UNREACH_CACHE_SIZE) {
19644 slot = oldest;
19645 }
19646
19647 if (expire < seconds) {
19648 /* Expired or new entry, reset count to 1 */
19649 zmgr->unreachable[slot].count = 1;
19650 } else {
19651 zmgr->unreachable[slot].count++;
19652 }
19653 atomic_store_relaxed(&zmgr->unreachable[slot].expire,
19654 seconds + UNREACH_HOLD_TIME);
19655 atomic_store_relaxed(&zmgr->unreachable[slot].last, seconds);
19656 if (update_entry) {
19657 zmgr->unreachable[slot].remote = *remote;
19658 zmgr->unreachable[slot].local = *local;
19659 }
19660
19661 RWUNLOCK(&zmgr->urlock, isc_rwlocktype_write);
19662 }
19663
19664 void
19665 dns_zone_forcereload(dns_zone_t *zone) {
19666 REQUIRE(DNS_ZONE_VALID(zone));
19667
19668 if (zone->type == dns_zone_primary ||
19669 (zone->type == dns_zone_redirect && zone->masters == NULL))
19670 {
19671 return;
19672 }
19673
19674 LOCK_ZONE(zone);
19675 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
19676 UNLOCK_ZONE(zone);
19677 dns_zone_refresh(zone);
19678 }
19679
19680 bool
19681 dns_zone_isforced(dns_zone_t *zone) {
19682 REQUIRE(DNS_ZONE_VALID(zone));
19683
19684 return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER));
19685 }
19686
19687 isc_result_t
19688 dns_zone_setstatistics(dns_zone_t *zone, bool on) {
19689 /*
19690 * This function is obsoleted.
19691 */
19692 UNUSED(zone);
19693 UNUSED(on);
19694 return (ISC_R_NOTIMPLEMENTED);
19695 }
19696
19697 uint64_t *
19698 dns_zone_getstatscounters(dns_zone_t *zone) {
19699 /*
19700 * This function is obsoleted.
19701 */
19702 UNUSED(zone);
19703 return (NULL);
19704 }
19705
19706 void
19707 dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats) {
19708 REQUIRE(DNS_ZONE_VALID(zone));
19709 REQUIRE(zone->stats == NULL);
19710
19711 LOCK_ZONE(zone);
19712 zone->stats = NULL;
19713 isc_stats_attach(stats, &zone->stats);
19714 UNLOCK_ZONE(zone);
19715 }
19716
19717 void
19718 dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats) {
19719 REQUIRE(DNS_ZONE_VALID(zone));
19720
19721 LOCK_ZONE(zone);
19722 if (zone->requeststats_on && stats == NULL) {
19723 zone->requeststats_on = false;
19724 } else if (!zone->requeststats_on && stats != NULL) {
19725 if (zone->requeststats == NULL) {
19726 isc_stats_attach(stats, &zone->requeststats);
19727 }
19728 zone->requeststats_on = true;
19729 }
19730 UNLOCK_ZONE(zone);
19731 }
19732
19733 void
19734 dns_zone_setrcvquerystats(dns_zone_t *zone, dns_stats_t *stats) {
19735 REQUIRE(DNS_ZONE_VALID(zone));
19736
19737 LOCK_ZONE(zone);
19738 if (zone->requeststats_on && stats != NULL) {
19739 if (zone->rcvquerystats == NULL) {
19740 dns_stats_attach(stats, &zone->rcvquerystats);
19741 zone->requeststats_on = true;
19742 }
19743 }
19744 UNLOCK_ZONE(zone);
19745 }
19746
19747 void
19748 dns_zone_setdnssecsignstats(dns_zone_t *zone, dns_stats_t *stats) {
19749 REQUIRE(DNS_ZONE_VALID(zone));
19750
19751 LOCK_ZONE(zone);
19752 if (stats != NULL && zone->dnssecsignstats == NULL) {
19753 dns_stats_attach(stats, &zone->dnssecsignstats);
19754 }
19755 UNLOCK_ZONE(zone);
19756 }
19757
19758 dns_stats_t *
19759 dns_zone_getdnssecsignstats(dns_zone_t *zone) {
19760 REQUIRE(DNS_ZONE_VALID(zone));
19761
19762 return (zone->dnssecsignstats);
19763 }
19764
19765 isc_stats_t *
19766 dns_zone_getrequeststats(dns_zone_t *zone) {
19767 /*
19768 * We don't lock zone for efficiency reason. This is not catastrophic
19769 * because requeststats must always be valid when requeststats_on is
19770 * true.
19771 * Some counters may be incremented while requeststats_on is becoming
19772 * false, or some cannot be incremented just after the statistics are
19773 * installed, but it shouldn't matter much in practice.
19774 */
19775 if (zone->requeststats_on) {
19776 return (zone->requeststats);
19777 } else {
19778 return (NULL);
19779 }
19780 }
19781
19782 /*
19783 * Return the received query stats bucket
19784 * see note from dns_zone_getrequeststats()
19785 */
19786 dns_stats_t *
19787 dns_zone_getrcvquerystats(dns_zone_t *zone) {
19788 if (zone->requeststats_on) {
19789 return (zone->rcvquerystats);
19790 } else {
19791 return (NULL);
19792 }
19793 }
19794
19795 void
19796 dns_zone_dialup(dns_zone_t *zone) {
19797 REQUIRE(DNS_ZONE_VALID(zone));
19798
19799 zone_debuglog(zone, "dns_zone_dialup", 3, "notify = %d, refresh = %d",
19800 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY),
19801 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH));
19802
19803 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY)) {
19804 dns_zone_notify(zone);
19805 }
19806 if (zone->type != dns_zone_primary && zone->masters != NULL &&
19807 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
19808 {
19809 dns_zone_refresh(zone);
19810 }
19811 }
19812
19813 void
19814 dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
19815 REQUIRE(DNS_ZONE_VALID(zone));
19816
19817 LOCK_ZONE(zone);
19818 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
19819 DNS_ZONEFLG_DIALREFRESH |
19820 DNS_ZONEFLG_NOREFRESH);
19821 switch (dialup) {
19822 case dns_dialuptype_no:
19823 break;
19824 case dns_dialuptype_yes:
19825 DNS_ZONE_SETFLAG(zone, (DNS_ZONEFLG_DIALNOTIFY |
19826 DNS_ZONEFLG_DIALREFRESH |
19827 DNS_ZONEFLG_NOREFRESH));
19828 break;
19829 case dns_dialuptype_notify:
19830 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
19831 break;
19832 case dns_dialuptype_notifypassive:
19833 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
19834 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
19835 break;
19836 case dns_dialuptype_refresh:
19837 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALREFRESH);
19838 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
19839 break;
19840 case dns_dialuptype_passive:
19841 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
19842 break;
19843 default:
19844 UNREACHABLE();
19845 }
19846 UNLOCK_ZONE(zone);
19847 }
19848
19849 isc_result_t
19850 dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory) {
19851 isc_result_t result = ISC_R_SUCCESS;
19852
19853 REQUIRE(DNS_ZONE_VALID(zone));
19854
19855 LOCK_ZONE(zone);
19856 result = dns_zone_setstring(zone, &zone->keydirectory, directory);
19857 UNLOCK_ZONE(zone);
19858
19859 return (result);
19860 }
19861
19862 const char *
19863 dns_zone_getkeydirectory(dns_zone_t *zone) {
19864 REQUIRE(DNS_ZONE_VALID(zone));
19865
19866 return (zone->keydirectory);
19867 }
19868
19869 unsigned int
19870 dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state) {
19871 dns_zone_t *zone;
19872 unsigned int count = 0;
19873
19874 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19875
19876 RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
19877 switch (state) {
19878 case DNS_ZONESTATE_XFERRUNNING:
19879 for (zone = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
19880 zone != NULL; zone = ISC_LIST_NEXT(zone, statelink))
19881 {
19882 count++;
19883 }
19884 break;
19885 case DNS_ZONESTATE_XFERDEFERRED:
19886 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
19887 zone != NULL; zone = ISC_LIST_NEXT(zone, statelink))
19888 {
19889 count++;
19890 }
19891 break;
19892 case DNS_ZONESTATE_SOAQUERY:
19893 for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
19894 zone = ISC_LIST_NEXT(zone, link))
19895 {
19896 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
19897 count++;
19898 }
19899 }
19900 break;
19901 case DNS_ZONESTATE_ANY:
19902 for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
19903 zone = ISC_LIST_NEXT(zone, link))
19904 {
19905 dns_view_t *view = zone->view;
19906 if (view != NULL && strcmp(view->name, "_bind") == 0) {
19907 continue;
19908 }
19909 count++;
19910 }
19911 break;
19912 case DNS_ZONESTATE_AUTOMATIC:
19913 for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
19914 zone = ISC_LIST_NEXT(zone, link))
19915 {
19916 dns_view_t *view = zone->view;
19917 if (view != NULL && strcmp(view->name, "_bind") == 0) {
19918 continue;
19919 }
19920 if (zone->automatic) {
19921 count++;
19922 }
19923 }
19924 break;
19925 default:
19926 UNREACHABLE();
19927 }
19928
19929 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
19930
19931 return (count);
19932 }
19933
19934 void
19935 dns_zone_lock_keyfiles(dns_zone_t *zone) {
19936 REQUIRE(DNS_ZONE_VALID(zone));
19937
19938 if (zone->kasp == NULL) {
19939 /* No need to lock, nothing is writing key files. */
19940 return;
19941 }
19942
19943 REQUIRE(DNS_KEYFILEIO_VALID(zone->kfio));
19944 isc_mutex_lock(&zone->kfio->lock);
19945 }
19946
19947 void
19948 dns_zone_unlock_keyfiles(dns_zone_t *zone) {
19949 REQUIRE(DNS_ZONE_VALID(zone));
19950
19951 if (zone->kasp == NULL) {
19952 /* No need to lock, nothing is writing key files. */
19953 return;
19954 }
19955
19956 REQUIRE(DNS_KEYFILEIO_VALID(zone->kfio));
19957 isc_mutex_unlock(&zone->kfio->lock);
19958 }
19959
19960 isc_result_t
19961 dns_zone_checknames(dns_zone_t *zone, const dns_name_t *name,
19962 dns_rdata_t *rdata) {
19963 bool ok = true;
19964 bool fail = false;
19965 char namebuf[DNS_NAME_FORMATSIZE];
19966 char namebuf2[DNS_NAME_FORMATSIZE];
19967 char typebuf[DNS_RDATATYPE_FORMATSIZE];
19968 int level = ISC_LOG_WARNING;
19969 dns_name_t bad;
19970
19971 REQUIRE(DNS_ZONE_VALID(zone));
19972
19973 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES) &&
19974 rdata->type != dns_rdatatype_nsec3)
19975 {
19976 return (ISC_R_SUCCESS);
19977 }
19978
19979 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL) ||
19980 rdata->type == dns_rdatatype_nsec3)
19981 {
19982 level = ISC_LOG_ERROR;
19983 fail = true;
19984 }
19985
19986 ok = dns_rdata_checkowner(name, rdata->rdclass, rdata->type, true);
19987 if (!ok) {
19988 dns_name_format(name, namebuf, sizeof(namebuf));
19989 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
19990 dns_zone_log(zone, level, "%s/%s: %s", namebuf, typebuf,
19991 dns_result_totext(DNS_R_BADOWNERNAME));
19992 if (fail) {
19993 return (DNS_R_BADOWNERNAME);
19994 }
19995 }
19996
19997 dns_name_init(&bad, NULL);
19998 ok = dns_rdata_checknames(rdata, name, &bad);
19999 if (!ok) {
20000 dns_name_format(name, namebuf, sizeof(namebuf));
20001 dns_name_format(&bad, namebuf2, sizeof(namebuf2));
20002 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
20003 dns_zone_log(zone, level, "%s/%s: %s: %s ", namebuf, typebuf,
20004 namebuf2, dns_result_totext(DNS_R_BADNAME));
20005 if (fail) {
20006 return (DNS_R_BADNAME);
20007 }
20008 }
20009
20010 return (ISC_R_SUCCESS);
20011 }
20012
20013 void
20014 dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx) {
20015 REQUIRE(DNS_ZONE_VALID(zone));
20016 zone->checkmx = checkmx;
20017 }
20018
20019 void
20020 dns_zone_setchecksrv(dns_zone_t *zone, dns_checksrvfunc_t checksrv) {
20021 REQUIRE(DNS_ZONE_VALID(zone));
20022 zone->checksrv = checksrv;
20023 }
20024
20025 void
20026 dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns) {
20027 REQUIRE(DNS_ZONE_VALID(zone));
20028 zone->checkns = checkns;
20029 }
20030
20031 void
20032 dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg) {
20033 REQUIRE(DNS_ZONE_VALID(zone));
20034
20035 LOCK_ZONE(zone);
20036 zone->isself = isself;
20037 zone->isselfarg = arg;
20038 UNLOCK_ZONE(zone);
20039 }
20040
20041 void
20042 dns_zone_setnotifydelay(dns_zone_t *zone, uint32_t delay) {
20043 REQUIRE(DNS_ZONE_VALID(zone));
20044
20045 LOCK_ZONE(zone);
20046 zone->notifydelay = delay;
20047 UNLOCK_ZONE(zone);
20048 }
20049
20050 uint32_t
20051 dns_zone_getnotifydelay(dns_zone_t *zone) {
20052 REQUIRE(DNS_ZONE_VALID(zone));
20053
20054 return (zone->notifydelay);
20055 }
20056
20057 isc_result_t
20058 dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid,
20059 bool deleteit) {
20060 isc_result_t result;
20061 REQUIRE(DNS_ZONE_VALID(zone));
20062
20063 dnssec_log(zone, ISC_LOG_NOTICE,
20064 "dns_zone_signwithkey(algorithm=%u, keyid=%u)", algorithm,
20065 keyid);
20066 LOCK_ZONE(zone);
20067 result = zone_signwithkey(zone, algorithm, keyid, deleteit);
20068 UNLOCK_ZONE(zone);
20069
20070 return (result);
20071 }
20072
20073 /*
20074 * Called when a dynamic update for an NSEC3PARAM record is received.
20075 *
20076 * If set, transform the NSEC3 salt into human-readable form so that it can be
20077 * logged. Then call zone_addnsec3chain(), passing NSEC3PARAM RDATA to it.
20078 */
20079 isc_result_t
20080 dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
20081 isc_result_t result;
20082 char salt[255 * 2 + 1];
20083
20084 REQUIRE(DNS_ZONE_VALID(zone));
20085
20086 result = dns_nsec3param_salttotext(nsec3param, salt, sizeof(salt));
20087 RUNTIME_CHECK(result == ISC_R_SUCCESS);
20088 dnssec_log(zone, ISC_LOG_NOTICE,
20089 "dns_zone_addnsec3chain(hash=%u, iterations=%u, salt=%s)",
20090 nsec3param->hash, nsec3param->iterations, salt);
20091 LOCK_ZONE(zone);
20092 result = zone_addnsec3chain(zone, nsec3param);
20093 UNLOCK_ZONE(zone);
20094
20095 return (result);
20096 }
20097
20098 void
20099 dns_zone_setnodes(dns_zone_t *zone, uint32_t nodes) {
20100 REQUIRE(DNS_ZONE_VALID(zone));
20101
20102 if (nodes == 0) {
20103 nodes = 1;
20104 }
20105 zone->nodes = nodes;
20106 }
20107
20108 void
20109 dns_zone_setsignatures(dns_zone_t *zone, uint32_t signatures) {
20110 REQUIRE(DNS_ZONE_VALID(zone));
20111
20112 /*
20113 * We treat signatures as a signed value so explicitly
20114 * limit its range here.
20115 */
20116 if (signatures > INT32_MAX) {
20117 signatures = INT32_MAX;
20118 } else if (signatures == 0) {
20119 signatures = 1;
20120 }
20121 zone->signatures = signatures;
20122 }
20123
20124 uint32_t
20125 dns_zone_getsignatures(dns_zone_t *zone) {
20126 REQUIRE(DNS_ZONE_VALID(zone));
20127 return (zone->signatures);
20128 }
20129
20130 void
20131 dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type) {
20132 REQUIRE(DNS_ZONE_VALID(zone));
20133 zone->privatetype = type;
20134 }
20135
20136 dns_rdatatype_t
20137 dns_zone_getprivatetype(dns_zone_t *zone) {
20138 REQUIRE(DNS_ZONE_VALID(zone));
20139 return (zone->privatetype);
20140 }
20141
20142 static isc_result_t
20143 zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid,
20144 bool deleteit) {
20145 dns_signing_t *signing;
20146 dns_signing_t *current;
20147 isc_result_t result = ISC_R_SUCCESS;
20148 isc_time_t now;
20149 dns_db_t *db = NULL;
20150
20151 signing = isc_mem_get(zone->mctx, sizeof *signing);
20152
20153 signing->magic = 0;
20154 signing->db = NULL;
20155 signing->dbiterator = NULL;
20156 signing->algorithm = algorithm;
20157 signing->keyid = keyid;
20158 signing->deleteit = deleteit;
20159 signing->done = false;
20160
20161 TIME_NOW(&now);
20162
20163 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
20164 if (zone->db != NULL) {
20165 dns_db_attach(zone->db, &db);
20166 }
20167 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
20168
20169 if (db == NULL) {
20170 result = ISC_R_NOTFOUND;
20171 goto cleanup;
20172 }
20173
20174 dns_db_attach(db, &signing->db);
20175
20176 for (current = ISC_LIST_HEAD(zone->signing); current != NULL;
20177 current = ISC_LIST_NEXT(current, link))
20178 {
20179 if (current->db == signing->db &&
20180 current->algorithm == signing->algorithm &&
20181 current->keyid == signing->keyid)
20182 {
20183 if (current->deleteit != signing->deleteit) {
20184 current->done = true;
20185 } else {
20186 goto cleanup;
20187 }
20188 }
20189 }
20190
20191 result = dns_db_createiterator(signing->db, 0, &signing->dbiterator);
20192
20193 if (result == ISC_R_SUCCESS) {
20194 result = dns_dbiterator_first(signing->dbiterator);
20195 }
20196 if (result == ISC_R_SUCCESS) {
20197 dns_dbiterator_pause(signing->dbiterator);
20198 ISC_LIST_INITANDAPPEND(zone->signing, signing, link);
20199 signing = NULL;
20200 if (isc_time_isepoch(&zone->signingtime)) {
20201 zone->signingtime = now;
20202 if (zone->task != NULL) {
20203 zone_settimer(zone, &now);
20204 }
20205 }
20206 }
20207
20208 cleanup:
20209 if (signing != NULL) {
20210 if (signing->db != NULL) {
20211 dns_db_detach(&signing->db);
20212 }
20213 if (signing->dbiterator != NULL) {
20214 dns_dbiterator_destroy(&signing->dbiterator);
20215 }
20216 isc_mem_put(zone->mctx, signing, sizeof *signing);
20217 }
20218 if (db != NULL) {
20219 dns_db_detach(&db);
20220 }
20221 return (result);
20222 }
20223
20224 /* Called once; *timep should be set to the current time. */
20225 static isc_result_t
20226 next_keyevent(dst_key_t *key, isc_stdtime_t *timep) {
20227 isc_result_t result;
20228 isc_stdtime_t now, then = 0, event;
20229 int i;
20230
20231 now = *timep;
20232
20233 for (i = 0; i <= DST_MAX_TIMES; i++) {
20234 result = dst_key_gettime(key, i, &event);
20235 if (result == ISC_R_SUCCESS && event > now &&
20236 (then == 0 || event < then))
20237 {
20238 then = event;
20239 }
20240 }
20241
20242 if (then != 0) {
20243 *timep = then;
20244 return (ISC_R_SUCCESS);
20245 }
20246
20247 return (ISC_R_NOTFOUND);
20248 }
20249
20250 static isc_result_t
20251 rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
20252 const dns_rdata_t *rdata, bool *flag) {
20253 dns_rdataset_t rdataset;
20254 dns_dbnode_t *node = NULL;
20255 isc_result_t result;
20256
20257 dns_rdataset_init(&rdataset);
20258 if (rdata->type == dns_rdatatype_nsec3) {
20259 CHECK(dns_db_findnsec3node(db, name, false, &node));
20260 } else {
20261 CHECK(dns_db_findnode(db, name, false, &node));
20262 }
20263 result = dns_db_findrdataset(db, node, ver, rdata->type, 0,
20264 (isc_stdtime_t)0, &rdataset, NULL);
20265 if (result == ISC_R_NOTFOUND) {
20266 *flag = false;
20267 result = ISC_R_SUCCESS;
20268 goto failure;
20269 }
20270
20271 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
20272 result = dns_rdataset_next(&rdataset))
20273 {
20274 dns_rdata_t myrdata = DNS_RDATA_INIT;
20275 dns_rdataset_current(&rdataset, &myrdata);
20276 if (!dns_rdata_compare(&myrdata, rdata)) {
20277 break;
20278 }
20279 }
20280 dns_rdataset_disassociate(&rdataset);
20281 if (result == ISC_R_SUCCESS) {
20282 *flag = true;
20283 } else if (result == ISC_R_NOMORE) {
20284 *flag = false;
20285 result = ISC_R_SUCCESS;
20286 }
20287
20288 failure:
20289 if (node != NULL) {
20290 dns_db_detachnode(db, &node);
20291 }
20292 return (result);
20293 }
20294
20295 /*
20296 * Add records to signal the state of signing or of key removal.
20297 */
20298 static isc_result_t
20299 add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
20300 dns_dbversion_t *ver, dns_diff_t *diff, bool sign_all) {
20301 dns_difftuple_t *tuple, *newtuple = NULL;
20302 dns_rdata_dnskey_t dnskey;
20303 dns_rdata_t rdata = DNS_RDATA_INIT;
20304 bool flag;
20305 isc_region_t r;
20306 isc_result_t result = ISC_R_SUCCESS;
20307 uint16_t keyid;
20308 unsigned char buf[5];
20309 dns_name_t *name = dns_db_origin(db);
20310
20311 for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL;
20312 tuple = ISC_LIST_NEXT(tuple, link))
20313 {
20314 if (tuple->rdata.type != dns_rdatatype_dnskey) {
20315 continue;
20316 }
20317
20318 result = dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
20319 RUNTIME_CHECK(result == ISC_R_SUCCESS);
20320 if ((dnskey.flags & (DNS_KEYFLAG_OWNERMASK |
20321 DNS_KEYTYPE_NOAUTH)) != DNS_KEYOWNER_ZONE)
20322 {
20323 continue;
20324 }
20325
20326 dns_rdata_toregion(&tuple->rdata, &r);
20327
20328 keyid = dst_region_computeid(&r);
20329
20330 buf[0] = dnskey.algorithm;
20331 buf[1] = (keyid & 0xff00) >> 8;
20332 buf[2] = (keyid & 0xff);
20333 buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1;
20334 buf[4] = 0;
20335 rdata.data = buf;
20336 rdata.length = sizeof(buf);
20337 rdata.type = privatetype;
20338 rdata.rdclass = tuple->rdata.rdclass;
20339
20340 if (sign_all || tuple->op == DNS_DIFFOP_DEL) {
20341 CHECK(rr_exists(db, ver, name, &rdata, &flag));
20342 if (flag) {
20343 continue;
20344 }
20345
20346 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
20347 name, 0, &rdata, &newtuple));
20348 CHECK(do_one_tuple(&newtuple, db, ver, diff));
20349 INSIST(newtuple == NULL);
20350 }
20351
20352 /*
20353 * Remove any record which says this operation has already
20354 * completed.
20355 */
20356 buf[4] = 1;
20357 CHECK(rr_exists(db, ver, name, &rdata, &flag));
20358 if (flag) {
20359 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL,
20360 name, 0, &rdata, &newtuple));
20361 CHECK(do_one_tuple(&newtuple, db, ver, diff));
20362 INSIST(newtuple == NULL);
20363 }
20364 }
20365 failure:
20366 return (result);
20367 }
20368
20369 /*
20370 * See if dns__zone_updatesigs() will update signature for RRset 'rrtype' at
20371 * the apex, and if not tickle them and cause to sign so that newly activated
20372 * keys are used.
20373 */
20374 static isc_result_t
20375 tickle_apex_rrset(dns_rdatatype_t rrtype, dns_zone_t *zone, dns_db_t *db,
20376 dns_dbversion_t *ver, isc_stdtime_t now, dns_diff_t *diff,
20377 dns__zonediff_t *zonediff, dst_key_t **keys,
20378 unsigned int nkeys, isc_stdtime_t inception,
20379 isc_stdtime_t keyexpire, bool check_ksk,
20380 bool keyset_kskonly) {
20381 dns_difftuple_t *tuple;
20382 isc_result_t result;
20383
20384 for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL;
20385 tuple = ISC_LIST_NEXT(tuple, link))
20386 {
20387 if (tuple->rdata.type == rrtype &&
20388 dns_name_equal(&tuple->name, &zone->origin))
20389 {
20390 break;
20391 }
20392 }
20393
20394 if (tuple == NULL) {
20395 result = del_sigs(zone, db, ver, &zone->origin, rrtype,
20396 zonediff, keys, nkeys, now, false);
20397 if (result != ISC_R_SUCCESS) {
20398 dnssec_log(zone, ISC_LOG_ERROR,
20399 "sign_apex:del_sigs -> %s",
20400 dns_result_totext(result));
20401 return (result);
20402 }
20403 result = add_sigs(db, ver, &zone->origin, zone, rrtype,
20404 zonediff->diff, keys, nkeys, zone->mctx,
20405 inception, keyexpire, check_ksk,
20406 keyset_kskonly);
20407 if (result != ISC_R_SUCCESS) {
20408 dnssec_log(zone, ISC_LOG_ERROR,
20409 "sign_apex:add_sigs -> %s",
20410 dns_result_totext(result));
20411 return (result);
20412 }
20413 }
20414
20415 return (ISC_R_SUCCESS);
20416 }
20417
20418 static isc_result_t
20419 sign_apex(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
20420 isc_stdtime_t now, dns_diff_t *diff, dns__zonediff_t *zonediff) {
20421 isc_result_t result;
20422 isc_stdtime_t inception, soaexpire, keyexpire;
20423 bool check_ksk, keyset_kskonly;
20424 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
20425 unsigned int nkeys = 0, i;
20426
20427 result = dns__zone_findkeys(zone, db, ver, now, zone->mctx,
20428 DNS_MAXZONEKEYS, zone_keys, &nkeys);
20429 if (result != ISC_R_SUCCESS) {
20430 dnssec_log(zone, ISC_LOG_ERROR,
20431 "sign_apex:dns__zone_findkeys -> %s",
20432 dns_result_totext(result));
20433 return (result);
20434 }
20435
20436 inception = now - 3600; /* Allow for clock skew. */
20437 soaexpire = now + dns_zone_getsigvalidityinterval(zone);
20438
20439 keyexpire = dns_zone_getkeyvalidityinterval(zone);
20440 if (keyexpire == 0) {
20441 keyexpire = soaexpire - 1;
20442 } else {
20443 keyexpire += now;
20444 }
20445
20446 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
20447 keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
20448
20449 /*
20450 * See if dns__zone_updatesigs() will update DNSKEY/CDS/CDNSKEY
20451 * signature and if not cause them to sign so that newly activated
20452 * keys are used.
20453 */
20454 result = tickle_apex_rrset(dns_rdatatype_dnskey, zone, db, ver, now,
20455 diff, zonediff, zone_keys, nkeys, inception,
20456 keyexpire, check_ksk, keyset_kskonly);
20457 if (result != ISC_R_SUCCESS) {
20458 goto failure;
20459 }
20460 result = tickle_apex_rrset(dns_rdatatype_cds, zone, db, ver, now, diff,
20461 zonediff, zone_keys, nkeys, inception,
20462 keyexpire, check_ksk, keyset_kskonly);
20463 if (result != ISC_R_SUCCESS) {
20464 goto failure;
20465 }
20466 result = tickle_apex_rrset(dns_rdatatype_cdnskey, zone, db, ver, now,
20467 diff, zonediff, zone_keys, nkeys, inception,
20468 keyexpire, check_ksk, keyset_kskonly);
20469 if (result != ISC_R_SUCCESS) {
20470 goto failure;
20471 }
20472
20473 result = dns__zone_updatesigs(diff, db, ver, zone_keys, nkeys, zone,
20474 inception, soaexpire, keyexpire, now,
20475 check_ksk, keyset_kskonly, zonediff);
20476
20477 if (result != ISC_R_SUCCESS) {
20478 dnssec_log(zone, ISC_LOG_ERROR,
20479 "sign_apex:dns__zone_updatesigs -> %s",
20480 dns_result_totext(result));
20481 goto failure;
20482 }
20483
20484 failure:
20485 for (i = 0; i < nkeys; i++) {
20486 dst_key_free(&zone_keys[i]);
20487 }
20488 return (result);
20489 }
20490
20491 /*
20492 * Prevent the zone entering a inconsistent state where
20493 * NSEC only DNSKEYs are present with NSEC3 chains.
20494 * See update.c:check_dnssec()
20495 */
20496 static bool
20497 dnskey_sane(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
20498 dns_diff_t *diff) {
20499 isc_result_t result;
20500 dns_difftuple_t *tuple;
20501 bool nseconly = false, nsec3 = false;
20502 dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
20503
20504 /* Scan the tuples for an NSEC-only DNSKEY */
20505 for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL;
20506 tuple = ISC_LIST_NEXT(tuple, link))
20507 {
20508 uint8_t alg;
20509 if (tuple->rdata.type != dns_rdatatype_dnskey ||
20510 tuple->op != DNS_DIFFOP_ADD)
20511 {
20512 continue;
20513 }
20514
20515 alg = tuple->rdata.data[3];
20516 if (alg == DST_ALG_RSASHA1) {
20517 nseconly = true;
20518 break;
20519 }
20520 }
20521
20522 /* Check existing DB for NSEC-only DNSKEY */
20523 if (!nseconly) {
20524 result = dns_nsec_nseconly(db, ver, &nseconly);
20525 if (result == ISC_R_NOTFOUND) {
20526 result = ISC_R_SUCCESS;
20527 }
20528 CHECK(result);
20529 }
20530
20531 /* Check existing DB for NSEC3 */
20532 if (!nsec3) {
20533 CHECK(dns_nsec3_activex(db, ver, false, privatetype, &nsec3));
20534 }
20535
20536 /* Refuse to allow NSEC3 with NSEC-only keys */
20537 if (nseconly && nsec3) {
20538 dnssec_log(zone, ISC_LOG_ERROR,
20539 "NSEC only DNSKEYs and NSEC3 chains not allowed");
20540 goto failure;
20541 }
20542
20543 return (true);
20544
20545 failure:
20546 return (false);
20547 }
20548
20549 static isc_result_t
20550 clean_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
20551 dns_diff_t *diff) {
20552 isc_result_t result;
20553 dns_dbnode_t *node = NULL;
20554 dns_rdataset_t rdataset;
20555
20556 dns_rdataset_init(&rdataset);
20557 CHECK(dns_db_getoriginnode(db, &node));
20558
20559 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
20560 dns_rdatatype_none, 0, &rdataset, NULL);
20561 if (dns_rdataset_isassociated(&rdataset)) {
20562 dns_rdataset_disassociate(&rdataset);
20563 }
20564 if (result != ISC_R_NOTFOUND) {
20565 goto failure;
20566 }
20567
20568 result = dns_nsec3param_deletechains(db, ver, zone, true, diff);
20569
20570 failure:
20571 if (node != NULL) {
20572 dns_db_detachnode(db, &node);
20573 }
20574 return (result);
20575 }
20576
20577 /*
20578 * Given an RRSIG rdataset and an algorithm, determine whether there
20579 * are any signatures using that algorithm.
20580 */
20581 static bool
20582 signed_with_alg(dns_rdataset_t *rdataset, dns_secalg_t alg) {
20583 dns_rdata_t rdata = DNS_RDATA_INIT;
20584 dns_rdata_rrsig_t rrsig;
20585 isc_result_t result;
20586
20587 REQUIRE(rdataset == NULL || rdataset->type == dns_rdatatype_rrsig);
20588 if (rdataset == NULL || !dns_rdataset_isassociated(rdataset)) {
20589 return (false);
20590 }
20591
20592 for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
20593 result = dns_rdataset_next(rdataset))
20594 {
20595 dns_rdataset_current(rdataset, &rdata);
20596 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
20597 RUNTIME_CHECK(result == ISC_R_SUCCESS);
20598 dns_rdata_reset(&rdata);
20599 if (rrsig.algorithm == alg) {
20600 return (true);
20601 }
20602 }
20603
20604 return (false);
20605 }
20606
20607 static isc_result_t
20608 add_chains(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
20609 dns_diff_t *diff) {
20610 dns_name_t *origin;
20611 bool build_nsec3;
20612 isc_result_t result;
20613
20614 origin = dns_db_origin(db);
20615 CHECK(dns_private_chains(db, ver, zone->privatetype, NULL,
20616 &build_nsec3));
20617 if (build_nsec3) {
20618 CHECK(dns_nsec3_addnsec3sx(db, ver, origin, zone_nsecttl(zone),
20619 false, zone->privatetype, diff));
20620 }
20621 CHECK(updatesecure(db, ver, origin, zone_nsecttl(zone), true, diff));
20622
20623 failure:
20624 return (result);
20625 }
20626
20627 static void
20628 dnssec_report(const char *format, ...) {
20629 va_list args;
20630 va_start(args, format);
20631 isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_ZONE,
20632 ISC_LOG_INFO, format, args);
20633 va_end(args);
20634 }
20635
20636 static void
20637 checkds_destroy(dns_checkds_t *checkds, bool locked) {
20638 isc_mem_t *mctx;
20639
20640 REQUIRE(DNS_CHECKDS_VALID(checkds));
20641
20642 dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
20643 "checkds: destroy DS query");
20644
20645 if (checkds->zone != NULL) {
20646 if (!locked) {
20647 LOCK_ZONE(checkds->zone);
20648 }
20649 REQUIRE(LOCKED_ZONE(checkds->zone));
20650 if (ISC_LINK_LINKED(checkds, link)) {
20651 ISC_LIST_UNLINK(checkds->zone->checkds_requests,
20652 checkds, link);
20653 }
20654 if (!locked) {
20655 UNLOCK_ZONE(checkds->zone);
20656 }
20657 if (locked) {
20658 zone_idetach(&checkds->zone);
20659 } else {
20660 dns_zone_idetach(&checkds->zone);
20661 }
20662 }
20663 if (checkds->request != NULL) {
20664 dns_request_destroy(&checkds->request);
20665 }
20666 if (checkds->key != NULL) {
20667 dns_tsigkey_detach(&checkds->key);
20668 }
20669 mctx = checkds->mctx;
20670 isc_mem_put(checkds->mctx, checkds, sizeof(*checkds));
20671 isc_mem_detach(&mctx);
20672 }
20673
20674 static isc_result_t
20675 make_dnskey(dst_key_t *key, unsigned char *buf, int bufsize,
20676 dns_rdata_t *target) {
20677 isc_result_t result;
20678 isc_buffer_t b;
20679 isc_region_t r;
20680
20681 isc_buffer_init(&b, buf, bufsize);
20682 result = dst_key_todns(key, &b);
20683 if (result != ISC_R_SUCCESS) {
20684 return (result);
20685 }
20686
20687 dns_rdata_reset(target);
20688 isc_buffer_usedregion(&b, &r);
20689 dns_rdata_fromregion(target, dst_key_class(key), dns_rdatatype_dnskey,
20690 &r);
20691 return (ISC_R_SUCCESS);
20692 }
20693
20694 static bool
20695 do_checkds(dns_zone_t *zone, dst_key_t *key, isc_stdtime_t now,
20696 bool dspublish) {
20697 dns_kasp_t *kasp = dns_zone_getkasp(zone);
20698 const char *dir = dns_zone_getkeydirectory(zone);
20699 isc_result_t result;
20700 uint32_t count = 0;
20701
20702 if (dspublish) {
20703 (void)dst_key_getnum(key, DST_NUM_DSPUBCOUNT, &count);
20704 count += 1;
20705 dst_key_setnum(key, DST_NUM_DSPUBCOUNT, count);
20706 dns_zone_log(zone, ISC_LOG_DEBUG(3),
20707 "checkds: %u DS published "
20708 "for key %u",
20709 count, dst_key_id(key));
20710
20711 if (count != zone->parentalscnt) {
20712 return false;
20713 }
20714 } else {
20715 (void)dst_key_getnum(key, DST_NUM_DSDELCOUNT, &count);
20716 count += 1;
20717 dst_key_setnum(key, DST_NUM_DSDELCOUNT, count);
20718 dns_zone_log(zone, ISC_LOG_DEBUG(3),
20719 "checkds: %u DS withdrawn "
20720 "for key %u",
20721 count, dst_key_id(key));
20722
20723 if (count != zone->parentalscnt) {
20724 return false;
20725 }
20726 }
20727
20728 dns_zone_log(zone, ISC_LOG_DEBUG(3),
20729 "checkds: checkds %s for key "
20730 "%u",
20731 dspublish ? "published" : "withdrawn", dst_key_id(key));
20732
20733 dns_zone_lock_keyfiles(zone);
20734 result = dns_keymgr_checkds_id(kasp, &zone->checkds_ok, dir, now, now,
20735 dspublish, dst_key_id(key),
20736 dst_key_alg(key));
20737 dns_zone_unlock_keyfiles(zone);
20738
20739 if (result != ISC_R_SUCCESS) {
20740 dns_zone_log(zone, ISC_LOG_WARNING,
20741 "checkds: checkds for key %u failed: %s",
20742 dst_key_id(key), isc_result_totext(result));
20743 return false;
20744 }
20745
20746 return true;
20747 }
20748
20749 static isc_result_t
20750 validate_ds(dns_zone_t *zone, dns_message_t *message) {
20751 UNUSED(zone);
20752 UNUSED(message);
20753
20754 /* Get closest trust anchor */
20755
20756 /* Check that trust anchor is (grand)parent of zone. */
20757
20758 /* Find the DNSKEY signing the message. */
20759
20760 /* Check that DNSKEY is in chain of trust. */
20761
20762 /* Validate DS RRset. */
20763
20764 return (ISC_R_SUCCESS);
20765 }
20766
20767 static void
20768 checkds_done(isc_task_t *task, isc_event_t *event) {
20769 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
20770 char rcode[128];
20771 dns_checkds_t *checkds;
20772 dns_zone_t *zone;
20773 dns_db_t *db = NULL;
20774 dns_dbversion_t *version = NULL;
20775 dns_dnsseckey_t *key;
20776 dns_dnsseckeylist_t keys;
20777 dns_kasp_t *kasp = NULL;
20778 dns_message_t *message = NULL;
20779 dns_rdataset_t *ds_rrset = NULL;
20780 dns_requestevent_t *revent = (dns_requestevent_t *)event;
20781 isc_buffer_t buf;
20782 isc_result_t result;
20783 isc_stdtime_t now;
20784 isc_time_t timenow;
20785 bool rekey = false;
20786 bool empty = false;
20787
20788 UNUSED(task);
20789
20790 checkds = event->ev_arg;
20791 REQUIRE(DNS_CHECKDS_VALID(checkds));
20792
20793 zone = checkds->zone;
20794 INSIST(task == zone->task);
20795
20796 ISC_LIST_INIT(keys);
20797
20798 kasp = zone->kasp;
20799 INSIST(kasp != NULL);
20800
20801 isc_buffer_init(&buf, rcode, sizeof(rcode));
20802 isc_sockaddr_format(&checkds->dst, addrbuf, sizeof(addrbuf));
20803
20804 dns_zone_log(zone, ISC_LOG_DEBUG(1), "checkds: DS query to %s: done",
20805 addrbuf);
20806
20807 dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &message);
20808 INSIST(message != NULL);
20809
20810 CHECK(revent->result);
20811 CHECK(dns_request_getresponse(revent->request, message,
20812 DNS_MESSAGEPARSE_PRESERVEORDER));
20813 CHECK(dns_rcode_totext(message->rcode, &buf));
20814
20815 dns_zone_log(zone, ISC_LOG_DEBUG(3),
20816 "checkds: DS response from %s: %.*s", addrbuf,
20817 (int)buf.used, rcode);
20818
20819 /* Validate response. */
20820 CHECK(validate_ds(zone, message));
20821
20822 if (message->rcode != dns_rcode_noerror) {
20823 dns_zone_log(zone, ISC_LOG_NOTICE,
20824 "checkds: bad DS response from %s: %.*s", addrbuf,
20825 (int)buf.used, rcode);
20826 goto failure;
20827 }
20828
20829 /* Lookup DS RRset. */
20830 result = dns_message_firstname(message, DNS_SECTION_ANSWER);
20831 while (result == ISC_R_SUCCESS) {
20832 dns_name_t *name = NULL;
20833 dns_rdataset_t *rdataset;
20834
20835 dns_message_currentname(message, DNS_SECTION_ANSWER, &name);
20836 if (dns_name_compare(&zone->origin, name) != 0) {
20837 goto next;
20838 }
20839
20840 for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL;
20841 rdataset = ISC_LIST_NEXT(rdataset, link))
20842 {
20843 if (rdataset->type != dns_rdatatype_ds) {
20844 goto next;
20845 }
20846
20847 ds_rrset = rdataset;
20848 break;
20849 }
20850
20851 if (ds_rrset != NULL) {
20852 break;
20853 }
20854
20855 next:
20856 result = dns_message_nextname(message, DNS_SECTION_ANSWER);
20857 }
20858
20859 if (ds_rrset == NULL) {
20860 empty = true;
20861 dns_zone_log(zone, ISC_LOG_NOTICE,
20862 "checkds: empty DS response from %s", addrbuf);
20863 }
20864
20865 TIME_NOW(&timenow);
20866 now = isc_time_seconds(&timenow);
20867
20868 CHECK(dns_zone_getdb(zone, &db));
20869 dns_db_currentversion(db, &version);
20870
20871 KASP_LOCK(kasp);
20872 LOCK_ZONE(zone);
20873 for (key = ISC_LIST_HEAD(zone->checkds_ok); key != NULL;
20874 key = ISC_LIST_NEXT(key, link))
20875 {
20876 bool alldone = false, found = false;
20877 bool checkdspub = false, checkdsdel = false, ksk = false;
20878 dst_key_state_t ds_state = DST_KEY_STATE_NA;
20879 isc_stdtime_t published = 0, withdrawn = 0;
20880 isc_result_t ret = ISC_R_SUCCESS;
20881
20882 /* Is this key have the KSK role? */
20883 (void)dst_key_role(key->key, &ksk, NULL);
20884 if (!ksk) {
20885 continue;
20886 }
20887
20888 /* Do we need to check the DS RRset for this key? */
20889 (void)dst_key_getstate(key->key, DST_KEY_DS, &ds_state);
20890 (void)dst_key_gettime(key->key, DST_TIME_DSPUBLISH, &published);
20891 (void)dst_key_gettime(key->key, DST_TIME_DSDELETE, &withdrawn);
20892
20893 if (ds_state == DST_KEY_STATE_RUMOURED && published == 0) {
20894 checkdspub = true;
20895 } else if (ds_state == DST_KEY_STATE_UNRETENTIVE &&
20896 withdrawn == 0)
20897 {
20898 checkdsdel = true;
20899 }
20900 if (!checkdspub && !checkdsdel) {
20901 continue;
20902 }
20903
20904 if (empty) {
20905 goto dswithdrawn;
20906 }
20907
20908 /* Find the appropriate DS record. */
20909 ret = dns_rdataset_first(ds_rrset);
20910 while (ret == ISC_R_SUCCESS) {
20911 dns_rdata_ds_t ds;
20912 dns_rdata_t dnskey = DNS_RDATA_INIT;
20913 dns_rdata_t dsrdata = DNS_RDATA_INIT;
20914 dns_rdata_t rdata = DNS_RDATA_INIT;
20915 isc_result_t r;
20916 unsigned char dsbuf[DNS_DS_BUFFERSIZE];
20917 unsigned char keybuf[DST_KEY_MAXSIZE];
20918
20919 dns_rdataset_current(ds_rrset, &rdata);
20920 r = dns_rdata_tostruct(&rdata, &ds, NULL);
20921 if (r != ISC_R_SUCCESS) {
20922 goto nextds;
20923 }
20924 /* Check key tag and algorithm. */
20925 if (dst_key_id(key->key) != ds.key_tag) {
20926 goto nextds;
20927 }
20928 if (dst_key_alg(key->key) != ds.algorithm) {
20929 goto nextds;
20930 }
20931 /* Derive DS from DNSKEY, see if the rdata is equal. */
20932 make_dnskey(key->key, keybuf, sizeof(keybuf), &dnskey);
20933 r = dns_ds_buildrdata(&zone->origin, &dnskey,
20934 ds.digest_type, dsbuf, &dsrdata);
20935 if (r != ISC_R_SUCCESS) {
20936 goto nextds;
20937 }
20938 if (dns_rdata_compare(&rdata, &dsrdata) == 0) {
20939 found = true;
20940 if (checkdspub) {
20941 /* DS Published. */
20942 alldone = do_checkds(zone, key->key,
20943 now, true);
20944 if (alldone) {
20945 rekey = true;
20946 }
20947 }
20948 }
20949
20950 nextds:
20951 ret = dns_rdataset_next(ds_rrset);
20952 }
20953
20954 dswithdrawn:
20955 /* DS withdrawn. */
20956 if (checkdsdel && !found) {
20957 alldone = do_checkds(zone, key->key, now, false);
20958 if (alldone) {
20959 rekey = true;
20960 }
20961 }
20962 }
20963 UNLOCK_ZONE(zone);
20964 KASP_UNLOCK(kasp);
20965
20966 /* Rekey after checkds. */
20967 if (rekey) {
20968 dns_zone_rekey(zone, false);
20969 }
20970
20971 failure:
20972 if (result != ISC_R_SUCCESS) {
20973 dns_zone_log(zone, ISC_LOG_DEBUG(3),
20974 "checkds: DS request failed: %s",
20975 isc_result_totext(result));
20976 }
20977
20978 if (version != NULL) {
20979 dns_db_closeversion(db, &version, false);
20980 }
20981 if (db != NULL) {
20982 dns_db_detach(&db);
20983 }
20984
20985 while (!ISC_LIST_EMPTY(keys)) {
20986 key = ISC_LIST_HEAD(keys);
20987 ISC_LIST_UNLINK(keys, key, link);
20988 dns_dnsseckey_destroy(dns_zone_getmctx(zone), &key);
20989 }
20990
20991 isc_event_free(&event);
20992 checkds_destroy(checkds, false);
20993 dns_message_detach(&message);
20994 }
20995
20996 static bool
20997 checkds_isqueued(dns_zone_t *zone, isc_sockaddr_t *addr, dns_tsigkey_t *key) {
20998 dns_checkds_t *checkds;
20999
21000 for (checkds = ISC_LIST_HEAD(zone->checkds_requests); checkds != NULL;
21001 checkds = ISC_LIST_NEXT(checkds, link))
21002 {
21003 if (checkds->request != NULL) {
21004 continue;
21005 }
21006 if (addr != NULL && isc_sockaddr_equal(addr, &checkds->dst) &&
21007 checkds->key == key)
21008 {
21009 return (true);
21010 }
21011 }
21012 return (false);
21013 }
21014
21015 static isc_result_t
21016 checkds_create(isc_mem_t *mctx, unsigned int flags, dns_checkds_t **checkdsp) {
21017 dns_checkds_t *checkds;
21018
21019 REQUIRE(checkdsp != NULL && *checkdsp == NULL);
21020
21021 checkds = isc_mem_get(mctx, sizeof(*checkds));
21022 *checkds = (dns_checkds_t){
21023 .flags = flags,
21024 };
21025
21026 isc_mem_attach(mctx, &checkds->mctx);
21027 isc_sockaddr_any(&checkds->dst);
21028 ISC_LINK_INIT(checkds, link);
21029 checkds->magic = CHECKDS_MAGIC;
21030 *checkdsp = checkds;
21031 return (ISC_R_SUCCESS);
21032 }
21033
21034 static isc_result_t
21035 checkds_createmessage(dns_zone_t *zone, dns_message_t **messagep) {
21036 dns_message_t *message = NULL;
21037
21038 dns_name_t *tempname = NULL;
21039 dns_rdataset_t *temprdataset = NULL;
21040
21041 isc_result_t result;
21042
21043 REQUIRE(DNS_ZONE_VALID(zone));
21044 REQUIRE(messagep != NULL && *messagep == NULL);
21045
21046 dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER, &message);
21047
21048 message->opcode = dns_opcode_query;
21049 message->rdclass = zone->rdclass;
21050
21051 result = dns_message_gettempname(message, &tempname);
21052 if (result != ISC_R_SUCCESS) {
21053 goto cleanup;
21054 }
21055
21056 result = dns_message_gettemprdataset(message, &temprdataset);
21057 if (result != ISC_R_SUCCESS) {
21058 goto cleanup;
21059 }
21060
21061 /*
21062 * Make question.
21063 */
21064 dns_name_init(tempname, NULL);
21065 dns_name_clone(&zone->origin, tempname);
21066 dns_rdataset_makequestion(temprdataset, zone->rdclass,
21067 dns_rdatatype_ds);
21068 ISC_LIST_APPEND(tempname->list, temprdataset, link);
21069 dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
21070 tempname = NULL;
21071 temprdataset = NULL;
21072
21073 *messagep = message;
21074 return (ISC_R_SUCCESS);
21075
21076 cleanup:
21077 if (tempname != NULL) {
21078 dns_message_puttempname(message, &tempname);
21079 }
21080 if (temprdataset != NULL) {
21081 dns_message_puttemprdataset(message, &temprdataset);
21082 }
21083 dns_message_detach(&message);
21084 return (result);
21085 }
21086
21087 static void
21088 checkds_send_toaddr(isc_task_t *task, isc_event_t *event) {
21089 dns_checkds_t *checkds;
21090 isc_result_t result;
21091 dns_message_t *message = NULL;
21092 isc_netaddr_t dstip;
21093 dns_tsigkey_t *key = NULL;
21094 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
21095 isc_sockaddr_t src;
21096 unsigned int options, timeout;
21097 bool have_checkdssource = false;
21098 bool have_checkdsdscp = false;
21099 isc_dscp_t dscp = -1;
21100
21101 checkds = event->ev_arg;
21102 REQUIRE(DNS_CHECKDS_VALID(checkds));
21103
21104 UNUSED(task);
21105
21106 LOCK_ZONE(checkds->zone);
21107
21108 checkds->event = NULL;
21109
21110 if (DNS_ZONE_FLAG(checkds->zone, DNS_ZONEFLG_LOADED) == 0) {
21111 result = ISC_R_CANCELED;
21112 goto cleanup;
21113 }
21114
21115 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
21116 DNS_ZONE_FLAG(checkds->zone, DNS_ZONEFLG_EXITING) ||
21117 checkds->zone->view->requestmgr == NULL ||
21118 checkds->zone->db == NULL)
21119 {
21120 result = ISC_R_CANCELED;
21121 goto cleanup;
21122 }
21123
21124 /*
21125 * The raw IPv4 address should also exist. Don't send to the
21126 * mapped form.
21127 */
21128 if (isc_sockaddr_pf(&checkds->dst) == PF_INET6 &&
21129 IN6_IS_ADDR_V4MAPPED(&checkds->dst.type.sin6.sin6_addr))
21130 {
21131 isc_sockaddr_format(&checkds->dst, addrbuf, sizeof(addrbuf));
21132 dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
21133 "checkds: ignoring IPv6 mapped IPV4 address: %s",
21134 addrbuf);
21135 result = ISC_R_CANCELED;
21136 goto cleanup;
21137 }
21138
21139 result = checkds_createmessage(checkds->zone, &message);
21140 if (result != ISC_R_SUCCESS) {
21141 goto cleanup;
21142 }
21143
21144 isc_sockaddr_format(&checkds->dst, addrbuf, sizeof(addrbuf));
21145 if (checkds->key != NULL) {
21146 /* Transfer ownership of key */
21147 key = checkds->key;
21148 checkds->key = NULL;
21149 } else {
21150 isc_netaddr_fromsockaddr(&dstip, &checkds->dst);
21151 result = dns_view_getpeertsig(checkds->zone->view, &dstip,
21152 &key);
21153 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
21154 dns_zone_log(checkds->zone, ISC_LOG_ERROR,
21155 "checkds: DS query to %s not sent. "
21156 "Peer TSIG key lookup failure.",
21157 addrbuf);
21158 goto cleanup_message;
21159 }
21160 }
21161
21162 if (key != NULL) {
21163 char namebuf[DNS_NAME_FORMATSIZE];
21164
21165 dns_name_format(&key->name, namebuf, sizeof(namebuf));
21166 dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
21167 "checkds: sending DS query to %s : TSIG (%s)",
21168 addrbuf, namebuf);
21169 } else {
21170 dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
21171 "checkds: sending DS query to %s", addrbuf);
21172 }
21173 options = 0;
21174 if (checkds->zone->view->peers != NULL) {
21175 dns_peer_t *peer = NULL;
21176 bool usetcp = false;
21177 result = dns_peerlist_peerbyaddr(checkds->zone->view->peers,
21178 &dstip, &peer);
21179 if (result == ISC_R_SUCCESS) {
21180 result = dns_peer_getquerysource(peer, &src);
21181 if (result == ISC_R_SUCCESS) {
21182 have_checkdssource = true;
21183 }
21184 dns_peer_getquerydscp(peer, &dscp);
21185 if (dscp != -1) {
21186 have_checkdsdscp = true;
21187 }
21188 result = dns_peer_getforcetcp(peer, &usetcp);
21189 if (result == ISC_R_SUCCESS && usetcp) {
21190 options |= DNS_FETCHOPT_TCP;
21191 }
21192 }
21193 }
21194 switch (isc_sockaddr_pf(&checkds->dst)) {
21195 case PF_INET:
21196 if (!have_checkdssource) {
21197 src = checkds->zone->parentalsrc4;
21198 }
21199 if (!have_checkdsdscp) {
21200 dscp = checkds->zone->parentalsrc4dscp;
21201 }
21202 break;
21203 case PF_INET6:
21204 if (!have_checkdssource) {
21205 src = checkds->zone->parentalsrc6;
21206 }
21207 if (!have_checkdsdscp) {
21208 dscp = checkds->zone->parentalsrc6dscp;
21209 }
21210 break;
21211 default:
21212 result = ISC_R_NOTIMPLEMENTED;
21213 goto cleanup_key;
21214 }
21215
21216 dns_zone_log(checkds->zone, ISC_LOG_DEBUG(3),
21217 "checkds: create request for DS query to %s", addrbuf);
21218
21219 timeout = 15;
21220 options |= DNS_REQUESTOPT_TCP;
21221 result = dns_request_createvia(
21222 checkds->zone->view->requestmgr, message, &src, &checkds->dst,
21223 dscp, options, key, timeout * 3, timeout, 0,
21224 checkds->zone->task, checkds_done, checkds, &checkds->request);
21225 if (result != ISC_R_SUCCESS) {
21226 dns_zone_log(
21227 checkds->zone, ISC_LOG_DEBUG(3),
21228 "checkds: dns_request_createvia() to %s failed: %s",
21229 addrbuf, dns_result_totext(result));
21230 }
21231
21232 cleanup_key:
21233 if (key != NULL) {
21234 dns_tsigkey_detach(&key);
21235 }
21236 cleanup_message:
21237 dns_message_detach(&message);
21238 cleanup:
21239 UNLOCK_ZONE(checkds->zone);
21240 isc_event_free(&event);
21241 if (result != ISC_R_SUCCESS) {
21242 checkds_destroy(checkds, false);
21243 }
21244 }
21245
21246 static isc_result_t
21247 checkds_send_queue(dns_checkds_t *checkds) {
21248 isc_event_t *e;
21249 isc_result_t result;
21250
21251 INSIST(checkds->event == NULL);
21252 e = isc_event_allocate(checkds->mctx, NULL, DNS_EVENT_CHECKDSSENDTOADDR,
21253 checkds_send_toaddr, checkds,
21254 sizeof(isc_event_t));
21255 e->ev_arg = checkds;
21256 e->ev_sender = NULL;
21257 result = isc_ratelimiter_enqueue(checkds->zone->zmgr->checkdsrl,
21258 checkds->zone->task, &e);
21259 if (result != ISC_R_SUCCESS) {
21260 isc_event_free(&e);
21261 checkds->event = NULL;
21262 }
21263 return (result);
21264 }
21265
21266 static void
21267 checkds_send(dns_zone_t *zone) {
21268 dns_view_t *view = dns_zone_getview(zone);
21269 isc_result_t result;
21270 unsigned int flags = 0;
21271
21272 /*
21273 * Zone lock held by caller.
21274 */
21275 REQUIRE(LOCKED_ZONE(zone));
21276
21277 dns_zone_log(zone, ISC_LOG_DEBUG(3),
21278 "checkds: start sending DS queries to %u parentals",
21279 zone->parentalscnt);
21280
21281 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
21282 dns_zone_log(zone, ISC_LOG_DEBUG(3),
21283 "checkds: abort, named exiting");
21284 return;
21285 }
21286
21287 for (unsigned int i = 0; i < zone->parentalscnt; i++) {
21288 dns_tsigkey_t *key = NULL;
21289 isc_sockaddr_t dst;
21290 dns_checkds_t *checkds = NULL;
21291
21292 if ((zone->parentalkeynames != NULL) &&
21293 (zone->parentalkeynames[i] != NULL))
21294 {
21295 dns_name_t *keyname = zone->parentalkeynames[i];
21296 (void)dns_view_gettsig(view, keyname, &key);
21297 }
21298
21299 dst = zone->parentals[i];
21300
21301 if (checkds_isqueued(zone, &dst, key)) {
21302 dns_zone_log(zone, ISC_LOG_DEBUG(3),
21303 "checkds: DS query to parent "
21304 "%d is queued",
21305 i);
21306 if (key != NULL) {
21307 dns_tsigkey_detach(&key);
21308 }
21309 continue;
21310 }
21311
21312 dns_zone_log(zone, ISC_LOG_DEBUG(3),
21313 "checkds: create DS query for "
21314 "parent %d",
21315 i);
21316
21317 result = checkds_create(zone->mctx, flags, &checkds);
21318 if (result != ISC_R_SUCCESS) {
21319 dns_zone_log(zone, ISC_LOG_DEBUG(3),
21320 "checkds: create DS query for "
21321 "parent %d failed",
21322 i);
21323 continue;
21324 }
21325 zone_iattach(zone, &checkds->zone);
21326 checkds->dst = dst;
21327
21328 INSIST(checkds->key == NULL);
21329 if (key != NULL) {
21330 checkds->key = key;
21331 key = NULL;
21332 }
21333
21334 ISC_LIST_APPEND(zone->checkds_requests, checkds, link);
21335 result = checkds_send_queue(checkds);
21336 if (result != ISC_R_SUCCESS) {
21337 dns_zone_log(zone, ISC_LOG_DEBUG(3),
21338 "checkds: send DS query to "
21339 "parent %d failed",
21340 i);
21341 checkds_destroy(checkds, true);
21342 }
21343 }
21344 }
21345
21346 static void
21347 zone_checkds(dns_zone_t *zone) {
21348 bool cdscheck = false;
21349
21350 for (dns_dnsseckey_t *key = ISC_LIST_HEAD(zone->checkds_ok);
21351 key != NULL; key = ISC_LIST_NEXT(key, link))
21352 {
21353 dst_key_state_t ds_state = DST_KEY_STATE_NA;
21354 bool ksk = false;
21355 isc_stdtime_t published = 0, withdrawn = 0;
21356
21357 /* Is this key have the KSK role? */
21358 (void)dst_key_role(key->key, &ksk, NULL);
21359 if (!ksk) {
21360 continue;
21361 }
21362
21363 /* Do we need to check the DS RRset? */
21364 (void)dst_key_getstate(key->key, DST_KEY_DS, &ds_state);
21365 (void)dst_key_gettime(key->key, DST_TIME_DSPUBLISH, &published);
21366 (void)dst_key_gettime(key->key, DST_TIME_DSDELETE, &withdrawn);
21367
21368 if (ds_state == DST_KEY_STATE_RUMOURED && published == 0) {
21369 dst_key_setnum(key->key, DST_NUM_DSPUBCOUNT, 0);
21370 cdscheck = true;
21371 } else if (ds_state == DST_KEY_STATE_UNRETENTIVE &&
21372 withdrawn == 0)
21373 {
21374 dst_key_setnum(key->key, DST_NUM_DSDELCOUNT, 0);
21375 cdscheck = true;
21376 }
21377 }
21378
21379 if (cdscheck) {
21380 /* Request the DS RRset. */
21381 LOCK_ZONE(zone);
21382 checkds_send(zone);
21383 UNLOCK_ZONE(zone);
21384 }
21385 }
21386
21387 static void
21388 zone_rekey(dns_zone_t *zone) {
21389 isc_result_t result;
21390 dns_db_t *db = NULL;
21391 dns_dbnode_t *node = NULL;
21392 dns_dbversion_t *ver = NULL;
21393 dns_rdataset_t cdsset, soaset, soasigs, keyset, keysigs, cdnskeyset;
21394 dns_dnsseckeylist_t dnskeys, keys, rmkeys;
21395 dns_dnsseckey_t *key = NULL;
21396 dns_diff_t diff, _sig_diff;
21397 dns_kasp_t *kasp;
21398 dns__zonediff_t zonediff;
21399 bool commit = false, newactive = false;
21400 bool newalg = false;
21401 bool fullsign;
21402 dns_ttl_t ttl = 3600;
21403 const char *dir = NULL;
21404 isc_mem_t *mctx = NULL;
21405 isc_stdtime_t now, nexttime = 0;
21406 isc_time_t timenow;
21407 isc_interval_t ival;
21408 char timebuf[80];
21409
21410 REQUIRE(DNS_ZONE_VALID(zone));
21411
21412 ISC_LIST_INIT(dnskeys);
21413 ISC_LIST_INIT(keys);
21414 ISC_LIST_INIT(rmkeys);
21415 dns_rdataset_init(&soaset);
21416 dns_rdataset_init(&soasigs);
21417 dns_rdataset_init(&keyset);
21418 dns_rdataset_init(&keysigs);
21419 dns_rdataset_init(&cdsset);
21420 dns_rdataset_init(&cdnskeyset);
21421 dir = dns_zone_getkeydirectory(zone);
21422 mctx = zone->mctx;
21423 dns_diff_init(mctx, &diff);
21424 dns_diff_init(mctx, &_sig_diff);
21425 zonediff_init(&zonediff, &_sig_diff);
21426
21427 CHECK(dns_zone_getdb(zone, &db));
21428 CHECK(dns_db_newversion(db, &ver));
21429 CHECK(dns_db_getoriginnode(db, &node));
21430
21431 TIME_NOW(&timenow);
21432 now = isc_time_seconds(&timenow);
21433
21434 kasp = dns_zone_getkasp(zone);
21435
21436 dnssec_log(zone, ISC_LOG_INFO, "reconfiguring zone keys");
21437
21438 /* Get the SOA record's TTL */
21439 CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_soa,
21440 dns_rdatatype_none, 0, &soaset, &soasigs));
21441 ttl = soaset.ttl;
21442 dns_rdataset_disassociate(&soaset);
21443
21444 /* Get the DNSKEY rdataset */
21445 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
21446 dns_rdatatype_none, 0, &keyset, &keysigs);
21447 if (result == ISC_R_SUCCESS) {
21448 ttl = keyset.ttl;
21449
21450 dns_zone_lock_keyfiles(zone);
21451
21452 result = dns_dnssec_keylistfromrdataset(
21453 &zone->origin, dir, mctx, &keyset, &keysigs, &soasigs,
21454 false, false, &dnskeys);
21455
21456 dns_zone_unlock_keyfiles(zone);
21457
21458 if (result != ISC_R_SUCCESS) {
21459 goto failure;
21460 }
21461 } else if (result != ISC_R_NOTFOUND) {
21462 goto failure;
21463 }
21464
21465 /* Get the CDS rdataset */
21466 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_cds,
21467 dns_rdatatype_none, 0, &cdsset, NULL);
21468 if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdsset)) {
21469 dns_rdataset_disassociate(&cdsset);
21470 }
21471
21472 /* Get the CDNSKEY rdataset */
21473 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_cdnskey,
21474 dns_rdatatype_none, 0, &cdnskeyset, NULL);
21475 if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdnskeyset)) {
21476 dns_rdataset_disassociate(&cdnskeyset);
21477 }
21478
21479 /*
21480 * True when called from "rndc sign". Indicates the zone should be
21481 * fully signed now.
21482 */
21483 fullsign = DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_FULLSIGN);
21484
21485 KASP_LOCK(kasp);
21486
21487 dns_zone_lock_keyfiles(zone);
21488 result = dns_dnssec_findmatchingkeys(&zone->origin, dir, now, mctx,
21489 &keys);
21490 dns_zone_unlock_keyfiles(zone);
21491
21492 if (result != ISC_R_SUCCESS) {
21493 dnssec_log(zone, ISC_LOG_DEBUG(1),
21494 "zone_rekey:dns_dnssec_findmatchingkeys failed: %s",
21495 isc_result_totext(result));
21496 }
21497
21498 if (kasp != NULL) {
21499 /*
21500 * Check DS at parental agents. Clear ongoing checks.
21501 */
21502 LOCK_ZONE(zone);
21503 checkds_cancel(zone);
21504 clear_keylist(&zone->checkds_ok, zone->mctx);
21505 ISC_LIST_INIT(zone->checkds_ok);
21506 UNLOCK_ZONE(zone);
21507
21508 result = dns_zone_getdnsseckeys(zone, db, ver, now,
21509 &zone->checkds_ok);
21510
21511 if (result == ISC_R_SUCCESS) {
21512 zone_checkds(zone);
21513 } else {
21514 dnssec_log(zone,
21515 (result == ISC_R_NOTFOUND) ? ISC_LOG_DEBUG(1)
21516 : ISC_LOG_ERROR,
21517 "zone_rekey:dns_zone_getdnsseckeys failed: "
21518 "%s",
21519 isc_result_totext(result));
21520 }
21521
21522 if (result == ISC_R_SUCCESS || result == ISC_R_NOTFOUND) {
21523 dns_zone_lock_keyfiles(zone);
21524 result = dns_keymgr_run(&zone->origin, zone->rdclass,
21525 dir, mctx, &keys, &dnskeys,
21526 kasp, now, &nexttime);
21527 dns_zone_unlock_keyfiles(zone);
21528
21529 if (result != ISC_R_SUCCESS) {
21530 dnssec_log(zone, ISC_LOG_ERROR,
21531 "zone_rekey:dns_dnssec_keymgr "
21532 "failed: %s",
21533 isc_result_totext(result));
21534 KASP_UNLOCK(kasp);
21535 goto failure;
21536 }
21537 }
21538 }
21539
21540 KASP_UNLOCK(kasp);
21541
21542 if (result == ISC_R_SUCCESS) {
21543 bool cdsdel = false;
21544 bool cdnskeydel = false;
21545 isc_stdtime_t when;
21546
21547 /*
21548 * Publish CDS/CDNSKEY DELETE records if the zone is
21549 * transitioning from secure to insecure.
21550 */
21551 if (kasp != NULL) {
21552 if (strcmp(dns_kasp_getname(kasp), "insecure") == 0) {
21553 cdsdel = true;
21554 cdnskeydel = true;
21555 }
21556 } else {
21557 /* Check if there is a CDS DELETE record. */
21558 if (dns_rdataset_isassociated(&cdsset)) {
21559 for (result = dns_rdataset_first(&cdsset);
21560 result == ISC_R_SUCCESS;
21561 result = dns_rdataset_next(&cdsset))
21562 {
21563 dns_rdata_t crdata = DNS_RDATA_INIT;
21564 dns_rdataset_current(&cdsset, &crdata);
21565 /*
21566 * CDS deletion record has this form
21567 * "0 0 0 00" which is 5 zero octets.
21568 */
21569 if (crdata.length == 5U &&
21570 memcmp(crdata.data,
21571 (unsigned char[5]){ 0, 0, 0,
21572 0, 0 },
21573 5) == 0)
21574 {
21575 cdsdel = true;
21576 break;
21577 }
21578 }
21579 }
21580
21581 /* Check if there is a CDNSKEY DELETE record. */
21582 if (dns_rdataset_isassociated(&cdnskeyset)) {
21583 for (result = dns_rdataset_first(&cdnskeyset);
21584 result == ISC_R_SUCCESS;
21585 result = dns_rdataset_next(&cdnskeyset))
21586 {
21587 dns_rdata_t crdata = DNS_RDATA_INIT;
21588 dns_rdataset_current(&cdnskeyset,
21589 &crdata);
21590 /*
21591 * CDNSKEY deletion record has this form
21592 * "0 3 0 AA==" which is 2 zero octets,
21593 * a 3, and 2 zero octets.
21594 */
21595 if (crdata.length == 5U &&
21596 memcmp(crdata.data,
21597 (unsigned char[5]){ 0, 0, 3,
21598 0, 0 },
21599 5) == 0)
21600 {
21601 cdnskeydel = true;
21602 break;
21603 }
21604 }
21605 }
21606 }
21607
21608 /*
21609 * Only update DNSKEY TTL if we have a policy.
21610 */
21611 if (kasp != NULL) {
21612 ttl = dns_kasp_dnskeyttl(kasp);
21613 }
21614
21615 result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys,
21616 &zone->origin, ttl, &diff, mctx,
21617 dnssec_report);
21618 /*
21619 * Keys couldn't be updated for some reason;
21620 * try again later.
21621 */
21622 if (result != ISC_R_SUCCESS) {
21623 dnssec_log(zone, ISC_LOG_ERROR,
21624 "zone_rekey:couldn't update zone keys: %s",
21625 isc_result_totext(result));
21626 goto failure;
21627 }
21628
21629 /*
21630 * Update CDS / CDNSKEY records.
21631 */
21632 result = dns_dnssec_syncupdate(&dnskeys, &rmkeys, &cdsset,
21633 &cdnskeyset, now, ttl, &diff,
21634 mctx);
21635 if (result != ISC_R_SUCCESS) {
21636 dnssec_log(zone, ISC_LOG_ERROR,
21637 "zone_rekey:couldn't update CDS/CDNSKEY: %s",
21638 isc_result_totext(result));
21639 goto failure;
21640 }
21641
21642 if (cdsdel || cdnskeydel) {
21643 /*
21644 * Only publish CDS/CDNSKEY DELETE records if there is
21645 * a KSK that can be used to verify the RRset. This
21646 * means there must be a key with the KSK role that is
21647 * published and is used for signing.
21648 */
21649 bool allow = false;
21650 for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
21651 key = ISC_LIST_NEXT(key, link))
21652 {
21653 dst_key_t *dstk = key->key;
21654
21655 if (dst_key_is_published(dstk, now, &when) &&
21656 dst_key_is_signing(dstk, DST_BOOL_KSK, now,
21657 &when))
21658 {
21659 allow = true;
21660 break;
21661 }
21662 }
21663 if (cdsdel) {
21664 cdsdel = allow;
21665 }
21666 if (cdnskeydel) {
21667 cdnskeydel = allow;
21668 }
21669 }
21670 result = dns_dnssec_syncdelete(
21671 &cdsset, &cdnskeyset, &zone->origin, zone->rdclass, ttl,
21672 &diff, mctx, cdsdel, cdnskeydel);
21673 if (result != ISC_R_SUCCESS) {
21674 dnssec_log(zone, ISC_LOG_ERROR,
21675 "zone_rekey:couldn't update CDS/CDNSKEY "
21676 "DELETE records: %s",
21677 isc_result_totext(result));
21678 goto failure;
21679 }
21680
21681 /*
21682 * See if any pre-existing keys have newly become active;
21683 * also, see if any new key is for a new algorithm, as in that
21684 * event, we need to sign the zone fully. (If there's a new
21685 * key, but it's for an already-existing algorithm, then
21686 * the zone signing can be handled incrementally.)
21687 */
21688 for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
21689 key = ISC_LIST_NEXT(key, link))
21690 {
21691 if (!key->first_sign) {
21692 continue;
21693 }
21694
21695 newactive = true;
21696
21697 if (!dns_rdataset_isassociated(&keysigs)) {
21698 newalg = true;
21699 break;
21700 }
21701
21702 if (signed_with_alg(&keysigs, dst_key_alg(key->key))) {
21703 /*
21704 * This isn't a new algorithm; clear
21705 * first_sign so we won't sign the
21706 * whole zone with this key later.
21707 */
21708 key->first_sign = false;
21709 } else {
21710 newalg = true;
21711 break;
21712 }
21713 }
21714
21715 if ((newactive || fullsign || !ISC_LIST_EMPTY(diff.tuples)) &&
21716 dnskey_sane(zone, db, ver, &diff))
21717 {
21718 CHECK(dns_diff_apply(&diff, db, ver));
21719 CHECK(clean_nsec3param(zone, db, ver, &diff));
21720 CHECK(add_signing_records(db, zone->privatetype, ver,
21721 &diff, (newalg || fullsign)));
21722 CHECK(update_soa_serial(zone, db, ver, &diff, mctx,
21723 zone->updatemethod));
21724 CHECK(add_chains(zone, db, ver, &diff));
21725 CHECK(sign_apex(zone, db, ver, now, &diff, &zonediff));
21726 CHECK(zone_journal(zone, zonediff.diff, NULL,
21727 "zone_rekey"));
21728 commit = true;
21729 }
21730 }
21731
21732 dns_db_closeversion(db, &ver, true);
21733
21734 LOCK_ZONE(zone);
21735
21736 if (commit) {
21737 dns_difftuple_t *tuple;
21738 dns_stats_t *dnssecsignstats =
21739 dns_zone_getdnssecsignstats(zone);
21740
21741 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
21742
21743 zone_needdump(zone, DNS_DUMP_DELAY);
21744
21745 zone_settimer(zone, &timenow);
21746
21747 /* Remove any signatures from removed keys. */
21748 if (!ISC_LIST_EMPTY(rmkeys)) {
21749 for (key = ISC_LIST_HEAD(rmkeys); key != NULL;
21750 key = ISC_LIST_NEXT(key, link))
21751 {
21752 result = zone_signwithkey(
21753 zone, dst_key_alg(key->key),
21754 dst_key_id(key->key), true);
21755 if (result != ISC_R_SUCCESS) {
21756 dnssec_log(zone, ISC_LOG_ERROR,
21757 "zone_signwithkey failed: "
21758 "%s",
21759 dns_result_totext(result));
21760 }
21761
21762 /* Clear DNSSEC sign statistics. */
21763 if (dnssecsignstats != NULL) {
21764 dns_dnssecsignstats_clear(
21765 dnssecsignstats,
21766 dst_key_id(key->key),
21767 dst_key_alg(key->key));
21768 /*
21769 * Also clear the dnssec-sign
21770 * statistics of the revoked key id.
21771 */
21772 dns_dnssecsignstats_clear(
21773 dnssecsignstats,
21774 dst_key_rid(key->key),
21775 dst_key_alg(key->key));
21776 }
21777 }
21778 }
21779
21780 if (fullsign) {
21781 /*
21782 * "rndc sign" was called, so we now sign the zone
21783 * with all active keys, whether they're new or not.
21784 */
21785 for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
21786 key = ISC_LIST_NEXT(key, link))
21787 {
21788 if (!key->force_sign && !key->hint_sign) {
21789 continue;
21790 }
21791
21792 result = zone_signwithkey(
21793 zone, dst_key_alg(key->key),
21794 dst_key_id(key->key), false);
21795 if (result != ISC_R_SUCCESS) {
21796 dnssec_log(zone, ISC_LOG_ERROR,
21797 "zone_signwithkey failed: "
21798 "%s",
21799 dns_result_totext(result));
21800 }
21801 }
21802 } else if (newalg) {
21803 /*
21804 * We haven't been told to sign fully, but a new
21805 * algorithm was added to the DNSKEY. We sign
21806 * the full zone, but only with newly active
21807 * keys.
21808 */
21809 for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
21810 key = ISC_LIST_NEXT(key, link))
21811 {
21812 if (!key->first_sign) {
21813 continue;
21814 }
21815
21816 result = zone_signwithkey(
21817 zone, dst_key_alg(key->key),
21818 dst_key_id(key->key), false);
21819 if (result != ISC_R_SUCCESS) {
21820 dnssec_log(zone, ISC_LOG_ERROR,
21821 "zone_signwithkey failed: "
21822 "%s",
21823 dns_result_totext(result));
21824 }
21825 }
21826 }
21827
21828 /*
21829 * Clear fullsign flag, if it was set, so we don't do
21830 * another full signing next time.
21831 */
21832 DNS_ZONEKEY_CLROPTION(zone, DNS_ZONEKEY_FULLSIGN);
21833
21834 /*
21835 * Cause the zone to add/delete NSEC3 chains for the
21836 * deferred NSEC3PARAM changes.
21837 */
21838 for (tuple = ISC_LIST_HEAD(zonediff.diff->tuples);
21839 tuple != NULL; tuple = ISC_LIST_NEXT(tuple, link))
21840 {
21841 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
21842 dns_rdata_t rdata = DNS_RDATA_INIT;
21843 dns_rdata_nsec3param_t nsec3param;
21844
21845 if (tuple->rdata.type != zone->privatetype ||
21846 tuple->op != DNS_DIFFOP_ADD)
21847 {
21848 continue;
21849 }
21850
21851 if (!dns_nsec3param_fromprivate(&tuple->rdata, &rdata,
21852 buf, sizeof(buf)))
21853 {
21854 continue;
21855 }
21856
21857 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
21858 RUNTIME_CHECK(result == ISC_R_SUCCESS);
21859 if (nsec3param.flags == 0) {
21860 continue;
21861 }
21862
21863 result = zone_addnsec3chain(zone, &nsec3param);
21864 if (result != ISC_R_SUCCESS) {
21865 dnssec_log(zone, ISC_LOG_ERROR,
21866 "zone_addnsec3chain failed: %s",
21867 dns_result_totext(result));
21868 }
21869 }
21870
21871 /*
21872 * Activate any NSEC3 chain updates that may have
21873 * been scheduled before this rekey.
21874 */
21875 if (fullsign || newalg) {
21876 resume_addnsec3chain(zone);
21877 }
21878
21879 /*
21880 * Schedule the next resigning event
21881 */
21882 set_resigntime(zone);
21883 }
21884
21885 isc_time_settoepoch(&zone->refreshkeytime);
21886
21887 /*
21888 * If keymgr provided a next time, use the calculated next rekey time.
21889 */
21890 if (kasp != NULL) {
21891 isc_time_t timenext;
21892 uint32_t nexttime_seconds;
21893
21894 /*
21895 * Set the key refresh timer to the next scheduled key event
21896 * or to 'dnssec-loadkeys-interval' seconds in the future
21897 * if no next key event is scheduled (nexttime == 0).
21898 */
21899 if (nexttime > 0) {
21900 nexttime_seconds = nexttime - now;
21901 } else {
21902 nexttime_seconds = zone->refreshkeyinterval;
21903 }
21904
21905 DNS_ZONE_TIME_ADD(&timenow, nexttime_seconds, &timenext);
21906 zone->refreshkeytime = timenext;
21907 zone_settimer(zone, &timenow);
21908 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
21909
21910 dnssec_log(zone, ISC_LOG_DEBUG(3),
21911 "next key event in %u seconds", nexttime_seconds);
21912 dnssec_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
21913 }
21914 /*
21915 * If we're doing key maintenance, set the key refresh timer to
21916 * the next scheduled key event or to 'dnssec-loadkeys-interval'
21917 * seconds in the future, whichever is sooner.
21918 */
21919 else if (DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
21920 {
21921 isc_time_t timethen;
21922 isc_stdtime_t then;
21923
21924 DNS_ZONE_TIME_ADD(&timenow, zone->refreshkeyinterval,
21925 &timethen);
21926 zone->refreshkeytime = timethen;
21927
21928 for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
21929 key = ISC_LIST_NEXT(key, link))
21930 {
21931 then = now;
21932 result = next_keyevent(key->key, &then);
21933 if (result != ISC_R_SUCCESS) {
21934 continue;
21935 }
21936
21937 DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
21938 if (isc_time_compare(&timethen, &zone->refreshkeytime) <
21939 0)
21940 {
21941 zone->refreshkeytime = timethen;
21942 }
21943 }
21944
21945 zone_settimer(zone, &timenow);
21946
21947 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
21948 dnssec_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
21949 }
21950 UNLOCK_ZONE(zone);
21951
21952 if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
21953 for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
21954 key = ISC_LIST_NEXT(key, link))
21955 {
21956 /* This debug log is used in the kasp system test */
21957 char algbuf[DNS_SECALG_FORMATSIZE];
21958 dns_secalg_format(dst_key_alg(key->key), algbuf,
21959 sizeof(algbuf));
21960 dnssec_log(zone, ISC_LOG_DEBUG(3),
21961 "zone_rekey done: key %d/%s",
21962 dst_key_id(key->key), algbuf);
21963 }
21964 }
21965
21966 result = ISC_R_SUCCESS;
21967
21968 failure:
21969 LOCK_ZONE(zone);
21970 if (result != ISC_R_SUCCESS) {
21971 /*
21972 * Something went wrong; try again in ten minutes or
21973 * after a key refresh interval, whichever is shorter.
21974 */
21975 dnssec_log(zone, ISC_LOG_DEBUG(3),
21976 "zone_rekey failure: %s (retry in %u seconds)",
21977 isc_result_totext(result),
21978 ISC_MIN(zone->refreshkeyinterval, 600));
21979 isc_interval_set(&ival, ISC_MIN(zone->refreshkeyinterval, 600),
21980 0);
21981 isc_time_nowplusinterval(&zone->refreshkeytime, &ival);
21982 }
21983 UNLOCK_ZONE(zone);
21984
21985 dns_diff_clear(&diff);
21986 dns_diff_clear(&_sig_diff);
21987
21988 clear_keylist(&dnskeys, mctx);
21989 clear_keylist(&keys, mctx);
21990 clear_keylist(&rmkeys, mctx);
21991
21992 if (ver != NULL) {
21993 dns_db_closeversion(db, &ver, false);
21994 }
21995 if (dns_rdataset_isassociated(&cdsset)) {
21996 dns_rdataset_disassociate(&cdsset);
21997 }
21998 if (dns_rdataset_isassociated(&keyset)) {
21999 dns_rdataset_disassociate(&keyset);
22000 }
22001 if (dns_rdataset_isassociated(&keysigs)) {
22002 dns_rdataset_disassociate(&keysigs);
22003 }
22004 if (dns_rdataset_isassociated(&soasigs)) {
22005 dns_rdataset_disassociate(&soasigs);
22006 }
22007 if (dns_rdataset_isassociated(&cdnskeyset)) {
22008 dns_rdataset_disassociate(&cdnskeyset);
22009 }
22010 if (node != NULL) {
22011 dns_db_detachnode(db, &node);
22012 }
22013 if (db != NULL) {
22014 dns_db_detach(&db);
22015 }
22016
22017 INSIST(ver == NULL);
22018 }
22019
22020 void
22021 dns_zone_rekey(dns_zone_t *zone, bool fullsign) {
22022 isc_time_t now;
22023
22024 if (zone->type == dns_zone_primary && zone->task != NULL) {
22025 LOCK_ZONE(zone);
22026
22027 if (fullsign) {
22028 DNS_ZONEKEY_SETOPTION(zone, DNS_ZONEKEY_FULLSIGN);
22029 }
22030
22031 TIME_NOW(&now);
22032 zone->refreshkeytime = now;
22033 zone_settimer(zone, &now);
22034
22035 UNLOCK_ZONE(zone);
22036 }
22037 }
22038
22039 isc_result_t
22040 dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
22041 unsigned int *errors) {
22042 isc_result_t result;
22043 dns_dbnode_t *node = NULL;
22044
22045 REQUIRE(DNS_ZONE_VALID(zone));
22046 REQUIRE(errors != NULL);
22047
22048 result = dns_db_getoriginnode(db, &node);
22049 if (result != ISC_R_SUCCESS) {
22050 return (result);
22051 }
22052 result = zone_count_ns_rr(zone, db, node, version, NULL, errors, false);
22053 dns_db_detachnode(db, &node);
22054 return (result);
22055 }
22056
22057 isc_result_t
22058 dns_zone_cdscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version) {
22059 isc_result_t result;
22060 dns_dbnode_t *node = NULL;
22061 dns_rdataset_t dnskey, cds, cdnskey;
22062 unsigned char algorithms[256];
22063 unsigned int i;
22064 bool empty = false;
22065
22066 enum { notexpected = 0, expected = 1, found = 2 };
22067
22068 REQUIRE(DNS_ZONE_VALID(zone));
22069
22070 result = dns_db_getoriginnode(db, &node);
22071 if (result != ISC_R_SUCCESS) {
22072 return (result);
22073 }
22074
22075 dns_rdataset_init(&cds);
22076 dns_rdataset_init(&dnskey);
22077 dns_rdataset_init(&cdnskey);
22078
22079 result = dns_db_findrdataset(db, node, version, dns_rdatatype_cds,
22080 dns_rdatatype_none, 0, &cds, NULL);
22081 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
22082 goto failure;
22083 }
22084
22085 result = dns_db_findrdataset(db, node, version, dns_rdatatype_cdnskey,
22086 dns_rdatatype_none, 0, &cdnskey, NULL);
22087 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
22088 goto failure;
22089 }
22090
22091 if (!dns_rdataset_isassociated(&cds) &&
22092 !dns_rdataset_isassociated(&cdnskey))
22093 {
22094 result = ISC_R_SUCCESS;
22095 goto failure;
22096 }
22097
22098 result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
22099 dns_rdatatype_none, 0, &dnskey, NULL);
22100 if (result == ISC_R_NOTFOUND) {
22101 empty = true;
22102 } else if (result != ISC_R_SUCCESS) {
22103 goto failure;
22104 }
22105
22106 /*
22107 * For each DNSSEC algorithm in the CDS RRset there must be
22108 * a matching DNSKEY record with the exception of a CDS deletion
22109 * record which must be by itself.
22110 */
22111 if (dns_rdataset_isassociated(&cds)) {
22112 bool delete = false;
22113 memset(algorithms, notexpected, sizeof(algorithms));
22114 for (result = dns_rdataset_first(&cds); result == ISC_R_SUCCESS;
22115 result = dns_rdataset_next(&cds))
22116 {
22117 dns_rdata_t crdata = DNS_RDATA_INIT;
22118 dns_rdata_cds_t structcds;
22119
22120 dns_rdataset_current(&cds, &crdata);
22121 /*
22122 * CDS deletion record has this form "0 0 0 00" which
22123 * is 5 zero octets.
22124 */
22125 if (crdata.length == 5U &&
22126 memcmp(crdata.data,
22127 (unsigned char[5]){ 0, 0, 0, 0, 0 }, 5) == 0)
22128 {
22129 delete = true;
22130 continue;
22131 }
22132
22133 if (empty) {
22134 result = DNS_R_BADCDS;
22135 goto failure;
22136 }
22137
22138 CHECK(dns_rdata_tostruct(&crdata, &structcds, NULL));
22139 if (algorithms[structcds.algorithm] == 0) {
22140 algorithms[structcds.algorithm] = expected;
22141 }
22142 for (result = dns_rdataset_first(&dnskey);
22143 result == ISC_R_SUCCESS;
22144 result = dns_rdataset_next(&dnskey))
22145 {
22146 dns_rdata_t rdata = DNS_RDATA_INIT;
22147 dns_rdata_dnskey_t structdnskey;
22148
22149 dns_rdataset_current(&dnskey, &rdata);
22150 CHECK(dns_rdata_tostruct(&rdata, &structdnskey,
22151 NULL));
22152
22153 if (structdnskey.algorithm ==
22154 structcds.algorithm)
22155 {
22156 algorithms[structcds.algorithm] = found;
22157 }
22158 }
22159 if (result != ISC_R_NOMORE) {
22160 goto failure;
22161 }
22162 }
22163 for (i = 0; i < sizeof(algorithms); i++) {
22164 if (delete) {
22165 if (algorithms[i] != notexpected) {
22166 result = DNS_R_BADCDS;
22167 goto failure;
22168 }
22169 } else if (algorithms[i] == expected) {
22170 result = DNS_R_BADCDS;
22171 goto failure;
22172 }
22173 }
22174 }
22175
22176 /*
22177 * For each DNSSEC algorithm in the CDNSKEY RRset there must be
22178 * a matching DNSKEY record with the exception of a CDNSKEY deletion
22179 * record which must be by itself.
22180 */
22181 if (dns_rdataset_isassociated(&cdnskey)) {
22182 bool delete = false;
22183 memset(algorithms, notexpected, sizeof(algorithms));
22184 for (result = dns_rdataset_first(&cdnskey);
22185 result == ISC_R_SUCCESS;
22186 result = dns_rdataset_next(&cdnskey))
22187 {
22188 dns_rdata_t crdata = DNS_RDATA_INIT;
22189 dns_rdata_cdnskey_t structcdnskey;
22190
22191 dns_rdataset_current(&cdnskey, &crdata);
22192 /*
22193 * CDNSKEY deletion record has this form
22194 * "0 3 0 AA==" which is 2 zero octets, a 3,
22195 * and 2 zero octets.
22196 */
22197 if (crdata.length == 5U &&
22198 memcmp(crdata.data,
22199 (unsigned char[5]){ 0, 0, 3, 0, 0 }, 5) == 0)
22200 {
22201 delete = true;
22202 continue;
22203 }
22204
22205 if (empty) {
22206 result = DNS_R_BADCDNSKEY;
22207 goto failure;
22208 }
22209
22210 CHECK(dns_rdata_tostruct(&crdata, &structcdnskey,
22211 NULL));
22212 if (algorithms[structcdnskey.algorithm] == 0) {
22213 algorithms[structcdnskey.algorithm] = expected;
22214 }
22215 for (result = dns_rdataset_first(&dnskey);
22216 result == ISC_R_SUCCESS;
22217 result = dns_rdataset_next(&dnskey))
22218 {
22219 dns_rdata_t rdata = DNS_RDATA_INIT;
22220 dns_rdata_dnskey_t structdnskey;
22221
22222 dns_rdataset_current(&dnskey, &rdata);
22223 CHECK(dns_rdata_tostruct(&rdata, &structdnskey,
22224 NULL));
22225
22226 if (structdnskey.algorithm ==
22227 structcdnskey.algorithm)
22228 {
22229 algorithms[structcdnskey.algorithm] =
22230 found;
22231 }
22232 }
22233 if (result != ISC_R_NOMORE) {
22234 goto failure;
22235 }
22236 }
22237 for (i = 0; i < sizeof(algorithms); i++) {
22238 if (delete) {
22239 if (algorithms[i] != notexpected) {
22240 result = DNS_R_BADCDNSKEY;
22241 goto failure;
22242 }
22243 } else if (algorithms[i] == expected) {
22244 result = DNS_R_BADCDNSKEY;
22245 goto failure;
22246 }
22247 }
22248 }
22249 result = ISC_R_SUCCESS;
22250
22251 failure:
22252 if (dns_rdataset_isassociated(&cds)) {
22253 dns_rdataset_disassociate(&cds);
22254 }
22255 if (dns_rdataset_isassociated(&dnskey)) {
22256 dns_rdataset_disassociate(&dnskey);
22257 }
22258 if (dns_rdataset_isassociated(&cdnskey)) {
22259 dns_rdataset_disassociate(&cdnskey);
22260 }
22261 dns_db_detachnode(db, &node);
22262 return (result);
22263 }
22264
22265 void
22266 dns_zone_setautomatic(dns_zone_t *zone, bool automatic) {
22267 REQUIRE(DNS_ZONE_VALID(zone));
22268
22269 LOCK_ZONE(zone);
22270 zone->automatic = automatic;
22271 UNLOCK_ZONE(zone);
22272 }
22273
22274 bool
22275 dns_zone_getautomatic(dns_zone_t *zone) {
22276 REQUIRE(DNS_ZONE_VALID(zone));
22277 return (zone->automatic);
22278 }
22279
22280 void
22281 dns_zone_setadded(dns_zone_t *zone, bool added) {
22282 REQUIRE(DNS_ZONE_VALID(zone));
22283
22284 LOCK_ZONE(zone);
22285 zone->added = added;
22286 UNLOCK_ZONE(zone);
22287 }
22288
22289 bool
22290 dns_zone_getadded(dns_zone_t *zone) {
22291 REQUIRE(DNS_ZONE_VALID(zone));
22292 return (zone->added);
22293 }
22294
22295 isc_result_t
22296 dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db) {
22297 isc_time_t loadtime;
22298 isc_result_t result;
22299 dns_zone_t *secure = NULL;
22300
22301 TIME_NOW(&loadtime);
22302
22303 /*
22304 * Lock hierarchy: zmgr, zone, raw.
22305 */
22306 again:
22307 LOCK_ZONE(zone);
22308 INSIST(zone != zone->raw);
22309 if (inline_secure(zone)) {
22310 LOCK_ZONE(zone->raw);
22311 } else if (inline_raw(zone)) {
22312 secure = zone->secure;
22313 TRYLOCK_ZONE(result, secure);
22314 if (result != ISC_R_SUCCESS) {
22315 UNLOCK_ZONE(zone);
22316 secure = NULL;
22317 isc_thread_yield();
22318 goto again;
22319 }
22320 }
22321 result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
22322 if (inline_secure(zone)) {
22323 UNLOCK_ZONE(zone->raw);
22324 } else if (secure != NULL) {
22325 UNLOCK_ZONE(secure);
22326 }
22327 UNLOCK_ZONE(zone);
22328 return (result);
22329 }
22330
22331 isc_result_t
22332 dns_zone_setrefreshkeyinterval(dns_zone_t *zone, uint32_t interval) {
22333 REQUIRE(DNS_ZONE_VALID(zone));
22334 if (interval == 0) {
22335 return (ISC_R_RANGE);
22336 }
22337 /* Maximum value: 24 hours (3600 minutes) */
22338 if (interval > (24 * 60)) {
22339 interval = (24 * 60);
22340 }
22341 /* Multiply by 60 for seconds */
22342 zone->refreshkeyinterval = interval * 60;
22343 return (ISC_R_SUCCESS);
22344 }
22345
22346 void
22347 dns_zone_setrequestixfr(dns_zone_t *zone, bool flag) {
22348 REQUIRE(DNS_ZONE_VALID(zone));
22349 zone->requestixfr = flag;
22350 }
22351
22352 bool
22353 dns_zone_getrequestixfr(dns_zone_t *zone) {
22354 REQUIRE(DNS_ZONE_VALID(zone));
22355 return (zone->requestixfr);
22356 }
22357
22358 void
22359 dns_zone_setixfrratio(dns_zone_t *zone, uint32_t ratio) {
22360 REQUIRE(DNS_ZONE_VALID(zone));
22361 zone->ixfr_ratio = ratio;
22362 }
22363
22364 uint32_t
22365 dns_zone_getixfrratio(dns_zone_t *zone) {
22366 REQUIRE(DNS_ZONE_VALID(zone));
22367 return (zone->ixfr_ratio);
22368 }
22369
22370 void
22371 dns_zone_setrequestexpire(dns_zone_t *zone, bool flag) {
22372 REQUIRE(DNS_ZONE_VALID(zone));
22373 zone->requestexpire = flag;
22374 }
22375
22376 bool
22377 dns_zone_getrequestexpire(dns_zone_t *zone) {
22378 REQUIRE(DNS_ZONE_VALID(zone));
22379 return (zone->requestexpire);
22380 }
22381
22382 void
22383 dns_zone_setserialupdatemethod(dns_zone_t *zone, dns_updatemethod_t method) {
22384 REQUIRE(DNS_ZONE_VALID(zone));
22385 zone->updatemethod = method;
22386 }
22387
22388 dns_updatemethod_t
22389 dns_zone_getserialupdatemethod(dns_zone_t *zone) {
22390 REQUIRE(DNS_ZONE_VALID(zone));
22391 return (zone->updatemethod);
22392 }
22393
22394 /*
22395 * Lock hierarchy: zmgr, zone, raw.
22396 */
22397 isc_result_t
22398 dns_zone_link(dns_zone_t *zone, dns_zone_t *raw) {
22399 isc_result_t result;
22400 dns_zonemgr_t *zmgr;
22401
22402 REQUIRE(DNS_ZONE_VALID(zone));
22403 REQUIRE(zone->zmgr != NULL);
22404 REQUIRE(zone->task != NULL);
22405 REQUIRE(zone->loadtask != NULL);
22406 REQUIRE(zone->raw == NULL);
22407
22408 REQUIRE(DNS_ZONE_VALID(raw));
22409 REQUIRE(raw->zmgr == NULL);
22410 REQUIRE(raw->task == NULL);
22411 REQUIRE(raw->loadtask == NULL);
22412 REQUIRE(raw->secure == NULL);
22413
22414 REQUIRE(zone != raw);
22415
22416 /*
22417 * Lock hierarchy: zmgr, zone, raw.
22418 */
22419 zmgr = zone->zmgr;
22420 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
22421 LOCK_ZONE(zone);
22422 LOCK_ZONE(raw);
22423
22424 result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive, NULL,
22425 NULL, zone->task, zone_timer, raw,
22426 &raw->timer);
22427 if (result != ISC_R_SUCCESS) {
22428 goto unlock;
22429 }
22430
22431 /*
22432 * The timer "holds" a iref.
22433 */
22434 isc_refcount_increment0(&raw->irefs);
22435
22436 /* dns_zone_attach(raw, &zone->raw); */
22437 isc_refcount_increment(&raw->erefs);
22438 zone->raw = raw;
22439
22440 /* dns_zone_iattach(zone, &raw->secure); */
22441 zone_iattach(zone, &raw->secure);
22442
22443 isc_task_attach(zone->task, &raw->task);
22444 isc_task_attach(zone->loadtask, &raw->loadtask);
22445
22446 ISC_LIST_APPEND(zmgr->zones, raw, link);
22447 raw->zmgr = zmgr;
22448 isc_refcount_increment(&zmgr->refs);
22449
22450 unlock:
22451 UNLOCK_ZONE(raw);
22452 UNLOCK_ZONE(zone);
22453 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
22454 return (result);
22455 }
22456
22457 void
22458 dns_zone_getraw(dns_zone_t *zone, dns_zone_t **raw) {
22459 REQUIRE(DNS_ZONE_VALID(zone));
22460 REQUIRE(raw != NULL && *raw == NULL);
22461
22462 LOCK(&zone->lock);
22463 INSIST(zone != zone->raw);
22464 if (zone->raw != NULL) {
22465 dns_zone_attach(zone->raw, raw);
22466 }
22467 UNLOCK(&zone->lock);
22468 }
22469
22470 struct keydone {
22471 isc_event_t event;
22472 bool all;
22473 unsigned char data[5];
22474 };
22475
22476 #define PENDINGFLAGS (DNS_NSEC3FLAG_CREATE | DNS_NSEC3FLAG_INITIAL)
22477
22478 static void
22479 keydone(isc_task_t *task, isc_event_t *event) {
22480 const char *me = "keydone";
22481 bool commit = false;
22482 isc_result_t result;
22483 dns_rdata_t rdata = DNS_RDATA_INIT;
22484 dns_dbversion_t *oldver = NULL, *newver = NULL;
22485 dns_zone_t *zone;
22486 dns_db_t *db = NULL;
22487 dns_dbnode_t *node = NULL;
22488 dns_rdataset_t rdataset;
22489 dns_diff_t diff;
22490 struct keydone *kd = (struct keydone *)event;
22491 dns_update_log_t log = { update_log_cb, NULL };
22492 bool clear_pending = false;
22493
22494 UNUSED(task);
22495
22496 zone = event->ev_arg;
22497 INSIST(DNS_ZONE_VALID(zone));
22498
22499 ENTER;
22500
22501 dns_rdataset_init(&rdataset);
22502 dns_diff_init(zone->mctx, &diff);
22503
22504 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
22505 if (zone->db != NULL) {
22506 dns_db_attach(zone->db, &db);
22507 }
22508 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
22509 if (db == NULL) {
22510 goto failure;
22511 }
22512
22513 dns_db_currentversion(db, &oldver);
22514 result = dns_db_newversion(db, &newver);
22515 if (result != ISC_R_SUCCESS) {
22516 dnssec_log(zone, ISC_LOG_ERROR,
22517 "keydone:dns_db_newversion -> %s",
22518 dns_result_totext(result));
22519 goto failure;
22520 }
22521
22522 result = dns_db_getoriginnode(db, &node);
22523 if (result != ISC_R_SUCCESS) {
22524 goto failure;
22525 }
22526
22527 result = dns_db_findrdataset(db, node, newver, zone->privatetype,
22528 dns_rdatatype_none, 0, &rdataset, NULL);
22529 if (result == ISC_R_NOTFOUND) {
22530 INSIST(!dns_rdataset_isassociated(&rdataset));
22531 goto failure;
22532 }
22533 if (result != ISC_R_SUCCESS) {
22534 INSIST(!dns_rdataset_isassociated(&rdataset));
22535 goto failure;
22536 }
22537
22538 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
22539 result = dns_rdataset_next(&rdataset))
22540 {
22541 bool found = false;
22542
22543 dns_rdataset_current(&rdataset, &rdata);
22544
22545 if (kd->all) {
22546 if (rdata.length == 5 && rdata.data[0] != 0 &&
22547 rdata.data[3] == 0 && rdata.data[4] == 1)
22548 {
22549 found = true;
22550 } else if (rdata.data[0] == 0 &&
22551 (rdata.data[2] & PENDINGFLAGS) != 0)
22552 {
22553 found = true;
22554 clear_pending = true;
22555 }
22556 } else if (rdata.length == 5 &&
22557 memcmp(rdata.data, kd->data, 5) == 0)
22558 {
22559 found = true;
22560 }
22561
22562 if (found) {
22563 CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_DEL,
22564 &zone->origin, rdataset.ttl,
22565 &rdata));
22566 }
22567 dns_rdata_reset(&rdata);
22568 }
22569
22570 if (!ISC_LIST_EMPTY(diff.tuples)) {
22571 /* Write changes to journal file. */
22572 CHECK(update_soa_serial(zone, db, newver, &diff, zone->mctx,
22573 zone->updatemethod));
22574
22575 result = dns_update_signatures(&log, zone, db, oldver, newver,
22576 &diff,
22577 zone->sigvalidityinterval);
22578 if (!clear_pending) {
22579 CHECK(result);
22580 }
22581
22582 CHECK(zone_journal(zone, &diff, NULL, "keydone"));
22583 commit = true;
22584
22585 LOCK_ZONE(zone);
22586 DNS_ZONE_SETFLAG(zone,
22587 DNS_ZONEFLG_LOADED | DNS_ZONEFLG_NEEDNOTIFY);
22588 zone_needdump(zone, 30);
22589 UNLOCK_ZONE(zone);
22590 }
22591
22592 failure:
22593 if (dns_rdataset_isassociated(&rdataset)) {
22594 dns_rdataset_disassociate(&rdataset);
22595 }
22596 if (db != NULL) {
22597 if (node != NULL) {
22598 dns_db_detachnode(db, &node);
22599 }
22600 if (oldver != NULL) {
22601 dns_db_closeversion(db, &oldver, false);
22602 }
22603 if (newver != NULL) {
22604 dns_db_closeversion(db, &newver, commit);
22605 }
22606 dns_db_detach(&db);
22607 }
22608 dns_diff_clear(&diff);
22609 isc_event_free(&event);
22610 dns_zone_idetach(&zone);
22611
22612 INSIST(oldver == NULL);
22613 INSIST(newver == NULL);
22614 }
22615
22616 isc_result_t
22617 dns_zone_keydone(dns_zone_t *zone, const char *keystr) {
22618 isc_result_t result = ISC_R_SUCCESS;
22619 isc_event_t *e;
22620 isc_buffer_t b;
22621 dns_zone_t *dummy = NULL;
22622 struct keydone *kd;
22623
22624 REQUIRE(DNS_ZONE_VALID(zone));
22625
22626 LOCK_ZONE(zone);
22627
22628 e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_KEYDONE, keydone,
22629 zone, sizeof(struct keydone));
22630
22631 kd = (struct keydone *)e;
22632 if (strcasecmp(keystr, "all") == 0) {
22633 kd->all = true;
22634 } else {
22635 isc_textregion_t r;
22636 const char *algstr;
22637 dns_keytag_t keyid;
22638 dns_secalg_t alg;
22639 size_t n;
22640
22641 kd->all = false;
22642
22643 n = sscanf(keystr, "%hu/", &keyid);
22644 if (n == 0U) {
22645 CHECK(ISC_R_FAILURE);
22646 }
22647
22648 algstr = strchr(keystr, '/');
22649 if (algstr != NULL) {
22650 algstr++;
22651 } else {
22652 CHECK(ISC_R_FAILURE);
22653 }
22654
22655 n = sscanf(algstr, "%hhu", &alg);
22656 if (n == 0U) {
22657 DE_CONST(algstr, r.base);
22658 r.length = strlen(algstr);
22659 CHECK(dns_secalg_fromtext(&alg, &r));
22660 }
22661
22662 /* construct a private-type rdata */
22663 isc_buffer_init(&b, kd->data, sizeof(kd->data));
22664 isc_buffer_putuint8(&b, alg);
22665 isc_buffer_putuint8(&b, (keyid & 0xff00) >> 8);
22666 isc_buffer_putuint8(&b, (keyid & 0xff));
22667 isc_buffer_putuint8(&b, 0);
22668 isc_buffer_putuint8(&b, 1);
22669 }
22670
22671 zone_iattach(zone, &dummy);
22672 isc_task_send(zone->task, &e);
22673
22674 failure:
22675 if (e != NULL) {
22676 isc_event_free(&e);
22677 }
22678 UNLOCK_ZONE(zone);
22679 return (result);
22680 }
22681
22682 /*
22683 * Called from the zone task's queue after the relevant event is posted by
22684 * dns_zone_setnsec3param().
22685 */
22686 static void
22687 setnsec3param(isc_task_t *task, isc_event_t *event) {
22688 const char *me = "setnsec3param";
22689 dns_zone_t *zone = event->ev_arg;
22690 bool loadpending;
22691
22692 INSIST(DNS_ZONE_VALID(zone));
22693
22694 UNUSED(task);
22695
22696 ENTER;
22697
22698 LOCK_ZONE(zone);
22699 loadpending = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING);
22700 UNLOCK_ZONE(zone);
22701
22702 /*
22703 * If receive_secure_serial is still processing or we have a
22704 * queued event append rss_post queue.
22705 */
22706 if (zone->rss_newver != NULL || ISC_LIST_HEAD(zone->rss_post) != NULL) {
22707 /*
22708 * Wait for receive_secure_serial() to finish processing.
22709 */
22710 ISC_LIST_APPEND(zone->rss_post, event, ev_link);
22711 } else {
22712 bool rescheduled = false;
22713 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
22714 /*
22715 * The zone is not yet fully loaded. Reschedule the event to
22716 * be picked up later. This turns this function into a busy
22717 * wait, but it only happens at startup.
22718 */
22719 if (zone->db == NULL && loadpending) {
22720 rescheduled = true;
22721 isc_task_send(task, &event);
22722 }
22723 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
22724 if (rescheduled) {
22725 return;
22726 }
22727
22728 rss_post(zone, event);
22729 }
22730 dns_zone_idetach(&zone);
22731 }
22732
22733 static void
22734 salt2text(unsigned char *salt, uint8_t saltlen, unsigned char *text,
22735 unsigned int textlen) {
22736 isc_region_t r;
22737 isc_buffer_t buf;
22738 isc_result_t result;
22739
22740 r.base = salt;
22741 r.length = (unsigned int)saltlen;
22742
22743 isc_buffer_init(&buf, text, textlen);
22744 result = isc_hex_totext(&r, 2, "", &buf);
22745 if (result == ISC_R_SUCCESS) {
22746 text[saltlen * 2] = 0;
22747 } else {
22748 text[0] = 0;
22749 }
22750 }
22751
22752 /*
22753 * Check whether NSEC3 chain addition or removal specified by the private-type
22754 * record passed with the event was already queued (or even fully performed).
22755 * If not, modify the relevant private-type records at the zone apex and call
22756 * resume_addnsec3chain().
22757 */
22758 static void
22759 rss_post(dns_zone_t *zone, isc_event_t *event) {
22760 const char *me = "rss_post";
22761 bool commit = false;
22762 isc_result_t result;
22763 dns_dbversion_t *oldver = NULL, *newver = NULL;
22764 dns_db_t *db = NULL;
22765 dns_dbnode_t *node = NULL;
22766 dns_rdataset_t prdataset, nrdataset;
22767 dns_diff_t diff;
22768 struct np3event *npe = (struct np3event *)event;
22769 nsec3param_t *np;
22770 dns_update_log_t log = { update_log_cb, NULL };
22771 dns_rdata_t rdata;
22772 bool nseconly;
22773 bool exists = false;
22774
22775 ENTER;
22776
22777 np = &npe->params;
22778
22779 dns_rdataset_init(&prdataset);
22780 dns_rdataset_init(&nrdataset);
22781 dns_diff_init(zone->mctx, &diff);
22782
22783 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
22784 if (zone->db != NULL) {
22785 dns_db_attach(zone->db, &db);
22786 }
22787 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
22788 if (db == NULL) {
22789 goto failure;
22790 }
22791
22792 dns_db_currentversion(db, &oldver);
22793 result = dns_db_newversion(db, &newver);
22794 if (result != ISC_R_SUCCESS) {
22795 dnssec_log(zone, ISC_LOG_ERROR,
22796 "setnsec3param:dns_db_newversion -> %s",
22797 dns_result_totext(result));
22798 goto failure;
22799 }
22800
22801 CHECK(dns_db_getoriginnode(db, &node));
22802
22803 /*
22804 * Do we need to look up the NSEC3 parameters?
22805 */
22806 if (np->lookup) {
22807 dns_rdata_nsec3param_t param;
22808 dns_rdata_t nrdata = DNS_RDATA_INIT;
22809 dns_rdata_t prdata = DNS_RDATA_INIT;
22810 unsigned char nbuf[DNS_NSEC3PARAM_BUFFERSIZE];
22811 unsigned char saltbuf[255];
22812 isc_buffer_t b;
22813
22814 param.salt = NULL;
22815 result = dns__zone_lookup_nsec3param(zone, &np->rdata, ¶m,
22816 saltbuf, np->resalt);
22817 if (result == ISC_R_SUCCESS) {
22818 /*
22819 * Success because the NSEC3PARAM already exists, but
22820 * function returns void, so goto failure to clean up.
22821 */
22822 goto failure;
22823 }
22824 if (result != DNS_R_NSEC3RESALT && result != ISC_R_NOTFOUND) {
22825 dnssec_log(zone, ISC_LOG_DEBUG(3),
22826 "setnsec3param:lookup nsec3param -> %s",
22827 isc_result_totext(result));
22828 goto failure;
22829 }
22830
22831 INSIST(param.salt != NULL);
22832
22833 /* Update NSEC3 parameters. */
22834 np->rdata.hash = param.hash;
22835 np->rdata.flags = param.flags;
22836 np->rdata.iterations = param.iterations;
22837 np->rdata.salt_length = param.salt_length;
22838 np->rdata.salt = param.salt;
22839
22840 isc_buffer_init(&b, nbuf, sizeof(nbuf));
22841 CHECK(dns_rdata_fromstruct(&nrdata, zone->rdclass,
22842 dns_rdatatype_nsec3param, &np->rdata,
22843 &b));
22844 dns_nsec3param_toprivate(&nrdata, &prdata, zone->privatetype,
22845 np->data, sizeof(np->data));
22846 np->length = prdata.length;
22847 np->nsec = false;
22848 }
22849
22850 /*
22851 * Does a private-type record already exist for this chain?
22852 */
22853 result = dns_db_findrdataset(db, node, newver, zone->privatetype,
22854 dns_rdatatype_none, 0, &prdataset, NULL);
22855 if (result == ISC_R_SUCCESS) {
22856 for (result = dns_rdataset_first(&prdataset);
22857 result == ISC_R_SUCCESS;
22858 result = dns_rdataset_next(&prdataset))
22859 {
22860 dns_rdata_init(&rdata);
22861 dns_rdataset_current(&prdataset, &rdata);
22862
22863 if (np->length == rdata.length &&
22864 memcmp(rdata.data, np->data, np->length) == 0)
22865 {
22866 exists = true;
22867 break;
22868 }
22869 }
22870 } else if (result != ISC_R_NOTFOUND) {
22871 INSIST(!dns_rdataset_isassociated(&prdataset));
22872 goto failure;
22873 }
22874
22875 /*
22876 * Does the chain already exist?
22877 */
22878 result = dns_db_findrdataset(db, node, newver, dns_rdatatype_nsec3param,
22879 dns_rdatatype_none, 0, &nrdataset, NULL);
22880 if (result == ISC_R_SUCCESS) {
22881 for (result = dns_rdataset_first(&nrdataset);
22882 result == ISC_R_SUCCESS;
22883 result = dns_rdataset_next(&nrdataset))
22884 {
22885 dns_rdata_init(&rdata);
22886 dns_rdataset_current(&nrdataset, &rdata);
22887
22888 if (np->length == (rdata.length + 1) &&
22889 memcmp(rdata.data, np->data + 1, np->length - 1) ==
22890 0)
22891 {
22892 exists = true;
22893 break;
22894 }
22895 }
22896 } else if (result != ISC_R_NOTFOUND) {
22897 INSIST(!dns_rdataset_isassociated(&nrdataset));
22898 goto failure;
22899 }
22900
22901 /*
22902 * We need to remove any existing NSEC3 chains if the supplied NSEC3
22903 * parameters are supposed to replace the current ones or if we are
22904 * switching to NSEC.
22905 */
22906 if (!exists && np->replace && (np->length != 0 || np->nsec)) {
22907 CHECK(dns_nsec3param_deletechains(db, newver, zone, !np->nsec,
22908 &diff));
22909 }
22910
22911 if (!exists && np->length != 0) {
22912 /*
22913 * We're creating an NSEC3 chain. Add the private-type record
22914 * passed in the event handler's argument to the zone apex.
22915 *
22916 * If the zone is not currently capable of supporting an NSEC3
22917 * chain (due to the DNSKEY RRset at the zone apex not existing
22918 * or containing at least one key using an NSEC-only
22919 * algorithm), add the INITIAL flag, so these parameters can be
22920 * used later when NSEC3 becomes available.
22921 */
22922 dns_rdata_init(&rdata);
22923
22924 np->data[2] |= DNS_NSEC3FLAG_CREATE;
22925 result = dns_nsec_nseconly(db, newver, &nseconly);
22926 if (result == ISC_R_NOTFOUND || nseconly) {
22927 np->data[2] |= DNS_NSEC3FLAG_INITIAL;
22928 }
22929
22930 rdata.length = np->length;
22931 rdata.data = np->data;
22932 rdata.type = zone->privatetype;
22933 rdata.rdclass = zone->rdclass;
22934 CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_ADD,
22935 &zone->origin, 0, &rdata));
22936 }
22937
22938 /*
22939 * If we changed anything in the zone, write changes to journal file
22940 * and set commit to true so that resume_addnsec3chain() will be
22941 * called below in order to kick off adding/removing relevant NSEC3
22942 * records.
22943 */
22944 if (!ISC_LIST_EMPTY(diff.tuples)) {
22945 CHECK(update_soa_serial(zone, db, newver, &diff, zone->mctx,
22946 zone->updatemethod));
22947 result = dns_update_signatures(&log, zone, db, oldver, newver,
22948 &diff,
22949 zone->sigvalidityinterval);
22950 if (result != ISC_R_NOTFOUND) {
22951 CHECK(result);
22952 }
22953 CHECK(zone_journal(zone, &diff, NULL, "setnsec3param"));
22954 commit = true;
22955
22956 LOCK_ZONE(zone);
22957 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
22958 zone_needdump(zone, 30);
22959 UNLOCK_ZONE(zone);
22960 }
22961
22962 failure:
22963 if (dns_rdataset_isassociated(&prdataset)) {
22964 dns_rdataset_disassociate(&prdataset);
22965 }
22966 if (dns_rdataset_isassociated(&nrdataset)) {
22967 dns_rdataset_disassociate(&nrdataset);
22968 }
22969 if (node != NULL) {
22970 dns_db_detachnode(db, &node);
22971 }
22972 if (oldver != NULL) {
22973 dns_db_closeversion(db, &oldver, false);
22974 }
22975 if (newver != NULL) {
22976 dns_db_closeversion(db, &newver, commit);
22977 }
22978 if (db != NULL) {
22979 dns_db_detach(&db);
22980 }
22981 if (commit) {
22982 LOCK_ZONE(zone);
22983 resume_addnsec3chain(zone);
22984 UNLOCK_ZONE(zone);
22985 }
22986 dns_diff_clear(&diff);
22987 isc_event_free(&event);
22988
22989 INSIST(oldver == NULL);
22990 INSIST(newver == NULL);
22991 }
22992
22993 /*
22994 * Check if zone has NSEC3PARAM (and thus a chain) with the right parameters.
22995 *
22996 * If 'salt' is NULL, a match is found if the salt has the requested length,
22997 * otherwise the NSEC3 salt must match the requested salt value too.
22998 *
22999 * Returns ISC_R_SUCCESS, if a match is found, or an error if no match is
23000 * found, or if the db lookup failed.
23001 */
23002 isc_result_t
23003 dns__zone_lookup_nsec3param(dns_zone_t *zone, dns_rdata_nsec3param_t *lookup,
23004 dns_rdata_nsec3param_t *param,
23005 unsigned char saltbuf[255], bool resalt) {
23006 isc_result_t result = ISC_R_UNEXPECTED;
23007 dns_dbnode_t *node = NULL;
23008 dns_db_t *db = NULL;
23009 dns_dbversion_t *version = NULL;
23010 dns_rdataset_t rdataset;
23011 dns_rdata_nsec3param_t nsec3param;
23012 dns_rdata_t rdata = DNS_RDATA_INIT;
23013
23014 REQUIRE(DNS_ZONE_VALID(zone));
23015
23016 dns_rdataset_init(&rdataset);
23017
23018 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
23019 if (zone->db != NULL) {
23020 dns_db_attach(zone->db, &db);
23021 }
23022 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
23023 if (db == NULL) {
23024 result = ISC_R_FAILURE;
23025 goto setparam;
23026 }
23027
23028 result = dns_db_findnode(db, &zone->origin, false, &node);
23029 if (result != ISC_R_SUCCESS) {
23030 dns_zone_log(zone, ISC_LOG_ERROR,
23031 "dns__zone_lookup_nsec3param:"
23032 "dns_db_findnode -> %s",
23033 dns_result_totext(result));
23034 result = ISC_R_FAILURE;
23035 goto setparam;
23036 }
23037 dns_db_currentversion(db, &version);
23038
23039 result = dns_db_findrdataset(db, node, version,
23040 dns_rdatatype_nsec3param,
23041 dns_rdatatype_none, 0, &rdataset, NULL);
23042 if (result != ISC_R_SUCCESS) {
23043 INSIST(!dns_rdataset_isassociated(&rdataset));
23044 if (result != ISC_R_NOTFOUND) {
23045 dns_zone_log(zone, ISC_LOG_ERROR,
23046 "dns__zone_lookup_nsec3param:"
23047 "dns_db_findrdataset -> %s",
23048 dns_result_totext(result));
23049 }
23050 goto setparam;
23051 }
23052
23053 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
23054 result = dns_rdataset_next(&rdataset))
23055 {
23056 dns_rdataset_current(&rdataset, &rdata);
23057 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
23058 INSIST(result == ISC_R_SUCCESS);
23059 dns_rdata_reset(&rdata);
23060
23061 /* Check parameters. */
23062 if (nsec3param.hash != lookup->hash) {
23063 continue;
23064 }
23065 if (nsec3param.iterations != lookup->iterations) {
23066 continue;
23067 }
23068 if (nsec3param.salt_length != lookup->salt_length) {
23069 continue;
23070 }
23071 if (lookup->salt != NULL) {
23072 if (memcmp(nsec3param.salt, lookup->salt,
23073 lookup->salt_length) != 0)
23074 {
23075 continue;
23076 }
23077 }
23078 /* Found a match. */
23079 result = ISC_R_SUCCESS;
23080 param->hash = nsec3param.hash;
23081 param->flags = nsec3param.flags;
23082 param->iterations = nsec3param.iterations;
23083 param->salt_length = nsec3param.salt_length;
23084 param->salt = nsec3param.salt;
23085 break;
23086 }
23087
23088 if (result == ISC_R_NOMORE) {
23089 result = ISC_R_NOTFOUND;
23090 }
23091
23092 setparam:
23093 if (result != ISC_R_SUCCESS) {
23094 /* Found no match. */
23095 param->hash = lookup->hash;
23096 param->flags = lookup->flags;
23097 param->iterations = lookup->iterations;
23098 param->salt_length = lookup->salt_length;
23099 param->salt = lookup->salt;
23100 }
23101
23102 if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS) {
23103 goto failure;
23104 }
23105
23106 if (param->salt_length == 0) {
23107 DE_CONST("-", param->salt);
23108 } else if (resalt || param->salt == NULL) {
23109 unsigned char *newsalt;
23110 unsigned char salttext[255 * 2 + 1];
23111 do {
23112 /* Generate a new salt. */
23113 result = dns_nsec3_generate_salt(saltbuf,
23114 param->salt_length);
23115 if (result != ISC_R_SUCCESS) {
23116 break;
23117 }
23118 newsalt = saltbuf;
23119 salt2text(newsalt, param->salt_length, salttext,
23120 sizeof(salttext));
23121 dnssec_log(zone, ISC_LOG_INFO, "generated salt: %s",
23122 salttext);
23123 /* Check for salt conflict. */
23124 if (param->salt != NULL &&
23125 memcmp(newsalt, param->salt, param->salt_length) ==
23126 0)
23127 {
23128 result = ISC_R_SUCCESS;
23129 } else {
23130 param->salt = newsalt;
23131 result = DNS_R_NSEC3RESALT;
23132 }
23133 } while (result == ISC_R_SUCCESS);
23134
23135 INSIST(result != ISC_R_SUCCESS);
23136 }
23137
23138 failure:
23139 if (dns_rdataset_isassociated(&rdataset)) {
23140 dns_rdataset_disassociate(&rdataset);
23141 }
23142 if (node != NULL) {
23143 dns_db_detachnode(db, &node);
23144 }
23145 if (version != NULL) {
23146 dns_db_closeversion(db, &version, false);
23147 }
23148 if (db != NULL) {
23149 dns_db_detach(&db);
23150 }
23151
23152 return (result);
23153 }
23154
23155 /*
23156 * Called when an "rndc signing -nsec3param ..." command is received, or the
23157 * 'dnssec-policy' has changed.
23158 *
23159 * Allocate and prepare an nsec3param_t structure which holds information about
23160 * the NSEC3 changes requested for the zone:
23161 *
23162 * - if NSEC3 is to be disabled ("-nsec3param none"), only set the "nsec"
23163 * field of the structure to true and the "replace" field to the value
23164 * of the "replace" argument, leaving other fields initialized to zeros, to
23165 * signal that the zone should be signed using NSEC instead of NSEC3,
23166 *
23167 * - otherwise, prepare NSEC3PARAM RDATA that will eventually be inserted at
23168 * the zone apex, convert it to a private-type record and store the latter
23169 * in the "data" field of the nsec3param_t structure.
23170 *
23171 * Once the nsec3param_t structure is prepared, post an event to the zone's
23172 * task which will cause setnsec3param() to be called with the prepared
23173 * structure passed as an argument.
23174 */
23175 isc_result_t
23176 dns_zone_setnsec3param(dns_zone_t *zone, uint8_t hash, uint8_t flags,
23177 uint16_t iter, uint8_t saltlen, unsigned char *salt,
23178 bool replace, bool resalt) {
23179 isc_result_t result = ISC_R_SUCCESS;
23180 dns_rdata_nsec3param_t param, lookup;
23181 dns_rdata_t nrdata = DNS_RDATA_INIT;
23182 dns_rdata_t prdata = DNS_RDATA_INIT;
23183 unsigned char nbuf[DNS_NSEC3PARAM_BUFFERSIZE];
23184 unsigned char saltbuf[255];
23185 struct np3event *npe;
23186 nsec3param_t *np;
23187 dns_zone_t *dummy = NULL;
23188 isc_buffer_t b;
23189 isc_event_t *e = NULL;
23190 bool do_lookup = false;
23191
23192 REQUIRE(DNS_ZONE_VALID(zone));
23193
23194 LOCK_ZONE(zone);
23195
23196 /*
23197 * First check if the requested NSEC3 parameters are already set,
23198 * if so, no need to set again.
23199 */
23200 if (hash != 0) {
23201 lookup.hash = hash;
23202 lookup.flags = flags;
23203 lookup.iterations = iter;
23204 lookup.salt_length = saltlen;
23205 lookup.salt = salt;
23206 param.salt = NULL;
23207 result = dns__zone_lookup_nsec3param(zone, &lookup, ¶m,
23208 saltbuf, resalt);
23209 if (result == ISC_R_SUCCESS) {
23210 UNLOCK_ZONE(zone);
23211 return (ISC_R_SUCCESS);
23212 }
23213 /*
23214 * Schedule lookup if lookup above failed (may happen if zone
23215 * db is NULL for example).
23216 */
23217 do_lookup = (param.salt == NULL) ? true : false;
23218 }
23219
23220 e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETNSEC3PARAM,
23221 setnsec3param, zone, sizeof(struct np3event));
23222
23223 npe = (struct np3event *)e;
23224 np = &npe->params;
23225 np->replace = replace;
23226 np->resalt = resalt;
23227 np->lookup = do_lookup;
23228 if (hash == 0) {
23229 np->length = 0;
23230 np->nsec = true;
23231 dnssec_log(zone, ISC_LOG_DEBUG(3), "setnsec3param:nsec");
23232 } else {
23233 param.common.rdclass = zone->rdclass;
23234 param.common.rdtype = dns_rdatatype_nsec3param;
23235 ISC_LINK_INIT(¶m.common, link);
23236 param.mctx = NULL;
23237 /* nsec3 specific param set in dns__zone_lookup_nsec3param() */
23238 isc_buffer_init(&b, nbuf, sizeof(nbuf));
23239
23240 if (param.salt != NULL) {
23241 CHECK(dns_rdata_fromstruct(&nrdata, zone->rdclass,
23242 dns_rdatatype_nsec3param,
23243 ¶m, &b));
23244 dns_nsec3param_toprivate(&nrdata, &prdata,
23245 zone->privatetype, np->data,
23246 sizeof(np->data));
23247 np->length = prdata.length;
23248 }
23249
23250 np->rdata = param;
23251 np->nsec = false;
23252
23253 if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
23254 unsigned char salttext[255 * 2 + 1];
23255 if (param.salt != NULL) {
23256 salt2text(param.salt, param.salt_length,
23257 salttext, sizeof(salttext));
23258 }
23259 dnssec_log(zone, ISC_LOG_DEBUG(3),
23260 "setnsec3param:nsec3 %u %u %u %u:%s",
23261 param.hash, param.flags, param.iterations,
23262 param.salt_length,
23263 param.salt == NULL ? "unknown"
23264 : (char *)salttext);
23265 }
23266 }
23267
23268 /*
23269 * setnsec3param() will silently return early if the zone does not yet
23270 * have a database. Prevent that by queueing the event up if zone->db
23271 * is NULL. All events queued here are subsequently processed by
23272 * receive_secure_db() if it ever gets called or simply freed by
23273 * zone_free() otherwise.
23274 */
23275
23276 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
23277 if (zone->db != NULL) {
23278 zone_iattach(zone, &dummy);
23279 isc_task_send(zone->task, &e);
23280 } else {
23281 ISC_LIST_APPEND(zone->setnsec3param_queue, e, ev_link);
23282 e = NULL;
23283 }
23284 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
23285
23286 result = ISC_R_SUCCESS;
23287
23288 failure:
23289 if (e != NULL) {
23290 isc_event_free(&e);
23291 }
23292 UNLOCK_ZONE(zone);
23293 return (result);
23294 }
23295
23296 isc_result_t
23297 dns_zone_getloadtime(dns_zone_t *zone, isc_time_t *loadtime) {
23298 REQUIRE(DNS_ZONE_VALID(zone));
23299 REQUIRE(loadtime != NULL);
23300
23301 LOCK_ZONE(zone);
23302 *loadtime = zone->loadtime;
23303 UNLOCK_ZONE(zone);
23304 return (ISC_R_SUCCESS);
23305 }
23306
23307 isc_result_t
23308 dns_zone_getexpiretime(dns_zone_t *zone, isc_time_t *expiretime) {
23309 REQUIRE(DNS_ZONE_VALID(zone));
23310 REQUIRE(expiretime != NULL);
23311
23312 LOCK_ZONE(zone);
23313 *expiretime = zone->expiretime;
23314 UNLOCK_ZONE(zone);
23315 return (ISC_R_SUCCESS);
23316 }
23317
23318 isc_result_t
23319 dns_zone_getrefreshtime(dns_zone_t *zone, isc_time_t *refreshtime) {
23320 REQUIRE(DNS_ZONE_VALID(zone));
23321 REQUIRE(refreshtime != NULL);
23322
23323 LOCK_ZONE(zone);
23324 *refreshtime = zone->refreshtime;
23325 UNLOCK_ZONE(zone);
23326 return (ISC_R_SUCCESS);
23327 }
23328
23329 isc_result_t
23330 dns_zone_getrefreshkeytime(dns_zone_t *zone, isc_time_t *refreshkeytime) {
23331 REQUIRE(DNS_ZONE_VALID(zone));
23332 REQUIRE(refreshkeytime != NULL);
23333
23334 LOCK_ZONE(zone);
23335 *refreshkeytime = zone->refreshkeytime;
23336 UNLOCK_ZONE(zone);
23337 return (ISC_R_SUCCESS);
23338 }
23339
23340 unsigned int
23341 dns_zone_getincludes(dns_zone_t *zone, char ***includesp) {
23342 dns_include_t *include;
23343 char **array = NULL;
23344 unsigned int n = 0;
23345
23346 REQUIRE(DNS_ZONE_VALID(zone));
23347 REQUIRE(includesp != NULL && *includesp == NULL);
23348
23349 LOCK_ZONE(zone);
23350 if (zone->nincludes == 0) {
23351 goto done;
23352 }
23353
23354 array = isc_mem_allocate(zone->mctx, sizeof(char *) * zone->nincludes);
23355 for (include = ISC_LIST_HEAD(zone->includes); include != NULL;
23356 include = ISC_LIST_NEXT(include, link))
23357 {
23358 INSIST(n < zone->nincludes);
23359 array[n++] = isc_mem_strdup(zone->mctx, include->name);
23360 }
23361 INSIST(n == zone->nincludes);
23362 *includesp = array;
23363
23364 done:
23365 UNLOCK_ZONE(zone);
23366 return (n);
23367 }
23368
23369 void
23370 dns_zone_setstatlevel(dns_zone_t *zone, dns_zonestat_level_t level) {
23371 REQUIRE(DNS_ZONE_VALID(zone));
23372
23373 zone->statlevel = level;
23374 }
23375
23376 dns_zonestat_level_t
23377 dns_zone_getstatlevel(dns_zone_t *zone) {
23378 REQUIRE(DNS_ZONE_VALID(zone));
23379
23380 return (zone->statlevel);
23381 }
23382
23383 static void
23384 setserial(isc_task_t *task, isc_event_t *event) {
23385 uint32_t oldserial, desired;
23386 const char *me = "setserial";
23387 bool commit = false;
23388 isc_result_t result;
23389 dns_dbversion_t *oldver = NULL, *newver = NULL;
23390 dns_zone_t *zone;
23391 dns_db_t *db = NULL;
23392 dns_diff_t diff;
23393 struct ssevent *sse = (struct ssevent *)event;
23394 dns_update_log_t log = { update_log_cb, NULL };
23395 dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
23396
23397 UNUSED(task);
23398
23399 zone = event->ev_arg;
23400 INSIST(DNS_ZONE_VALID(zone));
23401
23402 ENTER;
23403
23404 if (zone->update_disabled) {
23405 goto disabled;
23406 }
23407
23408 desired = sse->serial;
23409
23410 dns_diff_init(zone->mctx, &diff);
23411
23412 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
23413 if (zone->db != NULL) {
23414 dns_db_attach(zone->db, &db);
23415 }
23416 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
23417 if (db == NULL) {
23418 goto failure;
23419 }
23420
23421 dns_db_currentversion(db, &oldver);
23422 result = dns_db_newversion(db, &newver);
23423 if (result != ISC_R_SUCCESS) {
23424 dns_zone_log(zone, ISC_LOG_ERROR,
23425 "setserial:dns_db_newversion -> %s",
23426 dns_result_totext(result));
23427 goto failure;
23428 }
23429
23430 CHECK(dns_db_createsoatuple(db, oldver, diff.mctx, DNS_DIFFOP_DEL,
23431 &oldtuple));
23432 CHECK(dns_difftuple_copy(oldtuple, &newtuple));
23433 newtuple->op = DNS_DIFFOP_ADD;
23434
23435 oldserial = dns_soa_getserial(&oldtuple->rdata);
23436 if (desired == 0U) {
23437 desired = 1;
23438 }
23439 if (!isc_serial_gt(desired, oldserial)) {
23440 if (desired != oldserial) {
23441 dns_zone_log(zone, ISC_LOG_INFO,
23442 "setserial: desired serial (%u) "
23443 "out of range (%u-%u)",
23444 desired, oldserial + 1,
23445 (oldserial + 0x7fffffff));
23446 }
23447 goto failure;
23448 }
23449
23450 dns_soa_setserial(desired, &newtuple->rdata);
23451 CHECK(do_one_tuple(&oldtuple, db, newver, &diff));
23452 CHECK(do_one_tuple(&newtuple, db, newver, &diff));
23453 result = dns_update_signatures(&log, zone, db, oldver, newver, &diff,
23454 zone->sigvalidityinterval);
23455 if (result != ISC_R_NOTFOUND) {
23456 CHECK(result);
23457 }
23458
23459 /* Write changes to journal file. */
23460 CHECK(zone_journal(zone, &diff, NULL, "setserial"));
23461 commit = true;
23462
23463 LOCK_ZONE(zone);
23464 zone_needdump(zone, 30);
23465 UNLOCK_ZONE(zone);
23466
23467 failure:
23468 if (oldtuple != NULL) {
23469 dns_difftuple_free(&oldtuple);
23470 }
23471 if (newtuple != NULL) {
23472 dns_difftuple_free(&newtuple);
23473 }
23474 if (oldver != NULL) {
23475 dns_db_closeversion(db, &oldver, false);
23476 }
23477 if (newver != NULL) {
23478 dns_db_closeversion(db, &newver, commit);
23479 }
23480 if (db != NULL) {
23481 dns_db_detach(&db);
23482 }
23483 dns_diff_clear(&diff);
23484
23485 disabled:
23486 isc_event_free(&event);
23487 dns_zone_idetach(&zone);
23488
23489 INSIST(oldver == NULL);
23490 INSIST(newver == NULL);
23491 }
23492
23493 isc_result_t
23494 dns_zone_setserial(dns_zone_t *zone, uint32_t serial) {
23495 isc_result_t result = ISC_R_SUCCESS;
23496 dns_zone_t *dummy = NULL;
23497 isc_event_t *e = NULL;
23498 struct ssevent *sse;
23499
23500 REQUIRE(DNS_ZONE_VALID(zone));
23501
23502 LOCK_ZONE(zone);
23503
23504 if (!inline_secure(zone)) {
23505 if (!dns_zone_isdynamic(zone, true)) {
23506 result = DNS_R_NOTDYNAMIC;
23507 goto failure;
23508 }
23509 }
23510
23511 if (zone->update_disabled) {
23512 result = DNS_R_FROZEN;
23513 goto failure;
23514 }
23515
23516 e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETSERIAL, setserial,
23517 zone, sizeof(struct ssevent));
23518
23519 sse = (struct ssevent *)e;
23520 sse->serial = serial;
23521
23522 zone_iattach(zone, &dummy);
23523 isc_task_send(zone->task, &e);
23524
23525 failure:
23526 if (e != NULL) {
23527 isc_event_free(&e);
23528 }
23529 UNLOCK_ZONE(zone);
23530 return (result);
23531 }
23532
23533 isc_stats_t *
23534 dns_zone_getgluecachestats(dns_zone_t *zone) {
23535 REQUIRE(DNS_ZONE_VALID(zone));
23536
23537 return (zone->gluecachestats);
23538 }
23539
23540 bool
23541 dns_zone_isloaded(dns_zone_t *zone) {
23542 REQUIRE(DNS_ZONE_VALID(zone));
23543
23544 return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED));
23545 }
23546
23547 isc_result_t
23548 dns_zone_verifydb(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver) {
23549 dns_dbversion_t *version = NULL;
23550 dns_keytable_t *secroots = NULL;
23551 isc_result_t result;
23552 dns_name_t *origin;
23553
23554 const char me[] = "dns_zone_verifydb";
23555
23556 REQUIRE(DNS_ZONE_VALID(zone));
23557 REQUIRE(db != NULL);
23558
23559 ENTER;
23560
23561 if (dns_zone_gettype(zone) != dns_zone_mirror) {
23562 return (ISC_R_SUCCESS);
23563 }
23564
23565 if (ver == NULL) {
23566 dns_db_currentversion(db, &version);
23567 } else {
23568 version = ver;
23569 }
23570
23571 if (zone->view != NULL) {
23572 result = dns_view_getsecroots(zone->view, &secroots);
23573 if (result != ISC_R_SUCCESS) {
23574 goto done;
23575 }
23576 }
23577
23578 origin = dns_db_origin(db);
23579 result = dns_zoneverify_dnssec(zone, db, version, origin, secroots,
23580 zone->mctx, true, false, dnssec_report);
23581
23582 done:
23583 if (secroots != NULL) {
23584 dns_keytable_detach(&secroots);
23585 }
23586
23587 if (ver == NULL) {
23588 dns_db_closeversion(db, &version, false);
23589 }
23590
23591 if (result != ISC_R_SUCCESS) {
23592 dnssec_log(zone, ISC_LOG_ERROR, "zone verification failed: %s",
23593 isc_result_totext(result));
23594 result = DNS_R_VERIFYFAILURE;
23595 }
23596
23597 return (result);
23598 }
23599
23600 static dns_ttl_t
23601 zone_nsecttl(dns_zone_t *zone) {
23602 REQUIRE(DNS_ZONE_VALID(zone));
23603
23604 return (ISC_MIN(zone->minimum, zone->soattl));
23605 }
23606