zone.c revision 1.12 1 /* $NetBSD: zone.c,v 1.12 2021/02/19 16:42:16 christos Exp $ */
2
3 /*
4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5 *
6 * This Source Code Form is subject to the terms of the Mozilla Public
7 * License, v. 2.0. If a copy of the MPL was not distributed with this
8 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
9 *
10 * See the COPYRIGHT file distributed with this work for additional
11 * information regarding copyright ownership.
12 */
13
14 /*! \file */
15
16 #include <errno.h>
17 #include <inttypes.h>
18 #include <stdbool.h>
19
20 #include <isc/atomic.h>
21 #include <isc/file.h>
22 #include <isc/hex.h>
23 #include <isc/md.h>
24 #include <isc/mutex.h>
25 #include <isc/pool.h>
26 #include <isc/print.h>
27 #include <isc/random.h>
28 #include <isc/ratelimiter.h>
29 #include <isc/refcount.h>
30 #include <isc/rwlock.h>
31 #include <isc/serial.h>
32 #include <isc/stats.h>
33 #include <isc/stdtime.h>
34 #include <isc/strerr.h>
35 #include <isc/string.h>
36 #include <isc/taskpool.h>
37 #include <isc/thread.h>
38 #include <isc/timer.h>
39 #include <isc/util.h>
40
41 #include <dns/acl.h>
42 #include <dns/adb.h>
43 #include <dns/callbacks.h>
44 #include <dns/catz.h>
45 #include <dns/db.h>
46 #include <dns/dbiterator.h>
47 #include <dns/dlz.h>
48 #include <dns/dnssec.h>
49 #include <dns/events.h>
50 #include <dns/journal.h>
51 #include <dns/kasp.h>
52 #include <dns/keydata.h>
53 #include <dns/keymgr.h>
54 #include <dns/keytable.h>
55 #include <dns/keyvalues.h>
56 #include <dns/log.h>
57 #include <dns/master.h>
58 #include <dns/masterdump.h>
59 #include <dns/message.h>
60 #include <dns/name.h>
61 #include <dns/nsec.h>
62 #include <dns/nsec3.h>
63 #include <dns/peer.h>
64 #include <dns/private.h>
65 #include <dns/rcode.h>
66 #include <dns/rdata.h>
67 #include <dns/rdataclass.h>
68 #include <dns/rdatalist.h>
69 #include <dns/rdataset.h>
70 #include <dns/rdatasetiter.h>
71 #include <dns/rdatastruct.h>
72 #include <dns/rdatatype.h>
73 #include <dns/request.h>
74 #include <dns/resolver.h>
75 #include <dns/result.h>
76 #include <dns/rriterator.h>
77 #include <dns/soa.h>
78 #include <dns/ssu.h>
79 #include <dns/stats.h>
80 #include <dns/time.h>
81 #include <dns/tsig.h>
82 #include <dns/update.h>
83 #include <dns/xfrin.h>
84 #include <dns/zone.h>
85 #include <dns/zoneverify.h>
86 #include <dns/zt.h>
87
88 #include <dst/dst.h>
89
90 #include "zone_p.h"
91
92 #define ZONE_MAGIC ISC_MAGIC('Z', 'O', 'N', 'E')
93 #define DNS_ZONE_VALID(zone) ISC_MAGIC_VALID(zone, ZONE_MAGIC)
94
95 #define NOTIFY_MAGIC ISC_MAGIC('N', 't', 'f', 'y')
96 #define DNS_NOTIFY_VALID(notify) ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)
97
98 #define STUB_MAGIC ISC_MAGIC('S', 't', 'u', 'b')
99 #define DNS_STUB_VALID(stub) ISC_MAGIC_VALID(stub, STUB_MAGIC)
100
101 #define ZONEMGR_MAGIC ISC_MAGIC('Z', 'm', 'g', 'r')
102 #define DNS_ZONEMGR_VALID(stub) ISC_MAGIC_VALID(stub, ZONEMGR_MAGIC)
103
104 #define LOAD_MAGIC ISC_MAGIC('L', 'o', 'a', 'd')
105 #define DNS_LOAD_VALID(load) ISC_MAGIC_VALID(load, LOAD_MAGIC)
106
107 #define FORWARD_MAGIC ISC_MAGIC('F', 'o', 'r', 'w')
108 #define DNS_FORWARD_VALID(load) ISC_MAGIC_VALID(load, FORWARD_MAGIC)
109
110 #define IO_MAGIC ISC_MAGIC('Z', 'm', 'I', 'O')
111 #define DNS_IO_VALID(load) ISC_MAGIC_VALID(load, IO_MAGIC)
112
113 /*%
114 * Ensure 'a' is at least 'min' but not more than 'max'.
115 */
116 #define RANGE(a, min, max) (((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max)))
117
118 #define NSEC3REMOVE(x) (((x)&DNS_NSEC3FLAG_REMOVE) != 0)
119
120 /*%
121 * Key flags
122 */
123 #define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
124 #define KSK(x) ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
125 #define ID(x) dst_key_id(x)
126 #define ALG(x) dst_key_alg(x)
127
128 /*
129 * Default values.
130 */
131 #define DNS_DEFAULT_IDLEIN 3600 /*%< 1 hour */
132 #define DNS_DEFAULT_IDLEOUT 3600 /*%< 1 hour */
133 #define MAX_XFER_TIME (2 * 3600) /*%< Documented default is 2 hours */
134 #define RESIGN_DELAY 3600 /*%< 1 hour */
135
136 #ifndef DNS_MAX_EXPIRE
137 #define DNS_MAX_EXPIRE 14515200 /*%< 24 weeks */
138 #endif /* ifndef DNS_MAX_EXPIRE */
139
140 #ifndef DNS_DUMP_DELAY
141 #define DNS_DUMP_DELAY 900 /*%< 15 minutes */
142 #endif /* ifndef DNS_DUMP_DELAY */
143
144 typedef struct dns_notify dns_notify_t;
145 typedef struct dns_stub dns_stub_t;
146 typedef struct dns_load dns_load_t;
147 typedef struct dns_forward dns_forward_t;
148 typedef ISC_LIST(dns_forward_t) dns_forwardlist_t;
149 typedef struct dns_io dns_io_t;
150 typedef ISC_LIST(dns_io_t) dns_iolist_t;
151 typedef struct dns_signing dns_signing_t;
152 typedef ISC_LIST(dns_signing_t) dns_signinglist_t;
153 typedef struct dns_nsec3chain dns_nsec3chain_t;
154 typedef ISC_LIST(dns_nsec3chain_t) dns_nsec3chainlist_t;
155 typedef struct dns_keyfetch dns_keyfetch_t;
156 typedef struct dns_asyncload dns_asyncload_t;
157 typedef struct dns_include dns_include_t;
158
159 #define DNS_ZONE_CHECKLOCK
160 #ifdef DNS_ZONE_CHECKLOCK
161 #define LOCK_ZONE(z) \
162 do { \
163 LOCK(&(z)->lock); \
164 INSIST(!(z)->locked); \
165 (z)->locked = true; \
166 } while (/*CONSTCOND*/0)
167 #define UNLOCK_ZONE(z) \
168 do { \
169 (z)->locked = false; \
170 UNLOCK(&(z)->lock); \
171 } while (/*CONSTCOND*/0)
172 #define LOCKED_ZONE(z) ((z)->locked)
173 #define TRYLOCK_ZONE(result, z) \
174 do { \
175 result = isc_mutex_trylock(&(z)->lock); \
176 if (result == ISC_R_SUCCESS) { \
177 INSIST(!(z)->locked); \
178 (z)->locked = true; \
179 } \
180 } while (/*CONSTCOND*/0)
181 #else /* ifdef DNS_ZONE_CHECKLOCK */
182 #define LOCK_ZONE(z) LOCK(&(z)->lock)
183 #define UNLOCK_ZONE(z) UNLOCK(&(z)->lock)
184 #define LOCKED_ZONE(z) true
185 #define TRYLOCK_ZONE(result, z) \
186 do { \
187 result = isc_mutex_trylock(&(z)->lock); \
188 } while (/*CONSTCOND*/0)
189 #endif /* ifdef DNS_ZONE_CHECKLOCK */
190
191 #define ZONEDB_INITLOCK(l) isc_rwlock_init((l), 0, 0)
192 #define ZONEDB_DESTROYLOCK(l) isc_rwlock_destroy(l)
193 #define ZONEDB_LOCK(l, t) RWLOCK((l), (t))
194 #define ZONEDB_UNLOCK(l, t) RWUNLOCK((l), (t))
195
196 #ifdef ENABLE_AFL
197 extern bool dns_fuzzing_resolver;
198 #endif /* ifdef ENABLE_AFL */
199
200 struct dns_zone {
201 /* Unlocked */
202 unsigned int magic;
203 isc_mutex_t lock;
204 #ifdef DNS_ZONE_CHECKLOCK
205 bool locked;
206 #endif /* ifdef DNS_ZONE_CHECKLOCK */
207 isc_mem_t *mctx;
208 isc_refcount_t erefs;
209
210 isc_rwlock_t dblock;
211 dns_db_t *db; /* Locked by dblock */
212
213 /* Locked */
214 dns_zonemgr_t *zmgr;
215 ISC_LINK(dns_zone_t) link; /* Used by zmgr. */
216 isc_timer_t *timer;
217 isc_refcount_t irefs;
218 dns_name_t origin;
219 char *masterfile;
220 ISC_LIST(dns_include_t) includes; /* Include files */
221 ISC_LIST(dns_include_t) newincludes; /* Loading */
222 unsigned int nincludes;
223 dns_masterformat_t masterformat;
224 const dns_master_style_t *masterstyle;
225 char *journal;
226 int32_t journalsize;
227 dns_rdataclass_t rdclass;
228 dns_zonetype_t type;
229 #ifdef __NetBSD__
230 atomic_uint_fast32_t flags;
231 atomic_uint_fast32_t options;
232 #else
233 atomic_uint_fast64_t flags;
234 atomic_uint_fast64_t options;
235 #endif
236 unsigned int db_argc;
237 char **db_argv;
238 isc_time_t expiretime;
239 isc_time_t refreshtime;
240 isc_time_t dumptime;
241 isc_time_t loadtime;
242 isc_time_t notifytime;
243 isc_time_t resigntime;
244 isc_time_t keywarntime;
245 isc_time_t signingtime;
246 isc_time_t nsec3chaintime;
247 isc_time_t refreshkeytime;
248 uint32_t refreshkeyinterval;
249 uint32_t refreshkeycount;
250 uint32_t refresh;
251 uint32_t retry;
252 uint32_t expire;
253 uint32_t minimum;
254 isc_stdtime_t key_expiry;
255 isc_stdtime_t log_key_expired_timer;
256 char *keydirectory;
257
258 uint32_t maxrefresh;
259 uint32_t minrefresh;
260 uint32_t maxretry;
261 uint32_t minretry;
262
263 uint32_t maxrecords;
264
265 isc_sockaddr_t *masters;
266 isc_dscp_t *masterdscps;
267 dns_name_t **masterkeynames;
268 bool *mastersok;
269 unsigned int masterscnt;
270 unsigned int curmaster;
271 isc_sockaddr_t masteraddr;
272 dns_notifytype_t notifytype;
273 isc_sockaddr_t *notify;
274 dns_name_t **notifykeynames;
275 isc_dscp_t *notifydscp;
276 unsigned int notifycnt;
277 isc_sockaddr_t notifyfrom;
278 isc_task_t *task;
279 isc_task_t *loadtask;
280 isc_sockaddr_t notifysrc4;
281 isc_sockaddr_t notifysrc6;
282 isc_sockaddr_t xfrsource4;
283 isc_sockaddr_t xfrsource6;
284 isc_sockaddr_t altxfrsource4;
285 isc_sockaddr_t altxfrsource6;
286 isc_sockaddr_t sourceaddr;
287 isc_dscp_t notifysrc4dscp;
288 isc_dscp_t notifysrc6dscp;
289 isc_dscp_t xfrsource4dscp;
290 isc_dscp_t xfrsource6dscp;
291 isc_dscp_t altxfrsource4dscp;
292 isc_dscp_t altxfrsource6dscp;
293 dns_xfrin_ctx_t *xfr; /* task locked */
294 dns_tsigkey_t *tsigkey; /* key used for xfr */
295 /* Access Control Lists */
296 dns_acl_t *update_acl;
297 dns_acl_t *forward_acl;
298 dns_acl_t *notify_acl;
299 dns_acl_t *query_acl;
300 dns_acl_t *queryon_acl;
301 dns_acl_t *xfr_acl;
302 bool update_disabled;
303 bool zero_no_soa_ttl;
304 dns_severity_t check_names;
305 ISC_LIST(dns_notify_t) notifies;
306 dns_request_t *request;
307 dns_loadctx_t *lctx;
308 dns_io_t *readio;
309 dns_dumpctx_t *dctx;
310 dns_io_t *writeio;
311 uint32_t maxxfrin;
312 uint32_t maxxfrout;
313 uint32_t idlein;
314 uint32_t idleout;
315 isc_event_t ctlevent;
316 dns_ssutable_t *ssutable;
317 uint32_t sigvalidityinterval;
318 uint32_t keyvalidityinterval;
319 uint32_t sigresigninginterval;
320 dns_view_t *view;
321 dns_view_t *prev_view;
322 dns_kasp_t *kasp;
323 dns_checkmxfunc_t checkmx;
324 dns_checksrvfunc_t checksrv;
325 dns_checknsfunc_t checkns;
326 /*%
327 * Zones in certain states such as "waiting for zone transfer"
328 * or "zone transfer in progress" are kept on per-state linked lists
329 * in the zone manager using the 'statelink' field. The 'statelist'
330 * field points at the list the zone is currently on. It the zone
331 * is not on any such list, statelist is NULL.
332 */
333 ISC_LINK(dns_zone_t) statelink;
334 dns_zonelist_t *statelist;
335 /*%
336 * Statistics counters about zone management.
337 */
338 isc_stats_t *stats;
339 /*%
340 * Optional per-zone statistics counters. Counted outside of this
341 * module.
342 */
343 dns_zonestat_level_t statlevel;
344 bool requeststats_on;
345 isc_stats_t *requeststats;
346 dns_stats_t *rcvquerystats;
347 dns_stats_t *dnssecsignstats;
348 uint32_t notifydelay;
349 dns_isselffunc_t isself;
350 void *isselfarg;
351
352 char *strnamerd;
353 char *strname;
354 char *strrdclass;
355 char *strviewname;
356
357 /*%
358 * Serial number for deferred journal compaction.
359 */
360 uint32_t compact_serial;
361 /*%
362 * Keys that are signing the zone for the first time.
363 */
364 dns_signinglist_t signing;
365 dns_nsec3chainlist_t nsec3chain;
366 /*%
367 * List of outstanding NSEC3PARAM change requests.
368 */
369 isc_eventlist_t setnsec3param_queue;
370 /*%
371 * Signing / re-signing quantum stopping parameters.
372 */
373 uint32_t signatures;
374 uint32_t nodes;
375 dns_rdatatype_t privatetype;
376
377 /*%
378 * Autosigning/key-maintenance options
379 */
380 #ifdef __NetBSD__
381 atomic_uint_fast32_t keyopts;
382 #else
383 atomic_uint_fast64_t keyopts;
384 #endif
385
386 /*%
387 * True if added by "rndc addzone"
388 */
389 bool added;
390
391 /*%
392 * True if added by automatically by named.
393 */
394 bool automatic;
395
396 /*%
397 * response policy data to be relayed to the database
398 */
399 dns_rpz_zones_t *rpzs;
400 dns_rpz_num_t rpz_num;
401
402 /*%
403 * catalog zone data
404 */
405 dns_catz_zones_t *catzs;
406
407 /*%
408 * parent catalog zone
409 */
410 dns_catz_zone_t *parentcatz;
411
412 /*%
413 * Serial number update method.
414 */
415 dns_updatemethod_t updatemethod;
416
417 /*%
418 * whether ixfr is requested
419 */
420 bool requestixfr;
421 uint32_t ixfr_ratio;
422
423 /*%
424 * whether EDNS EXPIRE is requested
425 */
426 bool requestexpire;
427
428 /*%
429 * Outstanding forwarded UPDATE requests.
430 */
431 dns_forwardlist_t forwards;
432
433 dns_zone_t *raw;
434 dns_zone_t *secure;
435
436 bool sourceserialset;
437 uint32_t sourceserial;
438
439 /*%
440 * maximum zone ttl
441 */
442 dns_ttl_t maxttl;
443
444 /*
445 * Inline zone signing state.
446 */
447 dns_diff_t rss_diff;
448 isc_eventlist_t rss_events;
449 isc_eventlist_t rss_post;
450 dns_dbversion_t *rss_newver;
451 dns_dbversion_t *rss_oldver;
452 dns_db_t *rss_db;
453 dns_zone_t *rss_raw;
454 isc_event_t *rss_event;
455 dns_update_state_t *rss_state;
456
457 isc_stats_t *gluecachestats;
458 };
459
460 #define zonediff_init(z, d) \
461 do { \
462 dns__zonediff_t *_z = (z); \
463 (_z)->diff = (d); \
464 (_z)->offline = false; \
465 } while (/*CONSTCOND*/0)
466
467 #define DNS_ZONE_FLAG(z, f) ((atomic_load_relaxed(&(z)->flags) & (f)) != 0)
468 #define DNS_ZONE_SETFLAG(z, f) atomic_fetch_or(&(z)->flags, (f))
469 #define DNS_ZONE_CLRFLAG(z, f) atomic_fetch_and(&(z)->flags, ~(f))
470 typedef enum {
471 DNS_ZONEFLG_REFRESH = 0x00000001U, /*%< refresh check in progress */
472 DNS_ZONEFLG_NEEDDUMP = 0x00000002U, /*%< zone need consolidation */
473 DNS_ZONEFLG_USEVC = 0x00000004U, /*%< use tcp for refresh query */
474 DNS_ZONEFLG_DUMPING = 0x00000008U, /*%< a dump is in progress */
475 DNS_ZONEFLG_HASINCLUDE = 0x00000010U, /*%< $INCLUDE in zone file */
476 DNS_ZONEFLG_LOADED = 0x00000020U, /*%< database has loaded */
477 DNS_ZONEFLG_EXITING = 0x00000040U, /*%< zone is being destroyed */
478 DNS_ZONEFLG_EXPIRED = 0x00000080U, /*%< zone has expired */
479 DNS_ZONEFLG_NEEDREFRESH = 0x00000100U, /*%< refresh check needed */
480 DNS_ZONEFLG_UPTODATE = 0x00000200U, /*%< zone contents are
481 * up-to-date */
482 DNS_ZONEFLG_NEEDNOTIFY = 0x00000400U, /*%< need to send out notify
483 * messages */
484 DNS_ZONEFLG_DIFFONRELOAD = 0x00000800U, /*%< generate a journal diff on
485 * reload */
486 DNS_ZONEFLG_NOMASTERS = 0x00001000U, /*%< an attempt to refresh a
487 * zone with no primaries
488 * occurred */
489 DNS_ZONEFLG_LOADING = 0x00002000U, /*%< load from disk in progress*/
490 DNS_ZONEFLG_HAVETIMERS = 0x00004000U, /*%< timer values have been set
491 * from SOA (if not set, we
492 * are still using
493 * default timer values) */
494 DNS_ZONEFLG_FORCEXFER = 0x00008000U, /*%< Force a zone xfer */
495 DNS_ZONEFLG_NOREFRESH = 0x00010000U,
496 DNS_ZONEFLG_DIALNOTIFY = 0x00020000U,
497 DNS_ZONEFLG_DIALREFRESH = 0x00040000U,
498 DNS_ZONEFLG_SHUTDOWN = 0x00080000U,
499 DNS_ZONEFLG_NOIXFR = 0x00100000U, /*%< IXFR failed, force AXFR */
500 DNS_ZONEFLG_FLUSH = 0x00200000U,
501 DNS_ZONEFLG_NOEDNS = 0x00400000U,
502 DNS_ZONEFLG_USEALTXFRSRC = 0x00800000U,
503 DNS_ZONEFLG_SOABEFOREAXFR = 0x01000000U,
504 DNS_ZONEFLG_NEEDCOMPACT = 0x02000000U,
505 DNS_ZONEFLG_REFRESHING = 0x04000000U, /*%< Refreshing keydata */
506 DNS_ZONEFLG_THAW = 0x08000000U,
507 DNS_ZONEFLG_LOADPENDING = 0x10000000U, /*%< Loading scheduled */
508 DNS_ZONEFLG_NODELAY = 0x20000000U,
509 DNS_ZONEFLG_SENDSECURE = 0x40000000U,
510 DNS_ZONEFLG_NEEDSTARTUPNOTIFY = 0x80000000U, /*%< need to send out
511 * notify due to the zone
512 * just being loaded for
513 * the first time. */
514 #ifndef __NetBSD__
515 DNS_ZONEFLG___MAX = UINT64_MAX, /* trick to make the ENUM 64-bit wide */
516 #endif
517 } dns_zoneflg_t;
518
519 #define DNS_ZONE_OPTION(z, o) ((atomic_load_relaxed(&(z)->options) & (o)) != 0)
520 #define DNS_ZONE_SETOPTION(z, o) atomic_fetch_or(&(z)->options, (o))
521 #define DNS_ZONE_CLROPTION(z, o) atomic_fetch_and(&(z)->options, ~(o))
522
523 #define DNS_ZONEKEY_OPTION(z, o) \
524 ((atomic_load_relaxed(&(z)->keyopts) & (o)) != 0)
525 #define DNS_ZONEKEY_SETOPTION(z, o) atomic_fetch_or(&(z)->keyopts, (o))
526 #define DNS_ZONEKEY_CLROPTION(z, o) atomic_fetch_and(&(z)->keyopts, ~(o))
527
528 /* Flags for zone_load() */
529 typedef enum {
530 DNS_ZONELOADFLAG_NOSTAT = 0x00000001U, /* Do not stat() master files */
531 DNS_ZONELOADFLAG_THAW = 0x00000002U, /* Thaw the zone on successful
532 * load. */
533 } dns_zoneloadflag_t;
534
535 #define UNREACH_CACHE_SIZE 10U
536 #define UNREACH_HOLD_TIME 600 /* 10 minutes */
537
538 #define CHECK(op) \
539 do { \
540 result = (op); \
541 if (result != ISC_R_SUCCESS) \
542 goto failure; \
543 } while (/*CONSTCOND*/0)
544
545 struct dns_unreachable {
546 isc_sockaddr_t remote;
547 isc_sockaddr_t local;
548 atomic_uint_fast32_t expire;
549 atomic_uint_fast32_t last;
550 uint32_t count;
551 };
552
553 struct dns_zonemgr {
554 unsigned int magic;
555 isc_mem_t *mctx;
556 isc_refcount_t refs;
557 isc_taskmgr_t *taskmgr;
558 isc_timermgr_t *timermgr;
559 isc_socketmgr_t *socketmgr;
560 isc_taskpool_t *zonetasks;
561 isc_taskpool_t *loadtasks;
562 isc_task_t *task;
563 isc_pool_t *mctxpool;
564 isc_ratelimiter_t *notifyrl;
565 isc_ratelimiter_t *refreshrl;
566 isc_ratelimiter_t *startupnotifyrl;
567 isc_ratelimiter_t *startuprefreshrl;
568 isc_rwlock_t rwlock;
569 isc_mutex_t iolock;
570 isc_rwlock_t urlock;
571
572 /* Locked by rwlock. */
573 dns_zonelist_t zones;
574 dns_zonelist_t waiting_for_xfrin;
575 dns_zonelist_t xfrin_in_progress;
576
577 /* Configuration data. */
578 uint32_t transfersin;
579 uint32_t transfersperns;
580 unsigned int notifyrate;
581 unsigned int startupnotifyrate;
582 unsigned int serialqueryrate;
583 unsigned int startupserialqueryrate;
584
585 /* Locked by iolock */
586 uint32_t iolimit;
587 uint32_t ioactive;
588 dns_iolist_t high;
589 dns_iolist_t low;
590
591 /* Locked by urlock. */
592 /* LRU cache */
593 struct dns_unreachable unreachable[UNREACH_CACHE_SIZE];
594 };
595
596 /*%
597 * Hold notify state.
598 */
599 struct dns_notify {
600 unsigned int magic;
601 unsigned int flags;
602 isc_mem_t *mctx;
603 dns_zone_t *zone;
604 dns_adbfind_t *find;
605 dns_request_t *request;
606 dns_name_t ns;
607 isc_sockaddr_t dst;
608 dns_tsigkey_t *key;
609 isc_dscp_t dscp;
610 ISC_LINK(dns_notify_t) link;
611 isc_event_t *event;
612 };
613
614 #define DNS_NOTIFY_NOSOA 0x0001U
615 #define DNS_NOTIFY_STARTUP 0x0002U
616
617 /*%
618 * dns_stub holds state while performing a 'stub' transfer.
619 * 'db' is the zone's 'db' or a new one if this is the initial
620 * transfer.
621 */
622
623 struct dns_stub {
624 unsigned int magic;
625 isc_mem_t *mctx;
626 dns_zone_t *zone;
627 dns_db_t *db;
628 dns_dbversion_t *version;
629 atomic_uint_fast32_t pending_requests;
630 };
631
632 /*%
633 * Hold load state.
634 */
635 struct dns_load {
636 unsigned int magic;
637 isc_mem_t *mctx;
638 dns_zone_t *zone;
639 dns_db_t *db;
640 isc_time_t loadtime;
641 dns_rdatacallbacks_t callbacks;
642 };
643
644 /*%
645 * Hold forward state.
646 */
647 struct dns_forward {
648 unsigned int magic;
649 isc_mem_t *mctx;
650 dns_zone_t *zone;
651 isc_buffer_t *msgbuf;
652 dns_request_t *request;
653 uint32_t which;
654 isc_sockaddr_t addr;
655 dns_updatecallback_t callback;
656 void *callback_arg;
657 unsigned int options;
658 ISC_LINK(dns_forward_t) link;
659 };
660
661 /*%
662 * Hold IO request state.
663 */
664 struct dns_io {
665 unsigned int magic;
666 dns_zonemgr_t *zmgr;
667 bool high;
668 isc_task_t *task;
669 ISC_LINK(dns_io_t) link;
670 isc_event_t *event;
671 };
672
673 /*%
674 * Hold state for when we are signing a zone with a new
675 * DNSKEY as result of an update.
676 */
677 struct dns_signing {
678 unsigned int magic;
679 dns_db_t *db;
680 dns_dbiterator_t *dbiterator;
681 dns_secalg_t algorithm;
682 uint16_t keyid;
683 bool deleteit;
684 bool done;
685 ISC_LINK(dns_signing_t) link;
686 };
687
688 struct dns_nsec3chain {
689 unsigned int magic;
690 dns_db_t *db;
691 dns_dbiterator_t *dbiterator;
692 dns_rdata_nsec3param_t nsec3param;
693 unsigned char salt[255];
694 bool done;
695 bool seen_nsec;
696 bool delete_nsec;
697 bool save_delete_nsec;
698 ISC_LINK(dns_nsec3chain_t) link;
699 };
700 /*%<
701 * 'dbiterator' contains a iterator for the database. If we are creating
702 * a NSEC3 chain only the non-NSEC3 nodes will be iterated. If we are
703 * removing a NSEC3 chain then both NSEC3 and non-NSEC3 nodes will be
704 * iterated.
705 *
706 * 'nsec3param' contains the parameters of the NSEC3 chain being created
707 * or removed.
708 *
709 * 'salt' is buffer space and is referenced via 'nsec3param.salt'.
710 *
711 * 'seen_nsec' will be set to true if, while iterating the zone to create a
712 * NSEC3 chain, a NSEC record is seen.
713 *
714 * 'delete_nsec' will be set to true if, at the completion of the creation
715 * of a NSEC3 chain, 'seen_nsec' is true. If 'delete_nsec' is true then we
716 * are in the process of deleting the NSEC chain.
717 *
718 * 'save_delete_nsec' is used to store the initial state of 'delete_nsec'
719 * so it can be recovered in the event of a error.
720 */
721
722 struct dns_keyfetch {
723 dns_fixedname_t name;
724 dns_rdataset_t keydataset;
725 dns_rdataset_t dnskeyset;
726 dns_rdataset_t dnskeysigset;
727 dns_zone_t *zone;
728 dns_db_t *db;
729 dns_fetch_t *fetch;
730 };
731
732 /*%
733 * Hold state for an asynchronous load
734 */
735 struct dns_asyncload {
736 dns_zone_t *zone;
737 unsigned int flags;
738 dns_zt_zoneloaded_t loaded;
739 void *loaded_arg;
740 };
741
742 /*%
743 * Reference to an include file encountered during loading
744 */
745 struct dns_include {
746 char *name;
747 isc_time_t filetime;
748 ISC_LINK(dns_include_t) link;
749 };
750
751 /*
752 * These can be overridden by the -T mkeytimers option on the command
753 * line, so that we can test with shorter periods than specified in
754 * RFC 5011.
755 */
756 #define HOUR 3600
757 #define DAY (24 * HOUR)
758 #define MONTH (30 * DAY)
759 LIBDNS_EXTERNAL_DATA unsigned int dns_zone_mkey_hour = HOUR;
760 LIBDNS_EXTERNAL_DATA unsigned int dns_zone_mkey_day = DAY;
761 LIBDNS_EXTERNAL_DATA unsigned int dns_zone_mkey_month = MONTH;
762
763 #define SEND_BUFFER_SIZE 2048
764
765 static void
766 zone_settimer(dns_zone_t *, isc_time_t *);
767 static void
768 cancel_refresh(dns_zone_t *);
769 static void
770 zone_debuglog(dns_zone_t *zone, const char *, int debuglevel, const char *msg,
771 ...) ISC_FORMAT_PRINTF(4, 5);
772 static void
773 notify_log(dns_zone_t *zone, int level, const char *fmt, ...)
774 ISC_FORMAT_PRINTF(3, 4);
775 static void
776 dnssec_log(dns_zone_t *zone, int level, const char *fmt, ...)
777 ISC_FORMAT_PRINTF(3, 4);
778 static void
779 queue_xfrin(dns_zone_t *zone);
780 static isc_result_t
781 update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
782 dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
783 dns_rdata_t *rdata);
784 static void
785 zone_unload(dns_zone_t *zone);
786 static void
787 zone_expire(dns_zone_t *zone);
788 static void
789 zone_iattach(dns_zone_t *source, dns_zone_t **target);
790 static void
791 zone_idetach(dns_zone_t **zonep);
792 static isc_result_t
793 zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump);
794 static inline void
795 zone_attachdb(dns_zone_t *zone, dns_db_t *db);
796 static inline void
797 zone_detachdb(dns_zone_t *zone);
798 static isc_result_t
799 default_journal(dns_zone_t *zone);
800 static void
801 zone_xfrdone(dns_zone_t *zone, isc_result_t result);
802 static isc_result_t
803 zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
804 isc_result_t result);
805 static void
806 zone_needdump(dns_zone_t *zone, unsigned int delay);
807 static void
808 zone_shutdown(isc_task_t *, isc_event_t *);
809 static void
810 zone_loaddone(void *arg, isc_result_t result);
811 static isc_result_t
812 zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime);
813 static void
814 zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length);
815 static void
816 zone_name_tostr(dns_zone_t *zone, char *buf, size_t length);
817 static void
818 zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length);
819 static void
820 zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length);
821 static isc_result_t
822 zone_send_secureserial(dns_zone_t *zone, uint32_t serial);
823 static void
824 refresh_callback(isc_task_t *, isc_event_t *);
825 static void
826 stub_callback(isc_task_t *, isc_event_t *);
827 static void
828 queue_soa_query(dns_zone_t *zone);
829 static void
830 soa_query(isc_task_t *, isc_event_t *);
831 static void
832 ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub);
833 static int
834 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type);
835 static void
836 notify_cancel(dns_zone_t *zone);
837 static void
838 notify_find_address(dns_notify_t *notify);
839 static void
840 notify_send(dns_notify_t *notify);
841 static isc_result_t
842 notify_createmessage(dns_zone_t *zone, unsigned int flags,
843 dns_message_t **messagep);
844 static void
845 notify_done(isc_task_t *task, isc_event_t *event);
846 static void
847 notify_send_toaddr(isc_task_t *task, isc_event_t *event);
848 static isc_result_t
849 zone_dump(dns_zone_t *, bool);
850 static void
851 got_transfer_quota(isc_task_t *task, isc_event_t *event);
852 static isc_result_t
853 zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone);
854 static void
855 zmgr_resume_xfrs(dns_zonemgr_t *zmgr, bool multi);
856 static void
857 zonemgr_free(dns_zonemgr_t *zmgr);
858 static isc_result_t
859 zonemgr_getio(dns_zonemgr_t *zmgr, bool high, isc_task_t *task,
860 isc_taskaction_t action, void *arg, dns_io_t **iop);
861 static void
862 zonemgr_putio(dns_io_t **iop);
863 static void
864 zonemgr_cancelio(dns_io_t *io);
865 static void
866 rss_post(dns_zone_t *, isc_event_t *);
867
868 static isc_result_t
869 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
870 unsigned int *soacount, uint32_t *serial, uint32_t *refresh,
871 uint32_t *retry, uint32_t *expire, uint32_t *minimum,
872 unsigned int *errors);
873
874 static void
875 zone_freedbargs(dns_zone_t *zone);
876 static void
877 forward_callback(isc_task_t *task, isc_event_t *event);
878 static void
879 zone_saveunique(dns_zone_t *zone, const char *path, const char *templat);
880 static void
881 zone_maintenance(dns_zone_t *zone);
882 static void
883 zone_notify(dns_zone_t *zone, isc_time_t *now);
884 static void
885 dump_done(void *arg, isc_result_t result);
886 static isc_result_t
887 zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid,
888 bool deleteit);
889 static isc_result_t
890 delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
891 dns_name_t *name, dns_diff_t *diff);
892 static void
893 zone_rekey(dns_zone_t *zone);
894 static isc_result_t
895 zone_send_securedb(dns_zone_t *zone, dns_db_t *db);
896 static void
897 setrl(isc_ratelimiter_t *rl, unsigned int *rate, unsigned int value);
898
899 #define ENTER zone_debuglog(zone, me, 1, "enter")
900
901 static const unsigned int dbargc_default = 1;
902 static const char *dbargv_default[] = { "rbt" };
903
904 #define DNS_ZONE_JITTER_ADD(a, b, c) \
905 do { \
906 isc_interval_t _i; \
907 uint32_t _j; \
908 _j = (b)-isc_random_uniform((b) / 4); \
909 isc_interval_set(&_i, _j, 0); \
910 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
911 dns_zone_log(zone, ISC_LOG_WARNING, \
912 "epoch approaching: upgrade required: " \
913 "now + %s failed", \
914 #b); \
915 isc_interval_set(&_i, _j / 2, 0); \
916 (void)isc_time_add((a), &_i, (c)); \
917 } \
918 } while (/*CONSTCOND*/0)
919
920 #define DNS_ZONE_TIME_ADD(a, b, c) \
921 do { \
922 isc_interval_t _i; \
923 isc_interval_set(&_i, (b), 0); \
924 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
925 dns_zone_log(zone, ISC_LOG_WARNING, \
926 "epoch approaching: upgrade required: " \
927 "now + %s failed", \
928 #b); \
929 isc_interval_set(&_i, (b) / 2, 0); \
930 (void)isc_time_add((a), &_i, (c)); \
931 } \
932 } while (/*CONSTCOND*/0)
933
934 typedef struct nsec3param nsec3param_t;
935 struct nsec3param {
936 unsigned char data[DNS_NSEC3PARAM_BUFFERSIZE + 1];
937 unsigned int length;
938 bool nsec;
939 bool replace;
940 ISC_LINK(nsec3param_t) link;
941 };
942 typedef ISC_LIST(nsec3param_t) nsec3paramlist_t;
943 struct np3event {
944 isc_event_t event;
945 nsec3param_t params;
946 };
947
948 struct ssevent {
949 isc_event_t event;
950 uint32_t serial;
951 };
952
953 struct stub_cb_args {
954 dns_stub_t *stub;
955 dns_tsigkey_t *tsig_key;
956 isc_dscp_t dscp;
957 uint16_t udpsize;
958 int timeout;
959 bool reqnsid;
960 };
961
962 struct stub_glue_request {
963 dns_request_t *request;
964 dns_name_t name;
965 struct stub_cb_args *args;
966 bool ipv4;
967 };
968
969 /*%
970 * Increment resolver-related statistics counters. Zone must be locked.
971 */
972 static inline void
973 inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
974 if (zone->stats != NULL) {
975 isc_stats_increment(zone->stats, counter);
976 }
977 }
978
979 /***
980 *** Public functions.
981 ***/
982
983 isc_result_t
984 dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
985 isc_result_t result;
986 dns_zone_t *zone;
987 isc_time_t now;
988
989 REQUIRE(zonep != NULL && *zonep == NULL);
990 REQUIRE(mctx != NULL);
991
992 TIME_NOW(&now);
993 zone = isc_mem_get(mctx, sizeof(*zone));
994
995 zone->mctx = NULL;
996 isc_mem_attach(mctx, &zone->mctx);
997
998 isc_mutex_init(&zone->lock);
999
1000 result = ZONEDB_INITLOCK(&zone->dblock);
1001 if (result != ISC_R_SUCCESS) {
1002 goto free_mutex;
1003 }
1004
1005 /* XXX MPA check that all elements are initialised */
1006 #ifdef DNS_ZONE_CHECKLOCK
1007 zone->locked = false;
1008 #endif /* ifdef DNS_ZONE_CHECKLOCK */
1009 zone->db = NULL;
1010 zone->zmgr = NULL;
1011 ISC_LINK_INIT(zone, link);
1012 isc_refcount_init(&zone->erefs, 1);
1013 isc_refcount_init(&zone->irefs, 0);
1014 dns_name_init(&zone->origin, NULL);
1015 zone->strnamerd = NULL;
1016 zone->strname = NULL;
1017 zone->strrdclass = NULL;
1018 zone->strviewname = NULL;
1019 zone->masterfile = NULL;
1020 ISC_LIST_INIT(zone->includes);
1021 ISC_LIST_INIT(zone->newincludes);
1022 zone->nincludes = 0;
1023 zone->masterformat = dns_masterformat_none;
1024 zone->masterstyle = NULL;
1025 zone->keydirectory = NULL;
1026 zone->journalsize = -1;
1027 zone->journal = NULL;
1028 zone->rdclass = dns_rdataclass_none;
1029 zone->type = dns_zone_none;
1030 atomic_init(&zone->flags, 0);
1031 atomic_init(&zone->options, 0);
1032 atomic_init(&zone->keyopts, 0);
1033 zone->db_argc = 0;
1034 zone->db_argv = NULL;
1035 isc_time_settoepoch(&zone->expiretime);
1036 isc_time_settoepoch(&zone->refreshtime);
1037 isc_time_settoepoch(&zone->dumptime);
1038 isc_time_settoepoch(&zone->loadtime);
1039 zone->notifytime = now;
1040 isc_time_settoepoch(&zone->resigntime);
1041 isc_time_settoepoch(&zone->keywarntime);
1042 isc_time_settoepoch(&zone->signingtime);
1043 isc_time_settoepoch(&zone->nsec3chaintime);
1044 isc_time_settoepoch(&zone->refreshkeytime);
1045 zone->refreshkeyinterval = 0;
1046 zone->refreshkeycount = 0;
1047 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
1048 zone->retry = DNS_ZONE_DEFAULTRETRY;
1049 zone->expire = 0;
1050 zone->minimum = 0;
1051 zone->maxrefresh = DNS_ZONE_MAXREFRESH;
1052 zone->minrefresh = DNS_ZONE_MINREFRESH;
1053 zone->maxretry = DNS_ZONE_MAXRETRY;
1054 zone->minretry = DNS_ZONE_MINRETRY;
1055 zone->masters = NULL;
1056 zone->masterdscps = NULL;
1057 zone->masterkeynames = NULL;
1058 zone->mastersok = NULL;
1059 zone->masterscnt = 0;
1060 zone->curmaster = 0;
1061 zone->maxttl = 0;
1062 zone->notify = NULL;
1063 zone->notifykeynames = NULL;
1064 zone->notifydscp = NULL;
1065 zone->notifytype = dns_notifytype_yes;
1066 zone->notifycnt = 0;
1067 zone->task = NULL;
1068 zone->loadtask = NULL;
1069 zone->update_acl = NULL;
1070 zone->forward_acl = NULL;
1071 zone->notify_acl = NULL;
1072 zone->query_acl = NULL;
1073 zone->queryon_acl = NULL;
1074 zone->xfr_acl = NULL;
1075 zone->update_disabled = false;
1076 zone->zero_no_soa_ttl = true;
1077 zone->check_names = dns_severity_ignore;
1078 zone->request = NULL;
1079 zone->lctx = NULL;
1080 zone->readio = NULL;
1081 zone->dctx = NULL;
1082 zone->writeio = NULL;
1083 zone->timer = NULL;
1084 zone->idlein = DNS_DEFAULT_IDLEIN;
1085 zone->idleout = DNS_DEFAULT_IDLEOUT;
1086 zone->log_key_expired_timer = 0;
1087 ISC_LIST_INIT(zone->notifies);
1088 isc_sockaddr_any(&zone->notifysrc4);
1089 isc_sockaddr_any6(&zone->notifysrc6);
1090 isc_sockaddr_any(&zone->xfrsource4);
1091 isc_sockaddr_any6(&zone->xfrsource6);
1092 isc_sockaddr_any(&zone->altxfrsource4);
1093 isc_sockaddr_any6(&zone->altxfrsource6);
1094 zone->notifysrc4dscp = -1;
1095 zone->notifysrc6dscp = -1;
1096 zone->xfrsource4dscp = -1;
1097 zone->xfrsource6dscp = -1;
1098 zone->altxfrsource4dscp = -1;
1099 zone->altxfrsource6dscp = -1;
1100 zone->xfr = NULL;
1101 zone->tsigkey = NULL;
1102 zone->maxxfrin = MAX_XFER_TIME;
1103 zone->maxxfrout = MAX_XFER_TIME;
1104 zone->ssutable = NULL;
1105 zone->sigvalidityinterval = 30 * 24 * 3600;
1106 zone->keyvalidityinterval = 0;
1107 zone->sigresigninginterval = 7 * 24 * 3600;
1108 zone->kasp = NULL;
1109 zone->view = NULL;
1110 zone->prev_view = NULL;
1111 zone->checkmx = NULL;
1112 zone->checksrv = NULL;
1113 zone->checkns = NULL;
1114 ISC_LINK_INIT(zone, statelink);
1115 zone->statelist = NULL;
1116 zone->stats = NULL;
1117 zone->requeststats_on = false;
1118 zone->statlevel = dns_zonestat_none;
1119 zone->requeststats = NULL;
1120 zone->rcvquerystats = NULL;
1121 zone->dnssecsignstats = NULL;
1122 zone->notifydelay = 5;
1123 zone->isself = NULL;
1124 zone->isselfarg = NULL;
1125 ISC_LIST_INIT(zone->signing);
1126 ISC_LIST_INIT(zone->nsec3chain);
1127 ISC_LIST_INIT(zone->setnsec3param_queue);
1128 zone->signatures = 10;
1129 zone->nodes = 100;
1130 zone->privatetype = (dns_rdatatype_t)0xffffU;
1131 zone->added = false;
1132 zone->automatic = false;
1133 zone->rpzs = NULL;
1134 zone->rpz_num = DNS_RPZ_INVALID_NUM;
1135
1136 zone->catzs = NULL;
1137 zone->parentcatz = NULL;
1138
1139 ISC_LIST_INIT(zone->forwards);
1140 zone->raw = NULL;
1141 zone->secure = NULL;
1142 zone->sourceserial = 0;
1143 zone->sourceserialset = false;
1144 zone->requestixfr = true;
1145 zone->ixfr_ratio = 100;
1146 zone->requestexpire = true;
1147 ISC_LIST_INIT(zone->rss_events);
1148 ISC_LIST_INIT(zone->rss_post);
1149 zone->rss_db = NULL;
1150 zone->rss_raw = NULL;
1151 zone->rss_newver = NULL;
1152 zone->rss_oldver = NULL;
1153 zone->rss_event = NULL;
1154 zone->rss_state = NULL;
1155 zone->updatemethod = dns_updatemethod_increment;
1156 zone->maxrecords = 0U;
1157
1158 zone->magic = ZONE_MAGIC;
1159
1160 zone->gluecachestats = NULL;
1161 result = isc_stats_create(mctx, &zone->gluecachestats,
1162 dns_gluecachestatscounter_max);
1163 if (result != ISC_R_SUCCESS) {
1164 goto free_refs;
1165 }
1166
1167 /* Must be after magic is set. */
1168 dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
1169
1170 ISC_EVENT_INIT(&zone->ctlevent, sizeof(zone->ctlevent), 0, NULL,
1171 DNS_EVENT_ZONECONTROL, zone_shutdown, zone, zone, NULL,
1172 NULL);
1173 *zonep = zone;
1174 return (ISC_R_SUCCESS);
1175
1176 free_refs:
1177 isc_refcount_decrement0(&zone->erefs);
1178 isc_refcount_destroy(&zone->erefs);
1179 isc_refcount_destroy(&zone->irefs);
1180
1181 ZONEDB_DESTROYLOCK(&zone->dblock);
1182
1183 free_mutex:
1184 isc_mutex_destroy(&zone->lock);
1185
1186 isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
1187 return (result);
1188 }
1189
1190 /*
1191 * Free a zone. Because we require that there be no more
1192 * outstanding events or references, no locking is necessary.
1193 */
1194 static void
1195 zone_free(dns_zone_t *zone) {
1196 dns_signing_t *signing;
1197 dns_nsec3chain_t *nsec3chain;
1198 isc_event_t *event;
1199 dns_include_t *include;
1200
1201 REQUIRE(DNS_ZONE_VALID(zone));
1202 isc_refcount_destroy(&zone->erefs);
1203 isc_refcount_destroy(&zone->irefs);
1204 REQUIRE(!LOCKED_ZONE(zone));
1205 REQUIRE(zone->timer == NULL);
1206 REQUIRE(zone->zmgr == NULL);
1207
1208 /*
1209 * Managed objects. Order is important.
1210 */
1211 if (zone->request != NULL) {
1212 dns_request_destroy(&zone->request); /* XXXMPA */
1213 }
1214 INSIST(zone->readio == NULL);
1215 INSIST(zone->statelist == NULL);
1216 INSIST(zone->writeio == NULL);
1217
1218 if (zone->task != NULL) {
1219 isc_task_detach(&zone->task);
1220 }
1221 if (zone->loadtask != NULL) {
1222 isc_task_detach(&zone->loadtask);
1223 }
1224 if (zone->view != NULL) {
1225 dns_view_weakdetach(&zone->view);
1226 }
1227 if (zone->prev_view != NULL) {
1228 dns_view_weakdetach(&zone->prev_view);
1229 }
1230
1231 /* Unmanaged objects */
1232 while (!ISC_LIST_EMPTY(zone->setnsec3param_queue)) {
1233 event = ISC_LIST_HEAD(zone->setnsec3param_queue);
1234 ISC_LIST_UNLINK(zone->setnsec3param_queue, event, ev_link);
1235 isc_event_free(&event);
1236 }
1237 while (!ISC_LIST_EMPTY(zone->rss_post)) {
1238 event = ISC_LIST_HEAD(zone->rss_post);
1239 ISC_LIST_UNLINK(zone->rss_post, event, ev_link);
1240 isc_event_free(&event);
1241 }
1242 for (signing = ISC_LIST_HEAD(zone->signing); signing != NULL;
1243 signing = ISC_LIST_HEAD(zone->signing))
1244 {
1245 ISC_LIST_UNLINK(zone->signing, signing, link);
1246 dns_db_detach(&signing->db);
1247 dns_dbiterator_destroy(&signing->dbiterator);
1248 isc_mem_put(zone->mctx, signing, sizeof *signing);
1249 }
1250 for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain); nsec3chain != NULL;
1251 nsec3chain = ISC_LIST_HEAD(zone->nsec3chain))
1252 {
1253 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
1254 dns_db_detach(&nsec3chain->db);
1255 dns_dbiterator_destroy(&nsec3chain->dbiterator);
1256 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
1257 }
1258 for (include = ISC_LIST_HEAD(zone->includes); include != NULL;
1259 include = ISC_LIST_HEAD(zone->includes))
1260 {
1261 ISC_LIST_UNLINK(zone->includes, include, link);
1262 isc_mem_free(zone->mctx, include->name);
1263 isc_mem_put(zone->mctx, include, sizeof *include);
1264 }
1265 for (include = ISC_LIST_HEAD(zone->newincludes); include != NULL;
1266 include = ISC_LIST_HEAD(zone->newincludes))
1267 {
1268 ISC_LIST_UNLINK(zone->newincludes, include, link);
1269 isc_mem_free(zone->mctx, include->name);
1270 isc_mem_put(zone->mctx, include, sizeof *include);
1271 }
1272 if (zone->masterfile != NULL) {
1273 isc_mem_free(zone->mctx, zone->masterfile);
1274 }
1275 zone->masterfile = NULL;
1276 if (zone->keydirectory != NULL) {
1277 isc_mem_free(zone->mctx, zone->keydirectory);
1278 }
1279 zone->keydirectory = NULL;
1280 if (zone->kasp != NULL) {
1281 dns_kasp_detach(&zone->kasp);
1282 }
1283 zone->journalsize = -1;
1284 if (zone->journal != NULL) {
1285 isc_mem_free(zone->mctx, zone->journal);
1286 }
1287 zone->journal = NULL;
1288 if (zone->stats != NULL) {
1289 isc_stats_detach(&zone->stats);
1290 }
1291 if (zone->requeststats != NULL) {
1292 isc_stats_detach(&zone->requeststats);
1293 }
1294 if (zone->rcvquerystats != NULL) {
1295 dns_stats_detach(&zone->rcvquerystats);
1296 }
1297 if (zone->dnssecsignstats != NULL) {
1298 dns_stats_detach(&zone->dnssecsignstats);
1299 }
1300 if (zone->db != NULL) {
1301 zone_detachdb(zone);
1302 }
1303 if (zone->rpzs != NULL) {
1304 REQUIRE(zone->rpz_num < zone->rpzs->p.num_zones);
1305 dns_rpz_detach_rpzs(&zone->rpzs);
1306 zone->rpz_num = DNS_RPZ_INVALID_NUM;
1307 }
1308 if (zone->catzs != NULL) {
1309 dns_catz_catzs_detach(&zone->catzs);
1310 }
1311 zone_freedbargs(zone);
1312 RUNTIME_CHECK(dns_zone_setprimarieswithkeys(zone, NULL, NULL, 0) ==
1313 ISC_R_SUCCESS);
1314 RUNTIME_CHECK(dns_zone_setalsonotify(zone, NULL, 0) == ISC_R_SUCCESS);
1315 zone->check_names = dns_severity_ignore;
1316 if (zone->update_acl != NULL) {
1317 dns_acl_detach(&zone->update_acl);
1318 }
1319 if (zone->forward_acl != NULL) {
1320 dns_acl_detach(&zone->forward_acl);
1321 }
1322 if (zone->notify_acl != NULL) {
1323 dns_acl_detach(&zone->notify_acl);
1324 }
1325 if (zone->query_acl != NULL) {
1326 dns_acl_detach(&zone->query_acl);
1327 }
1328 if (zone->queryon_acl != NULL) {
1329 dns_acl_detach(&zone->queryon_acl);
1330 }
1331 if (zone->xfr_acl != NULL) {
1332 dns_acl_detach(&zone->xfr_acl);
1333 }
1334 if (dns_name_dynamic(&zone->origin)) {
1335 dns_name_free(&zone->origin, zone->mctx);
1336 }
1337 if (zone->strnamerd != NULL) {
1338 isc_mem_free(zone->mctx, zone->strnamerd);
1339 }
1340 if (zone->strname != NULL) {
1341 isc_mem_free(zone->mctx, zone->strname);
1342 }
1343 if (zone->strrdclass != NULL) {
1344 isc_mem_free(zone->mctx, zone->strrdclass);
1345 }
1346 if (zone->strviewname != NULL) {
1347 isc_mem_free(zone->mctx, zone->strviewname);
1348 }
1349 if (zone->ssutable != NULL) {
1350 dns_ssutable_detach(&zone->ssutable);
1351 }
1352 if (zone->gluecachestats != NULL) {
1353 isc_stats_detach(&zone->gluecachestats);
1354 }
1355
1356 /* last stuff */
1357 ZONEDB_DESTROYLOCK(&zone->dblock);
1358 isc_mutex_destroy(&zone->lock);
1359 zone->magic = 0;
1360 isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
1361 }
1362
1363 /*
1364 * Returns true iff this the signed side of an inline-signing zone.
1365 * Caller should hold zone lock.
1366 */
1367 static inline bool
1368 inline_secure(dns_zone_t *zone) {
1369 REQUIRE(DNS_ZONE_VALID(zone));
1370 if (zone->raw != NULL) {
1371 return (true);
1372 }
1373 return (false);
1374 }
1375
1376 /*
1377 * Returns true iff this the unsigned side of an inline-signing zone
1378 * Caller should hold zone lock.
1379 */
1380 static inline bool
1381 inline_raw(dns_zone_t *zone) {
1382 REQUIRE(DNS_ZONE_VALID(zone));
1383 if (zone->secure != NULL) {
1384 return (true);
1385 }
1386 return (false);
1387 }
1388
1389 /*
1390 * Single shot.
1391 */
1392 void
1393 dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
1394 char namebuf[1024];
1395
1396 REQUIRE(DNS_ZONE_VALID(zone));
1397 REQUIRE(rdclass != dns_rdataclass_none);
1398
1399 /*
1400 * Test and set.
1401 */
1402 LOCK_ZONE(zone);
1403 INSIST(zone != zone->raw);
1404 REQUIRE(zone->rdclass == dns_rdataclass_none ||
1405 zone->rdclass == rdclass);
1406 zone->rdclass = rdclass;
1407
1408 if (zone->strnamerd != NULL) {
1409 isc_mem_free(zone->mctx, zone->strnamerd);
1410 }
1411 if (zone->strrdclass != NULL) {
1412 isc_mem_free(zone->mctx, zone->strrdclass);
1413 }
1414
1415 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1416 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1417 zone_rdclass_tostr(zone, namebuf, sizeof namebuf);
1418 zone->strrdclass = isc_mem_strdup(zone->mctx, namebuf);
1419
1420 if (inline_secure(zone)) {
1421 dns_zone_setclass(zone->raw, rdclass);
1422 }
1423 UNLOCK_ZONE(zone);
1424 }
1425
1426 dns_rdataclass_t
1427 dns_zone_getclass(dns_zone_t *zone) {
1428 REQUIRE(DNS_ZONE_VALID(zone));
1429
1430 return (zone->rdclass);
1431 }
1432
1433 void
1434 dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
1435 REQUIRE(DNS_ZONE_VALID(zone));
1436
1437 LOCK_ZONE(zone);
1438 zone->notifytype = notifytype;
1439 UNLOCK_ZONE(zone);
1440 }
1441
1442 isc_result_t
1443 dns_zone_getserial(dns_zone_t *zone, uint32_t *serialp) {
1444 isc_result_t result;
1445 unsigned int soacount;
1446
1447 REQUIRE(DNS_ZONE_VALID(zone));
1448 REQUIRE(serialp != NULL);
1449
1450 LOCK_ZONE(zone);
1451 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1452 if (zone->db != NULL) {
1453 result = zone_get_from_db(zone, zone->db, NULL, &soacount,
1454 serialp, NULL, NULL, NULL, NULL,
1455 NULL);
1456 if (result == ISC_R_SUCCESS && soacount == 0) {
1457 result = ISC_R_FAILURE;
1458 }
1459 } else {
1460 result = DNS_R_NOTLOADED;
1461 }
1462 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1463 UNLOCK_ZONE(zone);
1464
1465 return (result);
1466 }
1467
1468 /*
1469 * Single shot.
1470 */
1471 void
1472 dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) {
1473 char namebuf[1024];
1474
1475 REQUIRE(DNS_ZONE_VALID(zone));
1476 REQUIRE(type != dns_zone_none);
1477
1478 /*
1479 * Test and set.
1480 */
1481 LOCK_ZONE(zone);
1482 REQUIRE(zone->type == dns_zone_none || zone->type == type);
1483 zone->type = type;
1484
1485 if (zone->strnamerd != NULL) {
1486 isc_mem_free(zone->mctx, zone->strnamerd);
1487 }
1488
1489 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1490 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1491 UNLOCK_ZONE(zone);
1492 }
1493
1494 static void
1495 zone_freedbargs(dns_zone_t *zone) {
1496 unsigned int i;
1497
1498 /* Free the old database argument list. */
1499 if (zone->db_argv != NULL) {
1500 for (i = 0; i < zone->db_argc; i++) {
1501 isc_mem_free(zone->mctx, zone->db_argv[i]);
1502 }
1503 isc_mem_put(zone->mctx, zone->db_argv,
1504 zone->db_argc * sizeof(*zone->db_argv));
1505 }
1506 zone->db_argc = 0;
1507 zone->db_argv = NULL;
1508 }
1509
1510 isc_result_t
1511 dns_zone_getdbtype(dns_zone_t *zone, char ***argv, isc_mem_t *mctx) {
1512 size_t size = 0;
1513 unsigned int i;
1514 isc_result_t result = ISC_R_SUCCESS;
1515 void *mem;
1516 char **tmp, *tmp2, *base;
1517
1518 REQUIRE(DNS_ZONE_VALID(zone));
1519 REQUIRE(argv != NULL && *argv == NULL);
1520
1521 LOCK_ZONE(zone);
1522 size = (zone->db_argc + 1) * sizeof(char *);
1523 for (i = 0; i < zone->db_argc; i++) {
1524 size += strlen(zone->db_argv[i]) + 1;
1525 }
1526 mem = isc_mem_allocate(mctx, size);
1527 {
1528 tmp = mem;
1529 tmp2 = mem;
1530 base = mem;
1531 tmp2 += (zone->db_argc + 1) * sizeof(char *);
1532 for (i = 0; i < zone->db_argc; i++) {
1533 *tmp++ = tmp2;
1534 strlcpy(tmp2, zone->db_argv[i], size - (tmp2 - base));
1535 tmp2 += strlen(tmp2) + 1;
1536 }
1537 *tmp = NULL;
1538 }
1539 UNLOCK_ZONE(zone);
1540 *argv = mem;
1541 return (result);
1542 }
1543
1544 void
1545 dns_zone_setdbtype(dns_zone_t *zone, unsigned int dbargc,
1546 const char *const *dbargv) {
1547 char **argv = NULL;
1548 unsigned int i;
1549
1550 REQUIRE(DNS_ZONE_VALID(zone));
1551 REQUIRE(dbargc >= 1);
1552 REQUIRE(dbargv != NULL);
1553
1554 LOCK_ZONE(zone);
1555
1556 /* Set up a new database argument list. */
1557 argv = isc_mem_get(zone->mctx, dbargc * sizeof(*argv));
1558 for (i = 0; i < dbargc; i++) {
1559 argv[i] = NULL;
1560 }
1561 for (i = 0; i < dbargc; i++) {
1562 argv[i] = isc_mem_strdup(zone->mctx, dbargv[i]);
1563 }
1564
1565 /* Free the old list. */
1566 zone_freedbargs(zone);
1567
1568 zone->db_argc = dbargc;
1569 zone->db_argv = argv;
1570
1571 UNLOCK_ZONE(zone);
1572 }
1573
1574 static void
1575 dns_zone_setview_helper(dns_zone_t *zone, dns_view_t *view) {
1576 char namebuf[1024];
1577
1578 if (zone->prev_view == NULL && zone->view != NULL) {
1579 dns_view_weakattach(zone->view, &zone->prev_view);
1580 }
1581
1582 INSIST(zone != zone->raw);
1583 if (zone->view != NULL) {
1584 dns_view_weakdetach(&zone->view);
1585 }
1586 dns_view_weakattach(view, &zone->view);
1587
1588 if (zone->strviewname != NULL) {
1589 isc_mem_free(zone->mctx, zone->strviewname);
1590 }
1591 if (zone->strnamerd != NULL) {
1592 isc_mem_free(zone->mctx, zone->strnamerd);
1593 }
1594
1595 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1596 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1597 zone_viewname_tostr(zone, namebuf, sizeof namebuf);
1598 zone->strviewname = isc_mem_strdup(zone->mctx, namebuf);
1599
1600 if (inline_secure(zone)) {
1601 dns_zone_setview(zone->raw, view);
1602 }
1603 }
1604
1605 void
1606 dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
1607 REQUIRE(DNS_ZONE_VALID(zone));
1608
1609 LOCK_ZONE(zone);
1610 dns_zone_setview_helper(zone, view);
1611 UNLOCK_ZONE(zone);
1612 }
1613
1614 dns_view_t *
1615 dns_zone_getview(dns_zone_t *zone) {
1616 REQUIRE(DNS_ZONE_VALID(zone));
1617
1618 return (zone->view);
1619 }
1620
1621 void
1622 dns_zone_setviewcommit(dns_zone_t *zone) {
1623 REQUIRE(DNS_ZONE_VALID(zone));
1624
1625 LOCK_ZONE(zone);
1626 if (zone->prev_view != NULL) {
1627 dns_view_weakdetach(&zone->prev_view);
1628 }
1629 UNLOCK_ZONE(zone);
1630 }
1631
1632 void
1633 dns_zone_setviewrevert(dns_zone_t *zone) {
1634 REQUIRE(DNS_ZONE_VALID(zone));
1635
1636 LOCK_ZONE(zone);
1637 if (zone->prev_view != NULL) {
1638 dns_zone_setview_helper(zone, zone->prev_view);
1639 dns_view_weakdetach(&zone->prev_view);
1640 }
1641 UNLOCK_ZONE(zone);
1642 }
1643
1644 isc_result_t
1645 dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
1646 isc_result_t result = ISC_R_SUCCESS;
1647 char namebuf[1024];
1648
1649 REQUIRE(DNS_ZONE_VALID(zone));
1650 REQUIRE(origin != NULL);
1651
1652 LOCK_ZONE(zone);
1653 INSIST(zone != zone->raw);
1654 if (dns_name_dynamic(&zone->origin)) {
1655 dns_name_free(&zone->origin, zone->mctx);
1656 dns_name_init(&zone->origin, NULL);
1657 }
1658 dns_name_dup(origin, zone->mctx, &zone->origin);
1659
1660 if (zone->strnamerd != NULL) {
1661 isc_mem_free(zone->mctx, zone->strnamerd);
1662 }
1663 if (zone->strname != NULL) {
1664 isc_mem_free(zone->mctx, zone->strname);
1665 }
1666
1667 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1668 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1669 zone_name_tostr(zone, namebuf, sizeof namebuf);
1670 zone->strname = isc_mem_strdup(zone->mctx, namebuf);
1671
1672 if (inline_secure(zone)) {
1673 result = dns_zone_setorigin(zone->raw, origin);
1674 }
1675 UNLOCK_ZONE(zone);
1676 return (result);
1677 }
1678
1679 static isc_result_t
1680 dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
1681 char *copy;
1682
1683 if (value != NULL) {
1684 copy = isc_mem_strdup(zone->mctx, value);
1685 } else {
1686 copy = NULL;
1687 }
1688
1689 if (*field != NULL) {
1690 isc_mem_free(zone->mctx, *field);
1691 }
1692
1693 *field = copy;
1694 return (ISC_R_SUCCESS);
1695 }
1696
1697 isc_result_t
1698 dns_zone_setfile(dns_zone_t *zone, const char *file, dns_masterformat_t format,
1699 const dns_master_style_t *style) {
1700 isc_result_t result = ISC_R_SUCCESS;
1701
1702 REQUIRE(DNS_ZONE_VALID(zone));
1703
1704 LOCK_ZONE(zone);
1705 result = dns_zone_setstring(zone, &zone->masterfile, file);
1706 if (result == ISC_R_SUCCESS) {
1707 zone->masterformat = format;
1708 if (format == dns_masterformat_text) {
1709 zone->masterstyle = style;
1710 }
1711 result = default_journal(zone);
1712 }
1713 UNLOCK_ZONE(zone);
1714
1715 return (result);
1716 }
1717
1718 const char *
1719 dns_zone_getfile(dns_zone_t *zone) {
1720 REQUIRE(DNS_ZONE_VALID(zone));
1721
1722 return (zone->masterfile);
1723 }
1724
1725 dns_ttl_t
1726 dns_zone_getmaxttl(dns_zone_t *zone) {
1727 REQUIRE(DNS_ZONE_VALID(zone));
1728
1729 return (zone->maxttl);
1730 }
1731
1732 void
1733 dns_zone_setmaxttl(dns_zone_t *zone, dns_ttl_t maxttl) {
1734 REQUIRE(DNS_ZONE_VALID(zone));
1735
1736 LOCK_ZONE(zone);
1737 if (maxttl != 0) {
1738 DNS_ZONE_SETOPTION(zone, DNS_ZONEOPT_CHECKTTL);
1739 } else {
1740 DNS_ZONE_CLROPTION(zone, DNS_ZONEOPT_CHECKTTL);
1741 }
1742 zone->maxttl = maxttl;
1743 UNLOCK_ZONE(zone);
1744
1745 return;
1746 }
1747
1748 static isc_result_t
1749 default_journal(dns_zone_t *zone) {
1750 isc_result_t result;
1751 char *journal;
1752
1753 REQUIRE(DNS_ZONE_VALID(zone));
1754 REQUIRE(LOCKED_ZONE(zone));
1755
1756 if (zone->masterfile != NULL) {
1757 /* Calculate string length including '\0'. */
1758 int len = strlen(zone->masterfile) + sizeof(".jnl");
1759 journal = isc_mem_allocate(zone->mctx, len);
1760 strlcpy(journal, zone->masterfile, len);
1761 strlcat(journal, ".jnl", len);
1762 } else {
1763 journal = NULL;
1764 }
1765 result = dns_zone_setstring(zone, &zone->journal, journal);
1766 if (journal != NULL) {
1767 isc_mem_free(zone->mctx, journal);
1768 }
1769 return (result);
1770 }
1771
1772 isc_result_t
1773 dns_zone_setjournal(dns_zone_t *zone, const char *myjournal) {
1774 isc_result_t result = ISC_R_SUCCESS;
1775
1776 REQUIRE(DNS_ZONE_VALID(zone));
1777
1778 LOCK_ZONE(zone);
1779 result = dns_zone_setstring(zone, &zone->journal, myjournal);
1780 UNLOCK_ZONE(zone);
1781
1782 return (result);
1783 }
1784
1785 char *
1786 dns_zone_getjournal(dns_zone_t *zone) {
1787 REQUIRE(DNS_ZONE_VALID(zone));
1788
1789 return (zone->journal);
1790 }
1791
1792 /*
1793 * Return true iff the zone is "dynamic", in the sense that the zone's
1794 * master file (if any) is written by the server, rather than being
1795 * updated manually and read by the server.
1796 *
1797 * This is true for slave zones, mirror zones, stub zones, key zones,
1798 * and zones that allow dynamic updates either by having an update
1799 * policy ("ssutable") or an "allow-update" ACL with a value other than
1800 * exactly "{ none; }".
1801 */
1802 bool
1803 dns_zone_isdynamic(dns_zone_t *zone, bool ignore_freeze) {
1804 REQUIRE(DNS_ZONE_VALID(zone));
1805
1806 if (zone->type == dns_zone_slave || zone->type == dns_zone_mirror ||
1807 zone->type == dns_zone_stub || zone->type == dns_zone_key ||
1808 (zone->type == dns_zone_redirect && zone->masters != NULL))
1809 {
1810 return (true);
1811 }
1812
1813 /* Inline zones are always dynamic. */
1814 if (zone->type == dns_zone_master && zone->raw != NULL) {
1815 return (true);
1816 }
1817
1818 /* Kasp zones are always dynamic. */
1819 if (dns_zone_use_kasp(zone)) {
1820 return (true);
1821 }
1822
1823 /* If !ignore_freeze, we need check whether updates are disabled. */
1824 if (zone->type == dns_zone_master &&
1825 (!zone->update_disabled || ignore_freeze) &&
1826 ((zone->ssutable != NULL) ||
1827 (zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl))))
1828 {
1829 return (true);
1830 }
1831
1832 return (false);
1833 }
1834
1835 /*
1836 * Set the response policy index and information for a zone.
1837 */
1838 isc_result_t
1839 dns_zone_rpz_enable(dns_zone_t *zone, dns_rpz_zones_t *rpzs,
1840 dns_rpz_num_t rpz_num) {
1841 /*
1842 * Only RBTDB zones can be used for response policy zones,
1843 * because only they have the code to create the summary data.
1844 * Only zones that are loaded instead of mmap()ed create the
1845 * summary data and so can be policy zones.
1846 */
1847 if (strcmp(zone->db_argv[0], "rbt") != 0 &&
1848 strcmp(zone->db_argv[0], "rbt64") != 0)
1849 {
1850 return (ISC_R_NOTIMPLEMENTED);
1851 }
1852 if (zone->masterformat == dns_masterformat_map) {
1853 return (ISC_R_NOTIMPLEMENTED);
1854 }
1855
1856 /*
1857 * This must happen only once or be redundant.
1858 */
1859 LOCK_ZONE(zone);
1860 if (zone->rpzs != NULL) {
1861 REQUIRE(zone->rpzs == rpzs && zone->rpz_num == rpz_num);
1862 } else {
1863 REQUIRE(zone->rpz_num == DNS_RPZ_INVALID_NUM);
1864 dns_rpz_attach_rpzs(rpzs, &zone->rpzs);
1865 zone->rpz_num = rpz_num;
1866 }
1867 rpzs->defined |= DNS_RPZ_ZBIT(rpz_num);
1868 UNLOCK_ZONE(zone);
1869
1870 return (ISC_R_SUCCESS);
1871 }
1872
1873 dns_rpz_num_t
1874 dns_zone_get_rpz_num(dns_zone_t *zone) {
1875 return (zone->rpz_num);
1876 }
1877
1878 /*
1879 * If a zone is a response policy zone, mark its new database.
1880 */
1881 void
1882 dns_zone_rpz_enable_db(dns_zone_t *zone, dns_db_t *db) {
1883 isc_result_t result;
1884 if (zone->rpz_num == DNS_RPZ_INVALID_NUM) {
1885 return;
1886 }
1887 REQUIRE(zone->rpzs != NULL);
1888 result = dns_db_updatenotify_register(db, dns_rpz_dbupdate_callback,
1889 zone->rpzs->zones[zone->rpz_num]);
1890 REQUIRE(result == ISC_R_SUCCESS);
1891 }
1892
1893 static void
1894 dns_zone_rpz_disable_db(dns_zone_t *zone, dns_db_t *db) {
1895 if (zone->rpz_num == DNS_RPZ_INVALID_NUM) {
1896 return;
1897 }
1898 REQUIRE(zone->rpzs != NULL);
1899 (void)dns_db_updatenotify_unregister(db, dns_rpz_dbupdate_callback,
1900 zone->rpzs->zones[zone->rpz_num]);
1901 }
1902
1903 void
1904 dns_zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs) {
1905 REQUIRE(DNS_ZONE_VALID(zone));
1906 REQUIRE(catzs != NULL);
1907
1908 LOCK_ZONE(zone);
1909 INSIST(zone->catzs == NULL || zone->catzs == catzs);
1910 dns_catz_catzs_set_view(catzs, zone->view);
1911 if (zone->catzs == NULL) {
1912 dns_catz_catzs_attach(catzs, &zone->catzs);
1913 }
1914 UNLOCK_ZONE(zone);
1915 }
1916
1917 /*
1918 * If a zone is a catalog zone, attach it to update notification in database.
1919 */
1920 void
1921 dns_zone_catz_enable_db(dns_zone_t *zone, dns_db_t *db) {
1922 REQUIRE(DNS_ZONE_VALID(zone));
1923 REQUIRE(db != NULL);
1924
1925 if (zone->catzs != NULL) {
1926 dns_db_updatenotify_register(db, dns_catz_dbupdate_callback,
1927 zone->catzs);
1928 }
1929 }
1930
1931 static void
1932 dns_zone_catz_disable_db(dns_zone_t *zone, dns_db_t *db) {
1933 REQUIRE(DNS_ZONE_VALID(zone));
1934 REQUIRE(db != NULL);
1935
1936 if (zone->catzs != NULL) {
1937 dns_db_updatenotify_unregister(db, dns_catz_dbupdate_callback,
1938 zone->catzs);
1939 }
1940 }
1941
1942 /*
1943 * Set catalog zone ownership of the zone
1944 */
1945 void
1946 dns_zone_set_parentcatz(dns_zone_t *zone, dns_catz_zone_t *catz) {
1947 REQUIRE(DNS_ZONE_VALID(zone));
1948 REQUIRE(catz != NULL);
1949 LOCK_ZONE(zone);
1950 INSIST(zone->parentcatz == NULL || zone->parentcatz == catz);
1951 zone->parentcatz = catz;
1952 UNLOCK_ZONE(zone);
1953 }
1954
1955 dns_catz_zone_t *
1956 dns_zone_get_parentcatz(const dns_zone_t *zone) {
1957 REQUIRE(DNS_ZONE_VALID(zone));
1958 return (zone->parentcatz);
1959 }
1960
1961 static bool
1962 zone_touched(dns_zone_t *zone) {
1963 isc_result_t result;
1964 isc_time_t modtime;
1965 dns_include_t *include;
1966
1967 REQUIRE(DNS_ZONE_VALID(zone));
1968
1969 result = isc_file_getmodtime(zone->masterfile, &modtime);
1970 if (result != ISC_R_SUCCESS ||
1971 isc_time_compare(&modtime, &zone->loadtime) > 0) {
1972 return (true);
1973 }
1974
1975 for (include = ISC_LIST_HEAD(zone->includes); include != NULL;
1976 include = ISC_LIST_NEXT(include, link))
1977 {
1978 result = isc_file_getmodtime(include->name, &modtime);
1979 if (result != ISC_R_SUCCESS ||
1980 isc_time_compare(&modtime, &include->filetime) > 0)
1981 {
1982 return (true);
1983 }
1984 }
1985
1986 return (false);
1987 }
1988
1989 /*
1990 * Note: when dealing with inline-signed zones, external callers will always
1991 * call zone_load() for the secure zone; zone_load() calls itself recursively
1992 * in order to load the raw zone.
1993 */
1994 static isc_result_t
1995 zone_load(dns_zone_t *zone, unsigned int flags, bool locked) {
1996 isc_result_t result;
1997 isc_time_t now;
1998 isc_time_t loadtime;
1999 dns_db_t *db = NULL;
2000 bool rbt, hasraw, is_dynamic;
2001
2002 REQUIRE(DNS_ZONE_VALID(zone));
2003
2004 if (!locked) {
2005 LOCK_ZONE(zone);
2006 }
2007
2008 INSIST(zone != zone->raw);
2009 hasraw = inline_secure(zone);
2010 if (hasraw) {
2011 /*
2012 * We are trying to load an inline-signed zone. First call
2013 * self recursively to try loading the raw version of the zone.
2014 * Assuming the raw zone file is readable, there are two
2015 * possibilities:
2016 *
2017 * a) the raw zone was not yet loaded and thus it will be
2018 * loaded now, synchronously; if this succeeds, a
2019 * subsequent attempt to load the signed zone file will
2020 * take place and thus zone_postload() will be called
2021 * twice: first for the raw zone and then for the secure
2022 * zone; the latter call will take care of syncing the raw
2023 * version with the secure version,
2024 *
2025 * b) the raw zone was already loaded and we are trying to
2026 * reload it, which will happen asynchronously; this means
2027 * zone_postload() will only be called for the raw zone
2028 * because "result" returned by the zone_load() call below
2029 * will not be ISC_R_SUCCESS but rather DNS_R_CONTINUE;
2030 * zone_postload() called for the raw zone will take care
2031 * of syncing the raw version with the secure version.
2032 */
2033 result = zone_load(zone->raw, flags, false);
2034 if (result != ISC_R_SUCCESS) {
2035 if (!locked) {
2036 UNLOCK_ZONE(zone);
2037 }
2038 return (result);
2039 }
2040 LOCK_ZONE(zone->raw);
2041 }
2042
2043 TIME_NOW(&now);
2044
2045 INSIST(zone->type != dns_zone_none);
2046
2047 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
2048 if ((flags & DNS_ZONELOADFLAG_THAW) != 0) {
2049 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
2050 }
2051 result = DNS_R_CONTINUE;
2052 goto cleanup;
2053 }
2054
2055 INSIST(zone->db_argc >= 1);
2056
2057 rbt = strcmp(zone->db_argv[0], "rbt") == 0 ||
2058 strcmp(zone->db_argv[0], "rbt64") == 0;
2059
2060 if (zone->db != NULL && zone->masterfile == NULL && rbt) {
2061 /*
2062 * The zone has no master file configured.
2063 */
2064 result = ISC_R_SUCCESS;
2065 goto cleanup;
2066 }
2067
2068 is_dynamic = dns_zone_isdynamic(zone, false);
2069 if (zone->db != NULL && is_dynamic) {
2070 /*
2071 * This is a slave, stub, dynamically updated, or kasp enabled
2072 * zone being reloaded. Do nothing - the database we already
2073 * have is guaranteed to be up-to-date.
2074 */
2075 if (zone->type == dns_zone_master && !hasraw) {
2076 result = DNS_R_DYNAMIC;
2077 } else {
2078 result = ISC_R_SUCCESS;
2079 }
2080 goto cleanup;
2081 }
2082
2083 /*
2084 * Store the current time before the zone is loaded, so that if the
2085 * file changes between the time of the load and the time that
2086 * zone->loadtime is set, then the file will still be reloaded
2087 * the next time dns_zone_load is called.
2088 */
2089 TIME_NOW(&loadtime);
2090
2091 /*
2092 * Don't do the load if the file that stores the zone is older
2093 * than the last time the zone was loaded. If the zone has not
2094 * been loaded yet, zone->loadtime will be the epoch.
2095 */
2096 if (zone->masterfile != NULL) {
2097 isc_time_t filetime;
2098
2099 /*
2100 * The file is already loaded. If we are just doing a
2101 * "rndc reconfig", we are done.
2102 */
2103 if (!isc_time_isepoch(&zone->loadtime) &&
2104 (flags & DNS_ZONELOADFLAG_NOSTAT) != 0)
2105 {
2106 result = ISC_R_SUCCESS;
2107 goto cleanup;
2108 }
2109
2110 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
2111 !zone_touched(zone)) {
2112 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2113 ISC_LOG_DEBUG(1),
2114 "skipping load: master file "
2115 "older than last load");
2116 result = DNS_R_UPTODATE;
2117 goto cleanup;
2118 }
2119
2120 /*
2121 * If the file modification time is in the past
2122 * set loadtime to that value.
2123 */
2124 result = isc_file_getmodtime(zone->masterfile, &filetime);
2125 if (result == ISC_R_SUCCESS &&
2126 isc_time_compare(&loadtime, &filetime) > 0) {
2127 loadtime = filetime;
2128 }
2129 }
2130
2131 /*
2132 * Built in zones (with the exception of empty zones) don't need
2133 * to be reloaded.
2134 */
2135 if (zone->type == dns_zone_master &&
2136 strcmp(zone->db_argv[0], "_builtin") == 0 &&
2137 (zone->db_argc < 2 || strcmp(zone->db_argv[1], "empty") != 0) &&
2138 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
2139 {
2140 result = ISC_R_SUCCESS;
2141 goto cleanup;
2142 }
2143
2144 /*
2145 * Zones associated with a DLZ don't need to be loaded either,
2146 * but we need to associate the database with the zone object.
2147 */
2148 if (strcmp(zone->db_argv[0], "dlz") == 0) {
2149 dns_dlzdb_t *dlzdb;
2150 dns_dlzfindzone_t findzone;
2151
2152 for (dlzdb = ISC_LIST_HEAD(zone->view->dlz_unsearched);
2153 dlzdb != NULL; dlzdb = ISC_LIST_NEXT(dlzdb, link))
2154 {
2155 INSIST(DNS_DLZ_VALID(dlzdb));
2156 if (strcmp(zone->db_argv[1], dlzdb->dlzname) == 0) {
2157 break;
2158 }
2159 }
2160
2161 if (dlzdb == NULL) {
2162 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2163 ISC_LOG_ERROR,
2164 "DLZ %s does not exist or is set "
2165 "to 'search yes;'",
2166 zone->db_argv[1]);
2167 result = ISC_R_NOTFOUND;
2168 goto cleanup;
2169 }
2170
2171 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
2172 /* ask SDLZ driver if the zone is supported */
2173 findzone = dlzdb->implementation->methods->findzone;
2174 result = (*findzone)(dlzdb->implementation->driverarg,
2175 dlzdb->dbdata, dlzdb->mctx,
2176 zone->view->rdclass, &zone->origin, NULL,
2177 NULL, &db);
2178 if (result != ISC_R_NOTFOUND) {
2179 if (zone->db != NULL) {
2180 zone_detachdb(zone);
2181 }
2182 zone_attachdb(zone, db);
2183 dns_db_detach(&db);
2184 result = ISC_R_SUCCESS;
2185 }
2186 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
2187
2188 if (result == ISC_R_SUCCESS) {
2189 if (dlzdb->configure_callback == NULL) {
2190 goto cleanup;
2191 }
2192
2193 result = (*dlzdb->configure_callback)(zone->view, dlzdb,
2194 zone);
2195 if (result != ISC_R_SUCCESS) {
2196 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2197 ISC_LOG_ERROR,
2198 "DLZ configuration callback: %s",
2199 isc_result_totext(result));
2200 }
2201 }
2202 goto cleanup;
2203 }
2204
2205 if ((zone->type == dns_zone_slave || zone->type == dns_zone_mirror ||
2206 zone->type == dns_zone_stub ||
2207 (zone->type == dns_zone_redirect && zone->masters != NULL)) &&
2208 rbt)
2209 {
2210 if (zone->masterfile == NULL ||
2211 !isc_file_exists(zone->masterfile)) {
2212 if (zone->masterfile != NULL) {
2213 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2214 ISC_LOG_DEBUG(1),
2215 "no master file");
2216 }
2217 zone->refreshtime = now;
2218 if (zone->task != NULL) {
2219 zone_settimer(zone, &now);
2220 }
2221 result = ISC_R_SUCCESS;
2222 goto cleanup;
2223 }
2224 }
2225
2226 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
2227 "starting load");
2228
2229 result = dns_db_create(zone->mctx, zone->db_argv[0], &zone->origin,
2230 (zone->type == dns_zone_stub) ? dns_dbtype_stub
2231 : dns_dbtype_zone,
2232 zone->rdclass, zone->db_argc - 1,
2233 zone->db_argv + 1, &db);
2234
2235 if (result != ISC_R_SUCCESS) {
2236 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
2237 "loading zone: creating database: %s",
2238 isc_result_totext(result));
2239 goto cleanup;
2240 }
2241 dns_db_settask(db, zone->task);
2242
2243 if (zone->type == dns_zone_master || zone->type == dns_zone_slave ||
2244 zone->type == dns_zone_mirror)
2245 {
2246 result = dns_db_setgluecachestats(db, zone->gluecachestats);
2247 if (result == ISC_R_NOTIMPLEMENTED) {
2248 result = ISC_R_SUCCESS;
2249 }
2250 if (result != ISC_R_SUCCESS) {
2251 goto cleanup;
2252 }
2253 }
2254
2255 if (!dns_db_ispersistent(db)) {
2256 if (zone->masterfile != NULL) {
2257 result = zone_startload(db, zone, loadtime);
2258 } else {
2259 result = DNS_R_NOMASTERFILE;
2260 if (zone->type == dns_zone_master ||
2261 (zone->type == dns_zone_redirect &&
2262 zone->masters == NULL))
2263 {
2264 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2265 ISC_LOG_ERROR,
2266 "loading zone: "
2267 "no master file configured");
2268 goto cleanup;
2269 }
2270 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2271 ISC_LOG_INFO,
2272 "loading zone: "
2273 "no master file configured: continuing");
2274 }
2275 }
2276
2277 if (result == DNS_R_CONTINUE) {
2278 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING);
2279 if ((flags & DNS_ZONELOADFLAG_THAW) != 0) {
2280 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
2281 }
2282 goto cleanup;
2283 }
2284
2285 result = zone_postload(zone, db, loadtime, result);
2286
2287 cleanup:
2288 if (hasraw) {
2289 UNLOCK_ZONE(zone->raw);
2290 }
2291 if (!locked) {
2292 UNLOCK_ZONE(zone);
2293 }
2294 if (db != NULL) {
2295 dns_db_detach(&db);
2296 }
2297 return (result);
2298 }
2299
2300 isc_result_t
2301 dns_zone_load(dns_zone_t *zone, bool newonly) {
2302 return (zone_load(zone, newonly ? DNS_ZONELOADFLAG_NOSTAT : 0, false));
2303 }
2304
2305 static void
2306 zone_asyncload(isc_task_t *task, isc_event_t *event) {
2307 dns_asyncload_t *asl = event->ev_arg;
2308 dns_zone_t *zone = asl->zone;
2309 isc_result_t result;
2310
2311 UNUSED(task);
2312
2313 REQUIRE(DNS_ZONE_VALID(zone));
2314
2315 isc_event_free(&event);
2316
2317 LOCK_ZONE(zone);
2318 result = zone_load(zone, asl->flags, true);
2319 if (result != DNS_R_CONTINUE) {
2320 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
2321 }
2322 UNLOCK_ZONE(zone);
2323
2324 /* Inform the zone table we've finished loading */
2325 if (asl->loaded != NULL) {
2326 (asl->loaded)(asl->loaded_arg, zone, task);
2327 }
2328
2329 isc_mem_put(zone->mctx, asl, sizeof(*asl));
2330 dns_zone_idetach(&zone);
2331 }
2332
2333 isc_result_t
2334 dns_zone_asyncload(dns_zone_t *zone, bool newonly, dns_zt_zoneloaded_t done,
2335 void *arg) {
2336 isc_event_t *e;
2337 dns_asyncload_t *asl = NULL;
2338
2339 REQUIRE(DNS_ZONE_VALID(zone));
2340
2341 if (zone->zmgr == NULL) {
2342 return (ISC_R_FAILURE);
2343 }
2344
2345 /* If we already have a load pending, stop now */
2346 LOCK_ZONE(zone);
2347 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING)) {
2348 UNLOCK_ZONE(zone);
2349 return (ISC_R_ALREADYRUNNING);
2350 }
2351
2352 asl = isc_mem_get(zone->mctx, sizeof(*asl));
2353
2354 asl->zone = NULL;
2355 asl->flags = newonly ? DNS_ZONELOADFLAG_NOSTAT : 0;
2356 asl->loaded = done;
2357 asl->loaded_arg = arg;
2358
2359 e = isc_event_allocate(zone->zmgr->mctx, zone->zmgr, DNS_EVENT_ZONELOAD,
2360 zone_asyncload, asl, sizeof(isc_event_t));
2361
2362 zone_iattach(zone, &asl->zone);
2363 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADPENDING);
2364 isc_task_send(zone->loadtask, &e);
2365 UNLOCK_ZONE(zone);
2366
2367 return (ISC_R_SUCCESS);
2368 }
2369
2370 bool
2371 dns__zone_loadpending(dns_zone_t *zone) {
2372 REQUIRE(DNS_ZONE_VALID(zone));
2373
2374 return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING));
2375 }
2376
2377 isc_result_t
2378 dns_zone_loadandthaw(dns_zone_t *zone) {
2379 isc_result_t result;
2380
2381 if (inline_raw(zone)) {
2382 result = zone_load(zone->secure, DNS_ZONELOADFLAG_THAW, false);
2383 } else {
2384 result = zone_load(zone, DNS_ZONELOADFLAG_THAW, false);
2385 }
2386
2387 switch (result) {
2388 case DNS_R_CONTINUE:
2389 /* Deferred thaw. */
2390 break;
2391 case DNS_R_UPTODATE:
2392 case ISC_R_SUCCESS:
2393 case DNS_R_SEENINCLUDE:
2394 zone->update_disabled = false;
2395 break;
2396 case DNS_R_NOMASTERFILE:
2397 zone->update_disabled = false;
2398 break;
2399 default:
2400 /* Error, remain in disabled state. */
2401 break;
2402 }
2403 return (result);
2404 }
2405
2406 static unsigned int
2407 get_master_options(dns_zone_t *zone) {
2408 unsigned int options;
2409
2410 options = DNS_MASTER_ZONE | DNS_MASTER_RESIGN;
2411 if (zone->type == dns_zone_slave || zone->type == dns_zone_mirror ||
2412 (zone->type == dns_zone_redirect && zone->masters == NULL))
2413 {
2414 options |= DNS_MASTER_SLAVE;
2415 }
2416 if (zone->type == dns_zone_key) {
2417 options |= DNS_MASTER_KEY;
2418 }
2419 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS)) {
2420 options |= DNS_MASTER_CHECKNS;
2421 }
2422 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS)) {
2423 options |= DNS_MASTER_FATALNS;
2424 }
2425 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES)) {
2426 options |= DNS_MASTER_CHECKNAMES;
2427 }
2428 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) {
2429 options |= DNS_MASTER_CHECKNAMESFAIL;
2430 }
2431 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMX)) {
2432 options |= DNS_MASTER_CHECKMX;
2433 }
2434 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL)) {
2435 options |= DNS_MASTER_CHECKMXFAIL;
2436 }
2437 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKWILDCARD)) {
2438 options |= DNS_MASTER_CHECKWILDCARD;
2439 }
2440 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKTTL)) {
2441 options |= DNS_MASTER_CHECKTTL;
2442 }
2443
2444 return (options);
2445 }
2446
2447 static void
2448 zone_registerinclude(const char *filename, void *arg) {
2449 isc_result_t result;
2450 dns_zone_t *zone = (dns_zone_t *)arg;
2451 dns_include_t *inc = NULL;
2452
2453 REQUIRE(DNS_ZONE_VALID(zone));
2454
2455 if (filename == NULL) {
2456 return;
2457 }
2458
2459 /*
2460 * Suppress duplicates.
2461 */
2462 for (inc = ISC_LIST_HEAD(zone->newincludes); inc != NULL;
2463 inc = ISC_LIST_NEXT(inc, link))
2464 {
2465 if (strcmp(filename, inc->name) == 0) {
2466 return;
2467 }
2468 }
2469
2470 inc = isc_mem_get(zone->mctx, sizeof(dns_include_t));
2471 inc->name = isc_mem_strdup(zone->mctx, filename);
2472 ISC_LINK_INIT(inc, link);
2473
2474 result = isc_file_getmodtime(filename, &inc->filetime);
2475 if (result != ISC_R_SUCCESS) {
2476 isc_time_settoepoch(&inc->filetime);
2477 }
2478
2479 ISC_LIST_APPEND(zone->newincludes, inc, link);
2480 }
2481
2482 static void
2483 zone_gotreadhandle(isc_task_t *task, isc_event_t *event) {
2484 dns_load_t *load = event->ev_arg;
2485 isc_result_t result = ISC_R_SUCCESS;
2486 unsigned int options;
2487
2488 REQUIRE(DNS_LOAD_VALID(load));
2489
2490 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) {
2491 result = ISC_R_CANCELED;
2492 }
2493 isc_event_free(&event);
2494 if (result == ISC_R_CANCELED) {
2495 goto fail;
2496 }
2497
2498 options = get_master_options(load->zone);
2499
2500 result = dns_master_loadfileinc(
2501 load->zone->masterfile, dns_db_origin(load->db),
2502 dns_db_origin(load->db), load->zone->rdclass, options, 0,
2503 &load->callbacks, task, zone_loaddone, load, &load->zone->lctx,
2504 zone_registerinclude, load->zone, load->zone->mctx,
2505 load->zone->masterformat, load->zone->maxttl);
2506 if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE &&
2507 result != DNS_R_SEENINCLUDE)
2508 {
2509 goto fail;
2510 }
2511 return;
2512
2513 fail:
2514 zone_loaddone(load, result);
2515 }
2516
2517 static void
2518 get_raw_serial(dns_zone_t *raw, dns_masterrawheader_t *rawdata) {
2519 isc_result_t result;
2520 unsigned int soacount;
2521
2522 LOCK(&raw->lock);
2523 if (raw->db != NULL) {
2524 result = zone_get_from_db(raw, raw->db, NULL, &soacount,
2525 &rawdata->sourceserial, NULL, NULL,
2526 NULL, NULL, NULL);
2527 if (result == ISC_R_SUCCESS && soacount > 0U) {
2528 rawdata->flags |= DNS_MASTERRAW_SOURCESERIALSET;
2529 }
2530 }
2531 UNLOCK(&raw->lock);
2532 }
2533
2534 static void
2535 zone_gotwritehandle(isc_task_t *task, isc_event_t *event) {
2536 const char me[] = "zone_gotwritehandle";
2537 dns_zone_t *zone = event->ev_arg;
2538 isc_result_t result = ISC_R_SUCCESS;
2539 dns_dbversion_t *version = NULL;
2540 dns_masterrawheader_t rawdata;
2541 dns_db_t *db = NULL;
2542
2543 REQUIRE(DNS_ZONE_VALID(zone));
2544 INSIST(task == zone->task);
2545 ENTER;
2546
2547 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) {
2548 result = ISC_R_CANCELED;
2549 }
2550 isc_event_free(&event);
2551 if (result == ISC_R_CANCELED) {
2552 goto fail;
2553 }
2554
2555 LOCK_ZONE(zone);
2556 INSIST(zone != zone->raw);
2557 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
2558 if (zone->db != NULL) {
2559 dns_db_attach(zone->db, &db);
2560 }
2561 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
2562 if (db != NULL) {
2563 const dns_master_style_t *output_style;
2564 dns_db_currentversion(db, &version);
2565 dns_master_initrawheader(&rawdata);
2566 if (inline_secure(zone)) {
2567 get_raw_serial(zone->raw, &rawdata);
2568 }
2569 if (zone->type == dns_zone_key) {
2570 output_style = &dns_master_style_keyzone;
2571 } else if (zone->masterstyle != NULL) {
2572 output_style = zone->masterstyle;
2573 } else {
2574 output_style = &dns_master_style_default;
2575 }
2576 result = dns_master_dumpinc(
2577 zone->mctx, db, version, output_style, zone->masterfile,
2578 zone->task, dump_done, zone, &zone->dctx,
2579 zone->masterformat, &rawdata);
2580 dns_db_closeversion(db, &version, false);
2581 } else {
2582 result = ISC_R_CANCELED;
2583 }
2584 if (db != NULL) {
2585 dns_db_detach(&db);
2586 }
2587 UNLOCK_ZONE(zone);
2588 if (result != DNS_R_CONTINUE) {
2589 goto fail;
2590 }
2591 return;
2592
2593 fail:
2594 dump_done(zone, result);
2595 }
2596
2597 /*
2598 * Save the raw serial number for inline-signing zones.
2599 * (XXX: Other information from the header will be used
2600 * for other purposes in the future, but for now this is
2601 * all we're interested in.)
2602 */
2603 static void
2604 zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
2605 if ((header->flags & DNS_MASTERRAW_SOURCESERIALSET) == 0) {
2606 return;
2607 }
2608
2609 zone->sourceserial = header->sourceserial;
2610 zone->sourceserialset = true;
2611 }
2612
2613 void
2614 dns_zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
2615 if (zone == NULL) {
2616 return;
2617 }
2618
2619 LOCK_ZONE(zone);
2620 zone_setrawdata(zone, header);
2621 UNLOCK_ZONE(zone);
2622 }
2623
2624 static isc_result_t
2625 zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
2626 const char me[] = "zone_startload";
2627 dns_load_t *load;
2628 isc_result_t result;
2629 isc_result_t tresult;
2630 unsigned int options;
2631
2632 ENTER;
2633
2634 dns_zone_rpz_enable_db(zone, db);
2635 dns_zone_catz_enable_db(zone, db);
2636
2637 options = get_master_options(zone);
2638 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS)) {
2639 options |= DNS_MASTER_MANYERRORS;
2640 }
2641
2642 if (zone->zmgr != NULL && zone->db != NULL && zone->loadtask != NULL) {
2643 load = isc_mem_get(zone->mctx, sizeof(*load));
2644
2645 load->mctx = NULL;
2646 load->zone = NULL;
2647 load->db = NULL;
2648 load->loadtime = loadtime;
2649 load->magic = LOAD_MAGIC;
2650
2651 isc_mem_attach(zone->mctx, &load->mctx);
2652 zone_iattach(zone, &load->zone);
2653 dns_db_attach(db, &load->db);
2654 dns_rdatacallbacks_init(&load->callbacks);
2655 load->callbacks.rawdata = zone_setrawdata;
2656 zone_iattach(zone, &load->callbacks.zone);
2657 result = dns_db_beginload(db, &load->callbacks);
2658 if (result != ISC_R_SUCCESS) {
2659 goto cleanup;
2660 }
2661 result = zonemgr_getio(zone->zmgr, true, zone->loadtask,
2662 zone_gotreadhandle, load, &zone->readio);
2663 if (result != ISC_R_SUCCESS) {
2664 /*
2665 * We can't report multiple errors so ignore
2666 * the result of dns_db_endload().
2667 */
2668 (void)dns_db_endload(load->db, &load->callbacks);
2669 goto cleanup;
2670 } else {
2671 result = DNS_R_CONTINUE;
2672 }
2673 } else {
2674 dns_rdatacallbacks_t callbacks;
2675
2676 dns_rdatacallbacks_init(&callbacks);
2677 callbacks.rawdata = zone_setrawdata;
2678 zone_iattach(zone, &callbacks.zone);
2679 result = dns_db_beginload(db, &callbacks);
2680 if (result != ISC_R_SUCCESS) {
2681 zone_idetach(&callbacks.zone);
2682 return (result);
2683 }
2684 result = dns_master_loadfile(
2685 zone->masterfile, &zone->origin, &zone->origin,
2686 zone->rdclass, options, 0, &callbacks,
2687 zone_registerinclude, zone, zone->mctx,
2688 zone->masterformat, zone->maxttl);
2689 tresult = dns_db_endload(db, &callbacks);
2690 if (result == ISC_R_SUCCESS) {
2691 result = tresult;
2692 }
2693 zone_idetach(&callbacks.zone);
2694 }
2695
2696 return (result);
2697
2698 cleanup:
2699 load->magic = 0;
2700 dns_db_detach(&load->db);
2701 zone_idetach(&load->zone);
2702 zone_idetach(&load->callbacks.zone);
2703 isc_mem_detach(&load->mctx);
2704 isc_mem_put(zone->mctx, load, sizeof(*load));
2705 return (result);
2706 }
2707
2708 static bool
2709 zone_check_mx(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2710 dns_name_t *owner) {
2711 isc_result_t result;
2712 char ownerbuf[DNS_NAME_FORMATSIZE];
2713 char namebuf[DNS_NAME_FORMATSIZE];
2714 char altbuf[DNS_NAME_FORMATSIZE];
2715 dns_fixedname_t fixed;
2716 dns_name_t *foundname;
2717 int level;
2718
2719 /*
2720 * "." means the services does not exist.
2721 */
2722 if (dns_name_equal(name, dns_rootname)) {
2723 return (true);
2724 }
2725
2726 /*
2727 * Outside of zone.
2728 */
2729 if (!dns_name_issubdomain(name, &zone->origin)) {
2730 if (zone->checkmx != NULL) {
2731 return ((zone->checkmx)(zone, name, owner));
2732 }
2733 return (true);
2734 }
2735
2736 if (zone->type == dns_zone_master) {
2737 level = ISC_LOG_ERROR;
2738 } else {
2739 level = ISC_LOG_WARNING;
2740 }
2741
2742 foundname = dns_fixedname_initname(&fixed);
2743
2744 result = dns_db_find(db, name, NULL, dns_rdatatype_a, 0, 0, NULL,
2745 foundname, NULL, NULL);
2746 if (result == ISC_R_SUCCESS) {
2747 return (true);
2748 }
2749
2750 if (result == DNS_R_NXRRSET) {
2751 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa, 0, 0,
2752 NULL, foundname, NULL, NULL);
2753 if (result == ISC_R_SUCCESS) {
2754 return (true);
2755 }
2756 }
2757
2758 dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2759 dns_name_format(name, namebuf, sizeof namebuf);
2760 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2761 result == DNS_R_EMPTYNAME)
2762 {
2763 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL)) {
2764 level = ISC_LOG_WARNING;
2765 }
2766 dns_zone_log(zone, level,
2767 "%s/MX '%s' has no address records (A or AAAA)",
2768 ownerbuf, namebuf);
2769 return ((level == ISC_LOG_WARNING) ? true : false);
2770 }
2771
2772 if (result == DNS_R_CNAME) {
2773 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
2774 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2775 {
2776 level = ISC_LOG_WARNING;
2777 }
2778 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
2779 dns_zone_log(zone, level,
2780 "%s/MX '%s' is a CNAME (illegal)",
2781 ownerbuf, namebuf);
2782 }
2783 return ((level == ISC_LOG_WARNING) ? true : false);
2784 }
2785
2786 if (result == DNS_R_DNAME) {
2787 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
2788 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2789 {
2790 level = ISC_LOG_WARNING;
2791 }
2792 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
2793 dns_name_format(foundname, altbuf, sizeof altbuf);
2794 dns_zone_log(zone, level,
2795 "%s/MX '%s' is below a DNAME"
2796 " '%s' (illegal)",
2797 ownerbuf, namebuf, altbuf);
2798 }
2799 return ((level == ISC_LOG_WARNING) ? true : false);
2800 }
2801
2802 if (zone->checkmx != NULL && result == DNS_R_DELEGATION) {
2803 return ((zone->checkmx)(zone, name, owner));
2804 }
2805
2806 return (true);
2807 }
2808
2809 static bool
2810 zone_check_srv(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2811 dns_name_t *owner) {
2812 isc_result_t result;
2813 char ownerbuf[DNS_NAME_FORMATSIZE];
2814 char namebuf[DNS_NAME_FORMATSIZE];
2815 char altbuf[DNS_NAME_FORMATSIZE];
2816 dns_fixedname_t fixed;
2817 dns_name_t *foundname;
2818 int level;
2819
2820 /*
2821 * "." means the services does not exist.
2822 */
2823 if (dns_name_equal(name, dns_rootname)) {
2824 return (true);
2825 }
2826
2827 /*
2828 * Outside of zone.
2829 */
2830 if (!dns_name_issubdomain(name, &zone->origin)) {
2831 if (zone->checksrv != NULL) {
2832 return ((zone->checksrv)(zone, name, owner));
2833 }
2834 return (true);
2835 }
2836
2837 if (zone->type == dns_zone_master) {
2838 level = ISC_LOG_ERROR;
2839 } else {
2840 level = ISC_LOG_WARNING;
2841 }
2842
2843 foundname = dns_fixedname_initname(&fixed);
2844
2845 result = dns_db_find(db, name, NULL, dns_rdatatype_a, 0, 0, NULL,
2846 foundname, NULL, NULL);
2847 if (result == ISC_R_SUCCESS) {
2848 return (true);
2849 }
2850
2851 if (result == DNS_R_NXRRSET) {
2852 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa, 0, 0,
2853 NULL, foundname, NULL, NULL);
2854 if (result == ISC_R_SUCCESS) {
2855 return (true);
2856 }
2857 }
2858
2859 dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2860 dns_name_format(name, namebuf, sizeof namebuf);
2861 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2862 result == DNS_R_EMPTYNAME)
2863 {
2864 dns_zone_log(zone, level,
2865 "%s/SRV '%s' has no address records (A or AAAA)",
2866 ownerbuf, namebuf);
2867 /* XXX950 make fatal for 9.5.0. */
2868 return (true);
2869 }
2870
2871 if (result == DNS_R_CNAME) {
2872 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
2873 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2874 {
2875 level = ISC_LOG_WARNING;
2876 }
2877 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
2878 dns_zone_log(zone, level,
2879 "%s/SRV '%s' is a CNAME (illegal)",
2880 ownerbuf, namebuf);
2881 }
2882 return ((level == ISC_LOG_WARNING) ? true : false);
2883 }
2884
2885 if (result == DNS_R_DNAME) {
2886 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
2887 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2888 {
2889 level = ISC_LOG_WARNING;
2890 }
2891 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
2892 dns_name_format(foundname, altbuf, sizeof altbuf);
2893 dns_zone_log(zone, level,
2894 "%s/SRV '%s' is below a "
2895 "DNAME '%s' (illegal)",
2896 ownerbuf, namebuf, altbuf);
2897 }
2898 return ((level == ISC_LOG_WARNING) ? true : false);
2899 }
2900
2901 if (zone->checksrv != NULL && result == DNS_R_DELEGATION) {
2902 return ((zone->checksrv)(zone, name, owner));
2903 }
2904
2905 return (true);
2906 }
2907
2908 static bool
2909 zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2910 dns_name_t *owner) {
2911 bool answer = true;
2912 isc_result_t result, tresult;
2913 char ownerbuf[DNS_NAME_FORMATSIZE];
2914 char namebuf[DNS_NAME_FORMATSIZE];
2915 char altbuf[DNS_NAME_FORMATSIZE];
2916 dns_fixedname_t fixed;
2917 dns_name_t *foundname;
2918 dns_rdataset_t a;
2919 dns_rdataset_t aaaa;
2920 int level;
2921
2922 /*
2923 * Outside of zone.
2924 */
2925 if (!dns_name_issubdomain(name, &zone->origin)) {
2926 if (zone->checkns != NULL) {
2927 return ((zone->checkns)(zone, name, owner, NULL, NULL));
2928 }
2929 return (true);
2930 }
2931
2932 if (zone->type == dns_zone_master) {
2933 level = ISC_LOG_ERROR;
2934 } else {
2935 level = ISC_LOG_WARNING;
2936 }
2937
2938 foundname = dns_fixedname_initname(&fixed);
2939 dns_rdataset_init(&a);
2940 dns_rdataset_init(&aaaa);
2941
2942 /*
2943 * Perform a regular lookup to catch DNAME records then look
2944 * for glue.
2945 */
2946 result = dns_db_find(db, name, NULL, dns_rdatatype_a, 0, 0, NULL,
2947 foundname, &a, NULL);
2948 switch (result) {
2949 case ISC_R_SUCCESS:
2950 case DNS_R_DNAME:
2951 case DNS_R_CNAME:
2952 break;
2953 default:
2954 if (dns_rdataset_isassociated(&a)) {
2955 dns_rdataset_disassociate(&a);
2956 }
2957 result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2958 DNS_DBFIND_GLUEOK, 0, NULL, foundname, &a,
2959 NULL);
2960 }
2961 if (result == ISC_R_SUCCESS) {
2962 dns_rdataset_disassociate(&a);
2963 return (true);
2964 } else if (result == DNS_R_DELEGATION) {
2965 dns_rdataset_disassociate(&a);
2966 }
2967
2968 if (result == DNS_R_NXRRSET || result == DNS_R_DELEGATION ||
2969 result == DNS_R_GLUE)
2970 {
2971 tresult = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2972 DNS_DBFIND_GLUEOK, 0, NULL, foundname,
2973 &aaaa, NULL);
2974 if (tresult == ISC_R_SUCCESS) {
2975 if (dns_rdataset_isassociated(&a)) {
2976 dns_rdataset_disassociate(&a);
2977 }
2978 dns_rdataset_disassociate(&aaaa);
2979 return (true);
2980 }
2981 if (tresult == DNS_R_DELEGATION || tresult == DNS_R_DNAME) {
2982 dns_rdataset_disassociate(&aaaa);
2983 }
2984 if (result == DNS_R_GLUE || tresult == DNS_R_GLUE) {
2985 /*
2986 * Check glue against child zone.
2987 */
2988 if (zone->checkns != NULL) {
2989 answer = (zone->checkns)(zone, name, owner, &a,
2990 &aaaa);
2991 }
2992 if (dns_rdataset_isassociated(&a)) {
2993 dns_rdataset_disassociate(&a);
2994 }
2995 if (dns_rdataset_isassociated(&aaaa)) {
2996 dns_rdataset_disassociate(&aaaa);
2997 }
2998 return (answer);
2999 }
3000 }
3001
3002 dns_name_format(owner, ownerbuf, sizeof ownerbuf);
3003 dns_name_format(name, namebuf, sizeof namebuf);
3004 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
3005 result == DNS_R_EMPTYNAME || result == DNS_R_DELEGATION)
3006 {
3007 const char *what;
3008 bool required = false;
3009 if (dns_name_issubdomain(name, owner)) {
3010 what = "REQUIRED GLUE ";
3011 required = true;
3012 } else if (result == DNS_R_DELEGATION) {
3013 what = "SIBLING GLUE ";
3014 } else {
3015 what = "";
3016 }
3017
3018 if (result != DNS_R_DELEGATION || required ||
3019 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSIBLING))
3020 {
3021 dns_zone_log(zone, level,
3022 "%s/NS '%s' has no %s"
3023 "address records (A or AAAA)",
3024 ownerbuf, namebuf, what);
3025 /*
3026 * Log missing address record.
3027 */
3028 if (result == DNS_R_DELEGATION && zone->checkns != NULL)
3029 {
3030 (void)(zone->checkns)(zone, name, owner, &a,
3031 &aaaa);
3032 }
3033 /* XXX950 make fatal for 9.5.0. */
3034 /* answer = false; */
3035 }
3036 } else if (result == DNS_R_CNAME) {
3037 dns_zone_log(zone, level, "%s/NS '%s' is a CNAME (illegal)",
3038 ownerbuf, namebuf);
3039 /* XXX950 make fatal for 9.5.0. */
3040 /* answer = false; */
3041 } else if (result == DNS_R_DNAME) {
3042 dns_name_format(foundname, altbuf, sizeof altbuf);
3043 dns_zone_log(zone, level,
3044 "%s/NS '%s' is below a DNAME '%s' (illegal)",
3045 ownerbuf, namebuf, altbuf);
3046 /* XXX950 make fatal for 9.5.0. */
3047 /* answer = false; */
3048 }
3049
3050 if (dns_rdataset_isassociated(&a)) {
3051 dns_rdataset_disassociate(&a);
3052 }
3053 if (dns_rdataset_isassociated(&aaaa)) {
3054 dns_rdataset_disassociate(&aaaa);
3055 }
3056 return (answer);
3057 }
3058
3059 static bool
3060 zone_rrset_check_dup(dns_zone_t *zone, dns_name_t *owner,
3061 dns_rdataset_t *rdataset) {
3062 dns_rdataset_t tmprdataset;
3063 isc_result_t result;
3064 bool answer = true;
3065 bool format = true;
3066 int level = ISC_LOG_WARNING;
3067 char ownerbuf[DNS_NAME_FORMATSIZE];
3068 char typebuf[DNS_RDATATYPE_FORMATSIZE];
3069 unsigned int count1 = 0;
3070
3071 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRRFAIL)) {
3072 level = ISC_LOG_ERROR;
3073 }
3074
3075 dns_rdataset_init(&tmprdataset);
3076 for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
3077 result = dns_rdataset_next(rdataset))
3078 {
3079 dns_rdata_t rdata1 = DNS_RDATA_INIT;
3080 unsigned int count2 = 0;
3081
3082 count1++;
3083 dns_rdataset_current(rdataset, &rdata1);
3084 dns_rdataset_clone(rdataset, &tmprdataset);
3085 for (result = dns_rdataset_first(&tmprdataset);
3086 result == ISC_R_SUCCESS;
3087 result = dns_rdataset_next(&tmprdataset))
3088 {
3089 dns_rdata_t rdata2 = DNS_RDATA_INIT;
3090 count2++;
3091 if (count1 >= count2) {
3092 continue;
3093 }
3094 dns_rdataset_current(&tmprdataset, &rdata2);
3095 if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) {
3096 if (format) {
3097 dns_name_format(owner, ownerbuf,
3098 sizeof ownerbuf);
3099 dns_rdatatype_format(rdata1.type,
3100 typebuf,
3101 sizeof(typebuf));
3102 format = false;
3103 }
3104 dns_zone_log(zone, level,
3105 "%s/%s has "
3106 "semantically identical records",
3107 ownerbuf, typebuf);
3108 if (level == ISC_LOG_ERROR) {
3109 answer = false;
3110 }
3111 break;
3112 }
3113 }
3114 dns_rdataset_disassociate(&tmprdataset);
3115 if (!format) {
3116 break;
3117 }
3118 }
3119 return (answer);
3120 }
3121
3122 static bool
3123 zone_check_dup(dns_zone_t *zone, dns_db_t *db) {
3124 dns_dbiterator_t *dbiterator = NULL;
3125 dns_dbnode_t *node = NULL;
3126 dns_fixedname_t fixed;
3127 dns_name_t *name;
3128 dns_rdataset_t rdataset;
3129 dns_rdatasetiter_t *rdsit = NULL;
3130 bool ok = true;
3131 isc_result_t result;
3132
3133 name = dns_fixedname_initname(&fixed);
3134 dns_rdataset_init(&rdataset);
3135
3136 result = dns_db_createiterator(db, 0, &dbiterator);
3137 if (result != ISC_R_SUCCESS) {
3138 return (true);
3139 }
3140
3141 for (result = dns_dbiterator_first(dbiterator); result == ISC_R_SUCCESS;
3142 result = dns_dbiterator_next(dbiterator))
3143 {
3144 result = dns_dbiterator_current(dbiterator, &node, name);
3145 if (result != ISC_R_SUCCESS) {
3146 continue;
3147 }
3148
3149 result = dns_db_allrdatasets(db, node, NULL, 0, &rdsit);
3150 if (result != ISC_R_SUCCESS) {
3151 continue;
3152 }
3153
3154 for (result = dns_rdatasetiter_first(rdsit);
3155 result == ISC_R_SUCCESS;
3156 result = dns_rdatasetiter_next(rdsit))
3157 {
3158 dns_rdatasetiter_current(rdsit, &rdataset);
3159 if (!zone_rrset_check_dup(zone, name, &rdataset)) {
3160 ok = false;
3161 }
3162 dns_rdataset_disassociate(&rdataset);
3163 }
3164 dns_rdatasetiter_destroy(&rdsit);
3165 dns_db_detachnode(db, &node);
3166 }
3167
3168 if (node != NULL) {
3169 dns_db_detachnode(db, &node);
3170 }
3171 dns_dbiterator_destroy(&dbiterator);
3172
3173 return (ok);
3174 }
3175
3176 static bool
3177 isspf(const dns_rdata_t *rdata) {
3178 char buf[1024];
3179 const unsigned char *data = rdata->data;
3180 unsigned int rdl = rdata->length, i = 0, tl, len;
3181
3182 while (rdl > 0U) {
3183 len = tl = *data;
3184 ++data;
3185 --rdl;
3186 INSIST(tl <= rdl);
3187 if (len > sizeof(buf) - i - 1) {
3188 len = sizeof(buf) - i - 1;
3189 }
3190 memmove(buf + i, data, len);
3191 i += len;
3192 data += tl;
3193 rdl -= tl;
3194 }
3195
3196 if (i < 6U) {
3197 return (false);
3198 }
3199
3200 buf[i] = 0;
3201 if (strncmp(buf, "v=spf1", 6) == 0 && (buf[6] == 0 || buf[6] == ' ')) {
3202 return (true);
3203 }
3204 return (false);
3205 }
3206
3207 static bool
3208 integrity_checks(dns_zone_t *zone, dns_db_t *db) {
3209 dns_dbiterator_t *dbiterator = NULL;
3210 dns_dbnode_t *node = NULL;
3211 dns_rdataset_t rdataset;
3212 dns_fixedname_t fixed;
3213 dns_fixedname_t fixedbottom;
3214 dns_rdata_mx_t mx;
3215 dns_rdata_ns_t ns;
3216 dns_rdata_in_srv_t srv;
3217 dns_rdata_t rdata;
3218 dns_name_t *name;
3219 dns_name_t *bottom;
3220 isc_result_t result;
3221 bool ok = true, have_spf, have_txt;
3222
3223 name = dns_fixedname_initname(&fixed);
3224 bottom = dns_fixedname_initname(&fixedbottom);
3225 dns_rdataset_init(&rdataset);
3226 dns_rdata_init(&rdata);
3227
3228 result = dns_db_createiterator(db, 0, &dbiterator);
3229 if (result != ISC_R_SUCCESS) {
3230 return (true);
3231 }
3232
3233 result = dns_dbiterator_first(dbiterator);
3234 while (result == ISC_R_SUCCESS) {
3235 result = dns_dbiterator_current(dbiterator, &node, name);
3236 if (result != ISC_R_SUCCESS) {
3237 goto cleanup;
3238 }
3239
3240 /*
3241 * Is this name visible in the zone?
3242 */
3243 if (!dns_name_issubdomain(name, &zone->origin) ||
3244 (dns_name_countlabels(bottom) > 0 &&
3245 dns_name_issubdomain(name, bottom)))
3246 {
3247 goto next;
3248 }
3249
3250 /*
3251 * Don't check the NS records at the origin.
3252 */
3253 if (dns_name_equal(name, &zone->origin)) {
3254 goto checkfordname;
3255 }
3256
3257 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ns,
3258 0, 0, &rdataset, NULL);
3259 if (result != ISC_R_SUCCESS) {
3260 goto checkfordname;
3261 }
3262 /*
3263 * Remember bottom of zone due to NS.
3264 */
3265 dns_name_copynf(name, bottom);
3266
3267 result = dns_rdataset_first(&rdataset);
3268 while (result == ISC_R_SUCCESS) {
3269 dns_rdataset_current(&rdataset, &rdata);
3270 result = dns_rdata_tostruct(&rdata, &ns, NULL);
3271 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3272 if (!zone_check_glue(zone, db, &ns.name, name)) {
3273 ok = false;
3274 }
3275 dns_rdata_reset(&rdata);
3276 result = dns_rdataset_next(&rdataset);
3277 }
3278 dns_rdataset_disassociate(&rdataset);
3279 goto next;
3280
3281 checkfordname:
3282 result = dns_db_findrdataset(db, node, NULL,
3283 dns_rdatatype_dname, 0, 0,
3284 &rdataset, NULL);
3285 if (result == ISC_R_SUCCESS) {
3286 /*
3287 * Remember bottom of zone due to DNAME.
3288 */
3289 dns_name_copynf(name, bottom);
3290 dns_rdataset_disassociate(&rdataset);
3291 }
3292
3293 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_mx,
3294 0, 0, &rdataset, NULL);
3295 if (result != ISC_R_SUCCESS) {
3296 goto checksrv;
3297 }
3298 result = dns_rdataset_first(&rdataset);
3299 while (result == ISC_R_SUCCESS) {
3300 dns_rdataset_current(&rdataset, &rdata);
3301 result = dns_rdata_tostruct(&rdata, &mx, NULL);
3302 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3303 if (!zone_check_mx(zone, db, &mx.mx, name)) {
3304 ok = false;
3305 }
3306 dns_rdata_reset(&rdata);
3307 result = dns_rdataset_next(&rdataset);
3308 }
3309 dns_rdataset_disassociate(&rdataset);
3310
3311 checksrv:
3312 if (zone->rdclass != dns_rdataclass_in) {
3313 goto next;
3314 }
3315 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_srv,
3316 0, 0, &rdataset, NULL);
3317 if (result != ISC_R_SUCCESS) {
3318 goto checkspf;
3319 }
3320 result = dns_rdataset_first(&rdataset);
3321 while (result == ISC_R_SUCCESS) {
3322 dns_rdataset_current(&rdataset, &rdata);
3323 result = dns_rdata_tostruct(&rdata, &srv, NULL);
3324 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3325 if (!zone_check_srv(zone, db, &srv.target, name)) {
3326 ok = false;
3327 }
3328 dns_rdata_reset(&rdata);
3329 result = dns_rdataset_next(&rdataset);
3330 }
3331 dns_rdataset_disassociate(&rdataset);
3332
3333 checkspf:
3334 /*
3335 * Check if there is a type SPF record without an
3336 * SPF-formatted type TXT record also being present.
3337 */
3338 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSPF)) {
3339 goto next;
3340 }
3341 if (zone->rdclass != dns_rdataclass_in) {
3342 goto next;
3343 }
3344 have_spf = have_txt = false;
3345 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_spf,
3346 0, 0, &rdataset, NULL);
3347 if (result == ISC_R_SUCCESS) {
3348 dns_rdataset_disassociate(&rdataset);
3349 have_spf = true;
3350 }
3351 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_txt,
3352 0, 0, &rdataset, NULL);
3353 if (result != ISC_R_SUCCESS) {
3354 goto notxt;
3355 }
3356 result = dns_rdataset_first(&rdataset);
3357 while (result == ISC_R_SUCCESS) {
3358 dns_rdataset_current(&rdataset, &rdata);
3359 have_txt = isspf(&rdata);
3360 dns_rdata_reset(&rdata);
3361 if (have_txt) {
3362 break;
3363 }
3364 result = dns_rdataset_next(&rdataset);
3365 }
3366 dns_rdataset_disassociate(&rdataset);
3367
3368 notxt:
3369 if (have_spf && !have_txt) {
3370 char namebuf[DNS_NAME_FORMATSIZE];
3371
3372 dns_name_format(name, namebuf, sizeof(namebuf));
3373 dns_zone_log(zone, ISC_LOG_WARNING,
3374 "'%s' found type "
3375 "SPF record but no SPF TXT record found, "
3376 "add matching type TXT record",
3377 namebuf);
3378 }
3379
3380 next:
3381 dns_db_detachnode(db, &node);
3382 result = dns_dbiterator_next(dbiterator);
3383 }
3384
3385 cleanup:
3386 if (node != NULL) {
3387 dns_db_detachnode(db, &node);
3388 }
3389 dns_dbiterator_destroy(&dbiterator);
3390
3391 return (ok);
3392 }
3393
3394 /*
3395 * OpenSSL verification of RSA keys with exponent 3 is known to be
3396 * broken prior OpenSSL 0.9.8c/0.9.7k. Look for such keys and warn
3397 * if they are in use.
3398 */
3399 static void
3400 zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
3401 dns_dbnode_t *node = NULL;
3402 dns_dbversion_t *version = NULL;
3403 dns_rdata_dnskey_t dnskey;
3404 dns_rdata_t rdata = DNS_RDATA_INIT;
3405 dns_rdataset_t rdataset;
3406 isc_result_t result;
3407
3408 result = dns_db_findnode(db, &zone->origin, false, &node);
3409 if (result != ISC_R_SUCCESS) {
3410 goto cleanup;
3411 }
3412
3413 dns_db_currentversion(db, &version);
3414 dns_rdataset_init(&rdataset);
3415 result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
3416 dns_rdatatype_none, 0, &rdataset, NULL);
3417 if (result != ISC_R_SUCCESS) {
3418 goto cleanup;
3419 }
3420
3421 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
3422 result = dns_rdataset_next(&rdataset))
3423 {
3424 dns_rdataset_current(&rdataset, &rdata);
3425 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
3426 INSIST(result == ISC_R_SUCCESS);
3427
3428 /* RFC 3110, section 4: Performance Considerations:
3429 *
3430 * A public exponent of 3 minimizes the effort needed to verify
3431 * a signature. Use of 3 as the public exponent is weak for
3432 * confidentiality uses since, if the same data can be collected
3433 * encrypted under three different keys with an exponent of 3
3434 * then, using the Chinese Remainder Theorem [NETSEC], the
3435 * original plain text can be easily recovered. If a key is
3436 * known to be used only for authentication, as is the case with
3437 * DNSSEC, then an exponent of 3 is acceptable. However other
3438 * applications in the future may wish to leverage DNS
3439 * distributed keys for applications that do require
3440 * confidentiality. For keys which might have such other uses,
3441 * a more conservative choice would be 65537 (F4, the fourth
3442 * fermat number).
3443 */
3444 if (dnskey.datalen > 1 && dnskey.data[0] == 1 &&
3445 dnskey.data[1] == 3) {
3446 const char *algorithm = "";
3447 isc_region_t r;
3448 bool logit = true;
3449
3450 dns_rdata_toregion(&rdata, &r);
3451
3452 switch (dnskey.algorithm) {
3453 case DNS_KEYALG_RSAMD5:
3454 algorithm = "RSAMD5";
3455 break;
3456 case DNS_KEYALG_RSASHA1:
3457 algorithm = "RSASHA1";
3458 break;
3459 case DNS_KEYALG_NSEC3RSASHA1:
3460 algorithm = "NSEC3RSASHA1";
3461 break;
3462 case DNS_KEYALG_RSASHA256:
3463 algorithm = "RSASHA236";
3464 break;
3465 case DNS_KEYALG_RSASHA512:
3466 algorithm = "RSASHA512";
3467 break;
3468 default:
3469 logit = false;
3470 break;
3471 }
3472
3473 if (logit) {
3474 dnssec_log(zone, ISC_LOG_WARNING,
3475 "weak %s (%u) key found "
3476 "(exponent=3, id=%u)",
3477 algorithm, dnskey.algorithm,
3478 dst_region_computeid(&r));
3479 }
3480 }
3481 dns_rdata_reset(&rdata);
3482 }
3483 dns_rdataset_disassociate(&rdataset);
3484
3485 cleanup:
3486 if (node != NULL) {
3487 dns_db_detachnode(db, &node);
3488 }
3489 if (version != NULL) {
3490 dns_db_closeversion(db, &version, false);
3491 }
3492 }
3493
3494 static void
3495 resume_signingwithkey(dns_zone_t *zone) {
3496 dns_dbnode_t *node = NULL;
3497 dns_dbversion_t *version = NULL;
3498 dns_rdata_t rdata = DNS_RDATA_INIT;
3499 dns_rdataset_t rdataset;
3500 isc_result_t result;
3501 dns_db_t *db = NULL;
3502
3503 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3504 if (zone->db != NULL) {
3505 dns_db_attach(zone->db, &db);
3506 }
3507 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3508 if (db == NULL) {
3509 goto cleanup;
3510 }
3511
3512 result = dns_db_findnode(db, &zone->origin, false, &node);
3513 if (result != ISC_R_SUCCESS) {
3514 goto cleanup;
3515 }
3516
3517 dns_db_currentversion(db, &version);
3518 dns_rdataset_init(&rdataset);
3519 result = dns_db_findrdataset(db, node, version, zone->privatetype,
3520 dns_rdatatype_none, 0, &rdataset, NULL);
3521 if (result != ISC_R_SUCCESS) {
3522 INSIST(!dns_rdataset_isassociated(&rdataset));
3523 goto cleanup;
3524 }
3525
3526 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
3527 result = dns_rdataset_next(&rdataset))
3528 {
3529 dns_rdataset_current(&rdataset, &rdata);
3530 if (rdata.length != 5 || rdata.data[0] == 0 ||
3531 rdata.data[4] != 0) {
3532 dns_rdata_reset(&rdata);
3533 continue;
3534 }
3535
3536 result = zone_signwithkey(zone, rdata.data[0],
3537 (rdata.data[1] << 8) | rdata.data[2],
3538 rdata.data[3]);
3539 if (result != ISC_R_SUCCESS) {
3540 dnssec_log(zone, ISC_LOG_ERROR,
3541 "zone_signwithkey failed: %s",
3542 dns_result_totext(result));
3543 }
3544 dns_rdata_reset(&rdata);
3545 }
3546 dns_rdataset_disassociate(&rdataset);
3547
3548 cleanup:
3549 if (db != NULL) {
3550 if (node != NULL) {
3551 dns_db_detachnode(db, &node);
3552 }
3553 if (version != NULL) {
3554 dns_db_closeversion(db, &version, false);
3555 }
3556 dns_db_detach(&db);
3557 }
3558 }
3559
3560 /*
3561 * Initiate adding/removing NSEC3 records belonging to the chain defined by the
3562 * supplied NSEC3PARAM RDATA.
3563 *
3564 * Zone must be locked by caller.
3565 */
3566 static isc_result_t
3567 zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
3568 dns_nsec3chain_t *nsec3chain, *current;
3569 dns_dbversion_t *version = NULL;
3570 bool nseconly = false, nsec3ok = false;
3571 isc_result_t result;
3572 isc_time_t now;
3573 unsigned int options = 0;
3574 char saltbuf[255 * 2 + 1];
3575 char flags[sizeof("INITIAL|REMOVE|CREATE|NONSEC|OPTOUT")];
3576 dns_db_t *db = NULL;
3577
3578 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3579 if (zone->db != NULL) {
3580 dns_db_attach(zone->db, &db);
3581 }
3582 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3583
3584 if (db == NULL) {
3585 result = ISC_R_SUCCESS;
3586 goto cleanup;
3587 }
3588
3589 /*
3590 * If this zone is not NSEC3-capable, attempting to remove any NSEC3
3591 * chain from it is pointless as it would not be possible for the
3592 * latter to exist in the first place.
3593 */
3594 dns_db_currentversion(db, &version);
3595 result = dns_nsec_nseconly(db, version, &nseconly);
3596 nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
3597 dns_db_closeversion(db, &version, false);
3598 if (!nsec3ok && (nsec3param->flags & DNS_NSEC3FLAG_REMOVE) == 0) {
3599 result = ISC_R_SUCCESS;
3600 goto cleanup;
3601 }
3602
3603 /*
3604 * Allocate and initialize structure preserving state of
3605 * adding/removing records belonging to this NSEC3 chain between
3606 * separate zone_nsec3chain() calls.
3607 */
3608 nsec3chain = isc_mem_get(zone->mctx, sizeof *nsec3chain);
3609
3610 nsec3chain->magic = 0;
3611 nsec3chain->done = false;
3612 nsec3chain->db = NULL;
3613 nsec3chain->dbiterator = NULL;
3614 nsec3chain->nsec3param.common.rdclass = nsec3param->common.rdclass;
3615 nsec3chain->nsec3param.common.rdtype = nsec3param->common.rdtype;
3616 nsec3chain->nsec3param.hash = nsec3param->hash;
3617 nsec3chain->nsec3param.iterations = nsec3param->iterations;
3618 nsec3chain->nsec3param.flags = nsec3param->flags;
3619 nsec3chain->nsec3param.salt_length = nsec3param->salt_length;
3620 memmove(nsec3chain->salt, nsec3param->salt, nsec3param->salt_length);
3621 nsec3chain->nsec3param.salt = nsec3chain->salt;
3622 nsec3chain->seen_nsec = false;
3623 nsec3chain->delete_nsec = false;
3624 nsec3chain->save_delete_nsec = false;
3625
3626 /*
3627 * Log NSEC3 parameters defined by supplied NSEC3PARAM RDATA.
3628 */
3629 if (nsec3param->flags == 0) {
3630 strlcpy(flags, "NONE", sizeof(flags));
3631 } else {
3632 flags[0] = '\0';
3633 if ((nsec3param->flags & DNS_NSEC3FLAG_REMOVE) != 0) {
3634 strlcat(flags, "REMOVE", sizeof(flags));
3635 }
3636 if ((nsec3param->flags & DNS_NSEC3FLAG_INITIAL) != 0) {
3637 if (flags[0] == '\0') {
3638 strlcpy(flags, "INITIAL", sizeof(flags));
3639 } else {
3640 strlcat(flags, "|INITIAL", sizeof(flags));
3641 }
3642 }
3643 if ((nsec3param->flags & DNS_NSEC3FLAG_CREATE) != 0) {
3644 if (flags[0] == '\0') {
3645 strlcpy(flags, "CREATE", sizeof(flags));
3646 } else {
3647 strlcat(flags, "|CREATE", sizeof(flags));
3648 }
3649 }
3650 if ((nsec3param->flags & DNS_NSEC3FLAG_NONSEC) != 0) {
3651 if (flags[0] == '\0') {
3652 strlcpy(flags, "NONSEC", sizeof(flags));
3653 } else {
3654 strlcat(flags, "|NONSEC", sizeof(flags));
3655 }
3656 }
3657 if ((nsec3param->flags & DNS_NSEC3FLAG_OPTOUT) != 0) {
3658 if (flags[0] == '\0') {
3659 strlcpy(flags, "OPTOUT", sizeof(flags));
3660 } else {
3661 strlcat(flags, "|OPTOUT", sizeof(flags));
3662 }
3663 }
3664 }
3665 result = dns_nsec3param_salttotext(nsec3param, saltbuf,
3666 sizeof(saltbuf));
3667 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3668 dnssec_log(zone, ISC_LOG_INFO, "zone_addnsec3chain(%u,%s,%u,%s)",
3669 nsec3param->hash, flags, nsec3param->iterations, saltbuf);
3670
3671 /*
3672 * If the NSEC3 chain defined by the supplied NSEC3PARAM RDATA is
3673 * currently being processed, interrupt its processing to avoid
3674 * simultaneously adding and removing records for the same NSEC3 chain.
3675 */
3676 for (current = ISC_LIST_HEAD(zone->nsec3chain); current != NULL;
3677 current = ISC_LIST_NEXT(current, link))
3678 {
3679 if ((current->db == db) &&
3680 (current->nsec3param.hash == nsec3param->hash) &&
3681 (current->nsec3param.iterations ==
3682 nsec3param->iterations) &&
3683 (current->nsec3param.salt_length ==
3684 nsec3param->salt_length) &&
3685 memcmp(current->nsec3param.salt, nsec3param->salt,
3686 nsec3param->salt_length) == 0)
3687 {
3688 current->done = true;
3689 }
3690 }
3691
3692 /*
3693 * Attach zone database to the structure initialized above and create
3694 * an iterator for it with appropriate options in order to avoid
3695 * creating NSEC3 records for NSEC3 records.
3696 */
3697 dns_db_attach(db, &nsec3chain->db);
3698 if ((nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0) {
3699 options = DNS_DB_NONSEC3;
3700 }
3701 result = dns_db_createiterator(nsec3chain->db, options,
3702 &nsec3chain->dbiterator);
3703 if (result == ISC_R_SUCCESS) {
3704 result = dns_dbiterator_first(nsec3chain->dbiterator);
3705 }
3706 if (result == ISC_R_SUCCESS) {
3707 /*
3708 * Database iterator initialization succeeded. We are now
3709 * ready to kick off adding/removing records belonging to this
3710 * NSEC3 chain. Append the structure initialized above to the
3711 * "nsec3chain" list for the zone and set the appropriate zone
3712 * timer so that zone_nsec3chain() is called as soon as
3713 * possible.
3714 */
3715 dns_dbiterator_pause(nsec3chain->dbiterator);
3716 ISC_LIST_INITANDAPPEND(zone->nsec3chain, nsec3chain, link);
3717 nsec3chain = NULL;
3718 if (isc_time_isepoch(&zone->nsec3chaintime)) {
3719 TIME_NOW(&now);
3720 zone->nsec3chaintime = now;
3721 if (zone->task != NULL) {
3722 zone_settimer(zone, &now);
3723 }
3724 }
3725 }
3726
3727 if (nsec3chain != NULL) {
3728 if (nsec3chain->db != NULL) {
3729 dns_db_detach(&nsec3chain->db);
3730 }
3731 if (nsec3chain->dbiterator != NULL) {
3732 dns_dbiterator_destroy(&nsec3chain->dbiterator);
3733 }
3734 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
3735 }
3736
3737 cleanup:
3738 if (db != NULL) {
3739 dns_db_detach(&db);
3740 }
3741 return (result);
3742 }
3743
3744 /*
3745 * Find private-type records at the zone apex which signal that an NSEC3 chain
3746 * should be added or removed. For each such record, extract NSEC3PARAM RDATA
3747 * and pass it to zone_addnsec3chain().
3748 *
3749 * Zone must be locked by caller.
3750 */
3751 static void
3752 resume_addnsec3chain(dns_zone_t *zone) {
3753 dns_dbnode_t *node = NULL;
3754 dns_dbversion_t *version = NULL;
3755 dns_rdataset_t rdataset;
3756 isc_result_t result;
3757 dns_rdata_nsec3param_t nsec3param;
3758 bool nseconly = false, nsec3ok = false;
3759 dns_db_t *db = NULL;
3760
3761 INSIST(LOCKED_ZONE(zone));
3762
3763 if (zone->privatetype == 0) {
3764 return;
3765 }
3766
3767 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3768 if (zone->db != NULL) {
3769 dns_db_attach(zone->db, &db);
3770 }
3771 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3772 if (db == NULL) {
3773 goto cleanup;
3774 }
3775
3776 result = dns_db_findnode(db, &zone->origin, false, &node);
3777 if (result != ISC_R_SUCCESS) {
3778 goto cleanup;
3779 }
3780
3781 dns_db_currentversion(db, &version);
3782
3783 /*
3784 * In order to create NSEC3 chains we need the DNSKEY RRset at zone
3785 * apex to exist and contain no keys using NSEC-only algorithms.
3786 */
3787 result = dns_nsec_nseconly(db, version, &nseconly);
3788 nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
3789
3790 /*
3791 * Get the RRset containing all private-type records at the zone apex.
3792 */
3793 dns_rdataset_init(&rdataset);
3794 result = dns_db_findrdataset(db, node, version, zone->privatetype,
3795 dns_rdatatype_none, 0, &rdataset, NULL);
3796 if (result != ISC_R_SUCCESS) {
3797 INSIST(!dns_rdataset_isassociated(&rdataset));
3798 goto cleanup;
3799 }
3800
3801 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
3802 result = dns_rdataset_next(&rdataset))
3803 {
3804 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
3805 dns_rdata_t rdata = DNS_RDATA_INIT;
3806 dns_rdata_t private = DNS_RDATA_INIT;
3807
3808 dns_rdataset_current(&rdataset, &private);
3809 /*
3810 * Try extracting NSEC3PARAM RDATA from this private-type
3811 * record. Failure means this private-type record does not
3812 * represent an NSEC3PARAM record, so skip it.
3813 */
3814 if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
3815 sizeof(buf))) {
3816 continue;
3817 }
3818 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
3819 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3820 if (((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) ||
3821 ((nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0 && nsec3ok))
3822 {
3823 /*
3824 * Pass the NSEC3PARAM RDATA contained in this
3825 * private-type record to zone_addnsec3chain() so that
3826 * it can kick off adding or removing NSEC3 records.
3827 */
3828 result = zone_addnsec3chain(zone, &nsec3param);
3829 if (result != ISC_R_SUCCESS) {
3830 dnssec_log(zone, ISC_LOG_ERROR,
3831 "zone_addnsec3chain failed: %s",
3832 dns_result_totext(result));
3833 }
3834 }
3835 }
3836 dns_rdataset_disassociate(&rdataset);
3837
3838 cleanup:
3839 if (db != NULL) {
3840 if (node != NULL) {
3841 dns_db_detachnode(db, &node);
3842 }
3843 if (version != NULL) {
3844 dns_db_closeversion(db, &version, false);
3845 }
3846 dns_db_detach(&db);
3847 }
3848 }
3849
3850 static void
3851 set_resigntime(dns_zone_t *zone) {
3852 dns_rdataset_t rdataset;
3853 dns_fixedname_t fixed;
3854 unsigned int resign;
3855 isc_result_t result;
3856 uint32_t nanosecs;
3857 dns_db_t *db = NULL;
3858
3859 INSIST(LOCKED_ZONE(zone));
3860
3861 /* We only re-sign zones that can be dynamically updated */
3862 if (zone->update_disabled) {
3863 return;
3864 }
3865
3866 if (!inline_secure(zone) &&
3867 (zone->type != dns_zone_master ||
3868 (zone->ssutable == NULL &&
3869 (zone->update_acl == NULL || dns_acl_isnone(zone->update_acl)))))
3870 {
3871 return;
3872 }
3873
3874 dns_rdataset_init(&rdataset);
3875 dns_fixedname_init(&fixed);
3876
3877 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3878 if (zone->db != NULL) {
3879 dns_db_attach(zone->db, &db);
3880 }
3881 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3882 if (db == NULL) {
3883 isc_time_settoepoch(&zone->resigntime);
3884 return;
3885 }
3886
3887 result = dns_db_getsigningtime(db, &rdataset,
3888 dns_fixedname_name(&fixed));
3889 if (result != ISC_R_SUCCESS) {
3890 isc_time_settoepoch(&zone->resigntime);
3891 goto cleanup;
3892 }
3893
3894 resign = rdataset.resign - dns_zone_getsigresigninginterval(zone);
3895 dns_rdataset_disassociate(&rdataset);
3896 nanosecs = isc_random_uniform(1000000000);
3897 isc_time_set(&zone->resigntime, resign, nanosecs);
3898
3899 cleanup:
3900 dns_db_detach(&db);
3901 return;
3902 }
3903
3904 static isc_result_t
3905 check_nsec3param(dns_zone_t *zone, dns_db_t *db) {
3906 dns_dbnode_t *node = NULL;
3907 dns_rdataset_t rdataset;
3908 dns_dbversion_t *version = NULL;
3909 dns_rdata_nsec3param_t nsec3param;
3910 bool ok = false;
3911 isc_result_t result;
3912 dns_rdata_t rdata = DNS_RDATA_INIT;
3913 bool dynamic = (zone->type == dns_zone_master)
3914 ? dns_zone_isdynamic(zone, false)
3915 : false;
3916
3917 dns_rdataset_init(&rdataset);
3918 result = dns_db_findnode(db, &zone->origin, false, &node);
3919 if (result != ISC_R_SUCCESS) {
3920 dns_zone_log(zone, ISC_LOG_ERROR,
3921 "nsec3param lookup failure: %s",
3922 dns_result_totext(result));
3923 return (result);
3924 }
3925 dns_db_currentversion(db, &version);
3926
3927 result = dns_db_findrdataset(db, node, version,
3928 dns_rdatatype_nsec3param,
3929 dns_rdatatype_none, 0, &rdataset, NULL);
3930 if (result == ISC_R_NOTFOUND) {
3931 INSIST(!dns_rdataset_isassociated(&rdataset));
3932 result = ISC_R_SUCCESS;
3933 goto cleanup;
3934 }
3935 if (result != ISC_R_SUCCESS) {
3936 INSIST(!dns_rdataset_isassociated(&rdataset));
3937 dns_zone_log(zone, ISC_LOG_ERROR,
3938 "nsec3param lookup failure: %s",
3939 dns_result_totext(result));
3940 goto cleanup;
3941 }
3942
3943 /*
3944 * For dynamic zones we must support every algorithm so we can
3945 * regenerate all the NSEC3 chains.
3946 * For non-dynamic zones we only need to find a supported algorithm.
3947 */
3948 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
3949 result = dns_rdataset_next(&rdataset))
3950 {
3951 dns_rdataset_current(&rdataset, &rdata);
3952 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
3953 dns_rdata_reset(&rdata);
3954 INSIST(result == ISC_R_SUCCESS);
3955 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NSEC3TESTZONE) &&
3956 nsec3param.hash == DNS_NSEC3_UNKNOWNALG && !dynamic)
3957 {
3958 dns_zone_log(zone, ISC_LOG_WARNING,
3959 "nsec3 test \"unknown\" hash algorithm "
3960 "found: %u",
3961 nsec3param.hash);
3962 ok = true;
3963 } else if (!dns_nsec3_supportedhash(nsec3param.hash)) {
3964 if (dynamic) {
3965 dns_zone_log(zone, ISC_LOG_ERROR,
3966 "unsupported nsec3 hash algorithm"
3967 " in dynamic zone: %u",
3968 nsec3param.hash);
3969 result = DNS_R_BADZONE;
3970 /* Stop second error message. */
3971 ok = true;
3972 break;
3973 } else {
3974 dns_zone_log(zone, ISC_LOG_WARNING,
3975 "unsupported nsec3 hash "
3976 "algorithm: %u",
3977 nsec3param.hash);
3978 }
3979 } else {
3980 ok = true;
3981 }
3982 }
3983 if (result == ISC_R_NOMORE) {
3984 result = ISC_R_SUCCESS;
3985 }
3986
3987 if (!ok) {
3988 result = DNS_R_BADZONE;
3989 dns_zone_log(zone, ISC_LOG_ERROR,
3990 "no supported nsec3 hash algorithm");
3991 }
3992
3993 cleanup:
3994 if (dns_rdataset_isassociated(&rdataset)) {
3995 dns_rdataset_disassociate(&rdataset);
3996 }
3997 dns_db_closeversion(db, &version, false);
3998 dns_db_detachnode(db, &node);
3999 return (result);
4000 }
4001
4002 /*
4003 * Set the timer for refreshing the key zone to the soonest future time
4004 * of the set (current timer, keydata->refresh, keydata->addhd,
4005 * keydata->removehd).
4006 */
4007 static void
4008 set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key,
4009 isc_stdtime_t now, bool force) {
4010 const char me[] = "set_refreshkeytimer";
4011 isc_stdtime_t then;
4012 isc_time_t timenow, timethen;
4013 char timebuf[80];
4014
4015 ENTER;
4016 then = key->refresh;
4017 if (force) {
4018 then = now;
4019 }
4020 if (key->addhd > now && key->addhd < then) {
4021 then = key->addhd;
4022 }
4023 if (key->removehd > now && key->removehd < then) {
4024 then = key->removehd;
4025 }
4026
4027 TIME_NOW(&timenow);
4028 if (then > now) {
4029 DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
4030 } else {
4031 timethen = timenow;
4032 }
4033 if (isc_time_compare(&zone->refreshkeytime, &timenow) < 0 ||
4034 isc_time_compare(&timethen, &zone->refreshkeytime) < 0)
4035 {
4036 zone->refreshkeytime = timethen;
4037 }
4038
4039 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
4040 dns_zone_log(zone, ISC_LOG_DEBUG(1), "next key refresh: %s", timebuf);
4041 zone_settimer(zone, &timenow);
4042 }
4043
4044 /*
4045 * If keynode references a key or a DS rdataset, and if the key
4046 * zone does not contain a KEYDATA record for the corresponding name,
4047 * then create an empty KEYDATA and push it into the zone as a placeholder,
4048 * then schedule a key refresh immediately. This new KEYDATA record will be
4049 * updated during the refresh.
4050 *
4051 * If the key zone is changed, set '*changed' to true.
4052 */
4053 static isc_result_t
4054 create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
4055 dns_diff_t *diff, dns_keynode_t *keynode, dns_name_t *keyname,
4056 bool *changed) {
4057 const char me[] = "create_keydata";
4058 isc_result_t result = ISC_R_SUCCESS;
4059 dns_rdata_t rdata = DNS_RDATA_INIT;
4060 dns_rdata_keydata_t kd;
4061 unsigned char rrdata[4096];
4062 isc_buffer_t rrdatabuf;
4063 isc_stdtime_t now;
4064
4065 REQUIRE(keynode != NULL);
4066
4067 ENTER;
4068 isc_stdtime_get(&now);
4069
4070 /*
4071 * If the keynode has no trust anchor set, we shouldn't be here.
4072 */
4073 if (!dns_keynode_dsset(keynode, NULL)) {
4074 return (ISC_R_FAILURE);
4075 }
4076
4077 memset(&kd, 0, sizeof(kd));
4078 kd.common.rdclass = zone->rdclass;
4079 kd.common.rdtype = dns_rdatatype_keydata;
4080 ISC_LINK_INIT(&kd.common, link);
4081
4082 isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
4083
4084 CHECK(dns_rdata_fromstruct(&rdata, zone->rdclass, dns_rdatatype_keydata,
4085 &kd, &rrdatabuf));
4086 /* Add rdata to zone. */
4087 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, keyname, 0, &rdata));
4088 *changed = true;
4089
4090 /* Refresh new keys from the zone apex as soon as possible. */
4091 set_refreshkeytimer(zone, &kd, now, true);
4092 return (ISC_R_SUCCESS);
4093
4094 failure:
4095 return (result);
4096 }
4097
4098 /*
4099 * Remove from the key zone all the KEYDATA records found in rdataset.
4100 */
4101 static isc_result_t
4102 delete_keydata(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
4103 dns_name_t *name, dns_rdataset_t *rdataset) {
4104 dns_rdata_t rdata = DNS_RDATA_INIT;
4105 isc_result_t result, uresult;
4106
4107 for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
4108 result = dns_rdataset_next(rdataset))
4109 {
4110 dns_rdata_reset(&rdata);
4111 dns_rdataset_current(rdataset, &rdata);
4112 uresult = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name, 0,
4113 &rdata);
4114 if (uresult != ISC_R_SUCCESS) {
4115 return (uresult);
4116 }
4117 }
4118 if (result == ISC_R_NOMORE) {
4119 result = ISC_R_SUCCESS;
4120 }
4121 return (result);
4122 }
4123
4124 /*
4125 * Compute the DNSSEC key ID for a DNSKEY record.
4126 */
4127 static isc_result_t
4128 compute_tag(dns_name_t *name, dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx,
4129 dns_keytag_t *tag) {
4130 isc_result_t result;
4131 dns_rdata_t rdata = DNS_RDATA_INIT;
4132 unsigned char data[4096];
4133 isc_buffer_t buffer;
4134 dst_key_t *dstkey = NULL;
4135
4136 isc_buffer_init(&buffer, data, sizeof(data));
4137 dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
4138 dns_rdatatype_dnskey, dnskey, &buffer);
4139
4140 result = dns_dnssec_keyfromrdata(name, &rdata, mctx, &dstkey);
4141 if (result == ISC_R_SUCCESS) {
4142 *tag = dst_key_id(dstkey);
4143 dst_key_free(&dstkey);
4144 }
4145
4146 return (result);
4147 }
4148
4149 /*
4150 * Add key to the security roots.
4151 */
4152 static void
4153 trust_key(dns_zone_t *zone, dns_name_t *keyname, dns_rdata_dnskey_t *dnskey,
4154 bool initial) {
4155 isc_result_t result;
4156 dns_rdata_t rdata = DNS_RDATA_INIT;
4157 unsigned char data[4096], digest[ISC_MAX_MD_SIZE];
4158 isc_buffer_t buffer;
4159 dns_keytable_t *sr = NULL;
4160 dns_rdata_ds_t ds;
4161
4162 result = dns_view_getsecroots(zone->view, &sr);
4163 if (result != ISC_R_SUCCESS) {
4164 return;
4165 }
4166
4167 /* Build DS record for key. */
4168 isc_buffer_init(&buffer, data, sizeof(data));
4169 dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
4170 dns_rdatatype_dnskey, dnskey, &buffer);
4171 CHECK(dns_ds_fromkeyrdata(keyname, &rdata, DNS_DSDIGEST_SHA256, digest,
4172 &ds));
4173 CHECK(dns_keytable_add(sr, true, initial, keyname, &ds));
4174
4175 dns_keytable_detach(&sr);
4176
4177 failure:
4178 if (sr != NULL) {
4179 dns_keytable_detach(&sr);
4180 }
4181 return;
4182 }
4183
4184 /*
4185 * Add a null key to the security roots for so that all queries
4186 * to the zone will fail.
4187 */
4188 static void
4189 fail_secure(dns_zone_t *zone, dns_name_t *keyname) {
4190 isc_result_t result;
4191 dns_keytable_t *sr = NULL;
4192
4193 result = dns_view_getsecroots(zone->view, &sr);
4194 if (result == ISC_R_SUCCESS) {
4195 dns_keytable_marksecure(sr, keyname);
4196 dns_keytable_detach(&sr);
4197 }
4198 }
4199
4200 /*
4201 * Scan a set of KEYDATA records from the key zone. The ones that are
4202 * valid (i.e., the add holddown timer has expired) become trusted keys.
4203 */
4204 static void
4205 load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
4206 isc_result_t result;
4207 dns_rdata_t rdata = DNS_RDATA_INIT;
4208 dns_rdata_keydata_t keydata;
4209 dns_rdata_dnskey_t dnskey;
4210 int trusted = 0, revoked = 0, pending = 0;
4211 isc_stdtime_t now;
4212 dns_keytable_t *sr = NULL;
4213
4214 isc_stdtime_get(&now);
4215
4216 result = dns_view_getsecroots(zone->view, &sr);
4217 if (result == ISC_R_SUCCESS) {
4218 dns_keytable_delete(sr, name);
4219 dns_keytable_detach(&sr);
4220 }
4221
4222 /* Now insert all the accepted trust anchors from this keydata set. */
4223 for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
4224 result = dns_rdataset_next(rdataset))
4225 {
4226 dns_rdata_reset(&rdata);
4227 dns_rdataset_current(rdataset, &rdata);
4228
4229 /* Convert rdata to keydata. */
4230 result = dns_rdata_tostruct(&rdata, &keydata, NULL);
4231 if (result == ISC_R_UNEXPECTEDEND) {
4232 continue;
4233 }
4234 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4235
4236 /* Set the key refresh timer to force a fast refresh. */
4237 set_refreshkeytimer(zone, &keydata, now, true);
4238
4239 /* If the removal timer is nonzero, this key was revoked. */
4240 if (keydata.removehd != 0) {
4241 revoked++;
4242 continue;
4243 }
4244
4245 /*
4246 * If the add timer is still pending, this key is not
4247 * trusted yet.
4248 */
4249 if (now < keydata.addhd) {
4250 pending++;
4251 continue;
4252 }
4253
4254 /* Convert keydata to dnskey. */
4255 dns_keydata_todnskey(&keydata, &dnskey, NULL);
4256
4257 /* Add to keytables. */
4258 trusted++;
4259 trust_key(zone, name, &dnskey, (keydata.addhd == 0));
4260 }
4261
4262 if (trusted == 0 && pending != 0) {
4263 char namebuf[DNS_NAME_FORMATSIZE];
4264 dns_name_format(name, namebuf, sizeof namebuf);
4265 dnssec_log(zone, ISC_LOG_ERROR,
4266 "No valid trust anchors for '%s'!", namebuf);
4267 dnssec_log(zone, ISC_LOG_ERROR,
4268 "%d key(s) revoked, %d still pending", revoked,
4269 pending);
4270 dnssec_log(zone, ISC_LOG_ERROR, "All queries to '%s' will fail",
4271 namebuf);
4272 fail_secure(zone, name);
4273 }
4274 }
4275
4276 static isc_result_t
4277 do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
4278 dns_diff_t *diff) {
4279 dns_diff_t temp_diff;
4280 isc_result_t result;
4281
4282 /*
4283 * Create a singleton diff.
4284 */
4285 dns_diff_init(diff->mctx, &temp_diff);
4286 ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
4287
4288 /*
4289 * Apply it to the database.
4290 */
4291 result = dns_diff_apply(&temp_diff, db, ver);
4292 ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
4293 if (result != ISC_R_SUCCESS) {
4294 dns_difftuple_free(tuple);
4295 return (result);
4296 }
4297
4298 /*
4299 * Merge it into the current pending journal entry.
4300 */
4301 dns_diff_appendminimal(diff, tuple);
4302
4303 /*
4304 * Do not clear temp_diff.
4305 */
4306 return (ISC_R_SUCCESS);
4307 }
4308
4309 static isc_result_t
4310 update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
4311 dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
4312 dns_rdata_t *rdata) {
4313 dns_difftuple_t *tuple = NULL;
4314 isc_result_t result;
4315 result = dns_difftuple_create(diff->mctx, op, name, ttl, rdata, &tuple);
4316 if (result != ISC_R_SUCCESS) {
4317 return (result);
4318 }
4319 return (do_one_tuple(&tuple, db, ver, diff));
4320 }
4321
4322 static isc_result_t
4323 update_soa_serial(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
4324 dns_diff_t *diff, isc_mem_t *mctx,
4325 dns_updatemethod_t method) {
4326 dns_difftuple_t *deltuple = NULL;
4327 dns_difftuple_t *addtuple = NULL;
4328 uint32_t serial;
4329 isc_result_t result;
4330 dns_updatemethod_t used = dns_updatemethod_none;
4331
4332 INSIST(method != dns_updatemethod_none);
4333
4334 CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple));
4335 CHECK(dns_difftuple_copy(deltuple, &addtuple));
4336 addtuple->op = DNS_DIFFOP_ADD;
4337
4338 serial = dns_soa_getserial(&addtuple->rdata);
4339 serial = dns_update_soaserial(serial, method, &used);
4340 if (method != used) {
4341 dns_zone_log(zone, ISC_LOG_WARNING,
4342 "update_soa_serial:new serial would be lower than "
4343 "old serial, using increment method instead");
4344 }
4345 dns_soa_setserial(serial, &addtuple->rdata);
4346 CHECK(do_one_tuple(&deltuple, db, ver, diff));
4347 CHECK(do_one_tuple(&addtuple, db, ver, diff));
4348 result = ISC_R_SUCCESS;
4349
4350 failure:
4351 if (addtuple != NULL) {
4352 dns_difftuple_free(&addtuple);
4353 }
4354 if (deltuple != NULL) {
4355 dns_difftuple_free(&deltuple);
4356 }
4357 return (result);
4358 }
4359
4360 /*
4361 * Write all transactions in 'diff' to the zone journal file.
4362 */
4363 static isc_result_t
4364 zone_journal(dns_zone_t *zone, dns_diff_t *diff, uint32_t *sourceserial,
4365 const char *caller) {
4366 const char me[] = "zone_journal";
4367 const char *journalfile;
4368 isc_result_t result = ISC_R_SUCCESS;
4369 dns_journal_t *journal = NULL;
4370 unsigned int mode = DNS_JOURNAL_CREATE | DNS_JOURNAL_WRITE;
4371
4372 ENTER;
4373 journalfile = dns_zone_getjournal(zone);
4374 if (journalfile != NULL) {
4375 result = dns_journal_open(zone->mctx, journalfile, mode,
4376 &journal);
4377 if (result != ISC_R_SUCCESS) {
4378 dns_zone_log(zone, ISC_LOG_ERROR,
4379 "%s:dns_journal_open -> %s", caller,
4380 dns_result_totext(result));
4381 return (result);
4382 }
4383
4384 if (sourceserial != NULL) {
4385 dns_journal_set_sourceserial(journal, *sourceserial);
4386 }
4387
4388 result = dns_journal_write_transaction(journal, diff);
4389 if (result != ISC_R_SUCCESS) {
4390 dns_zone_log(zone, ISC_LOG_ERROR,
4391 "%s:dns_journal_write_transaction -> %s",
4392 caller, dns_result_totext(result));
4393 }
4394 dns_journal_destroy(&journal);
4395 }
4396
4397 return (result);
4398 }
4399
4400 /*
4401 * Create an SOA record for a newly-created zone
4402 */
4403 static isc_result_t
4404 add_soa(dns_zone_t *zone, dns_db_t *db) {
4405 isc_result_t result;
4406 dns_rdata_t rdata = DNS_RDATA_INIT;
4407 unsigned char buf[DNS_SOA_BUFFERSIZE];
4408 dns_dbversion_t *ver = NULL;
4409 dns_diff_t diff;
4410
4411 dns_zone_log(zone, ISC_LOG_DEBUG(1), "creating SOA");
4412
4413 dns_diff_init(zone->mctx, &diff);
4414 result = dns_db_newversion(db, &ver);
4415 if (result != ISC_R_SUCCESS) {
4416 dns_zone_log(zone, ISC_LOG_ERROR,
4417 "add_soa:dns_db_newversion -> %s",
4418 dns_result_totext(result));
4419 goto failure;
4420 }
4421
4422 /* Build SOA record */
4423 result = dns_soa_buildrdata(&zone->origin, dns_rootname, zone->rdclass,
4424 0, 0, 0, 0, 0, buf, &rdata);
4425 if (result != ISC_R_SUCCESS) {
4426 dns_zone_log(zone, ISC_LOG_ERROR,
4427 "add_soa:dns_soa_buildrdata -> %s",
4428 dns_result_totext(result));
4429 goto failure;
4430 }
4431
4432 result = update_one_rr(db, ver, &diff, DNS_DIFFOP_ADD, &zone->origin, 0,
4433 &rdata);
4434
4435 failure:
4436 dns_diff_clear(&diff);
4437 if (ver != NULL) {
4438 dns_db_closeversion(db, &ver, (result == ISC_R_SUCCESS));
4439 }
4440
4441 INSIST(ver == NULL);
4442
4443 return (result);
4444 }
4445
4446 struct addifmissing_arg {
4447 dns_db_t *db;
4448 dns_dbversion_t *ver;
4449 dns_diff_t *diff;
4450 dns_zone_t *zone;
4451 bool *changed;
4452 isc_result_t result;
4453 };
4454
4455 static void
4456 addifmissing(dns_keytable_t *keytable, dns_keynode_t *keynode,
4457 dns_name_t *keyname, void *arg) {
4458 dns_db_t *db = ((struct addifmissing_arg *)arg)->db;
4459 dns_dbversion_t *ver = ((struct addifmissing_arg *)arg)->ver;
4460 dns_diff_t *diff = ((struct addifmissing_arg *)arg)->diff;
4461 dns_zone_t *zone = ((struct addifmissing_arg *)arg)->zone;
4462 bool *changed = ((struct addifmissing_arg *)arg)->changed;
4463 isc_result_t result;
4464 dns_fixedname_t fname;
4465
4466 UNUSED(keytable);
4467
4468 if (((struct addifmissing_arg *)arg)->result != ISC_R_SUCCESS) {
4469 return;
4470 }
4471
4472 if (!dns_keynode_managed(keynode)) {
4473 return;
4474 }
4475
4476 /*
4477 * If the keynode has no trust anchor set, return.
4478 */
4479 if (!dns_keynode_dsset(keynode, NULL)) {
4480 return;
4481 }
4482
4483 /*
4484 * Check whether there's already a KEYDATA entry for this name;
4485 * if so, we don't need to add another.
4486 */
4487 dns_fixedname_init(&fname);
4488 result = dns_db_find(db, keyname, ver, dns_rdatatype_keydata,
4489 DNS_DBFIND_NOWILD, 0, NULL,
4490 dns_fixedname_name(&fname), NULL, NULL);
4491 if (result == ISC_R_SUCCESS) {
4492 return;
4493 }
4494
4495 /*
4496 * Create the keydata.
4497 */
4498 result = create_keydata(zone, db, ver, diff, keynode, keyname, changed);
4499 if (result != ISC_R_SUCCESS && result != ISC_R_NOMORE) {
4500 ((struct addifmissing_arg *)arg)->result = result;
4501 }
4502 }
4503
4504 /*
4505 * Synchronize the set of initializing keys found in managed-keys {}
4506 * statements with the set of trust anchors found in the managed-keys.bind
4507 * zone. If a domain is no longer named in managed-keys, delete all keys
4508 * from that domain from the key zone. If a domain is configured as an
4509 * initial-key in trust-anchors, but there are no references to it in the
4510 * key zone, load the key zone with the initializing key(s) for that
4511 * domain and schedule a key refresh. If a domain is configured as
4512 * an initial-ds in trust-anchors, fetch the DNSKEY RRset, load the key
4513 * zone with the matching key, and schedule a key refresh.
4514 */
4515 static isc_result_t
4516 sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
4517 isc_result_t result = ISC_R_SUCCESS;
4518 bool changed = false;
4519 bool commit = false;
4520 dns_keynode_t *keynode = NULL;
4521 dns_view_t *view = zone->view;
4522 dns_keytable_t *sr = NULL;
4523 dns_dbversion_t *ver = NULL;
4524 dns_diff_t diff;
4525 dns_rriterator_t rrit;
4526 struct addifmissing_arg arg;
4527
4528 dns_zone_log(zone, ISC_LOG_DEBUG(1), "synchronizing trusted keys");
4529
4530 dns_diff_init(zone->mctx, &diff);
4531
4532 CHECK(dns_view_getsecroots(view, &sr));
4533
4534 result = dns_db_newversion(db, &ver);
4535 if (result != ISC_R_SUCCESS) {
4536 dnssec_log(zone, ISC_LOG_ERROR,
4537 "sync_keyzone:dns_db_newversion -> %s",
4538 dns_result_totext(result));
4539 goto failure;
4540 }
4541
4542 /*
4543 * Walk the zone DB. If we find any keys whose names are no longer
4544 * in trust-anchors, or which have been changed from initial to static,
4545 * (meaning they are permanent and not RFC5011-maintained), delete
4546 * them from the zone. Otherwise call load_secroots(), which
4547 * loads keys into secroots as appropriate.
4548 */
4549 dns_rriterator_init(&rrit, db, ver, 0);
4550 for (result = dns_rriterator_first(&rrit); result == ISC_R_SUCCESS;
4551 result = dns_rriterator_nextrrset(&rrit))
4552 {
4553 dns_rdataset_t *rdataset = NULL;
4554 dns_name_t *rrname = NULL;
4555 uint32_t ttl;
4556
4557 dns_rriterator_current(&rrit, &rrname, &ttl, &rdataset, NULL);
4558 if (!dns_rdataset_isassociated(rdataset)) {
4559 dns_rriterator_destroy(&rrit);
4560 goto failure;
4561 }
4562
4563 if (rdataset->type != dns_rdatatype_keydata) {
4564 continue;
4565 }
4566 /*
4567 * Release db wrlock to prevent LOR reports against
4568 * dns_keytable_forall() call below.
4569 */
4570 dns_rriterator_pause(&rrit);
4571 result = dns_keytable_find(sr, rrname, &keynode);
4572 if (result != ISC_R_SUCCESS || !dns_keynode_managed(keynode)) {
4573 CHECK(delete_keydata(db, ver, &diff, rrname, rdataset));
4574 changed = true;
4575 } else {
4576 load_secroots(zone, rrname, rdataset);
4577 }
4578
4579 if (keynode != NULL) {
4580 dns_keytable_detachkeynode(sr, &keynode);
4581 }
4582 }
4583 dns_rriterator_destroy(&rrit);
4584
4585 /*
4586 * Walk secroots to find any initial keys that aren't in
4587 * the zone. If we find any, add them to the zone directly.
4588 * If any DS-style initial keys are found, refresh the key
4589 * zone so that they'll be looked up.
4590 */
4591 arg.db = db;
4592 arg.ver = ver;
4593 arg.result = ISC_R_SUCCESS;
4594 arg.diff = &diff;
4595 arg.zone = zone;
4596 arg.changed = &changed;
4597 dns_keytable_forall(sr, addifmissing, &arg);
4598 result = arg.result;
4599 if (changed) {
4600 /* Write changes to journal file. */
4601 CHECK(update_soa_serial(zone, db, ver, &diff, zone->mctx,
4602 zone->updatemethod));
4603 CHECK(zone_journal(zone, &diff, NULL, "sync_keyzone"));
4604
4605 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
4606 zone_needdump(zone, 30);
4607 commit = true;
4608 }
4609
4610 failure:
4611 if (result != ISC_R_SUCCESS && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
4612 {
4613 dnssec_log(zone, ISC_LOG_ERROR,
4614 "unable to synchronize managed keys: %s",
4615 dns_result_totext(result));
4616 isc_time_settoepoch(&zone->refreshkeytime);
4617 }
4618 if (keynode != NULL) {
4619 dns_keytable_detachkeynode(sr, &keynode);
4620 }
4621 if (sr != NULL) {
4622 dns_keytable_detach(&sr);
4623 }
4624 if (ver != NULL) {
4625 dns_db_closeversion(db, &ver, commit);
4626 }
4627 dns_diff_clear(&diff);
4628
4629 INSIST(ver == NULL);
4630
4631 return (result);
4632 }
4633
4634 isc_result_t
4635 dns_zone_synckeyzone(dns_zone_t *zone) {
4636 isc_result_t result;
4637 dns_db_t *db = NULL;
4638
4639 if (zone->type != dns_zone_key) {
4640 return (DNS_R_BADZONE);
4641 }
4642
4643 CHECK(dns_zone_getdb(zone, &db));
4644
4645 LOCK_ZONE(zone);
4646 result = sync_keyzone(zone, db);
4647 UNLOCK_ZONE(zone);
4648
4649 failure:
4650 if (db != NULL) {
4651 dns_db_detach(&db);
4652 }
4653 return (result);
4654 }
4655
4656 static void
4657 maybe_send_secure(dns_zone_t *zone) {
4658 isc_result_t result;
4659
4660 /*
4661 * We've finished loading, or else failed to load, an inline-signing
4662 * 'secure' zone. We now need information about the status of the
4663 * 'raw' zone. If we failed to load, then we need it to send a
4664 * copy of its database; if we succeeded, we need it to send its
4665 * serial number so that we can sync with it. If it has not yet
4666 * loaded, we set a flag so that it will send the necessary
4667 * information when it has finished loading.
4668 */
4669 if (zone->raw->db != NULL) {
4670 if (zone->db != NULL) {
4671 uint32_t serial;
4672 unsigned int soacount;
4673
4674 result = zone_get_from_db(zone->raw, zone->raw->db,
4675 NULL, &soacount, &serial,
4676 NULL, NULL, NULL, NULL, NULL);
4677 if (result == ISC_R_SUCCESS && soacount > 0U) {
4678 zone_send_secureserial(zone->raw, serial);
4679 }
4680 } else {
4681 zone_send_securedb(zone->raw, zone->raw->db);
4682 }
4683 } else {
4684 DNS_ZONE_SETFLAG(zone->raw, DNS_ZONEFLG_SENDSECURE);
4685 }
4686 }
4687
4688 static bool
4689 zone_unchanged(dns_db_t *db1, dns_db_t *db2, isc_mem_t *mctx) {
4690 isc_result_t result;
4691 bool answer = false;
4692 dns_diff_t diff;
4693
4694 dns_diff_init(mctx, &diff);
4695 result = dns_db_diffx(&diff, db1, NULL, db2, NULL, NULL);
4696 if (result == ISC_R_SUCCESS && ISC_LIST_EMPTY(diff.tuples)) {
4697 answer = true;
4698 }
4699 dns_diff_clear(&diff);
4700 return (answer);
4701 }
4702
4703 /*
4704 * The zone is presumed to be locked.
4705 * If this is a inline_raw zone the secure version is also locked.
4706 */
4707 static isc_result_t
4708 zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
4709 isc_result_t result) {
4710 unsigned int soacount = 0;
4711 unsigned int nscount = 0;
4712 unsigned int errors = 0;
4713 uint32_t serial, oldserial, refresh, retry, expire, minimum;
4714 isc_time_t now;
4715 bool needdump = false;
4716 bool hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE);
4717 bool nomaster = false;
4718 bool had_db = false;
4719 unsigned int options;
4720 dns_include_t *inc;
4721 bool is_dynamic = false;
4722
4723 INSIST(LOCKED_ZONE(zone));
4724 if (inline_raw(zone)) {
4725 INSIST(LOCKED_ZONE(zone->secure));
4726 }
4727
4728 TIME_NOW(&now);
4729
4730 /*
4731 * Initiate zone transfer? We may need a error code that
4732 * indicates that the "permanent" form does not exist.
4733 * XXX better error feedback to log.
4734 */
4735 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
4736 if (zone->type == dns_zone_slave ||
4737 zone->type == dns_zone_mirror ||
4738 zone->type == dns_zone_stub ||
4739 (zone->type == dns_zone_redirect && zone->masters == NULL))
4740 {
4741 if (result == ISC_R_FILENOTFOUND) {
4742 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4743 ISC_LOG_DEBUG(1),
4744 "no master file");
4745 } else if (result != DNS_R_NOMASTERFILE) {
4746 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4747 ISC_LOG_ERROR,
4748 "loading from master file %s "
4749 "failed: %s",
4750 zone->masterfile,
4751 dns_result_totext(result));
4752 }
4753 } else if (zone->type == dns_zone_master &&
4754 inline_secure(zone) && result == ISC_R_FILENOTFOUND)
4755 {
4756 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4757 ISC_LOG_DEBUG(1),
4758 "no master file, requesting db");
4759 maybe_send_secure(zone);
4760 } else {
4761 int level = ISC_LOG_ERROR;
4762 if (zone->type == dns_zone_key &&
4763 result == ISC_R_FILENOTFOUND) {
4764 level = ISC_LOG_DEBUG(1);
4765 }
4766 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, level,
4767 "loading from master file %s failed: %s",
4768 zone->masterfile,
4769 dns_result_totext(result));
4770 nomaster = true;
4771 }
4772
4773 if (zone->type != dns_zone_key) {
4774 goto cleanup;
4775 }
4776 }
4777
4778 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(2),
4779 "number of nodes in database: %u", dns_db_nodecount(db));
4780
4781 if (result == DNS_R_SEENINCLUDE) {
4782 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
4783 } else {
4784 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
4785 }
4786
4787 /*
4788 * If there's no master file for a key zone, then the zone is new:
4789 * create an SOA record. (We do this now, instead of later, so that
4790 * if there happens to be a journal file, we can roll forward from
4791 * a sane starting point.)
4792 */
4793 if (nomaster && zone->type == dns_zone_key) {
4794 result = add_soa(zone, db);
4795 if (result != ISC_R_SUCCESS) {
4796 goto cleanup;
4797 }
4798 }
4799
4800 /*
4801 * Apply update log, if any, on initial load.
4802 */
4803 if (zone->journal != NULL &&
4804 !DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE) &&
4805 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
4806 {
4807 if (zone->type == dns_zone_master &&
4808 (inline_secure(zone) ||
4809 (zone->update_acl != NULL || zone->ssutable != NULL)))
4810 {
4811 options = DNS_JOURNALOPT_RESIGN;
4812 } else {
4813 options = 0;
4814 }
4815 result = dns_journal_rollforward(zone->mctx, db, options,
4816 zone->journal);
4817 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND &&
4818 result != DNS_R_UPTODATE && result != DNS_R_NOJOURNAL &&
4819 result != ISC_R_RANGE)
4820 {
4821 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4822 ISC_LOG_ERROR,
4823 "journal rollforward failed: %s",
4824 dns_result_totext(result));
4825 goto cleanup;
4826 }
4827 if (result == ISC_R_NOTFOUND || result == ISC_R_RANGE) {
4828 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4829 ISC_LOG_ERROR,
4830 "journal rollforward failed: "
4831 "journal out of sync with zone");
4832 goto cleanup;
4833 }
4834 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
4835 "journal rollforward completed "
4836 "successfully: %s",
4837 dns_result_totext(result));
4838 if (result == ISC_R_SUCCESS) {
4839 needdump = true;
4840 }
4841 }
4842
4843 /*
4844 * Obtain ns, soa and cname counts for top of zone.
4845 */
4846 INSIST(db != NULL);
4847 result = zone_get_from_db(zone, db, &nscount, &soacount, &serial,
4848 &refresh, &retry, &expire, &minimum, &errors);
4849 if (result != ISC_R_SUCCESS && zone->type != dns_zone_key) {
4850 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
4851 "could not find NS and/or SOA records");
4852 }
4853
4854 /*
4855 * Check to make sure the journal is up to date, and remove the
4856 * journal file if it isn't, as we wouldn't be able to apply
4857 * updates otherwise.
4858 */
4859 is_dynamic = dns_zone_isdynamic(zone, true);
4860 if (zone->journal != NULL && is_dynamic &&
4861 !DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS))
4862 {
4863 uint32_t jserial;
4864 dns_journal_t *journal = NULL;
4865 bool empty = false;
4866
4867 result = dns_journal_open(zone->mctx, zone->journal,
4868 DNS_JOURNAL_READ, &journal);
4869 if (result == ISC_R_SUCCESS) {
4870 jserial = dns_journal_last_serial(journal);
4871 empty = dns_journal_empty(journal);
4872 dns_journal_destroy(&journal);
4873 } else {
4874 jserial = serial;
4875 result = ISC_R_SUCCESS;
4876 }
4877
4878 if (jserial != serial) {
4879 if (!empty) {
4880 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4881 ISC_LOG_INFO,
4882 "journal file is out of date: "
4883 "removing journal file");
4884 }
4885 if (remove(zone->journal) < 0 && errno != ENOENT) {
4886 char strbuf[ISC_STRERRORSIZE];
4887 strerror_r(errno, strbuf, sizeof(strbuf));
4888 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
4889 DNS_LOGMODULE_ZONE,
4890 ISC_LOG_WARNING,
4891 "unable to remove journal "
4892 "'%s': '%s'",
4893 zone->journal, strbuf);
4894 }
4895 }
4896 }
4897
4898 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
4899 "loaded; checking validity");
4900
4901 /*
4902 * Master / Slave / Mirror / Stub zones require both NS and SOA records
4903 * at the top of the zone.
4904 */
4905
4906 switch (zone->type) {
4907 case dns_zone_dlz:
4908 case dns_zone_master:
4909 case dns_zone_slave:
4910 case dns_zone_mirror:
4911 case dns_zone_stub:
4912 case dns_zone_redirect:
4913 if (soacount != 1) {
4914 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4915 ISC_LOG_ERROR, "has %d SOA records",
4916 soacount);
4917 result = DNS_R_BADZONE;
4918 }
4919 if (nscount == 0) {
4920 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4921 ISC_LOG_ERROR, "has no NS records");
4922 result = DNS_R_BADZONE;
4923 }
4924 if (result != ISC_R_SUCCESS) {
4925 goto cleanup;
4926 }
4927 if (zone->type == dns_zone_master && errors != 0) {
4928 result = DNS_R_BADZONE;
4929 goto cleanup;
4930 }
4931 if (zone->type != dns_zone_stub &&
4932 zone->type != dns_zone_redirect) {
4933 result = check_nsec3param(zone, db);
4934 if (result != ISC_R_SUCCESS) {
4935 goto cleanup;
4936 }
4937 }
4938 if (zone->type == dns_zone_master &&
4939 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKINTEGRITY) &&
4940 !integrity_checks(zone, db))
4941 {
4942 result = DNS_R_BADZONE;
4943 goto cleanup;
4944 }
4945 if (zone->type == dns_zone_master &&
4946 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRR) &&
4947 !zone_check_dup(zone, db))
4948 {
4949 result = DNS_R_BADZONE;
4950 goto cleanup;
4951 }
4952
4953 if (zone->type == dns_zone_master) {
4954 result = dns_zone_cdscheck(zone, db, NULL);
4955 if (result != ISC_R_SUCCESS) {
4956 dns_zone_log(zone, ISC_LOG_ERROR,
4957 "CDS/CDNSKEY consistency checks "
4958 "failed");
4959 goto cleanup;
4960 }
4961 }
4962
4963 result = dns_zone_verifydb(zone, db, NULL);
4964 if (result != ISC_R_SUCCESS) {
4965 goto cleanup;
4966 }
4967
4968 if (zone->db != NULL) {
4969 unsigned int oldsoacount;
4970
4971 /*
4972 * This is checked in zone_replacedb() for slave zones
4973 * as they don't reload from disk.
4974 */
4975 result = zone_get_from_db(zone, zone->db, NULL,
4976 &oldsoacount, &oldserial,
4977 NULL, NULL, NULL, NULL, NULL);
4978 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4979 RUNTIME_CHECK(soacount > 0U);
4980 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
4981 !isc_serial_gt(serial, oldserial))
4982 {
4983 uint32_t serialmin, serialmax;
4984
4985 INSIST(zone->type == dns_zone_master);
4986 INSIST(zone->raw == NULL);
4987
4988 if (serial == oldserial &&
4989 zone_unchanged(zone->db, db, zone->mctx)) {
4990 dns_zone_logc(zone,
4991 DNS_LOGCATEGORY_ZONELOAD,
4992 ISC_LOG_INFO,
4993 "ixfr-from-differences: "
4994 "unchanged");
4995 goto done;
4996 }
4997
4998 serialmin = (oldserial + 1) & 0xffffffffU;
4999 serialmax = (oldserial + 0x7fffffffU) &
5000 0xffffffffU;
5001 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5002 ISC_LOG_ERROR,
5003 "ixfr-from-differences: "
5004 "new serial (%u) out of range "
5005 "[%u - %u]",
5006 serial, serialmin, serialmax);
5007 result = DNS_R_BADZONE;
5008 goto cleanup;
5009 } else if (!isc_serial_ge(serial, oldserial)) {
5010 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5011 ISC_LOG_ERROR,
5012 "zone serial (%u/%u) has gone "
5013 "backwards",
5014 serial, oldserial);
5015 } else if (serial == oldserial && !hasinclude &&
5016 strcmp(zone->db_argv[0], "_builtin") != 0)
5017 {
5018 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5019 ISC_LOG_ERROR,
5020 "zone serial (%u) unchanged. "
5021 "zone may fail to transfer "
5022 "to slaves.",
5023 serial);
5024 }
5025 }
5026
5027 if (zone->type == dns_zone_master &&
5028 (zone->update_acl != NULL || zone->ssutable != NULL) &&
5029 dns_zone_getsigresigninginterval(zone) < (3 * refresh) &&
5030 dns_db_issecure(db))
5031 {
5032 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5033 ISC_LOG_WARNING,
5034 "sig-re-signing-interval less than "
5035 "3 * refresh.");
5036 }
5037
5038 zone->refresh = RANGE(refresh, zone->minrefresh,
5039 zone->maxrefresh);
5040 zone->retry = RANGE(retry, zone->minretry, zone->maxretry);
5041 zone->expire = RANGE(expire, zone->refresh + zone->retry,
5042 DNS_MAX_EXPIRE);
5043 zone->minimum = minimum;
5044 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
5045
5046 if (zone->type == dns_zone_slave ||
5047 zone->type == dns_zone_mirror ||
5048 zone->type == dns_zone_stub ||
5049 (zone->type == dns_zone_redirect && zone->masters != NULL))
5050 {
5051 isc_time_t t;
5052 uint32_t delay;
5053
5054 result = isc_file_getmodtime(zone->journal, &t);
5055 if (result != ISC_R_SUCCESS) {
5056 result = isc_file_getmodtime(zone->masterfile,
5057 &t);
5058 }
5059 if (result == ISC_R_SUCCESS) {
5060 DNS_ZONE_TIME_ADD(&t, zone->expire,
5061 &zone->expiretime);
5062 } else {
5063 DNS_ZONE_TIME_ADD(&now, zone->retry,
5064 &zone->expiretime);
5065 }
5066
5067 delay = (zone->retry -
5068 isc_random_uniform((zone->retry * 3) / 4));
5069 DNS_ZONE_TIME_ADD(&now, delay, &zone->refreshtime);
5070 if (isc_time_compare(&zone->refreshtime,
5071 &zone->expiretime) >= 0) {
5072 zone->refreshtime = now;
5073 }
5074 }
5075
5076 break;
5077
5078 case dns_zone_key:
5079 result = sync_keyzone(zone, db);
5080 if (result != ISC_R_SUCCESS) {
5081 goto cleanup;
5082 }
5083 break;
5084
5085 default:
5086 UNEXPECTED_ERROR(__FILE__, __LINE__, "unexpected zone type %d",
5087 zone->type);
5088 result = ISC_R_UNEXPECTED;
5089 goto cleanup;
5090 }
5091
5092 /*
5093 * Check for weak DNSKEY's.
5094 */
5095 if (zone->type == dns_zone_master) {
5096 zone_check_dnskeys(zone, db);
5097 }
5098
5099 /*
5100 * Schedule DNSSEC key refresh.
5101 */
5102 if (zone->type == dns_zone_master &&
5103 DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
5104 {
5105 zone->refreshkeytime = now;
5106 }
5107
5108 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
5109 if (zone->db != NULL) {
5110 had_db = true;
5111 result = zone_replacedb(zone, db, false);
5112 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
5113 if (result != ISC_R_SUCCESS) {
5114 goto cleanup;
5115 }
5116 } else {
5117 zone_attachdb(zone, db);
5118 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
5119 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED |
5120 DNS_ZONEFLG_NEEDSTARTUPNOTIFY);
5121 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SENDSECURE) &&
5122 inline_raw(zone)) {
5123 if (zone->secure->db == NULL) {
5124 zone_send_securedb(zone, db);
5125 } else {
5126 zone_send_secureserial(zone, serial);
5127 }
5128 }
5129 }
5130
5131 /*
5132 * Finished loading inline-signing zone; need to get status
5133 * from the raw side now.
5134 */
5135 if (zone->type == dns_zone_master && inline_secure(zone)) {
5136 maybe_send_secure(zone);
5137 }
5138
5139 result = ISC_R_SUCCESS;
5140
5141 if (needdump) {
5142 if (zone->type == dns_zone_key) {
5143 zone_needdump(zone, 30);
5144 } else {
5145 zone_needdump(zone, DNS_DUMP_DELAY);
5146 }
5147 }
5148
5149 if (zone->task != NULL) {
5150 if (zone->type == dns_zone_master) {
5151 set_resigntime(zone);
5152 resume_signingwithkey(zone);
5153 resume_addnsec3chain(zone);
5154 }
5155
5156 is_dynamic = dns_zone_isdynamic(zone, false);
5157 if (zone->type == dns_zone_master &&
5158 !DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN) &&
5159 is_dynamic && dns_db_issecure(db))
5160 {
5161 dns_name_t *name;
5162 dns_fixedname_t fixed;
5163 dns_rdataset_t next;
5164
5165 dns_rdataset_init(&next);
5166 name = dns_fixedname_initname(&fixed);
5167
5168 result = dns_db_getsigningtime(db, &next, name);
5169 if (result == ISC_R_SUCCESS) {
5170 isc_stdtime_t timenow;
5171 char namebuf[DNS_NAME_FORMATSIZE];
5172 char typebuf[DNS_RDATATYPE_FORMATSIZE];
5173
5174 isc_stdtime_get(&timenow);
5175 dns_name_format(name, namebuf, sizeof(namebuf));
5176 dns_rdatatype_format(next.covers, typebuf,
5177 sizeof(typebuf));
5178 dnssec_log(
5179 zone, ISC_LOG_DEBUG(3),
5180 "next resign: %s/%s "
5181 "in %d seconds",
5182 namebuf, typebuf,
5183 next.resign - timenow -
5184 dns_zone_getsigresigninginterval(
5185 zone));
5186 dns_rdataset_disassociate(&next);
5187 } else {
5188 dnssec_log(zone, ISC_LOG_WARNING,
5189 "signed dynamic zone has no "
5190 "resign event scheduled");
5191 }
5192 }
5193
5194 zone_settimer(zone, &now);
5195 }
5196
5197 /*
5198 * Clear old include list.
5199 */
5200 for (inc = ISC_LIST_HEAD(zone->includes); inc != NULL;
5201 inc = ISC_LIST_HEAD(zone->includes))
5202 {
5203 ISC_LIST_UNLINK(zone->includes, inc, link);
5204 isc_mem_free(zone->mctx, inc->name);
5205 isc_mem_put(zone->mctx, inc, sizeof(*inc));
5206 }
5207 zone->nincludes = 0;
5208
5209 /*
5210 * Transfer new include list.
5211 */
5212 for (inc = ISC_LIST_HEAD(zone->newincludes); inc != NULL;
5213 inc = ISC_LIST_HEAD(zone->newincludes))
5214 {
5215 ISC_LIST_UNLINK(zone->newincludes, inc, link);
5216 ISC_LIST_APPEND(zone->includes, inc, link);
5217 zone->nincludes++;
5218 }
5219
5220 if (!dns_db_ispersistent(db)) {
5221 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_INFO,
5222 "loaded serial %u%s", serial,
5223 dns_db_issecure(db) ? " (DNSSEC signed)" : "");
5224 }
5225
5226 if (!had_db && zone->type == dns_zone_mirror) {
5227 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_INFO,
5228 "mirror zone is now in use");
5229 }
5230
5231 zone->loadtime = loadtime;
5232 goto done;
5233
5234 cleanup:
5235 if (zone->type == dns_zone_key && result != ISC_R_SUCCESS) {
5236 dnssec_log(zone, ISC_LOG_ERROR,
5237 "failed to initialize managed-keys (%s): "
5238 "DNSSEC validation is at risk",
5239 isc_result_totext(result));
5240 }
5241
5242 for (inc = ISC_LIST_HEAD(zone->newincludes); inc != NULL;
5243 inc = ISC_LIST_HEAD(zone->newincludes))
5244 {
5245 ISC_LIST_UNLINK(zone->newincludes, inc, link);
5246 isc_mem_free(zone->mctx, inc->name);
5247 isc_mem_put(zone->mctx, inc, sizeof(*inc));
5248 }
5249 if (zone->type == dns_zone_slave || zone->type == dns_zone_mirror ||
5250 zone->type == dns_zone_stub || zone->type == dns_zone_key ||
5251 (zone->type == dns_zone_redirect && zone->masters != NULL))
5252 {
5253 if (result != ISC_R_NOMEMORY) {
5254 if (zone->journal != NULL) {
5255 zone_saveunique(zone, zone->journal,
5256 "jn-XXXXXXXX");
5257 }
5258 if (zone->masterfile != NULL) {
5259 zone_saveunique(zone, zone->masterfile,
5260 "db-XXXXXXXX");
5261 }
5262 }
5263
5264 /* Mark the zone for immediate refresh. */
5265 zone->refreshtime = now;
5266 if (zone->task != NULL) {
5267 zone_settimer(zone, &now);
5268 }
5269 result = ISC_R_SUCCESS;
5270 } else if (zone->type == dns_zone_master ||
5271 zone->type == dns_zone_redirect) {
5272 if (!(inline_secure(zone) && result == ISC_R_FILENOTFOUND)) {
5273 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5274 ISC_LOG_ERROR,
5275 "not loaded due to errors.");
5276 } else if (zone->type == dns_zone_master) {
5277 result = ISC_R_SUCCESS;
5278 }
5279 }
5280
5281 done:
5282 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
5283 /*
5284 * If this is an inline-signed zone and we were called for the raw
5285 * zone, we need to clear DNS_ZONEFLG_LOADPENDING for the secure zone
5286 * as well, but only if this is a reload, not an initial zone load: in
5287 * the former case, zone_postload() will not be run for the secure
5288 * zone; in the latter case, it will be. Check which case we are
5289 * dealing with by consulting the DNS_ZONEFLG_LOADED flag for the
5290 * secure zone: if it is set, this must be a reload.
5291 */
5292 if (inline_raw(zone) && DNS_ZONE_FLAG(zone->secure, DNS_ZONEFLG_LOADED))
5293 {
5294 DNS_ZONE_CLRFLAG(zone->secure, DNS_ZONEFLG_LOADPENDING);
5295 /*
5296 * Re-start zone maintenance if it had been stalled
5297 * due to DNS_ZONEFLG_LOADPENDING being set when
5298 * zone_maintenance was called.
5299 */
5300 if (zone->secure->task != NULL) {
5301 zone_settimer(zone->secure, &now);
5302 }
5303 }
5304
5305 zone_debuglog(zone, "zone_postload", 99, "done");
5306
5307 return (result);
5308 }
5309
5310 static bool
5311 exit_check(dns_zone_t *zone) {
5312 REQUIRE(LOCKED_ZONE(zone));
5313
5314 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) &&
5315 isc_refcount_current(&zone->irefs) == 0)
5316 {
5317 /*
5318 * DNS_ZONEFLG_SHUTDOWN can only be set if erefs == 0.
5319 */
5320 INSIST(isc_refcount_current(&zone->erefs) == 0);
5321 return (true);
5322 }
5323 return (false);
5324 }
5325
5326 static bool
5327 zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
5328 dns_name_t *name, bool logit) {
5329 isc_result_t result;
5330 char namebuf[DNS_NAME_FORMATSIZE];
5331 char altbuf[DNS_NAME_FORMATSIZE];
5332 dns_fixedname_t fixed;
5333 dns_name_t *foundname;
5334 int level;
5335
5336 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOCHECKNS)) {
5337 return (true);
5338 }
5339
5340 if (zone->type == dns_zone_master) {
5341 level = ISC_LOG_ERROR;
5342 } else {
5343 level = ISC_LOG_WARNING;
5344 }
5345
5346 foundname = dns_fixedname_initname(&fixed);
5347
5348 result = dns_db_find(db, name, version, dns_rdatatype_a, 0, 0, NULL,
5349 foundname, NULL, NULL);
5350 if (result == ISC_R_SUCCESS) {
5351 return (true);
5352 }
5353
5354 if (result == DNS_R_NXRRSET) {
5355 result = dns_db_find(db, name, version, dns_rdatatype_aaaa, 0,
5356 0, NULL, foundname, NULL, NULL);
5357 if (result == ISC_R_SUCCESS) {
5358 return (true);
5359 }
5360 }
5361
5362 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
5363 result == DNS_R_EMPTYNAME)
5364 {
5365 if (logit) {
5366 dns_name_format(name, namebuf, sizeof namebuf);
5367 dns_zone_log(zone, level,
5368 "NS '%s' has no address "
5369 "records (A or AAAA)",
5370 namebuf);
5371 }
5372 return (false);
5373 }
5374
5375 if (result == DNS_R_CNAME) {
5376 if (logit) {
5377 dns_name_format(name, namebuf, sizeof namebuf);
5378 dns_zone_log(zone, level,
5379 "NS '%s' is a CNAME "
5380 "(illegal)",
5381 namebuf);
5382 }
5383 return (false);
5384 }
5385
5386 if (result == DNS_R_DNAME) {
5387 if (logit) {
5388 dns_name_format(name, namebuf, sizeof namebuf);
5389 dns_name_format(foundname, altbuf, sizeof altbuf);
5390 dns_zone_log(zone, level,
5391 "NS '%s' is below a DNAME "
5392 "'%s' (illegal)",
5393 namebuf, altbuf);
5394 }
5395 return (false);
5396 }
5397
5398 return (true);
5399 }
5400
5401 static isc_result_t
5402 zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
5403 dns_dbversion_t *version, unsigned int *nscount,
5404 unsigned int *errors, bool logit) {
5405 isc_result_t result;
5406 unsigned int count = 0;
5407 unsigned int ecount = 0;
5408 dns_rdataset_t rdataset;
5409 dns_rdata_t rdata;
5410 dns_rdata_ns_t ns;
5411
5412 dns_rdataset_init(&rdataset);
5413 result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns,
5414 dns_rdatatype_none, 0, &rdataset, NULL);
5415 if (result == ISC_R_NOTFOUND) {
5416 INSIST(!dns_rdataset_isassociated(&rdataset));
5417 goto success;
5418 }
5419 if (result != ISC_R_SUCCESS) {
5420 INSIST(!dns_rdataset_isassociated(&rdataset));
5421 goto invalidate_rdataset;
5422 }
5423
5424 result = dns_rdataset_first(&rdataset);
5425 while (result == ISC_R_SUCCESS) {
5426 if (errors != NULL && zone->rdclass == dns_rdataclass_in &&
5427 (zone->type == dns_zone_master ||
5428 zone->type == dns_zone_slave ||
5429 zone->type == dns_zone_mirror))
5430 {
5431 dns_rdata_init(&rdata);
5432 dns_rdataset_current(&rdataset, &rdata);
5433 result = dns_rdata_tostruct(&rdata, &ns, NULL);
5434 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5435 if (dns_name_issubdomain(&ns.name, &zone->origin) &&
5436 !zone_check_ns(zone, db, version, &ns.name, logit))
5437 {
5438 ecount++;
5439 }
5440 }
5441 count++;
5442 result = dns_rdataset_next(&rdataset);
5443 }
5444 dns_rdataset_disassociate(&rdataset);
5445
5446 success:
5447 if (nscount != NULL) {
5448 *nscount = count;
5449 }
5450 if (errors != NULL) {
5451 *errors = ecount;
5452 }
5453
5454 result = ISC_R_SUCCESS;
5455
5456 invalidate_rdataset:
5457 dns_rdataset_invalidate(&rdataset);
5458
5459 return (result);
5460 }
5461
5462 static isc_result_t
5463 zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
5464 unsigned int *soacount, uint32_t *serial, uint32_t *refresh,
5465 uint32_t *retry, uint32_t *expire, uint32_t *minimum) {
5466 isc_result_t result;
5467 unsigned int count;
5468 dns_rdataset_t rdataset;
5469 dns_rdata_t rdata = DNS_RDATA_INIT;
5470 dns_rdata_soa_t soa;
5471
5472 dns_rdataset_init(&rdataset);
5473 result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
5474 dns_rdatatype_none, 0, &rdataset, NULL);
5475 if (result == ISC_R_NOTFOUND) {
5476 INSIST(!dns_rdataset_isassociated(&rdataset));
5477 if (soacount != NULL) {
5478 *soacount = 0;
5479 }
5480 if (serial != NULL) {
5481 *serial = 0;
5482 }
5483 if (refresh != NULL) {
5484 *refresh = 0;
5485 }
5486 if (retry != NULL) {
5487 *retry = 0;
5488 }
5489 if (expire != NULL) {
5490 *expire = 0;
5491 }
5492 if (minimum != NULL) {
5493 *minimum = 0;
5494 }
5495 result = ISC_R_SUCCESS;
5496 goto invalidate_rdataset;
5497 }
5498 if (result != ISC_R_SUCCESS) {
5499 INSIST(!dns_rdataset_isassociated(&rdataset));
5500 goto invalidate_rdataset;
5501 }
5502
5503 count = 0;
5504 result = dns_rdataset_first(&rdataset);
5505 while (result == ISC_R_SUCCESS) {
5506 dns_rdata_init(&rdata);
5507 dns_rdataset_current(&rdataset, &rdata);
5508 count++;
5509 if (count == 1) {
5510 result = dns_rdata_tostruct(&rdata, &soa, NULL);
5511 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5512 }
5513
5514 result = dns_rdataset_next(&rdataset);
5515 dns_rdata_reset(&rdata);
5516 }
5517 dns_rdataset_disassociate(&rdataset);
5518
5519 if (soacount != NULL) {
5520 *soacount = count;
5521 }
5522
5523 if (count > 0) {
5524 if (serial != NULL) {
5525 *serial = soa.serial;
5526 }
5527 if (refresh != NULL) {
5528 *refresh = soa.refresh;
5529 }
5530 if (retry != NULL) {
5531 *retry = soa.retry;
5532 }
5533 if (expire != NULL) {
5534 *expire = soa.expire;
5535 }
5536 if (minimum != NULL) {
5537 *minimum = soa.minimum;
5538 }
5539 } else {
5540 if (soacount != NULL) {
5541 *soacount = 0;
5542 }
5543 if (serial != NULL) {
5544 *serial = 0;
5545 }
5546 if (refresh != NULL) {
5547 *refresh = 0;
5548 }
5549 if (retry != NULL) {
5550 *retry = 0;
5551 }
5552 if (expire != NULL) {
5553 *expire = 0;
5554 }
5555 if (minimum != NULL) {
5556 *minimum = 0;
5557 }
5558 }
5559
5560 result = ISC_R_SUCCESS;
5561
5562 invalidate_rdataset:
5563 dns_rdataset_invalidate(&rdataset);
5564
5565 return (result);
5566 }
5567
5568 /*
5569 * zone must be locked.
5570 */
5571 static isc_result_t
5572 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
5573 unsigned int *soacount, uint32_t *serial, uint32_t *refresh,
5574 uint32_t *retry, uint32_t *expire, uint32_t *minimum,
5575 unsigned int *errors) {
5576 isc_result_t result;
5577 isc_result_t answer = ISC_R_SUCCESS;
5578 dns_dbversion_t *version = NULL;
5579 dns_dbnode_t *node;
5580
5581 REQUIRE(db != NULL);
5582 REQUIRE(zone != NULL);
5583
5584 dns_db_currentversion(db, &version);
5585
5586 if (nscount != NULL) {
5587 *nscount = 0;
5588 }
5589 if (soacount != NULL) {
5590 *soacount = 0;
5591 }
5592 if (serial != NULL) {
5593 *serial = 0;
5594 }
5595 if (refresh != NULL) {
5596 *refresh = 0;
5597 }
5598 if (retry != NULL) {
5599 *retry = 0;
5600 }
5601 if (expire != NULL) {
5602 *expire = 0;
5603 }
5604 if (errors != NULL) {
5605 *errors = 0;
5606 }
5607
5608 node = NULL;
5609 result = dns_db_findnode(db, &zone->origin, false, &node);
5610 if (result != ISC_R_SUCCESS) {
5611 answer = result;
5612 goto closeversion;
5613 }
5614
5615 if (nscount != NULL || errors != NULL) {
5616 result = zone_count_ns_rr(zone, db, node, version, nscount,
5617 errors, true);
5618 if (result != ISC_R_SUCCESS) {
5619 answer = result;
5620 }
5621 }
5622
5623 if (soacount != NULL || serial != NULL || refresh != NULL ||
5624 retry != NULL || expire != NULL || minimum != NULL)
5625 {
5626 result = zone_load_soa_rr(db, node, version, soacount, serial,
5627 refresh, retry, expire, minimum);
5628 if (result != ISC_R_SUCCESS) {
5629 answer = result;
5630 }
5631 }
5632
5633 dns_db_detachnode(db, &node);
5634 closeversion:
5635 dns_db_closeversion(db, &version, false);
5636
5637 return (answer);
5638 }
5639
5640 void
5641 dns_zone_attach(dns_zone_t *source, dns_zone_t **target) {
5642 REQUIRE(DNS_ZONE_VALID(source));
5643 REQUIRE(target != NULL && *target == NULL);
5644 isc_refcount_increment(&source->erefs);
5645 *target = source;
5646 }
5647
5648 void
5649 dns_zone_detach(dns_zone_t **zonep) {
5650 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
5651 dns_zone_t *zone = *zonep;
5652 *zonep = NULL;
5653
5654 bool free_now = false;
5655 dns_zone_t *raw = NULL;
5656 dns_zone_t *secure = NULL;
5657 if (isc_refcount_decrement(&zone->erefs) == 1) {
5658 isc_refcount_destroy(&zone->erefs);
5659
5660 LOCK_ZONE(zone);
5661 INSIST(zone != zone->raw);
5662 /*
5663 * We just detached the last external reference.
5664 */
5665 if (zone->task != NULL) {
5666 /*
5667 * This zone is being managed. Post
5668 * its control event and let it clean
5669 * up synchronously in the context of
5670 * its task.
5671 */
5672 isc_event_t *ev = &zone->ctlevent;
5673 isc_task_send(zone->task, &ev);
5674 } else {
5675 /*
5676 * This zone is not being managed; it has
5677 * no task and can have no outstanding
5678 * events. Free it immediately.
5679 */
5680 /*
5681 * Unmanaged zones should not have non-null views;
5682 * we have no way of detaching from the view here
5683 * without causing deadlock because this code is called
5684 * with the view already locked.
5685 */
5686 INSIST(zone->view == NULL);
5687 free_now = true;
5688 raw = zone->raw;
5689 zone->raw = NULL;
5690 secure = zone->secure;
5691 zone->secure = NULL;
5692 }
5693 UNLOCK_ZONE(zone);
5694 }
5695 if (free_now) {
5696 if (raw != NULL) {
5697 dns_zone_detach(&raw);
5698 }
5699 if (secure != NULL) {
5700 dns_zone_idetach(&secure);
5701 }
5702 zone_free(zone);
5703 }
5704 }
5705
5706 void
5707 dns_zone_iattach(dns_zone_t *source, dns_zone_t **target) {
5708 REQUIRE(DNS_ZONE_VALID(source));
5709
5710 LOCK_ZONE(source);
5711 zone_iattach(source, target);
5712 UNLOCK_ZONE(source);
5713 }
5714
5715 static void
5716 zone_iattach(dns_zone_t *source, dns_zone_t **target) {
5717 REQUIRE(DNS_ZONE_VALID(source));
5718 REQUIRE(LOCKED_ZONE(source));
5719 REQUIRE(target != NULL && *target == NULL);
5720 INSIST(isc_refcount_increment0(&source->irefs) +
5721 isc_refcount_current(&source->erefs) >
5722 0);
5723 *target = source;
5724 }
5725
5726 static void
5727 zone_idetach(dns_zone_t **zonep) {
5728 dns_zone_t *zone;
5729
5730 /*
5731 * 'zone' locked by caller.
5732 */
5733 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
5734 REQUIRE(LOCKED_ZONE(*zonep));
5735
5736 zone = *zonep;
5737 *zonep = NULL;
5738
5739 INSIST(isc_refcount_decrement(&zone->irefs) - 1 +
5740 isc_refcount_current(&zone->erefs) >
5741 0);
5742 }
5743
5744 void
5745 dns_zone_idetach(dns_zone_t **zonep) {
5746 dns_zone_t *zone;
5747 bool free_needed;
5748
5749 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
5750
5751 zone = *zonep;
5752 *zonep = NULL;
5753
5754 if (isc_refcount_decrement(&zone->irefs) == 1) {
5755 LOCK_ZONE(zone);
5756 free_needed = exit_check(zone);
5757 UNLOCK_ZONE(zone);
5758 if (free_needed) {
5759 zone_free(zone);
5760 }
5761 }
5762 }
5763
5764 isc_mem_t *
5765 dns_zone_getmctx(dns_zone_t *zone) {
5766 REQUIRE(DNS_ZONE_VALID(zone));
5767
5768 return (zone->mctx);
5769 }
5770
5771 dns_zonemgr_t *
5772 dns_zone_getmgr(dns_zone_t *zone) {
5773 REQUIRE(DNS_ZONE_VALID(zone));
5774
5775 return (zone->zmgr);
5776 }
5777
5778 void
5779 dns_zone_setflag(dns_zone_t *zone, unsigned int flags, bool value) {
5780 REQUIRE(DNS_ZONE_VALID(zone));
5781
5782 if (value) {
5783 DNS_ZONE_SETFLAG(zone, flags);
5784 } else {
5785 DNS_ZONE_CLRFLAG(zone, flags);
5786 }
5787 }
5788
5789 void
5790 dns_zone_setkasp(dns_zone_t *zone, dns_kasp_t *kasp) {
5791 REQUIRE(DNS_ZONE_VALID(zone));
5792
5793 LOCK_ZONE(zone);
5794 if (zone->kasp != NULL) {
5795 dns_kasp_t *oldkasp = zone->kasp;
5796 zone->kasp = NULL;
5797 dns_kasp_detach(&oldkasp);
5798 }
5799 zone->kasp = kasp;
5800 UNLOCK_ZONE(zone);
5801 }
5802
5803 dns_kasp_t *
5804 dns_zone_getkasp(dns_zone_t *zone) {
5805 REQUIRE(DNS_ZONE_VALID(zone));
5806
5807 return (zone->kasp);
5808 }
5809
5810 static bool
5811 statefile_exist(dns_zone_t *zone) {
5812 isc_result_t ret;
5813 dns_dnsseckeylist_t keys;
5814 dns_dnsseckey_t *key = NULL;
5815 isc_stdtime_t now;
5816 isc_time_t timenow;
5817 bool found = false;
5818
5819 TIME_NOW(&timenow);
5820 now = isc_time_seconds(&timenow);
5821
5822 ISC_LIST_INIT(keys);
5823
5824 ret = dns_dnssec_findmatchingkeys(dns_zone_getorigin(zone),
5825 dns_zone_getkeydirectory(zone), now,
5826 dns_zone_getmctx(zone), &keys);
5827 if (ret == ISC_R_SUCCESS) {
5828 for (key = ISC_LIST_HEAD(keys); key != NULL;
5829 key = ISC_LIST_NEXT(key, link)) {
5830 if (dst_key_haskasp(key->key)) {
5831 found = true;
5832 break;
5833 }
5834 }
5835 }
5836
5837 /* Clean up keys */
5838 while (!ISC_LIST_EMPTY(keys)) {
5839 key = ISC_LIST_HEAD(keys);
5840 ISC_LIST_UNLINK(keys, key, link);
5841 dns_dnsseckey_destroy(dns_zone_getmctx(zone), &key);
5842 }
5843
5844 return (found);
5845 }
5846
5847 bool
5848 dns_zone_secure_to_insecure(dns_zone_t *zone, bool reconfig) {
5849 REQUIRE(DNS_ZONE_VALID(zone));
5850
5851 /*
5852 * If checking during reconfig, the zone is not yet updated
5853 * with the new kasp configuration, so only check the key
5854 * files.
5855 */
5856 if (reconfig) {
5857 return (statefile_exist(zone));
5858 }
5859
5860 if (zone->kasp == NULL) {
5861 return (false);
5862 }
5863 if (strcmp(dns_kasp_getname(zone->kasp), "none") != 0) {
5864 return (false);
5865 }
5866 /*
5867 * "dnssec-policy none", but if there are key state files
5868 * this zone used to be secure but is transitioning back to
5869 * insecure.
5870 */
5871 return (statefile_exist(zone));
5872 }
5873
5874 bool
5875 dns_zone_use_kasp(dns_zone_t *zone) {
5876 dns_kasp_t *kasp = dns_zone_getkasp(zone);
5877
5878 if (kasp == NULL) {
5879 return (false);
5880 } else if (strcmp(dns_kasp_getname(kasp), "none") != 0) {
5881 return (true);
5882 }
5883 return dns_zone_secure_to_insecure(zone, false);
5884 }
5885
5886 void
5887 dns_zone_setoption(dns_zone_t *zone, dns_zoneopt_t option, bool value) {
5888 REQUIRE(DNS_ZONE_VALID(zone));
5889
5890 if (value) {
5891 DNS_ZONE_SETOPTION(zone, option);
5892 } else {
5893 DNS_ZONE_CLROPTION(zone, option);
5894 }
5895 }
5896
5897 dns_zoneopt_t
5898 dns_zone_getoptions(dns_zone_t *zone) {
5899 REQUIRE(DNS_ZONE_VALID(zone));
5900
5901 return (atomic_load_relaxed(&zone->options));
5902 }
5903
5904 void
5905 dns_zone_setkeyopt(dns_zone_t *zone, unsigned int keyopt, bool value) {
5906 REQUIRE(DNS_ZONE_VALID(zone));
5907
5908 if (value) {
5909 DNS_ZONEKEY_SETOPTION(zone, keyopt);
5910 } else {
5911 DNS_ZONEKEY_CLROPTION(zone, keyopt);
5912 }
5913 }
5914
5915 unsigned int
5916 dns_zone_getkeyopts(dns_zone_t *zone) {
5917 REQUIRE(DNS_ZONE_VALID(zone));
5918
5919 return (atomic_load_relaxed(&zone->keyopts));
5920 }
5921
5922 isc_result_t
5923 dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
5924 REQUIRE(DNS_ZONE_VALID(zone));
5925
5926 LOCK_ZONE(zone);
5927 zone->xfrsource4 = *xfrsource;
5928 UNLOCK_ZONE(zone);
5929
5930 return (ISC_R_SUCCESS);
5931 }
5932
5933 isc_sockaddr_t *
5934 dns_zone_getxfrsource4(dns_zone_t *zone) {
5935 REQUIRE(DNS_ZONE_VALID(zone));
5936 return (&zone->xfrsource4);
5937 }
5938
5939 isc_result_t
5940 dns_zone_setxfrsource4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5941 REQUIRE(DNS_ZONE_VALID(zone));
5942
5943 LOCK_ZONE(zone);
5944 zone->xfrsource4dscp = dscp;
5945 UNLOCK_ZONE(zone);
5946
5947 return (ISC_R_SUCCESS);
5948 }
5949
5950 isc_dscp_t
5951 dns_zone_getxfrsource4dscp(dns_zone_t *zone) {
5952 REQUIRE(DNS_ZONE_VALID(zone));
5953 return (zone->xfrsource4dscp);
5954 }
5955
5956 isc_result_t
5957 dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
5958 REQUIRE(DNS_ZONE_VALID(zone));
5959
5960 LOCK_ZONE(zone);
5961 zone->xfrsource6 = *xfrsource;
5962 UNLOCK_ZONE(zone);
5963
5964 return (ISC_R_SUCCESS);
5965 }
5966
5967 isc_sockaddr_t *
5968 dns_zone_getxfrsource6(dns_zone_t *zone) {
5969 REQUIRE(DNS_ZONE_VALID(zone));
5970 return (&zone->xfrsource6);
5971 }
5972
5973 isc_dscp_t
5974 dns_zone_getxfrsource6dscp(dns_zone_t *zone) {
5975 REQUIRE(DNS_ZONE_VALID(zone));
5976 return (zone->xfrsource6dscp);
5977 }
5978
5979 isc_result_t
5980 dns_zone_setxfrsource6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5981 REQUIRE(DNS_ZONE_VALID(zone));
5982
5983 LOCK_ZONE(zone);
5984 zone->xfrsource6dscp = dscp;
5985 UNLOCK_ZONE(zone);
5986
5987 return (ISC_R_SUCCESS);
5988 }
5989
5990 isc_result_t
5991 dns_zone_setaltxfrsource4(dns_zone_t *zone,
5992 const isc_sockaddr_t *altxfrsource) {
5993 REQUIRE(DNS_ZONE_VALID(zone));
5994
5995 LOCK_ZONE(zone);
5996 zone->altxfrsource4 = *altxfrsource;
5997 UNLOCK_ZONE(zone);
5998
5999 return (ISC_R_SUCCESS);
6000 }
6001
6002 isc_sockaddr_t *
6003 dns_zone_getaltxfrsource4(dns_zone_t *zone) {
6004 REQUIRE(DNS_ZONE_VALID(zone));
6005 return (&zone->altxfrsource4);
6006 }
6007
6008 isc_result_t
6009 dns_zone_setaltxfrsource4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
6010 REQUIRE(DNS_ZONE_VALID(zone));
6011
6012 LOCK_ZONE(zone);
6013 zone->altxfrsource4dscp = dscp;
6014 UNLOCK_ZONE(zone);
6015
6016 return (ISC_R_SUCCESS);
6017 }
6018
6019 isc_dscp_t
6020 dns_zone_getaltxfrsource4dscp(dns_zone_t *zone) {
6021 REQUIRE(DNS_ZONE_VALID(zone));
6022 return (zone->altxfrsource4dscp);
6023 }
6024
6025 isc_result_t
6026 dns_zone_setaltxfrsource6(dns_zone_t *zone,
6027 const isc_sockaddr_t *altxfrsource) {
6028 REQUIRE(DNS_ZONE_VALID(zone));
6029
6030 LOCK_ZONE(zone);
6031 zone->altxfrsource6 = *altxfrsource;
6032 UNLOCK_ZONE(zone);
6033
6034 return (ISC_R_SUCCESS);
6035 }
6036
6037 isc_sockaddr_t *
6038 dns_zone_getaltxfrsource6(dns_zone_t *zone) {
6039 REQUIRE(DNS_ZONE_VALID(zone));
6040 return (&zone->altxfrsource6);
6041 }
6042
6043 isc_result_t
6044 dns_zone_setaltxfrsource6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
6045 REQUIRE(DNS_ZONE_VALID(zone));
6046
6047 LOCK_ZONE(zone);
6048 zone->altxfrsource6dscp = dscp;
6049 UNLOCK_ZONE(zone);
6050
6051 return (ISC_R_SUCCESS);
6052 }
6053
6054 isc_dscp_t
6055 dns_zone_getaltxfrsource6dscp(dns_zone_t *zone) {
6056 REQUIRE(DNS_ZONE_VALID(zone));
6057 return (zone->altxfrsource6dscp);
6058 }
6059
6060 isc_result_t
6061 dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
6062 REQUIRE(DNS_ZONE_VALID(zone));
6063
6064 LOCK_ZONE(zone);
6065 zone->notifysrc4 = *notifysrc;
6066 UNLOCK_ZONE(zone);
6067
6068 return (ISC_R_SUCCESS);
6069 }
6070
6071 isc_sockaddr_t *
6072 dns_zone_getnotifysrc4(dns_zone_t *zone) {
6073 REQUIRE(DNS_ZONE_VALID(zone));
6074 return (&zone->notifysrc4);
6075 }
6076
6077 isc_result_t
6078 dns_zone_setnotifysrc4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
6079 REQUIRE(DNS_ZONE_VALID(zone));
6080
6081 LOCK_ZONE(zone);
6082 zone->notifysrc4dscp = dscp;
6083 UNLOCK_ZONE(zone);
6084
6085 return (ISC_R_SUCCESS);
6086 }
6087
6088 isc_dscp_t
6089 dns_zone_getnotifysrc4dscp(dns_zone_t *zone) {
6090 REQUIRE(DNS_ZONE_VALID(zone));
6091 return (zone->notifysrc4dscp);
6092 }
6093
6094 isc_result_t
6095 dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
6096 REQUIRE(DNS_ZONE_VALID(zone));
6097
6098 LOCK_ZONE(zone);
6099 zone->notifysrc6 = *notifysrc;
6100 UNLOCK_ZONE(zone);
6101
6102 return (ISC_R_SUCCESS);
6103 }
6104
6105 isc_sockaddr_t *
6106 dns_zone_getnotifysrc6(dns_zone_t *zone) {
6107 REQUIRE(DNS_ZONE_VALID(zone));
6108 return (&zone->notifysrc6);
6109 }
6110
6111 static bool
6112 same_addrs(isc_sockaddr_t const *oldlist, isc_sockaddr_t const *newlist,
6113 uint32_t count) {
6114 unsigned int i;
6115
6116 for (i = 0; i < count; i++) {
6117 if (!isc_sockaddr_equal(&oldlist[i], &newlist[i])) {
6118 return (false);
6119 }
6120 }
6121 return (true);
6122 }
6123
6124 static bool
6125 same_keynames(dns_name_t *const *oldlist, dns_name_t *const *newlist,
6126 uint32_t count) {
6127 unsigned int i;
6128
6129 if (oldlist == NULL && newlist == NULL) {
6130 return (true);
6131 }
6132 if (oldlist == NULL || newlist == NULL) {
6133 return (false);
6134 }
6135
6136 for (i = 0; i < count; i++) {
6137 if (oldlist[i] == NULL && newlist[i] == NULL) {
6138 continue;
6139 }
6140 if (oldlist[i] == NULL || newlist[i] == NULL ||
6141 !dns_name_equal(oldlist[i], newlist[i]))
6142 {
6143 return (false);
6144 }
6145 }
6146 return (true);
6147 }
6148
6149 static void
6150 clear_addresskeylist(isc_sockaddr_t **addrsp, isc_dscp_t **dscpsp,
6151 dns_name_t ***keynamesp, unsigned int *countp,
6152 isc_mem_t *mctx) {
6153 unsigned int count;
6154 isc_sockaddr_t *addrs;
6155 isc_dscp_t *dscps;
6156 dns_name_t **keynames;
6157
6158 REQUIRE(countp != NULL && addrsp != NULL && dscpsp != NULL &&
6159 keynamesp != NULL);
6160
6161 count = *countp;
6162 *countp = 0;
6163 addrs = *addrsp;
6164 *addrsp = NULL;
6165 dscps = *dscpsp;
6166 *dscpsp = NULL;
6167 keynames = *keynamesp;
6168 *keynamesp = NULL;
6169
6170 if (addrs != NULL) {
6171 isc_mem_put(mctx, addrs, count * sizeof(isc_sockaddr_t));
6172 }
6173
6174 if (dscps != NULL) {
6175 isc_mem_put(mctx, dscps, count * sizeof(isc_dscp_t));
6176 }
6177
6178 if (keynames != NULL) {
6179 unsigned int i;
6180 for (i = 0; i < count; i++) {
6181 if (keynames[i] != NULL) {
6182 dns_name_free(keynames[i], mctx);
6183 isc_mem_put(mctx, keynames[i],
6184 sizeof(dns_name_t));
6185 keynames[i] = NULL;
6186 }
6187 }
6188 isc_mem_put(mctx, keynames, count * sizeof(dns_name_t *));
6189 }
6190 }
6191
6192 static isc_result_t
6193 set_addrkeylist(unsigned int count, const isc_sockaddr_t *addrs,
6194 isc_sockaddr_t **newaddrsp, const isc_dscp_t *dscp,
6195 isc_dscp_t **newdscpp, dns_name_t **names,
6196 dns_name_t ***newnamesp, isc_mem_t *mctx) {
6197 isc_sockaddr_t *newaddrs = NULL;
6198 isc_dscp_t *newdscp = NULL;
6199 dns_name_t **newnames = NULL;
6200 unsigned int i;
6201
6202 REQUIRE(newaddrsp != NULL && *newaddrsp == NULL);
6203 REQUIRE(newdscpp != NULL && *newdscpp == NULL);
6204 REQUIRE(newnamesp != NULL && *newnamesp == NULL);
6205
6206 newaddrs = isc_mem_get(mctx, count * sizeof(*newaddrs));
6207 memmove(newaddrs, addrs, count * sizeof(*newaddrs));
6208
6209 if (dscp != NULL) {
6210 newdscp = isc_mem_get(mctx, count * sizeof(*newdscp));
6211 memmove(newdscp, dscp, count * sizeof(*newdscp));
6212 } else {
6213 newdscp = NULL;
6214 }
6215
6216 if (names != NULL) {
6217 newnames = isc_mem_get(mctx, count * sizeof(*newnames));
6218 for (i = 0; i < count; i++) {
6219 newnames[i] = NULL;
6220 }
6221 for (i = 0; i < count; i++) {
6222 if (names[i] != NULL) {
6223 newnames[i] = isc_mem_get(mctx,
6224 sizeof(dns_name_t));
6225 dns_name_init(newnames[i], NULL);
6226 dns_name_dup(names[i], mctx, newnames[i]);
6227 }
6228 }
6229 } else {
6230 newnames = NULL;
6231 }
6232
6233 *newdscpp = newdscp;
6234 *newaddrsp = newaddrs;
6235 *newnamesp = newnames;
6236 return (ISC_R_SUCCESS);
6237 }
6238
6239 isc_result_t
6240 dns_zone_setnotifysrc6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
6241 REQUIRE(DNS_ZONE_VALID(zone));
6242
6243 LOCK_ZONE(zone);
6244 zone->notifysrc6dscp = dscp;
6245 UNLOCK_ZONE(zone);
6246
6247 return (ISC_R_SUCCESS);
6248 }
6249
6250 isc_dscp_t
6251 dns_zone_getnotifysrc6dscp(dns_zone_t *zone) {
6252 REQUIRE(DNS_ZONE_VALID(zone));
6253 return (zone->notifysrc6dscp);
6254 }
6255
6256 isc_result_t
6257 dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify,
6258 uint32_t count) {
6259 return (dns_zone_setalsonotifydscpkeys(zone, notify, NULL, NULL,
6260 count));
6261 }
6262
6263 isc_result_t
6264 dns_zone_setalsonotifywithkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
6265 dns_name_t **keynames, uint32_t count) {
6266 return (dns_zone_setalsonotifydscpkeys(zone, notify, NULL, keynames,
6267 count));
6268 }
6269
6270 isc_result_t
6271 dns_zone_setalsonotifydscpkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
6272 const isc_dscp_t *dscps, dns_name_t **keynames,
6273 uint32_t count) {
6274 isc_result_t result;
6275 isc_sockaddr_t *newaddrs = NULL;
6276 isc_dscp_t *newdscps = NULL;
6277 dns_name_t **newnames = NULL;
6278
6279 REQUIRE(DNS_ZONE_VALID(zone));
6280 REQUIRE(count == 0 || notify != NULL);
6281 if (keynames != NULL) {
6282 REQUIRE(count != 0);
6283 }
6284
6285 LOCK_ZONE(zone);
6286
6287 if (count == zone->notifycnt &&
6288 same_addrs(zone->notify, notify, count) &&
6289 same_keynames(zone->notifykeynames, keynames, count))
6290 {
6291 goto unlock;
6292 }
6293
6294 clear_addresskeylist(&zone->notify, &zone->notifydscp,
6295 &zone->notifykeynames, &zone->notifycnt,
6296 zone->mctx);
6297
6298 if (count == 0) {
6299 goto unlock;
6300 }
6301
6302 /*
6303 * Set up the notify and notifykey lists
6304 */
6305 result = set_addrkeylist(count, notify, &newaddrs, dscps, &newdscps,
6306 keynames, &newnames, zone->mctx);
6307 if (result != ISC_R_SUCCESS) {
6308 goto unlock;
6309 }
6310
6311 /*
6312 * Everything is ok so attach to the zone.
6313 */
6314 zone->notify = newaddrs;
6315 zone->notifydscp = newdscps;
6316 zone->notifykeynames = newnames;
6317 zone->notifycnt = count;
6318 unlock:
6319 UNLOCK_ZONE(zone);
6320 return (ISC_R_SUCCESS);
6321 }
6322
6323 isc_result_t
6324 dns_zone_setprimaries(dns_zone_t *zone, const isc_sockaddr_t *masters,
6325 uint32_t count) {
6326 isc_result_t result;
6327
6328 result = dns_zone_setprimarieswithkeys(zone, masters, NULL, count);
6329 return (result);
6330 }
6331
6332 isc_result_t
6333 dns_zone_setprimarieswithkeys(dns_zone_t *zone, const isc_sockaddr_t *masters,
6334 dns_name_t **keynames, uint32_t count) {
6335 isc_result_t result = ISC_R_SUCCESS;
6336 isc_sockaddr_t *newaddrs = NULL;
6337 isc_dscp_t *newdscps = NULL;
6338 dns_name_t **newnames = NULL;
6339 bool *newok;
6340 unsigned int i;
6341
6342 REQUIRE(DNS_ZONE_VALID(zone));
6343 REQUIRE(count == 0 || masters != NULL);
6344 if (keynames != NULL) {
6345 REQUIRE(count != 0);
6346 }
6347
6348 LOCK_ZONE(zone);
6349 /*
6350 * The refresh code assumes that 'primaries' wouldn't change under it.
6351 * If it will change then kill off any current refresh in progress
6352 * and update the primaries info. If it won't change then we can just
6353 * unlock and exit.
6354 */
6355 if (count != zone->masterscnt ||
6356 !same_addrs(zone->masters, masters, count) ||
6357 !same_keynames(zone->masterkeynames, keynames, count))
6358 {
6359 if (zone->request != NULL) {
6360 dns_request_cancel(zone->request);
6361 }
6362 } else {
6363 goto unlock;
6364 }
6365
6366 /*
6367 * This needs to happen before clear_addresskeylist() sets
6368 * zone->masterscnt to 0:
6369 */
6370 if (zone->mastersok != NULL) {
6371 isc_mem_put(zone->mctx, zone->mastersok,
6372 zone->masterscnt * sizeof(bool));
6373 zone->mastersok = NULL;
6374 }
6375 clear_addresskeylist(&zone->masters, &zone->masterdscps,
6376 &zone->masterkeynames, &zone->masterscnt,
6377 zone->mctx);
6378 /*
6379 * If count == 0, don't allocate any space for masters, mastersok or
6380 * keynames so internally, those pointers are NULL if count == 0
6381 */
6382 if (count == 0) {
6383 goto unlock;
6384 }
6385
6386 /*
6387 * mastersok must contain count elements
6388 */
6389 newok = isc_mem_get(zone->mctx, count * sizeof(*newok));
6390 for (i = 0; i < count; i++) {
6391 newok[i] = false;
6392 }
6393
6394 /*
6395 * Now set up the primaries and primary key lists
6396 */
6397 result = set_addrkeylist(count, masters, &newaddrs, NULL, &newdscps,
6398 keynames, &newnames, zone->mctx);
6399 INSIST(newdscps == NULL);
6400 if (result != ISC_R_SUCCESS) {
6401 isc_mem_put(zone->mctx, newok, count * sizeof(*newok));
6402 goto unlock;
6403 }
6404
6405 /*
6406 * Everything is ok so attach to the zone.
6407 */
6408 zone->curmaster = 0;
6409 zone->mastersok = newok;
6410 zone->masters = newaddrs;
6411 zone->masterdscps = newdscps;
6412 zone->masterkeynames = newnames;
6413 zone->masterscnt = count;
6414 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS);
6415
6416 unlock:
6417 UNLOCK_ZONE(zone);
6418 return (result);
6419 }
6420
6421 isc_result_t
6422 dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) {
6423 isc_result_t result = ISC_R_SUCCESS;
6424
6425 REQUIRE(DNS_ZONE_VALID(zone));
6426
6427 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6428 if (zone->db == NULL) {
6429 result = DNS_R_NOTLOADED;
6430 } else {
6431 dns_db_attach(zone->db, dpb);
6432 }
6433 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6434
6435 return (result);
6436 }
6437
6438 void
6439 dns_zone_setdb(dns_zone_t *zone, dns_db_t *db) {
6440 REQUIRE(DNS_ZONE_VALID(zone));
6441 REQUIRE(zone->type == dns_zone_staticstub);
6442
6443 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
6444 REQUIRE(zone->db == NULL);
6445 dns_db_attach(db, &zone->db);
6446 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
6447 }
6448
6449 /*
6450 * Coordinates the starting of routine jobs.
6451 */
6452 void
6453 dns_zone_maintenance(dns_zone_t *zone) {
6454 const char me[] = "dns_zone_maintenance";
6455 isc_time_t now;
6456
6457 REQUIRE(DNS_ZONE_VALID(zone));
6458 ENTER;
6459
6460 LOCK_ZONE(zone);
6461 TIME_NOW(&now);
6462 zone_settimer(zone, &now);
6463 UNLOCK_ZONE(zone);
6464 }
6465
6466 static inline bool
6467 was_dumping(dns_zone_t *zone) {
6468 REQUIRE(LOCKED_ZONE(zone));
6469
6470 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
6471 return (true);
6472 }
6473
6474 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
6475 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
6476 isc_time_settoepoch(&zone->dumptime);
6477 return (false);
6478 }
6479
6480 /*%
6481 * Find up to 'maxkeys' DNSSEC keys used for signing version 'ver' of database
6482 * 'db' for zone 'zone' in its key directory, then load these keys into 'keys'.
6483 * Only load the public part of a given key if it is not active at timestamp
6484 * 'now'. Store the number of keys found in 'nkeys'.
6485 */
6486 isc_result_t
6487 dns__zone_findkeys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
6488 isc_stdtime_t now, isc_mem_t *mctx, unsigned int maxkeys,
6489 dst_key_t **keys, unsigned int *nkeys) {
6490 isc_result_t result;
6491 dns_dbnode_t *node = NULL;
6492 const char *directory = dns_zone_getkeydirectory(zone);
6493
6494 CHECK(dns_db_findnode(db, dns_db_origin(db), false, &node));
6495 memset(keys, 0, sizeof(*keys) * maxkeys);
6496 result = dns_dnssec_findzonekeys(db, ver, node, dns_db_origin(db),
6497 directory, now, mctx, maxkeys, keys,
6498 nkeys);
6499 if (result == ISC_R_NOTFOUND) {
6500 result = ISC_R_SUCCESS;
6501 }
6502 failure:
6503 if (node != NULL) {
6504 dns_db_detachnode(db, &node);
6505 }
6506 return (result);
6507 }
6508
6509 static isc_result_t
6510 offline(dns_db_t *db, dns_dbversion_t *ver, dns__zonediff_t *zonediff,
6511 dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata) {
6512 isc_result_t result;
6513
6514 if ((rdata->flags & DNS_RDATA_OFFLINE) != 0) {
6515 return (ISC_R_SUCCESS);
6516 }
6517 result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_DELRESIGN,
6518 name, ttl, rdata);
6519 if (result != ISC_R_SUCCESS) {
6520 return (result);
6521 }
6522 rdata->flags |= DNS_RDATA_OFFLINE;
6523 result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_ADDRESIGN,
6524 name, ttl, rdata);
6525 zonediff->offline = true;
6526 return (result);
6527 }
6528
6529 static void
6530 set_key_expiry_warning(dns_zone_t *zone, isc_stdtime_t when,
6531 isc_stdtime_t now) {
6532 unsigned int delta;
6533 char timebuf[80];
6534
6535 zone->key_expiry = when;
6536 if (when <= now) {
6537 dns_zone_log(zone, ISC_LOG_ERROR,
6538 "DNSKEY RRSIG(s) have expired");
6539 isc_time_settoepoch(&zone->keywarntime);
6540 } else if (when < now + 7 * 24 * 3600) {
6541 isc_time_t t;
6542 isc_time_set(&t, when, 0);
6543 isc_time_formattimestamp(&t, timebuf, 80);
6544 dns_zone_log(zone, ISC_LOG_WARNING,
6545 "DNSKEY RRSIG(s) will expire within 7 days: %s",
6546 timebuf);
6547 delta = when - now;
6548 delta--; /* loop prevention */
6549 delta /= 24 * 3600; /* to whole days */
6550 delta *= 24 * 3600; /* to seconds */
6551 isc_time_set(&zone->keywarntime, when - delta, 0);
6552 } else {
6553 isc_time_set(&zone->keywarntime, when - 7 * 24 * 3600, 0);
6554 isc_time_formattimestamp(&zone->keywarntime, timebuf, 80);
6555 dns_zone_log(zone, ISC_LOG_NOTICE, "setting keywarntime to %s",
6556 timebuf);
6557 }
6558 }
6559
6560 /*
6561 * Helper function to del_sigs(). We don't want to delete RRSIGs that
6562 * have no new key.
6563 */
6564 static bool
6565 delsig_ok(dns_rdata_rrsig_t *rrsig_ptr, dst_key_t **keys, unsigned int nkeys,
6566 bool *warn) {
6567 unsigned int i = 0;
6568 isc_result_t ret;
6569 bool have_ksk = false, have_zsk = false;
6570 bool have_pksk = false, have_pzsk = false;
6571
6572 for (i = 0; i < nkeys; i++) {
6573 bool ksk, zsk;
6574
6575 if (have_pksk && have_ksk && have_pzsk && have_zsk) {
6576 break;
6577 }
6578
6579 if (rrsig_ptr->algorithm != dst_key_alg(keys[i])) {
6580 continue;
6581 }
6582
6583 ret = dst_key_getbool(keys[i], DST_BOOL_KSK, &ksk);
6584 if (ret != ISC_R_SUCCESS) {
6585 ksk = KSK(keys[i]);
6586 }
6587 ret = dst_key_getbool(keys[i], DST_BOOL_ZSK, &zsk);
6588 if (ret != ISC_R_SUCCESS) {
6589 zsk = !KSK(keys[i]);
6590 }
6591
6592 if (ksk) {
6593 have_ksk = true;
6594 if (dst_key_isprivate(keys[i])) {
6595 have_pksk = true;
6596 }
6597 }
6598 if (zsk) {
6599 have_zsk = true;
6600 if (dst_key_isprivate(keys[i])) {
6601 have_pzsk = true;
6602 }
6603 }
6604 }
6605
6606 if (have_zsk && have_ksk && !have_pzsk) {
6607 *warn = true;
6608 }
6609
6610 /*
6611 * It's okay to delete a signature if there is an active key
6612 * with the same algorithm to replace it.
6613 */
6614 if (have_pksk || have_pzsk) {
6615 return (true);
6616 }
6617
6618 /*
6619 * Failing that, it is *not* okay to delete a signature
6620 * if the associated public key is still in the DNSKEY RRset
6621 */
6622 for (i = 0; i < nkeys; i++) {
6623 if ((rrsig_ptr->algorithm == dst_key_alg(keys[i])) &&
6624 (rrsig_ptr->keyid == dst_key_id(keys[i])))
6625 {
6626 return (false);
6627 }
6628 }
6629
6630 /*
6631 * But if the key is gone, then go ahead.
6632 */
6633 return (true);
6634 }
6635
6636 /*
6637 * Delete expired RRsigs and any RRsigs we are about to re-sign.
6638 * See also update.c:del_keysigs().
6639 */
6640 static isc_result_t
6641 del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
6642 dns_rdatatype_t type, dns__zonediff_t *zonediff, dst_key_t **keys,
6643 unsigned int nkeys, isc_stdtime_t now, bool incremental) {
6644 isc_result_t result;
6645 dns_dbnode_t *node = NULL;
6646 dns_rdataset_t rdataset;
6647 unsigned int i;
6648 dns_rdata_rrsig_t rrsig;
6649 bool found;
6650 int64_t timewarn = 0, timemaybe = 0;
6651
6652 dns_rdataset_init(&rdataset);
6653
6654 if (type == dns_rdatatype_nsec3) {
6655 result = dns_db_findnsec3node(db, name, false, &node);
6656 } else {
6657 result = dns_db_findnode(db, name, false, &node);
6658 }
6659 if (result == ISC_R_NOTFOUND) {
6660 return (ISC_R_SUCCESS);
6661 }
6662 if (result != ISC_R_SUCCESS) {
6663 goto failure;
6664 }
6665 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig, type,
6666 (isc_stdtime_t)0, &rdataset, NULL);
6667 dns_db_detachnode(db, &node);
6668
6669 if (result == ISC_R_NOTFOUND) {
6670 INSIST(!dns_rdataset_isassociated(&rdataset));
6671 return (ISC_R_SUCCESS);
6672 }
6673 if (result != ISC_R_SUCCESS) {
6674 INSIST(!dns_rdataset_isassociated(&rdataset));
6675 goto failure;
6676 }
6677
6678 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
6679 result = dns_rdataset_next(&rdataset))
6680 {
6681 dns_rdata_t rdata = DNS_RDATA_INIT;
6682
6683 dns_rdataset_current(&rdataset, &rdata);
6684 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
6685 RUNTIME_CHECK(result == ISC_R_SUCCESS);
6686
6687 if (type != dns_rdatatype_dnskey && type != dns_rdatatype_cds &&
6688 type != dns_rdatatype_cdnskey)
6689 {
6690 bool warn = false, deleted = false;
6691 if (delsig_ok(&rrsig, keys, nkeys, &warn)) {
6692 result = update_one_rr(db, ver, zonediff->diff,
6693 DNS_DIFFOP_DELRESIGN,
6694 name, rdataset.ttl,
6695 &rdata);
6696 if (result != ISC_R_SUCCESS) {
6697 break;
6698 }
6699 deleted = true;
6700 }
6701 if (warn) {
6702 /*
6703 * At this point, we've got an RRSIG,
6704 * which is signed by an inactive key.
6705 * An administrator needs to provide a new
6706 * key/alg, but until that time, we want to
6707 * keep the old RRSIG. Marking the key as
6708 * offline will prevent us spinning waiting
6709 * for the private part.
6710 */
6711 if (incremental && !deleted) {
6712 result = offline(db, ver, zonediff,
6713 name, rdataset.ttl,
6714 &rdata);
6715 if (result != ISC_R_SUCCESS) {
6716 break;
6717 }
6718 }
6719
6720 /*
6721 * Log the key id and algorithm of
6722 * the inactive key with no replacement
6723 */
6724 if (zone->log_key_expired_timer <= now) {
6725 char origin[DNS_NAME_FORMATSIZE];
6726 char algbuf[DNS_NAME_FORMATSIZE];
6727 dns_name_format(&zone->origin, origin,
6728 sizeof(origin));
6729 dns_secalg_format(rrsig.algorithm,
6730 algbuf,
6731 sizeof(algbuf));
6732 dns_zone_log(zone, ISC_LOG_WARNING,
6733 "Key %s/%s/%d "
6734 "missing or inactive "
6735 "and has no replacement: "
6736 "retaining signatures.",
6737 origin, algbuf,
6738 rrsig.keyid);
6739 zone->log_key_expired_timer = now +
6740 3600;
6741 }
6742 }
6743 continue;
6744 }
6745
6746 /*
6747 * KSK RRSIGs requires special processing.
6748 */
6749 found = false;
6750 for (i = 0; i < nkeys; i++) {
6751 if (rrsig.algorithm == dst_key_alg(keys[i]) &&
6752 rrsig.keyid == dst_key_id(keys[i]))
6753 {
6754 found = true;
6755 /*
6756 * Mark offline DNSKEY.
6757 * We want the earliest offline expire time
6758 * iff there is a new offline signature.
6759 */
6760 if (!dst_key_inactive(keys[i]) &&
6761 !dst_key_isprivate(keys[i])) {
6762 int64_t timeexpire = dns_time64_from32(
6763 rrsig.timeexpire);
6764 if (timewarn != 0 &&
6765 timewarn > timeexpire) {
6766 timewarn = timeexpire;
6767 }
6768 if (rdata.flags & DNS_RDATA_OFFLINE) {
6769 if (timemaybe == 0 ||
6770 timemaybe > timeexpire) {
6771 timemaybe = timeexpire;
6772 }
6773 break;
6774 }
6775 if (timewarn == 0) {
6776 timewarn = timemaybe;
6777 }
6778 if (timewarn == 0 ||
6779 timewarn > timeexpire) {
6780 timewarn = timeexpire;
6781 }
6782 result = offline(db, ver, zonediff,
6783 name, rdataset.ttl,
6784 &rdata);
6785 break;
6786 }
6787 result = update_one_rr(db, ver, zonediff->diff,
6788 DNS_DIFFOP_DELRESIGN,
6789 name, rdataset.ttl,
6790 &rdata);
6791 break;
6792 }
6793 }
6794
6795 /*
6796 * If there is not a matching DNSKEY then
6797 * delete the RRSIG.
6798 */
6799 if (!found) {
6800 result = update_one_rr(db, ver, zonediff->diff,
6801 DNS_DIFFOP_DELRESIGN, name,
6802 rdataset.ttl, &rdata);
6803 }
6804 if (result != ISC_R_SUCCESS) {
6805 break;
6806 }
6807 }
6808
6809 dns_rdataset_disassociate(&rdataset);
6810 if (result == ISC_R_NOMORE) {
6811 result = ISC_R_SUCCESS;
6812 }
6813 if (timewarn > 0) {
6814 isc_stdtime_t stdwarn = (isc_stdtime_t)timewarn;
6815 if (timewarn == stdwarn) {
6816 set_key_expiry_warning(zone, (isc_stdtime_t)timewarn,
6817 now);
6818 } else {
6819 dns_zone_log(zone, ISC_LOG_ERROR,
6820 "key expiry warning time out of range");
6821 }
6822 }
6823 failure:
6824 if (node != NULL) {
6825 dns_db_detachnode(db, &node);
6826 }
6827 return (result);
6828 }
6829
6830 static isc_result_t
6831 add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_zone_t *zone,
6832 dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
6833 unsigned int nkeys, isc_mem_t *mctx, isc_stdtime_t inception,
6834 isc_stdtime_t expire, bool check_ksk, bool keyset_kskonly) {
6835 isc_result_t result;
6836 dns_dbnode_t *node = NULL;
6837 dns_stats_t *dnssecsignstats;
6838 dns_rdataset_t rdataset;
6839 dns_rdata_t sig_rdata = DNS_RDATA_INIT;
6840 unsigned char data[1024]; /* XXX */
6841 isc_buffer_t buffer;
6842 unsigned int i, j;
6843 bool use_kasp = false;
6844
6845 if (dns_zone_use_kasp(zone)) {
6846 check_ksk = false;
6847 keyset_kskonly = true;
6848 use_kasp = true;
6849 }
6850
6851 dns_rdataset_init(&rdataset);
6852 isc_buffer_init(&buffer, data, sizeof(data));
6853
6854 if (type == dns_rdatatype_nsec3) {
6855 result = dns_db_findnsec3node(db, name, false, &node);
6856 } else {
6857 result = dns_db_findnode(db, name, false, &node);
6858 }
6859 if (result == ISC_R_NOTFOUND) {
6860 return (ISC_R_SUCCESS);
6861 }
6862 if (result != ISC_R_SUCCESS) {
6863 goto failure;
6864 }
6865 result = dns_db_findrdataset(db, node, ver, type, 0, (isc_stdtime_t)0,
6866 &rdataset, NULL);
6867 dns_db_detachnode(db, &node);
6868 if (result == ISC_R_NOTFOUND) {
6869 INSIST(!dns_rdataset_isassociated(&rdataset));
6870 return (ISC_R_SUCCESS);
6871 }
6872 if (result != ISC_R_SUCCESS) {
6873 INSIST(!dns_rdataset_isassociated(&rdataset));
6874 goto failure;
6875 }
6876
6877 for (i = 0; i < nkeys; i++) {
6878 bool both = false;
6879
6880 /* Don't add signatures for offline or inactive keys */
6881 if (!dst_key_isprivate(keys[i])) {
6882 continue;
6883 }
6884 if (dst_key_inactive(keys[i])) {
6885 continue;
6886 }
6887
6888 if (check_ksk && !REVOKE(keys[i])) {
6889 bool have_ksk, have_nonksk;
6890 if (KSK(keys[i])) {
6891 have_ksk = true;
6892 have_nonksk = false;
6893 } else {
6894 have_ksk = false;
6895 have_nonksk = true;
6896 }
6897
6898 for (j = 0; j < nkeys; j++) {
6899 if (j == i || ALG(keys[i]) != ALG(keys[j])) {
6900 continue;
6901 }
6902
6903 /* Don't consider inactive keys, however
6904 * the key may be temporary offline, so do
6905 * consider keys which private key files are
6906 * unavailable.
6907 */
6908 if (dst_key_inactive(keys[j])) {
6909 continue;
6910 }
6911
6912 if (REVOKE(keys[j])) {
6913 continue;
6914 }
6915 if (KSK(keys[j])) {
6916 have_ksk = true;
6917 } else {
6918 have_nonksk = true;
6919 }
6920 both = have_ksk && have_nonksk;
6921 if (both) {
6922 break;
6923 }
6924 }
6925 }
6926 if (use_kasp) {
6927 /*
6928 * A dnssec-policy is found. Check what RRsets this
6929 * key should sign.
6930 */
6931 isc_result_t kresult;
6932 isc_stdtime_t when;
6933 bool ksk = false;
6934 bool zsk = false;
6935
6936 kresult = dst_key_getbool(keys[i], DST_BOOL_KSK, &ksk);
6937 if (kresult != ISC_R_SUCCESS) {
6938 if (KSK(keys[i])) {
6939 ksk = true;
6940 }
6941 }
6942 kresult = dst_key_getbool(keys[i], DST_BOOL_ZSK, &zsk);
6943 if (kresult != ISC_R_SUCCESS) {
6944 if (!KSK(keys[i])) {
6945 zsk = true;
6946 }
6947 }
6948
6949 if (type == dns_rdatatype_dnskey ||
6950 type == dns_rdatatype_cdnskey ||
6951 type == dns_rdatatype_cds)
6952 {
6953 /*
6954 * DNSKEY RRset is signed with KSK.
6955 * CDS and CDNSKEY RRsets too (RFC 7344, 4.1).
6956 */
6957 if (!ksk) {
6958 continue;
6959 }
6960 } else if (!zsk) {
6961 /*
6962 * Other RRsets are signed with ZSK.
6963 */
6964 continue;
6965 } else if (!dst_key_is_signing(keys[i], DST_BOOL_ZSK,
6966 inception, &when)) {
6967 /*
6968 * This key is not active for zone-signing.
6969 */
6970 continue;
6971 }
6972
6973 /*
6974 * If this key is revoked, it may only sign the
6975 * DNSKEY RRset.
6976 */
6977 if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey) {
6978 continue;
6979 }
6980 } else if (both) {
6981 /*
6982 * CDS and CDNSKEY are signed with KSK (RFC 7344, 4.1).
6983 */
6984 if (type == dns_rdatatype_dnskey ||
6985 type == dns_rdatatype_cdnskey ||
6986 type == dns_rdatatype_cds)
6987 {
6988 if (!KSK(keys[i]) && keyset_kskonly) {
6989 continue;
6990 }
6991 } else if (KSK(keys[i])) {
6992 continue;
6993 }
6994 } else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey) {
6995 continue;
6996 }
6997
6998 /* Calculate the signature, creating a RRSIG RDATA. */
6999 isc_buffer_clear(&buffer);
7000 CHECK(dns_dnssec_sign(name, &rdataset, keys[i], &inception,
7001 &expire, mctx, &buffer, &sig_rdata));
7002
7003 /* Update the database and journal with the RRSIG. */
7004 /* XXX inefficient - will cause dataset merging */
7005 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN, name,
7006 rdataset.ttl, &sig_rdata));
7007 dns_rdata_reset(&sig_rdata);
7008 isc_buffer_init(&buffer, data, sizeof(data));
7009
7010 /* Update DNSSEC sign statistics. */
7011 dnssecsignstats = dns_zone_getdnssecsignstats(zone);
7012 if (dnssecsignstats != NULL) {
7013 /* Generated a new signature. */
7014 dns_dnssecsignstats_increment(dnssecsignstats,
7015 ID(keys[i]),
7016 (uint8_t)ALG(keys[i]),
7017 dns_dnssecsignstats_sign);
7018 /* This is a refresh. */
7019 dns_dnssecsignstats_increment(
7020 dnssecsignstats, ID(keys[i]),
7021 (uint8_t)ALG(keys[i]),
7022 dns_dnssecsignstats_refresh);
7023 }
7024 }
7025
7026 failure:
7027 if (dns_rdataset_isassociated(&rdataset)) {
7028 dns_rdataset_disassociate(&rdataset);
7029 }
7030 if (node != NULL) {
7031 dns_db_detachnode(db, &node);
7032 }
7033 return (result);
7034 }
7035
7036 static void
7037 zone_resigninc(dns_zone_t *zone) {
7038 const char *me = "zone_resigninc";
7039 dns_db_t *db = NULL;
7040 dns_dbversion_t *version = NULL;
7041 dns_diff_t _sig_diff;
7042 dns__zonediff_t zonediff;
7043 dns_fixedname_t fixed;
7044 dns_name_t *name;
7045 dns_rdataset_t rdataset;
7046 dns_rdatatype_t covers;
7047 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
7048 bool check_ksk, keyset_kskonly = false;
7049 isc_result_t result;
7050 isc_stdtime_t now, inception, soaexpire, expire, fullexpire, stop;
7051 uint32_t sigvalidityinterval, expiryinterval;
7052 unsigned int i;
7053 unsigned int nkeys = 0;
7054 unsigned int resign;
7055
7056 ENTER;
7057
7058 dns_rdataset_init(&rdataset);
7059 dns_diff_init(zone->mctx, &_sig_diff);
7060 zonediff_init(&zonediff, &_sig_diff);
7061
7062 /*
7063 * Zone is frozen or automatic resigning is disabled.
7064 * Pause for 5 minutes.
7065 */
7066 if (zone->update_disabled ||
7067 DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN)) {
7068 result = ISC_R_FAILURE;
7069 goto failure;
7070 }
7071
7072 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
7073 dns_db_attach(zone->db, &db);
7074 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7075
7076 result = dns_db_newversion(db, &version);
7077 if (result != ISC_R_SUCCESS) {
7078 dns_zone_log(zone, ISC_LOG_ERROR,
7079 "zone_resigninc:dns_db_newversion -> %s",
7080 dns_result_totext(result));
7081 goto failure;
7082 }
7083
7084 isc_stdtime_get(&now);
7085
7086 result = dns__zone_findkeys(zone, db, version, now, zone->mctx,
7087 DNS_MAXZONEKEYS, zone_keys, &nkeys);
7088 if (result != ISC_R_SUCCESS) {
7089 dns_zone_log(zone, ISC_LOG_ERROR,
7090 "zone_resigninc:dns__zone_findkeys -> %s",
7091 dns_result_totext(result));
7092 goto failure;
7093 }
7094
7095 sigvalidityinterval = dns_zone_getsigvalidityinterval(zone);
7096 inception = now - 3600; /* Allow for clock skew. */
7097 soaexpire = now + sigvalidityinterval;
7098 expiryinterval = dns_zone_getsigresigninginterval(zone);
7099 if (expiryinterval > sigvalidityinterval) {
7100 expiryinterval = sigvalidityinterval;
7101 } else {
7102 expiryinterval = sigvalidityinterval - expiryinterval;
7103 }
7104
7105 /*
7106 * Spread out signatures over time if they happen to be
7107 * clumped. We don't do this for each add_sigs() call as
7108 * we still want some clustering to occur. In normal operations
7109 * the records should be re-signed as they fall due and they should
7110 * already be spread out. However if the server is off for a
7111 * period we need to ensure that the clusters don't become
7112 * synchronised by using the full jitter range.
7113 */
7114 if (sigvalidityinterval >= 3600U) {
7115 uint32_t normaljitter, fulljitter;
7116 if (sigvalidityinterval > 7200U) {
7117 normaljitter = isc_random_uniform(3600);
7118 fulljitter = isc_random_uniform(expiryinterval);
7119 } else {
7120 normaljitter = fulljitter = isc_random_uniform(1200);
7121 }
7122 expire = soaexpire - normaljitter - 1;
7123 fullexpire = soaexpire - fulljitter - 1;
7124 } else {
7125 expire = fullexpire = soaexpire - 1;
7126 }
7127 stop = now + 5;
7128
7129 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
7130 keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
7131
7132 name = dns_fixedname_initname(&fixed);
7133 result = dns_db_getsigningtime(db, &rdataset, name);
7134 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
7135 dns_zone_log(zone, ISC_LOG_ERROR,
7136 "zone_resigninc:dns_db_getsigningtime -> %s",
7137 dns_result_totext(result));
7138 }
7139
7140 i = 0;
7141 while (result == ISC_R_SUCCESS) {
7142 resign = rdataset.resign -
7143 dns_zone_getsigresigninginterval(zone);
7144 covers = rdataset.covers;
7145 dns_rdataset_disassociate(&rdataset);
7146
7147 /*
7148 * Stop if we hit the SOA as that means we have walked the
7149 * entire zone. The SOA record should always be the most
7150 * recent signature.
7151 */
7152 /* XXXMPA increase number of RRsets signed pre call */
7153 if (covers == dns_rdatatype_soa || i++ > zone->signatures ||
7154 resign > stop) {
7155 break;
7156 }
7157
7158 result = del_sigs(zone, db, version, name, covers, &zonediff,
7159 zone_keys, nkeys, now, true);
7160 if (result != ISC_R_SUCCESS) {
7161 dns_zone_log(zone, ISC_LOG_ERROR,
7162 "zone_resigninc:del_sigs -> %s",
7163 dns_result_totext(result));
7164 break;
7165 }
7166
7167 /*
7168 * If re-signing is over 5 minutes late use 'fullexpire'
7169 * to redistribute the signature over the complete
7170 * re-signing window, otherwise only add a small amount
7171 * of jitter.
7172 */
7173 result = add_sigs(db, version, name, zone, covers,
7174 zonediff.diff, zone_keys, nkeys, zone->mctx,
7175 inception,
7176 resign > (now - 300) ? expire : fullexpire,
7177 check_ksk, keyset_kskonly);
7178 if (result != ISC_R_SUCCESS) {
7179 dns_zone_log(zone, ISC_LOG_ERROR,
7180 "zone_resigninc:add_sigs -> %s",
7181 dns_result_totext(result));
7182 break;
7183 }
7184 result = dns_db_getsigningtime(db, &rdataset, name);
7185 if (nkeys == 0 && result == ISC_R_NOTFOUND) {
7186 result = ISC_R_SUCCESS;
7187 break;
7188 }
7189 if (result != ISC_R_SUCCESS) {
7190 dns_zone_log(zone, ISC_LOG_ERROR,
7191 "zone_resigninc:dns_db_getsigningtime -> "
7192 "%s",
7193 dns_result_totext(result));
7194 }
7195 }
7196
7197 if (result != ISC_R_NOMORE && result != ISC_R_SUCCESS) {
7198 goto failure;
7199 }
7200
7201 result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
7202 &zonediff, zone_keys, nkeys, now, true);
7203 if (result != ISC_R_SUCCESS) {
7204 dns_zone_log(zone, ISC_LOG_ERROR,
7205 "zone_resigninc:del_sigs -> %s",
7206 dns_result_totext(result));
7207 goto failure;
7208 }
7209
7210 /*
7211 * Did we change anything in the zone?
7212 */
7213 if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
7214 /*
7215 * Commit the changes if any key has been marked as offline.
7216 */
7217 if (zonediff.offline) {
7218 dns_db_closeversion(db, &version, true);
7219 }
7220 goto failure;
7221 }
7222
7223 /* Increment SOA serial if we have made changes */
7224 result = update_soa_serial(zone, db, version, zonediff.diff, zone->mctx,
7225 zone->updatemethod);
7226 if (result != ISC_R_SUCCESS) {
7227 dns_zone_log(zone, ISC_LOG_ERROR,
7228 "zone_resigninc:update_soa_serial -> %s",
7229 dns_result_totext(result));
7230 goto failure;
7231 }
7232
7233 /*
7234 * Generate maximum life time signatures so that the above loop
7235 * termination is sensible.
7236 */
7237 result = add_sigs(db, version, &zone->origin, zone, dns_rdatatype_soa,
7238 zonediff.diff, zone_keys, nkeys, zone->mctx,
7239 inception, soaexpire, check_ksk, keyset_kskonly);
7240 if (result != ISC_R_SUCCESS) {
7241 dns_zone_log(zone, ISC_LOG_ERROR,
7242 "zone_resigninc:add_sigs -> %s",
7243 dns_result_totext(result));
7244 goto failure;
7245 }
7246
7247 /* Write changes to journal file. */
7248 CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_resigninc"));
7249
7250 /* Everything has succeeded. Commit the changes. */
7251 dns_db_closeversion(db, &version, true);
7252
7253 failure:
7254 dns_diff_clear(&_sig_diff);
7255 for (i = 0; i < nkeys; i++) {
7256 dst_key_free(&zone_keys[i]);
7257 }
7258 if (version != NULL) {
7259 dns_db_closeversion(db, &version, false);
7260 dns_db_detach(&db);
7261 } else if (db != NULL) {
7262 dns_db_detach(&db);
7263 }
7264
7265 LOCK_ZONE(zone);
7266 if (result == ISC_R_SUCCESS) {
7267 set_resigntime(zone);
7268 zone_needdump(zone, DNS_DUMP_DELAY);
7269 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
7270 } else {
7271 /*
7272 * Something failed. Retry in 5 minutes.
7273 */
7274 isc_interval_t ival;
7275 isc_interval_set(&ival, 300, 0);
7276 isc_time_nowplusinterval(&zone->resigntime, &ival);
7277 }
7278 UNLOCK_ZONE(zone);
7279
7280 INSIST(version == NULL);
7281 }
7282
7283 static isc_result_t
7284 next_active(dns_db_t *db, dns_dbversion_t *version, dns_name_t *oldname,
7285 dns_name_t *newname, bool bottom) {
7286 isc_result_t result;
7287 dns_dbiterator_t *dbit = NULL;
7288 dns_rdatasetiter_t *rdsit = NULL;
7289 dns_dbnode_t *node = NULL;
7290
7291 CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit));
7292 CHECK(dns_dbiterator_seek(dbit, oldname));
7293 do {
7294 result = dns_dbiterator_next(dbit);
7295 if (result == ISC_R_NOMORE) {
7296 CHECK(dns_dbiterator_first(dbit));
7297 }
7298 CHECK(dns_dbiterator_current(dbit, &node, newname));
7299 if (bottom && dns_name_issubdomain(newname, oldname) &&
7300 !dns_name_equal(newname, oldname))
7301 {
7302 dns_db_detachnode(db, &node);
7303 continue;
7304 }
7305 /*
7306 * Is this node empty?
7307 */
7308 CHECK(dns_db_allrdatasets(db, node, version, 0, &rdsit));
7309 result = dns_rdatasetiter_first(rdsit);
7310 dns_db_detachnode(db, &node);
7311 dns_rdatasetiter_destroy(&rdsit);
7312 if (result != ISC_R_NOMORE) {
7313 break;
7314 }
7315 } while (1);
7316 failure:
7317 if (node != NULL) {
7318 dns_db_detachnode(db, &node);
7319 }
7320 if (dbit != NULL) {
7321 dns_dbiterator_destroy(&dbit);
7322 }
7323 return (result);
7324 }
7325
7326 static bool
7327 signed_with_good_key(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
7328 dns_dbversion_t *version, dns_rdatatype_t type,
7329 dst_key_t *key) {
7330 isc_result_t result;
7331 dns_rdataset_t rdataset;
7332 dns_rdata_t rdata = DNS_RDATA_INIT;
7333 dns_rdata_rrsig_t rrsig;
7334 int count = 0;
7335 dns_kasp_t *kasp = dns_zone_getkasp(zone);
7336
7337 dns_rdataset_init(&rdataset);
7338 result = dns_db_findrdataset(db, node, version, dns_rdatatype_rrsig,
7339 type, 0, &rdataset, NULL);
7340 if (result != ISC_R_SUCCESS) {
7341 INSIST(!dns_rdataset_isassociated(&rdataset));
7342 return (false);
7343 }
7344 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
7345 result = dns_rdataset_next(&rdataset))
7346 {
7347 dns_rdataset_current(&rdataset, &rdata);
7348 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
7349 INSIST(result == ISC_R_SUCCESS);
7350 if (rrsig.algorithm == dst_key_alg(key) &&
7351 rrsig.keyid == dst_key_id(key)) {
7352 dns_rdataset_disassociate(&rdataset);
7353 return (true);
7354 }
7355 if (rrsig.algorithm == dst_key_alg(key)) {
7356 count++;
7357 }
7358 dns_rdata_reset(&rdata);
7359 }
7360
7361 if (dns_zone_use_kasp(zone)) {
7362 dns_kasp_key_t *kkey;
7363 int zsk_count = 0;
7364 bool approved;
7365
7366 LOCK(&kasp->lock);
7367 for (kkey = ISC_LIST_HEAD(dns_kasp_keys(kasp)); kkey != NULL;
7368 kkey = ISC_LIST_NEXT(kkey, link))
7369 {
7370 if (dns_kasp_key_algorithm(kkey) != dst_key_alg(key)) {
7371 continue;
7372 }
7373 if (dns_kasp_key_zsk(kkey)) {
7374 zsk_count++;
7375 }
7376 }
7377 UNLOCK(&kasp->lock);
7378
7379 if (type == dns_rdatatype_dnskey ||
7380 type == dns_rdatatype_cdnskey || type == dns_rdatatype_cds)
7381 {
7382 /*
7383 * CDS and CDNSKEY are signed with KSK like DNSKEY.
7384 * (RFC 7344, section 4.1 specifies that they must
7385 * be signed with a key in the current DS RRset,
7386 * which would only include KSK's.)
7387 */
7388 approved = false;
7389 } else {
7390 approved = (zsk_count == count);
7391 }
7392
7393 dns_rdataset_disassociate(&rdataset);
7394 return (approved);
7395 }
7396
7397 dns_rdataset_disassociate(&rdataset);
7398 return (false);
7399 }
7400
7401 static isc_result_t
7402 add_nsec(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
7403 dns_dbnode_t *node, dns_ttl_t ttl, bool bottom, dns_diff_t *diff) {
7404 dns_fixedname_t fixed;
7405 dns_name_t *next;
7406 dns_rdata_t rdata = DNS_RDATA_INIT;
7407 isc_result_t result;
7408 unsigned char nsecbuffer[DNS_NSEC_BUFFERSIZE];
7409
7410 next = dns_fixedname_initname(&fixed);
7411
7412 CHECK(next_active(db, version, name, next, bottom));
7413 CHECK(dns_nsec_buildrdata(db, version, node, next, nsecbuffer, &rdata));
7414 CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADD, name, ttl,
7415 &rdata));
7416 failure:
7417 return (result);
7418 }
7419
7420 static isc_result_t
7421 check_if_bottom_of_zone(dns_db_t *db, dns_dbnode_t *node,
7422 dns_dbversion_t *version, bool *is_bottom_of_zone) {
7423 isc_result_t result;
7424 dns_rdatasetiter_t *iterator = NULL;
7425 dns_rdataset_t rdataset;
7426 bool seen_soa = false, seen_ns = false, seen_dname = false;
7427
7428 REQUIRE(is_bottom_of_zone != NULL);
7429
7430 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
7431 if (result != ISC_R_SUCCESS) {
7432 if (result == ISC_R_NOTFOUND) {
7433 result = ISC_R_SUCCESS;
7434 }
7435 return (result);
7436 }
7437
7438 dns_rdataset_init(&rdataset);
7439 for (result = dns_rdatasetiter_first(iterator); result == ISC_R_SUCCESS;
7440 result = dns_rdatasetiter_next(iterator))
7441 {
7442 dns_rdatasetiter_current(iterator, &rdataset);
7443 switch (rdataset.type) {
7444 case dns_rdatatype_soa:
7445 seen_soa = true;
7446 break;
7447 case dns_rdatatype_ns:
7448 seen_ns = true;
7449 break;
7450 case dns_rdatatype_dname:
7451 seen_dname = true;
7452 break;
7453 }
7454 dns_rdataset_disassociate(&rdataset);
7455 }
7456 if (result != ISC_R_NOMORE) {
7457 goto failure;
7458 }
7459 if ((seen_ns && !seen_soa) || seen_dname) {
7460 *is_bottom_of_zone = true;
7461 }
7462 result = ISC_R_SUCCESS;
7463
7464 failure:
7465 dns_rdatasetiter_destroy(&iterator);
7466
7467 return (result);
7468 }
7469
7470 static isc_result_t
7471 sign_a_node(dns_db_t *db, dns_zone_t *zone, dns_name_t *name,
7472 dns_dbnode_t *node, dns_dbversion_t *version, bool build_nsec3,
7473 bool build_nsec, dst_key_t *key, isc_stdtime_t inception,
7474 isc_stdtime_t expire, unsigned int minimum, bool is_ksk,
7475 bool is_zsk, bool keyset_kskonly, bool is_bottom_of_zone,
7476 dns_diff_t *diff, int32_t *signatures, isc_mem_t *mctx) {
7477 isc_result_t result;
7478 dns_rdatasetiter_t *iterator = NULL;
7479 dns_rdataset_t rdataset;
7480 dns_rdata_t rdata = DNS_RDATA_INIT;
7481 dns_stats_t *dnssecsignstats;
7482
7483 isc_buffer_t buffer;
7484 unsigned char data[1024];
7485 bool seen_soa, seen_ns, seen_rr, seen_nsec, seen_nsec3, seen_ds;
7486
7487 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
7488 if (result != ISC_R_SUCCESS) {
7489 if (result == ISC_R_NOTFOUND) {
7490 result = ISC_R_SUCCESS;
7491 }
7492 return (result);
7493 }
7494
7495 dns_rdataset_init(&rdataset);
7496 isc_buffer_init(&buffer, data, sizeof(data));
7497 seen_rr = seen_soa = seen_ns = seen_nsec = seen_nsec3 = seen_ds = false;
7498 for (result = dns_rdatasetiter_first(iterator); result == ISC_R_SUCCESS;
7499 result = dns_rdatasetiter_next(iterator))
7500 {
7501 dns_rdatasetiter_current(iterator, &rdataset);
7502 if (rdataset.type == dns_rdatatype_soa) {
7503 seen_soa = true;
7504 } else if (rdataset.type == dns_rdatatype_ns) {
7505 seen_ns = true;
7506 } else if (rdataset.type == dns_rdatatype_ds) {
7507 seen_ds = true;
7508 } else if (rdataset.type == dns_rdatatype_nsec) {
7509 seen_nsec = true;
7510 } else if (rdataset.type == dns_rdatatype_nsec3) {
7511 seen_nsec3 = true;
7512 }
7513 if (rdataset.type != dns_rdatatype_rrsig) {
7514 seen_rr = true;
7515 }
7516 dns_rdataset_disassociate(&rdataset);
7517 }
7518 if (result != ISC_R_NOMORE) {
7519 goto failure;
7520 }
7521 /*
7522 * Going from insecure to NSEC3.
7523 * Don't generate NSEC3 records for NSEC3 records.
7524 */
7525 if (build_nsec3 && !seen_nsec3 && seen_rr) {
7526 bool unsecure = !seen_ds && seen_ns && !seen_soa;
7527 CHECK(dns_nsec3_addnsec3s(db, version, name, minimum, unsecure,
7528 diff));
7529 (*signatures)--;
7530 }
7531 /*
7532 * Going from insecure to NSEC.
7533 * Don't generate NSEC records for NSEC3 records.
7534 */
7535 if (build_nsec && !seen_nsec3 && !seen_nsec && seen_rr) {
7536 /*
7537 * Build a NSEC record except at the origin.
7538 */
7539 if (!dns_name_equal(name, dns_db_origin(db))) {
7540 CHECK(add_nsec(db, version, name, node, minimum,
7541 is_bottom_of_zone, diff));
7542 /* Count a NSEC generation as a signature generation. */
7543 (*signatures)--;
7544 }
7545 }
7546 result = dns_rdatasetiter_first(iterator);
7547 while (result == ISC_R_SUCCESS) {
7548 isc_stdtime_t when;
7549
7550 dns_rdatasetiter_current(iterator, &rdataset);
7551 if (rdataset.type == dns_rdatatype_soa ||
7552 rdataset.type == dns_rdatatype_rrsig) {
7553 goto next_rdataset;
7554 }
7555 if (rdataset.type == dns_rdatatype_dnskey ||
7556 rdataset.type == dns_rdatatype_cdnskey ||
7557 rdataset.type == dns_rdatatype_cds)
7558 {
7559 /*
7560 * CDS and CDNSKEY are signed with KSK like DNSKEY.
7561 * (RFC 7344, section 4.1 specifies that they must
7562 * be signed with a key in the current DS RRset,
7563 * which would only include KSK's.)
7564 */
7565 if (!is_ksk && keyset_kskonly) {
7566 goto next_rdataset;
7567 }
7568 } else if (!is_zsk) {
7569 goto next_rdataset;
7570 } else if (is_zsk && !dst_key_is_signing(key, DST_BOOL_ZSK,
7571 inception, &when)) {
7572 /* Only applies to dnssec-policy. */
7573 if (dns_zone_use_kasp(zone)) {
7574 goto next_rdataset;
7575 }
7576 }
7577
7578 if (seen_ns && !seen_soa && rdataset.type != dns_rdatatype_ds &&
7579 rdataset.type != dns_rdatatype_nsec)
7580 {
7581 goto next_rdataset;
7582 }
7583 if (signed_with_good_key(zone, db, node, version, rdataset.type,
7584 key)) {
7585 goto next_rdataset;
7586 }
7587
7588 /* Calculate the signature, creating a RRSIG RDATA. */
7589 isc_buffer_clear(&buffer);
7590 CHECK(dns_dnssec_sign(name, &rdataset, key, &inception, &expire,
7591 mctx, &buffer, &rdata));
7592 /* Update the database and journal with the RRSIG. */
7593 /* XXX inefficient - will cause dataset merging */
7594 CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADDRESIGN,
7595 name, rdataset.ttl, &rdata));
7596 dns_rdata_reset(&rdata);
7597
7598 /* Update DNSSEC sign statistics. */
7599 dnssecsignstats = dns_zone_getdnssecsignstats(zone);
7600 if (dnssecsignstats != NULL) {
7601 /* Generated a new signature. */
7602 dns_dnssecsignstats_increment(dnssecsignstats, ID(key),
7603 ALG(key),
7604 dns_dnssecsignstats_sign);
7605 /* This is a refresh. */
7606 dns_dnssecsignstats_increment(
7607 dnssecsignstats, ID(key), ALG(key),
7608 dns_dnssecsignstats_refresh);
7609 }
7610
7611 (*signatures)--;
7612 next_rdataset:
7613 dns_rdataset_disassociate(&rdataset);
7614 result = dns_rdatasetiter_next(iterator);
7615 }
7616 if (result == ISC_R_NOMORE) {
7617 result = ISC_R_SUCCESS;
7618 }
7619 failure:
7620 if (dns_rdataset_isassociated(&rdataset)) {
7621 dns_rdataset_disassociate(&rdataset);
7622 }
7623 if (iterator != NULL) {
7624 dns_rdatasetiter_destroy(&iterator);
7625 }
7626 return (result);
7627 }
7628
7629 /*
7630 * If 'update_only' is set then don't create a NSEC RRset if it doesn't exist.
7631 */
7632 static isc_result_t
7633 updatesecure(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
7634 dns_ttl_t minimum, bool update_only, dns_diff_t *diff) {
7635 isc_result_t result;
7636 dns_rdataset_t rdataset;
7637 dns_dbnode_t *node = NULL;
7638
7639 CHECK(dns_db_getoriginnode(db, &node));
7640 if (update_only) {
7641 dns_rdataset_init(&rdataset);
7642 result = dns_db_findrdataset(
7643 db, node, version, dns_rdatatype_nsec,
7644 dns_rdatatype_none, 0, &rdataset, NULL);
7645 if (dns_rdataset_isassociated(&rdataset)) {
7646 dns_rdataset_disassociate(&rdataset);
7647 }
7648 if (result == ISC_R_NOTFOUND) {
7649 goto success;
7650 }
7651 if (result != ISC_R_SUCCESS) {
7652 goto failure;
7653 }
7654 }
7655 CHECK(delete_nsec(db, version, node, name, diff));
7656 CHECK(add_nsec(db, version, name, node, minimum, false, diff));
7657 success:
7658 result = ISC_R_SUCCESS;
7659 failure:
7660 if (node != NULL) {
7661 dns_db_detachnode(db, &node);
7662 }
7663 return (result);
7664 }
7665
7666 static isc_result_t
7667 updatesignwithkey(dns_zone_t *zone, dns_signing_t *signing,
7668 dns_dbversion_t *version, bool build_nsec3, dns_ttl_t minimum,
7669 dns_diff_t *diff) {
7670 isc_result_t result;
7671 dns_dbnode_t *node = NULL;
7672 dns_rdataset_t rdataset;
7673 dns_rdata_t rdata = DNS_RDATA_INIT;
7674 unsigned char data[5];
7675 bool seen_done = false;
7676 bool have_rr = false;
7677
7678 dns_rdataset_init(&rdataset);
7679 result = dns_db_getoriginnode(signing->db, &node);
7680 if (result != ISC_R_SUCCESS) {
7681 goto failure;
7682 }
7683
7684 result = dns_db_findrdataset(signing->db, node, version,
7685 zone->privatetype, dns_rdatatype_none, 0,
7686 &rdataset, NULL);
7687 if (result == ISC_R_NOTFOUND) {
7688 INSIST(!dns_rdataset_isassociated(&rdataset));
7689 result = ISC_R_SUCCESS;
7690 goto failure;
7691 }
7692 if (result != ISC_R_SUCCESS) {
7693 INSIST(!dns_rdataset_isassociated(&rdataset));
7694 goto failure;
7695 }
7696 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
7697 result = dns_rdataset_next(&rdataset))
7698 {
7699 dns_rdataset_current(&rdataset, &rdata);
7700 /*
7701 * If we don't match the algorithm or keyid skip the record.
7702 */
7703 if (rdata.length != 5 || rdata.data[0] != signing->algorithm ||
7704 rdata.data[1] != ((signing->keyid >> 8) & 0xff) ||
7705 rdata.data[2] != (signing->keyid & 0xff))
7706 {
7707 have_rr = true;
7708 dns_rdata_reset(&rdata);
7709 continue;
7710 }
7711 /*
7712 * We have a match. If we were signing (!signing->deleteit)
7713 * and we already have a record indicating that we have
7714 * finished signing (rdata.data[4] != 0) then keep it.
7715 * Otherwise it needs to be deleted as we have removed all
7716 * the signatures (signing->deleteit), so any record indicating
7717 * completion is now out of date, or we have finished signing
7718 * with the new record so we no longer need to remember that
7719 * we need to sign the zone with the matching key across a
7720 * nameserver re-start.
7721 */
7722 if (!signing->deleteit && rdata.data[4] != 0) {
7723 seen_done = true;
7724 have_rr = true;
7725 } else {
7726 CHECK(update_one_rr(signing->db, version, diff,
7727 DNS_DIFFOP_DEL, &zone->origin,
7728 rdataset.ttl, &rdata));
7729 }
7730 dns_rdata_reset(&rdata);
7731 }
7732 if (result == ISC_R_NOMORE) {
7733 result = ISC_R_SUCCESS;
7734 }
7735 if (!signing->deleteit && !seen_done) {
7736 /*
7737 * If we were signing then we need to indicate that we have
7738 * finished signing the zone with this key. If it is already
7739 * there we don't need to add it a second time.
7740 */
7741 data[0] = signing->algorithm;
7742 data[1] = (signing->keyid >> 8) & 0xff;
7743 data[2] = signing->keyid & 0xff;
7744 data[3] = 0;
7745 data[4] = 1;
7746 rdata.length = sizeof(data);
7747 rdata.data = data;
7748 rdata.type = zone->privatetype;
7749 rdata.rdclass = dns_db_class(signing->db);
7750 CHECK(update_one_rr(signing->db, version, diff, DNS_DIFFOP_ADD,
7751 &zone->origin, rdataset.ttl, &rdata));
7752 } else if (!have_rr) {
7753 dns_name_t *origin = dns_db_origin(signing->db);
7754 /*
7755 * Rebuild the NSEC/NSEC3 record for the origin as we no
7756 * longer have any private records.
7757 */
7758 if (build_nsec3) {
7759 CHECK(dns_nsec3_addnsec3s(signing->db, version, origin,
7760 minimum, false, diff));
7761 }
7762 CHECK(updatesecure(signing->db, version, origin, minimum, true,
7763 diff));
7764 }
7765
7766 failure:
7767 if (dns_rdataset_isassociated(&rdataset)) {
7768 dns_rdataset_disassociate(&rdataset);
7769 }
7770 if (node != NULL) {
7771 dns_db_detachnode(signing->db, &node);
7772 }
7773 return (result);
7774 }
7775
7776 /*
7777 * Called from zone_nsec3chain() in order to update zone records indicating
7778 * processing status of given NSEC3 chain:
7779 *
7780 * - If the supplied dns_nsec3chain_t structure has been fully processed
7781 * (which is indicated by "active" being set to false):
7782 *
7783 * - remove all NSEC3PARAM records matching the relevant NSEC3 chain,
7784 *
7785 * - remove all private-type records containing NSEC3PARAM RDATA matching
7786 * the relevant NSEC3 chain.
7787 *
7788 * - If the supplied dns_nsec3chain_t structure has not been fully processed
7789 * (which is indicated by "active" being set to true), only remove the
7790 * NSEC3PARAM record which matches the relevant NSEC3 chain and has the
7791 * "flags" field set to 0.
7792 *
7793 * - If given NSEC3 chain is being added, add an NSEC3PARAM record contained
7794 * in the relevant private-type record, but with the "flags" field set to
7795 * 0, indicating that this NSEC3 chain is now complete for this zone.
7796 *
7797 * Note that this function is called at different processing stages for NSEC3
7798 * chain additions vs. removals and needs to handle all cases properly.
7799 */
7800 static isc_result_t
7801 fixup_nsec3param(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3chain_t *chain,
7802 bool active, dns_rdatatype_t privatetype, dns_diff_t *diff) {
7803 dns_dbnode_t *node = NULL;
7804 dns_name_t *name = dns_db_origin(db);
7805 dns_rdata_t rdata = DNS_RDATA_INIT;
7806 dns_rdataset_t rdataset;
7807 dns_rdata_nsec3param_t nsec3param;
7808 isc_result_t result;
7809 isc_buffer_t buffer;
7810 unsigned char parambuf[DNS_NSEC3PARAM_BUFFERSIZE];
7811 dns_ttl_t ttl = 0;
7812 bool nseconly = false, nsec3ok = false;
7813
7814 dns_rdataset_init(&rdataset);
7815
7816 result = dns_db_getoriginnode(db, &node);
7817 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7818 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param, 0,
7819 0, &rdataset, NULL);
7820 if (result == ISC_R_NOTFOUND) {
7821 goto try_private;
7822 }
7823 if (result != ISC_R_SUCCESS) {
7824 goto failure;
7825 }
7826
7827 /*
7828 * Preserve the existing ttl.
7829 */
7830 ttl = rdataset.ttl;
7831
7832 /*
7833 * Delete all NSEC3PARAM records which match that in nsec3chain.
7834 */
7835 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
7836 result = dns_rdataset_next(&rdataset))
7837 {
7838 dns_rdataset_current(&rdataset, &rdata);
7839 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
7840
7841 if (nsec3param.hash != chain->nsec3param.hash ||
7842 (active && nsec3param.flags != 0) ||
7843 nsec3param.iterations != chain->nsec3param.iterations ||
7844 nsec3param.salt_length != chain->nsec3param.salt_length ||
7845 memcmp(nsec3param.salt, chain->nsec3param.salt,
7846 nsec3param.salt_length))
7847 {
7848 dns_rdata_reset(&rdata);
7849 continue;
7850 }
7851
7852 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
7853 rdataset.ttl, &rdata));
7854 dns_rdata_reset(&rdata);
7855 }
7856 if (result != ISC_R_NOMORE) {
7857 goto failure;
7858 }
7859
7860 dns_rdataset_disassociate(&rdataset);
7861
7862 try_private:
7863
7864 if (active) {
7865 goto add;
7866 }
7867
7868 result = dns_nsec_nseconly(db, ver, &nseconly);
7869 nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
7870
7871 /*
7872 * Delete all private records which match that in nsec3chain.
7873 */
7874 result = dns_db_findrdataset(db, node, ver, privatetype, 0, 0,
7875 &rdataset, NULL);
7876 if (result == ISC_R_NOTFOUND) {
7877 goto add;
7878 }
7879 if (result != ISC_R_SUCCESS) {
7880 goto failure;
7881 }
7882
7883 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
7884 result = dns_rdataset_next(&rdataset))
7885 {
7886 dns_rdata_t private = DNS_RDATA_INIT;
7887 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
7888
7889 dns_rdataset_current(&rdataset, &private);
7890 if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
7891 sizeof(buf))) {
7892 continue;
7893 }
7894 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
7895
7896 if ((!nsec3ok &&
7897 (nsec3param.flags & DNS_NSEC3FLAG_INITIAL) != 0) ||
7898 nsec3param.hash != chain->nsec3param.hash ||
7899 nsec3param.iterations != chain->nsec3param.iterations ||
7900 nsec3param.salt_length != chain->nsec3param.salt_length ||
7901 memcmp(nsec3param.salt, chain->nsec3param.salt,
7902 nsec3param.salt_length))
7903 {
7904 dns_rdata_reset(&rdata);
7905 continue;
7906 }
7907
7908 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
7909 rdataset.ttl, &private));
7910 dns_rdata_reset(&rdata);
7911 }
7912 if (result != ISC_R_NOMORE) {
7913 goto failure;
7914 }
7915
7916 add:
7917 if ((chain->nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
7918 result = ISC_R_SUCCESS;
7919 goto failure;
7920 }
7921
7922 /*
7923 * Add a NSEC3PARAM record which matches that in nsec3chain but
7924 * with all flags bits cleared.
7925 *
7926 * Note: we do not clear chain->nsec3param.flags as this change
7927 * may be reversed.
7928 */
7929 isc_buffer_init(&buffer, ¶mbuf, sizeof(parambuf));
7930 CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db),
7931 dns_rdatatype_nsec3param, &chain->nsec3param,
7932 &buffer));
7933 rdata.data[1] = 0; /* Clear flag bits. */
7934 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, name, ttl, &rdata));
7935
7936 failure:
7937 dns_db_detachnode(db, &node);
7938 if (dns_rdataset_isassociated(&rdataset)) {
7939 dns_rdataset_disassociate(&rdataset);
7940 }
7941 return (result);
7942 }
7943
7944 static isc_result_t
7945 delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
7946 dns_name_t *name, dns_diff_t *diff) {
7947 dns_rdataset_t rdataset;
7948 isc_result_t result;
7949
7950 dns_rdataset_init(&rdataset);
7951
7952 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec, 0, 0,
7953 &rdataset, NULL);
7954 if (result == ISC_R_NOTFOUND) {
7955 return (ISC_R_SUCCESS);
7956 }
7957 if (result != ISC_R_SUCCESS) {
7958 return (result);
7959 }
7960 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
7961 result = dns_rdataset_next(&rdataset))
7962 {
7963 dns_rdata_t rdata = DNS_RDATA_INIT;
7964
7965 dns_rdataset_current(&rdataset, &rdata);
7966 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
7967 rdataset.ttl, &rdata));
7968 }
7969 if (result == ISC_R_NOMORE) {
7970 result = ISC_R_SUCCESS;
7971 }
7972 failure:
7973 dns_rdataset_disassociate(&rdataset);
7974 return (result);
7975 }
7976
7977 static isc_result_t
7978 deletematchingnsec3(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
7979 dns_name_t *name, const dns_rdata_nsec3param_t *param,
7980 dns_diff_t *diff) {
7981 dns_rdataset_t rdataset;
7982 dns_rdata_nsec3_t nsec3;
7983 isc_result_t result;
7984
7985 dns_rdataset_init(&rdataset);
7986 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3, 0, 0,
7987 &rdataset, NULL);
7988 if (result == ISC_R_NOTFOUND) {
7989 return (ISC_R_SUCCESS);
7990 }
7991 if (result != ISC_R_SUCCESS) {
7992 return (result);
7993 }
7994
7995 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
7996 result = dns_rdataset_next(&rdataset))
7997 {
7998 dns_rdata_t rdata = DNS_RDATA_INIT;
7999
8000 dns_rdataset_current(&rdataset, &rdata);
8001 CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
8002 if (nsec3.hash != param->hash ||
8003 nsec3.iterations != param->iterations ||
8004 nsec3.salt_length != param->salt_length ||
8005 memcmp(nsec3.salt, param->salt, nsec3.salt_length))
8006 {
8007 continue;
8008 }
8009 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
8010 rdataset.ttl, &rdata));
8011 }
8012 if (result == ISC_R_NOMORE) {
8013 result = ISC_R_SUCCESS;
8014 }
8015 failure:
8016 dns_rdataset_disassociate(&rdataset);
8017 return (result);
8018 }
8019
8020 static isc_result_t
8021 need_nsec_chain(dns_db_t *db, dns_dbversion_t *ver,
8022 const dns_rdata_nsec3param_t *param, bool *answer) {
8023 dns_dbnode_t *node = NULL;
8024 dns_rdata_t rdata = DNS_RDATA_INIT;
8025 dns_rdata_nsec3param_t myparam;
8026 dns_rdataset_t rdataset;
8027 isc_result_t result;
8028
8029 *answer = false;
8030
8031 result = dns_db_getoriginnode(db, &node);
8032 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8033
8034 dns_rdataset_init(&rdataset);
8035
8036 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec, 0, 0,
8037 &rdataset, NULL);
8038 if (result == ISC_R_SUCCESS) {
8039 dns_rdataset_disassociate(&rdataset);
8040 dns_db_detachnode(db, &node);
8041 return (result);
8042 }
8043 if (result != ISC_R_NOTFOUND) {
8044 dns_db_detachnode(db, &node);
8045 return (result);
8046 }
8047
8048 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param, 0,
8049 0, &rdataset, NULL);
8050 if (result == ISC_R_NOTFOUND) {
8051 *answer = true;
8052 dns_db_detachnode(db, &node);
8053 return (ISC_R_SUCCESS);
8054 }
8055 if (result != ISC_R_SUCCESS) {
8056 dns_db_detachnode(db, &node);
8057 return (result);
8058 }
8059
8060 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
8061 result = dns_rdataset_next(&rdataset))
8062 {
8063 dns_rdataset_current(&rdataset, &rdata);
8064 CHECK(dns_rdata_tostruct(&rdata, &myparam, NULL));
8065 dns_rdata_reset(&rdata);
8066 /*
8067 * Ignore any NSEC3PARAM removals.
8068 */
8069 if (NSEC3REMOVE(myparam.flags)) {
8070 continue;
8071 }
8072 /*
8073 * Ignore the chain that we are in the process of deleting.
8074 */
8075 if (myparam.hash == param->hash &&
8076 myparam.iterations == param->iterations &&
8077 myparam.salt_length == param->salt_length &&
8078 !memcmp(myparam.salt, param->salt, myparam.salt_length))
8079 {
8080 continue;
8081 }
8082 /*
8083 * Found an active NSEC3 chain.
8084 */
8085 break;
8086 }
8087 if (result == ISC_R_NOMORE) {
8088 *answer = true;
8089 result = ISC_R_SUCCESS;
8090 }
8091
8092 failure:
8093 if (dns_rdataset_isassociated(&rdataset)) {
8094 dns_rdataset_disassociate(&rdataset);
8095 }
8096 dns_db_detachnode(db, &node);
8097 return (result);
8098 }
8099
8100 /*%
8101 * Given a tuple which is part of a diff, return a pointer to the next tuple in
8102 * that diff which has the same name and type (or NULL if no such tuple is
8103 * found).
8104 */
8105 static dns_difftuple_t *
8106 find_next_matching_tuple(dns_difftuple_t *cur) {
8107 dns_difftuple_t *next = cur;
8108
8109 while ((next = ISC_LIST_NEXT(next, link)) != NULL) {
8110 if (cur->rdata.type == next->rdata.type &&
8111 dns_name_equal(&cur->name, &next->name))
8112 {
8113 return (next);
8114 }
8115 }
8116
8117 return (NULL);
8118 }
8119
8120 /*%
8121 * Remove all tuples with the same name and type as 'cur' from 'src' and append
8122 * them to 'dst'.
8123 */
8124 static void
8125 move_matching_tuples(dns_difftuple_t *cur, dns_diff_t *src, dns_diff_t *dst) {
8126 do {
8127 dns_difftuple_t *next = find_next_matching_tuple(cur);
8128 ISC_LIST_UNLINK(src->tuples, cur, link);
8129 dns_diff_appendminimal(dst, &cur);
8130 cur = next;
8131 } while (cur != NULL);
8132 }
8133
8134 /*%
8135 * Add/remove DNSSEC signatures for the list of "raw" zone changes supplied in
8136 * 'diff'. Gradually remove tuples from 'diff' and append them to 'zonediff'
8137 * along with tuples representing relevant signature changes.
8138 */
8139 isc_result_t
8140 dns__zone_updatesigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version,
8141 dst_key_t *zone_keys[], unsigned int nkeys,
8142 dns_zone_t *zone, isc_stdtime_t inception,
8143 isc_stdtime_t expire, isc_stdtime_t keyexpire,
8144 isc_stdtime_t now, bool check_ksk, bool keyset_kskonly,
8145 dns__zonediff_t *zonediff) {
8146 dns_difftuple_t *tuple;
8147 isc_result_t result;
8148
8149 while ((tuple = ISC_LIST_HEAD(diff->tuples)) != NULL) {
8150 isc_stdtime_t exp = expire;
8151
8152 if (keyexpire != 0 &&
8153 (tuple->rdata.type == dns_rdatatype_dnskey ||
8154 tuple->rdata.type == dns_rdatatype_cdnskey ||
8155 tuple->rdata.type == dns_rdatatype_cds))
8156 {
8157 exp = keyexpire;
8158 }
8159
8160 result = del_sigs(zone, db, version, &tuple->name,
8161 tuple->rdata.type, zonediff, zone_keys, nkeys,
8162 now, false);
8163 if (result != ISC_R_SUCCESS) {
8164 dns_zone_log(zone, ISC_LOG_ERROR,
8165 "dns__zone_updatesigs:del_sigs -> %s",
8166 dns_result_totext(result));
8167 return (result);
8168 }
8169 result = add_sigs(db, version, &tuple->name, zone,
8170 tuple->rdata.type, zonediff->diff, zone_keys,
8171 nkeys, zone->mctx, inception, exp, check_ksk,
8172 keyset_kskonly);
8173 if (result != ISC_R_SUCCESS) {
8174 dns_zone_log(zone, ISC_LOG_ERROR,
8175 "dns__zone_updatesigs:add_sigs -> %s",
8176 dns_result_totext(result));
8177 return (result);
8178 }
8179
8180 /*
8181 * Signature changes for all RRs with name tuple->name and type
8182 * tuple->rdata.type were appended to zonediff->diff. Now we
8183 * remove all the "raw" changes with the same name and type
8184 * from diff (so that they are not processed by this loop
8185 * again) and append them to zonediff so that they get applied.
8186 */
8187 move_matching_tuples(tuple, diff, zonediff->diff);
8188 }
8189 return (ISC_R_SUCCESS);
8190 }
8191
8192 /*
8193 * Incrementally build and sign a new NSEC3 chain using the parameters
8194 * requested.
8195 */
8196 static void
8197 zone_nsec3chain(dns_zone_t *zone) {
8198 const char *me = "zone_nsec3chain";
8199 dns_db_t *db = NULL;
8200 dns_dbnode_t *node = NULL;
8201 dns_dbversion_t *version = NULL;
8202 dns_diff_t _sig_diff;
8203 dns_diff_t nsec_diff;
8204 dns_diff_t nsec3_diff;
8205 dns_diff_t param_diff;
8206 dns__zonediff_t zonediff;
8207 dns_fixedname_t fixed;
8208 dns_fixedname_t nextfixed;
8209 dns_name_t *name, *nextname;
8210 dns_rdataset_t rdataset;
8211 dns_nsec3chain_t *nsec3chain = NULL, *nextnsec3chain;
8212 dns_nsec3chainlist_t cleanup;
8213 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
8214 int32_t signatures;
8215 bool check_ksk, keyset_kskonly;
8216 bool delegation;
8217 bool first;
8218 isc_result_t result;
8219 isc_stdtime_t now, inception, soaexpire, expire;
8220 uint32_t jitter, sigvalidityinterval, expiryinterval;
8221 unsigned int i;
8222 unsigned int nkeys = 0;
8223 uint32_t nodes;
8224 bool unsecure = false;
8225 bool seen_soa, seen_ns, seen_dname, seen_ds;
8226 bool seen_nsec, seen_nsec3, seen_rr;
8227 dns_rdatasetiter_t *iterator = NULL;
8228 bool buildnsecchain;
8229 bool updatensec = false;
8230 dns_rdatatype_t privatetype = zone->privatetype;
8231
8232 ENTER;
8233
8234 dns_rdataset_init(&rdataset);
8235 name = dns_fixedname_initname(&fixed);
8236 nextname = dns_fixedname_initname(&nextfixed);
8237 dns_diff_init(zone->mctx, ¶m_diff);
8238 dns_diff_init(zone->mctx, &nsec3_diff);
8239 dns_diff_init(zone->mctx, &nsec_diff);
8240 dns_diff_init(zone->mctx, &_sig_diff);
8241 zonediff_init(&zonediff, &_sig_diff);
8242 ISC_LIST_INIT(cleanup);
8243
8244 /*
8245 * Updates are disabled. Pause for 5 minutes.
8246 */
8247 if (zone->update_disabled) {
8248 result = ISC_R_FAILURE;
8249 goto failure;
8250 }
8251
8252 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8253 /*
8254 * This function is called when zone timer fires, after the latter gets
8255 * set by zone_addnsec3chain(). If the action triggering the call to
8256 * zone_addnsec3chain() is closely followed by a zone deletion request,
8257 * it might turn out that the timer thread will not be woken up until
8258 * after the zone is deleted by rmzone(), which calls dns_db_detach()
8259 * for zone->db, causing the latter to become NULL. Return immediately
8260 * if that happens.
8261 */
8262 if (zone->db != NULL) {
8263 dns_db_attach(zone->db, &db);
8264 }
8265 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8266 if (db == NULL) {
8267 return;
8268 }
8269
8270 result = dns_db_newversion(db, &version);
8271 if (result != ISC_R_SUCCESS) {
8272 dnssec_log(zone, ISC_LOG_ERROR,
8273 "zone_nsec3chain:dns_db_newversion -> %s",
8274 dns_result_totext(result));
8275 goto failure;
8276 }
8277
8278 isc_stdtime_get(&now);
8279
8280 result = dns__zone_findkeys(zone, db, version, now, zone->mctx,
8281 DNS_MAXZONEKEYS, zone_keys, &nkeys);
8282 if (result != ISC_R_SUCCESS) {
8283 dnssec_log(zone, ISC_LOG_ERROR,
8284 "zone_nsec3chain:dns__zone_findkeys -> %s",
8285 dns_result_totext(result));
8286 goto failure;
8287 }
8288
8289 sigvalidityinterval = dns_zone_getsigvalidityinterval(zone);
8290 inception = now - 3600; /* Allow for clock skew. */
8291 soaexpire = now + sigvalidityinterval;
8292 expiryinterval = dns_zone_getsigresigninginterval(zone);
8293 if (expiryinterval > sigvalidityinterval) {
8294 expiryinterval = sigvalidityinterval;
8295 } else {
8296 expiryinterval = sigvalidityinterval - expiryinterval;
8297 }
8298
8299 /*
8300 * Spread out signatures over time if they happen to be
8301 * clumped. We don't do this for each add_sigs() call as
8302 * we still want some clustering to occur.
8303 */
8304 if (sigvalidityinterval >= 3600U) {
8305 if (sigvalidityinterval > 7200U) {
8306 jitter = isc_random_uniform(expiryinterval);
8307 } else {
8308 jitter = isc_random_uniform(1200);
8309 }
8310 expire = soaexpire - jitter - 1;
8311 } else {
8312 expire = soaexpire - 1;
8313 }
8314
8315 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
8316 keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
8317
8318 /*
8319 * We keep pulling nodes off each iterator in turn until
8320 * we have no more nodes to pull off or we reach the limits
8321 * for this quantum.
8322 */
8323 nodes = zone->nodes;
8324 signatures = zone->signatures;
8325 LOCK_ZONE(zone);
8326 nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
8327 UNLOCK_ZONE(zone);
8328 first = true;
8329
8330 if (nsec3chain != NULL) {
8331 nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
8332 }
8333 /*
8334 * Generate new NSEC3 chains first.
8335 *
8336 * The following while loop iterates over nodes in the zone database,
8337 * updating the NSEC3 chain by calling dns_nsec3_addnsec3() for each of
8338 * them. Once all nodes are processed, the "delete_nsec" field is
8339 * consulted to check whether we are supposed to remove NSEC records
8340 * from the zone database; if so, the database iterator is reset to
8341 * point to the first node and the loop traverses all of them again,
8342 * this time removing NSEC records. If we hit a node which is obscured
8343 * by a delegation or a DNAME, nodes are skipped over until we find one
8344 * that is not obscured by the same obscuring name and then normal
8345 * processing is resumed.
8346 *
8347 * The above is repeated until all requested NSEC3 chain changes are
8348 * applied or when we reach the limits for this quantum, whichever
8349 * happens first.
8350 *
8351 * Note that the "signatures" variable is only used here to limit the
8352 * amount of work performed. Actual DNSSEC signatures are only
8353 * generated by dns__zone_updatesigs() calls later in this function.
8354 */
8355 while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
8356 dns_dbiterator_pause(nsec3chain->dbiterator);
8357
8358 LOCK_ZONE(zone);
8359 nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
8360
8361 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8362 if (nsec3chain->done || nsec3chain->db != zone->db) {
8363 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
8364 ISC_LIST_APPEND(cleanup, nsec3chain, link);
8365 }
8366 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8367 UNLOCK_ZONE(zone);
8368 if (ISC_LIST_TAIL(cleanup) == nsec3chain) {
8369 goto next_addchain;
8370 }
8371
8372 /*
8373 * Possible future db.
8374 */
8375 if (nsec3chain->db != db) {
8376 goto next_addchain;
8377 }
8378
8379 if (NSEC3REMOVE(nsec3chain->nsec3param.flags)) {
8380 goto next_addchain;
8381 }
8382
8383 dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
8384
8385 if (nsec3chain->delete_nsec) {
8386 delegation = false;
8387 dns_dbiterator_pause(nsec3chain->dbiterator);
8388 CHECK(delete_nsec(db, version, node, name, &nsec_diff));
8389 goto next_addnode;
8390 }
8391 /*
8392 * On the first pass we need to check if the current node
8393 * has not been obscured.
8394 */
8395 delegation = false;
8396 unsecure = false;
8397 if (first) {
8398 dns_fixedname_t ffound;
8399 dns_name_t *found;
8400 found = dns_fixedname_initname(&ffound);
8401 result = dns_db_find(
8402 db, name, version, dns_rdatatype_soa,
8403 DNS_DBFIND_NOWILD, 0, NULL, found, NULL, NULL);
8404 if ((result == DNS_R_DELEGATION ||
8405 result == DNS_R_DNAME) &&
8406 !dns_name_equal(name, found))
8407 {
8408 /*
8409 * Remember the obscuring name so that
8410 * we skip all obscured names.
8411 */
8412 dns_name_copynf(found, name);
8413 delegation = true;
8414 goto next_addnode;
8415 }
8416 }
8417
8418 /*
8419 * Check to see if this is a bottom of zone node.
8420 */
8421 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
8422 if (result == ISC_R_NOTFOUND) {
8423 /* Empty node? */
8424 goto next_addnode;
8425 }
8426 if (result != ISC_R_SUCCESS) {
8427 goto failure;
8428 }
8429
8430 seen_soa = seen_ns = seen_dname = seen_ds = seen_nsec = false;
8431 for (result = dns_rdatasetiter_first(iterator);
8432 result == ISC_R_SUCCESS;
8433 result = dns_rdatasetiter_next(iterator))
8434 {
8435 dns_rdatasetiter_current(iterator, &rdataset);
8436 INSIST(rdataset.type != dns_rdatatype_nsec3);
8437 if (rdataset.type == dns_rdatatype_soa) {
8438 seen_soa = true;
8439 } else if (rdataset.type == dns_rdatatype_ns) {
8440 seen_ns = true;
8441 } else if (rdataset.type == dns_rdatatype_dname) {
8442 seen_dname = true;
8443 } else if (rdataset.type == dns_rdatatype_ds) {
8444 seen_ds = true;
8445 } else if (rdataset.type == dns_rdatatype_nsec) {
8446 seen_nsec = true;
8447 }
8448 dns_rdataset_disassociate(&rdataset);
8449 }
8450 dns_rdatasetiter_destroy(&iterator);
8451 /*
8452 * Is there a NSEC chain than needs to be cleaned up?
8453 */
8454 if (seen_nsec) {
8455 nsec3chain->seen_nsec = true;
8456 }
8457 if (seen_ns && !seen_soa && !seen_ds) {
8458 unsecure = true;
8459 }
8460 if ((seen_ns && !seen_soa) || seen_dname) {
8461 delegation = true;
8462 }
8463
8464 /*
8465 * Process one node.
8466 */
8467 dns_dbiterator_pause(nsec3chain->dbiterator);
8468 result = dns_nsec3_addnsec3(
8469 db, version, name, &nsec3chain->nsec3param,
8470 zone->minimum, unsecure, &nsec3_diff);
8471 if (result != ISC_R_SUCCESS) {
8472 dnssec_log(zone, ISC_LOG_ERROR,
8473 "zone_nsec3chain:"
8474 "dns_nsec3_addnsec3 -> %s",
8475 dns_result_totext(result));
8476 goto failure;
8477 }
8478
8479 /*
8480 * Treat each call to dns_nsec3_addnsec3() as if it's cost is
8481 * two signatures. Additionally there will, in general, be
8482 * two signature generated below.
8483 *
8484 * If we are only changing the optout flag the cost is half
8485 * that of the cost of generating a completely new chain.
8486 */
8487 signatures -= 4;
8488
8489 /*
8490 * Go onto next node.
8491 */
8492 next_addnode:
8493 first = false;
8494 dns_db_detachnode(db, &node);
8495 do {
8496 result = dns_dbiterator_next(nsec3chain->dbiterator);
8497
8498 if (result == ISC_R_NOMORE && nsec3chain->delete_nsec) {
8499 dns_dbiterator_pause(nsec3chain->dbiterator);
8500 CHECK(fixup_nsec3param(db, version, nsec3chain,
8501 false, privatetype,
8502 ¶m_diff));
8503 LOCK_ZONE(zone);
8504 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
8505 link);
8506 UNLOCK_ZONE(zone);
8507 ISC_LIST_APPEND(cleanup, nsec3chain, link);
8508 goto next_addchain;
8509 }
8510 if (result == ISC_R_NOMORE) {
8511 dns_dbiterator_pause(nsec3chain->dbiterator);
8512 if (nsec3chain->seen_nsec) {
8513 CHECK(fixup_nsec3param(
8514 db, version, nsec3chain, true,
8515 privatetype, ¶m_diff));
8516 nsec3chain->delete_nsec = true;
8517 goto same_addchain;
8518 }
8519 CHECK(fixup_nsec3param(db, version, nsec3chain,
8520 false, privatetype,
8521 ¶m_diff));
8522 LOCK_ZONE(zone);
8523 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
8524 link);
8525 UNLOCK_ZONE(zone);
8526 ISC_LIST_APPEND(cleanup, nsec3chain, link);
8527 goto next_addchain;
8528 } else if (result != ISC_R_SUCCESS) {
8529 dnssec_log(zone, ISC_LOG_ERROR,
8530 "zone_nsec3chain:"
8531 "dns_dbiterator_next -> %s",
8532 dns_result_totext(result));
8533 goto failure;
8534 } else if (delegation) {
8535 dns_dbiterator_current(nsec3chain->dbiterator,
8536 &node, nextname);
8537 dns_db_detachnode(db, &node);
8538 if (!dns_name_issubdomain(nextname, name)) {
8539 break;
8540 }
8541 } else {
8542 break;
8543 }
8544 } while (1);
8545 continue;
8546
8547 same_addchain:
8548 CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
8549 first = true;
8550 continue;
8551
8552 next_addchain:
8553 dns_dbiterator_pause(nsec3chain->dbiterator);
8554 nsec3chain = nextnsec3chain;
8555 first = true;
8556 if (nsec3chain != NULL) {
8557 nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
8558 }
8559 }
8560
8561 if (nsec3chain != NULL) {
8562 goto skip_removals;
8563 }
8564
8565 /*
8566 * Process removals.
8567 *
8568 * This is a counterpart of the above while loop which takes care of
8569 * removing an NSEC3 chain. It starts with determining whether the
8570 * zone needs to switch from NSEC3 to NSEC; if so, it first builds an
8571 * NSEC chain by iterating over all nodes in the zone database and only
8572 * then goes on to remove NSEC3 records be iterating over all nodes
8573 * again and calling deletematchingnsec3() for each of them; otherwise,
8574 * it starts removing NSEC3 records immediately. Rules for processing
8575 * obscured nodes and interrupting work are the same as for the while
8576 * loop above.
8577 */
8578 LOCK_ZONE(zone);
8579 nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
8580 UNLOCK_ZONE(zone);
8581 first = true;
8582 buildnsecchain = false;
8583 while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
8584 dns_dbiterator_pause(nsec3chain->dbiterator);
8585
8586 LOCK_ZONE(zone);
8587 nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
8588 UNLOCK_ZONE(zone);
8589
8590 if (nsec3chain->db != db) {
8591 goto next_removechain;
8592 }
8593
8594 if (!NSEC3REMOVE(nsec3chain->nsec3param.flags)) {
8595 goto next_removechain;
8596 }
8597
8598 /*
8599 * Work out if we need to build a NSEC chain as a consequence
8600 * of removing this NSEC3 chain.
8601 */
8602 if (first && !updatensec &&
8603 (nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_NONSEC) == 0)
8604 {
8605 result = need_nsec_chain(db, version,
8606 &nsec3chain->nsec3param,
8607 &buildnsecchain);
8608 if (result != ISC_R_SUCCESS) {
8609 dnssec_log(zone, ISC_LOG_ERROR,
8610 "zone_nsec3chain:"
8611 "need_nsec_chain -> %s",
8612 dns_result_totext(result));
8613 goto failure;
8614 }
8615 }
8616
8617 if (first) {
8618 dnssec_log(zone, ISC_LOG_DEBUG(3),
8619 "zone_nsec3chain:buildnsecchain = %u\n",
8620 buildnsecchain);
8621 }
8622
8623 dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
8624 dns_dbiterator_pause(nsec3chain->dbiterator);
8625 delegation = false;
8626
8627 if (!buildnsecchain) {
8628 /*
8629 * Delete the NSEC3PARAM record matching this chain.
8630 */
8631 if (first) {
8632 result = fixup_nsec3param(
8633 db, version, nsec3chain, true,
8634 privatetype, ¶m_diff);
8635 if (result != ISC_R_SUCCESS) {
8636 dnssec_log(zone, ISC_LOG_ERROR,
8637 "zone_nsec3chain:"
8638 "fixup_nsec3param -> %s",
8639 dns_result_totext(result));
8640 goto failure;
8641 }
8642 }
8643
8644 /*
8645 * Delete the NSEC3 records.
8646 */
8647 result = deletematchingnsec3(db, version, node, name,
8648 &nsec3chain->nsec3param,
8649 &nsec3_diff);
8650 if (result != ISC_R_SUCCESS) {
8651 dnssec_log(zone, ISC_LOG_ERROR,
8652 "zone_nsec3chain:"
8653 "deletematchingnsec3 -> %s",
8654 dns_result_totext(result));
8655 goto failure;
8656 }
8657 goto next_removenode;
8658 }
8659
8660 if (first) {
8661 dns_fixedname_t ffound;
8662 dns_name_t *found;
8663 found = dns_fixedname_initname(&ffound);
8664 result = dns_db_find(
8665 db, name, version, dns_rdatatype_soa,
8666 DNS_DBFIND_NOWILD, 0, NULL, found, NULL, NULL);
8667 if ((result == DNS_R_DELEGATION ||
8668 result == DNS_R_DNAME) &&
8669 !dns_name_equal(name, found))
8670 {
8671 /*
8672 * Remember the obscuring name so that
8673 * we skip all obscured names.
8674 */
8675 dns_name_copynf(found, name);
8676 delegation = true;
8677 goto next_removenode;
8678 }
8679 }
8680
8681 /*
8682 * Check to see if this is a bottom of zone node.
8683 */
8684 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
8685 if (result == ISC_R_NOTFOUND) {
8686 /* Empty node? */
8687 goto next_removenode;
8688 }
8689 if (result != ISC_R_SUCCESS) {
8690 goto failure;
8691 }
8692
8693 seen_soa = seen_ns = seen_dname = seen_nsec3 = seen_nsec =
8694 seen_rr = false;
8695 for (result = dns_rdatasetiter_first(iterator);
8696 result == ISC_R_SUCCESS;
8697 result = dns_rdatasetiter_next(iterator))
8698 {
8699 dns_rdatasetiter_current(iterator, &rdataset);
8700 if (rdataset.type == dns_rdatatype_soa) {
8701 seen_soa = true;
8702 } else if (rdataset.type == dns_rdatatype_ns) {
8703 seen_ns = true;
8704 } else if (rdataset.type == dns_rdatatype_dname) {
8705 seen_dname = true;
8706 } else if (rdataset.type == dns_rdatatype_nsec) {
8707 seen_nsec = true;
8708 } else if (rdataset.type == dns_rdatatype_nsec3) {
8709 seen_nsec3 = true;
8710 } else if (rdataset.type != dns_rdatatype_rrsig) {
8711 seen_rr = true;
8712 }
8713 dns_rdataset_disassociate(&rdataset);
8714 }
8715 dns_rdatasetiter_destroy(&iterator);
8716
8717 if (!seen_rr || seen_nsec3 || seen_nsec) {
8718 goto next_removenode;
8719 }
8720 if ((seen_ns && !seen_soa) || seen_dname) {
8721 delegation = true;
8722 }
8723
8724 /*
8725 * Add a NSEC record except at the origin.
8726 */
8727 if (!dns_name_equal(name, dns_db_origin(db))) {
8728 dns_dbiterator_pause(nsec3chain->dbiterator);
8729 CHECK(add_nsec(db, version, name, node, zone->minimum,
8730 delegation, &nsec_diff));
8731 signatures--;
8732 }
8733
8734 next_removenode:
8735 first = false;
8736 dns_db_detachnode(db, &node);
8737 do {
8738 result = dns_dbiterator_next(nsec3chain->dbiterator);
8739 if (result == ISC_R_NOMORE && buildnsecchain) {
8740 /*
8741 * The NSEC chain should now be built.
8742 * We can now remove the NSEC3 chain.
8743 */
8744 updatensec = true;
8745 goto same_removechain;
8746 }
8747 if (result == ISC_R_NOMORE) {
8748 dns_dbiterator_pause(nsec3chain->dbiterator);
8749 LOCK_ZONE(zone);
8750 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
8751 link);
8752 UNLOCK_ZONE(zone);
8753 ISC_LIST_APPEND(cleanup, nsec3chain, link);
8754 result = fixup_nsec3param(
8755 db, version, nsec3chain, false,
8756 privatetype, ¶m_diff);
8757 if (result != ISC_R_SUCCESS) {
8758 dnssec_log(zone, ISC_LOG_ERROR,
8759 "zone_nsec3chain:"
8760 "fixup_nsec3param -> %s",
8761 dns_result_totext(result));
8762 goto failure;
8763 }
8764 goto next_removechain;
8765 } else if (result != ISC_R_SUCCESS) {
8766 dnssec_log(zone, ISC_LOG_ERROR,
8767 "zone_nsec3chain:"
8768 "dns_dbiterator_next -> %s",
8769 dns_result_totext(result));
8770 goto failure;
8771 } else if (delegation) {
8772 dns_dbiterator_current(nsec3chain->dbiterator,
8773 &node, nextname);
8774 dns_db_detachnode(db, &node);
8775 if (!dns_name_issubdomain(nextname, name)) {
8776 break;
8777 }
8778 } else {
8779 break;
8780 }
8781 } while (1);
8782 continue;
8783
8784 same_removechain:
8785 CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
8786 buildnsecchain = false;
8787 first = true;
8788 continue;
8789
8790 next_removechain:
8791 dns_dbiterator_pause(nsec3chain->dbiterator);
8792 nsec3chain = nextnsec3chain;
8793 first = true;
8794 }
8795
8796 skip_removals:
8797 /*
8798 * We may need to update the NSEC/NSEC3 records for the zone apex.
8799 */
8800 if (!ISC_LIST_EMPTY(param_diff.tuples)) {
8801 bool rebuild_nsec = false, rebuild_nsec3 = false;
8802 result = dns_db_getoriginnode(db, &node);
8803 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8804 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
8805 if (result != ISC_R_SUCCESS) {
8806 dnssec_log(zone, ISC_LOG_ERROR,
8807 "zone_nsec3chain:dns_db_allrdatasets -> %s",
8808 dns_result_totext(result));
8809 goto failure;
8810 }
8811 for (result = dns_rdatasetiter_first(iterator);
8812 result == ISC_R_SUCCESS;
8813 result = dns_rdatasetiter_next(iterator))
8814 {
8815 dns_rdatasetiter_current(iterator, &rdataset);
8816 if (rdataset.type == dns_rdatatype_nsec) {
8817 rebuild_nsec = true;
8818 } else if (rdataset.type == dns_rdatatype_nsec3param) {
8819 rebuild_nsec3 = true;
8820 }
8821 dns_rdataset_disassociate(&rdataset);
8822 }
8823 dns_rdatasetiter_destroy(&iterator);
8824 dns_db_detachnode(db, &node);
8825
8826 if (rebuild_nsec) {
8827 if (nsec3chain != NULL) {
8828 dns_dbiterator_pause(nsec3chain->dbiterator);
8829 }
8830
8831 result = updatesecure(db, version, &zone->origin,
8832 zone->minimum, true, &nsec_diff);
8833 if (result != ISC_R_SUCCESS) {
8834 dnssec_log(zone, ISC_LOG_ERROR,
8835 "zone_nsec3chain:updatesecure -> %s",
8836 dns_result_totext(result));
8837 goto failure;
8838 }
8839 }
8840
8841 if (rebuild_nsec3) {
8842 if (nsec3chain != NULL) {
8843 dns_dbiterator_pause(nsec3chain->dbiterator);
8844 }
8845
8846 result = dns_nsec3_addnsec3s(
8847 db, version, dns_db_origin(db), zone->minimum,
8848 false, &nsec3_diff);
8849 if (result != ISC_R_SUCCESS) {
8850 dnssec_log(zone, ISC_LOG_ERROR,
8851 "zone_nsec3chain:"
8852 "dns_nsec3_addnsec3s -> %s",
8853 dns_result_totext(result));
8854 goto failure;
8855 }
8856 }
8857 }
8858
8859 /*
8860 * Add / update signatures for the NSEC3 records.
8861 */
8862 if (nsec3chain != NULL) {
8863 dns_dbiterator_pause(nsec3chain->dbiterator);
8864 }
8865 result = dns__zone_updatesigs(&nsec3_diff, db, version, zone_keys,
8866 nkeys, zone, inception, expire, 0, now,
8867 check_ksk, keyset_kskonly, &zonediff);
8868 if (result != ISC_R_SUCCESS) {
8869 dnssec_log(zone, ISC_LOG_ERROR,
8870 "zone_nsec3chain:dns__zone_updatesigs -> %s",
8871 dns_result_totext(result));
8872 goto failure;
8873 }
8874
8875 /*
8876 * We have changed the NSEC3PARAM or private RRsets
8877 * above so we need to update the signatures.
8878 */
8879 result = dns__zone_updatesigs(¶m_diff, db, version, zone_keys,
8880 nkeys, zone, inception, expire, 0, now,
8881 check_ksk, keyset_kskonly, &zonediff);
8882 if (result != ISC_R_SUCCESS) {
8883 dnssec_log(zone, ISC_LOG_ERROR,
8884 "zone_nsec3chain:dns__zone_updatesigs -> %s",
8885 dns_result_totext(result));
8886 goto failure;
8887 }
8888
8889 if (updatensec) {
8890 result = updatesecure(db, version, &zone->origin, zone->minimum,
8891 false, &nsec_diff);
8892 if (result != ISC_R_SUCCESS) {
8893 dnssec_log(zone, ISC_LOG_ERROR,
8894 "zone_nsec3chain:updatesecure -> %s",
8895 dns_result_totext(result));
8896 goto failure;
8897 }
8898 }
8899
8900 result = dns__zone_updatesigs(&nsec_diff, db, version, zone_keys, nkeys,
8901 zone, inception, expire, 0, now,
8902 check_ksk, keyset_kskonly, &zonediff);
8903 if (result != ISC_R_SUCCESS) {
8904 dnssec_log(zone, ISC_LOG_ERROR,
8905 "zone_nsec3chain:dns__zone_updatesigs -> %s",
8906 dns_result_totext(result));
8907 goto failure;
8908 }
8909
8910 /*
8911 * If we made no effective changes to the zone then we can just
8912 * cleanup otherwise we need to increment the serial.
8913 */
8914 if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
8915 /*
8916 * No need to call dns_db_closeversion() here as it is
8917 * called with commit = true below.
8918 */
8919 goto done;
8920 }
8921
8922 result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
8923 &zonediff, zone_keys, nkeys, now, false);
8924 if (result != ISC_R_SUCCESS) {
8925 dnssec_log(zone, ISC_LOG_ERROR,
8926 "zone_nsec3chain:del_sigs -> %s",
8927 dns_result_totext(result));
8928 goto failure;
8929 }
8930
8931 result = update_soa_serial(zone, db, version, zonediff.diff, zone->mctx,
8932 zone->updatemethod);
8933 if (result != ISC_R_SUCCESS) {
8934 dnssec_log(zone, ISC_LOG_ERROR,
8935 "zone_nsec3chain:update_soa_serial -> %s",
8936 dns_result_totext(result));
8937 goto failure;
8938 }
8939
8940 result = add_sigs(db, version, &zone->origin, zone, dns_rdatatype_soa,
8941 zonediff.diff, zone_keys, nkeys, zone->mctx,
8942 inception, soaexpire, check_ksk, keyset_kskonly);
8943 if (result != ISC_R_SUCCESS) {
8944 dnssec_log(zone, ISC_LOG_ERROR,
8945 "zone_nsec3chain:add_sigs -> %s",
8946 dns_result_totext(result));
8947 goto failure;
8948 }
8949
8950 /* Write changes to journal file. */
8951 CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_nsec3chain"));
8952
8953 LOCK_ZONE(zone);
8954 zone_needdump(zone, DNS_DUMP_DELAY);
8955 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
8956 UNLOCK_ZONE(zone);
8957
8958 done:
8959 /*
8960 * Pause all iterators so that dns_db_closeversion() can succeed.
8961 */
8962 LOCK_ZONE(zone);
8963 for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain); nsec3chain != NULL;
8964 nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
8965 {
8966 dns_dbiterator_pause(nsec3chain->dbiterator);
8967 }
8968 UNLOCK_ZONE(zone);
8969
8970 /*
8971 * Everything has succeeded. Commit the changes.
8972 * Unconditionally commit as zonediff.offline not checked above.
8973 */
8974 dns_db_closeversion(db, &version, true);
8975
8976 /*
8977 * Everything succeeded so we can clean these up now.
8978 */
8979 nsec3chain = ISC_LIST_HEAD(cleanup);
8980 while (nsec3chain != NULL) {
8981 ISC_LIST_UNLINK(cleanup, nsec3chain, link);
8982 dns_db_detach(&nsec3chain->db);
8983 dns_dbiterator_destroy(&nsec3chain->dbiterator);
8984 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
8985 nsec3chain = ISC_LIST_HEAD(cleanup);
8986 }
8987
8988 LOCK_ZONE(zone);
8989 set_resigntime(zone);
8990 UNLOCK_ZONE(zone);
8991
8992 failure:
8993 if (result != ISC_R_SUCCESS) {
8994 dnssec_log(zone, ISC_LOG_ERROR, "zone_nsec3chain: %s",
8995 dns_result_totext(result));
8996 }
8997
8998 /*
8999 * On error roll back the current nsec3chain.
9000 */
9001 if (result != ISC_R_SUCCESS && nsec3chain != NULL) {
9002 if (nsec3chain->done) {
9003 dns_db_detach(&nsec3chain->db);
9004 dns_dbiterator_destroy(&nsec3chain->dbiterator);
9005 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
9006 } else {
9007 result = dns_dbiterator_first(nsec3chain->dbiterator);
9008 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9009 dns_dbiterator_pause(nsec3chain->dbiterator);
9010 nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
9011 }
9012 }
9013
9014 /*
9015 * Rollback the cleanup list.
9016 */
9017 nsec3chain = ISC_LIST_TAIL(cleanup);
9018 while (nsec3chain != NULL) {
9019 ISC_LIST_UNLINK(cleanup, nsec3chain, link);
9020 if (nsec3chain->done) {
9021 dns_db_detach(&nsec3chain->db);
9022 dns_dbiterator_destroy(&nsec3chain->dbiterator);
9023 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
9024 } else {
9025 LOCK_ZONE(zone);
9026 ISC_LIST_PREPEND(zone->nsec3chain, nsec3chain, link);
9027 UNLOCK_ZONE(zone);
9028 result = dns_dbiterator_first(nsec3chain->dbiterator);
9029 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9030 dns_dbiterator_pause(nsec3chain->dbiterator);
9031 nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
9032 }
9033 nsec3chain = ISC_LIST_TAIL(cleanup);
9034 }
9035
9036 LOCK_ZONE(zone);
9037 for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain); nsec3chain != NULL;
9038 nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
9039 {
9040 dns_dbiterator_pause(nsec3chain->dbiterator);
9041 }
9042 UNLOCK_ZONE(zone);
9043
9044 dns_diff_clear(¶m_diff);
9045 dns_diff_clear(&nsec3_diff);
9046 dns_diff_clear(&nsec_diff);
9047 dns_diff_clear(&_sig_diff);
9048
9049 if (iterator != NULL) {
9050 dns_rdatasetiter_destroy(&iterator);
9051 }
9052
9053 for (i = 0; i < nkeys; i++) {
9054 dst_key_free(&zone_keys[i]);
9055 }
9056
9057 if (node != NULL) {
9058 dns_db_detachnode(db, &node);
9059 }
9060 if (version != NULL) {
9061 dns_db_closeversion(db, &version, false);
9062 dns_db_detach(&db);
9063 } else if (db != NULL) {
9064 dns_db_detach(&db);
9065 }
9066
9067 LOCK_ZONE(zone);
9068 if (ISC_LIST_HEAD(zone->nsec3chain) != NULL) {
9069 isc_interval_t interval;
9070 if (zone->update_disabled || result != ISC_R_SUCCESS) {
9071 isc_interval_set(&interval, 60, 0); /* 1 minute */
9072 } else {
9073 isc_interval_set(&interval, 0, 10000000); /* 10 ms */
9074 }
9075 isc_time_nowplusinterval(&zone->nsec3chaintime, &interval);
9076 } else {
9077 isc_time_settoepoch(&zone->nsec3chaintime);
9078 }
9079 UNLOCK_ZONE(zone);
9080
9081 INSIST(version == NULL);
9082 }
9083
9084 /*%
9085 * Delete all RRSIG records with the given algorithm and keyid.
9086 * Remove the NSEC record and RRSIGs if nkeys is zero.
9087 * If all remaining RRsets are signed with the given algorithm
9088 * set *has_algp to true.
9089 */
9090 static isc_result_t
9091 del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
9092 dns_dbnode_t *node, unsigned int nkeys, dns_secalg_t algorithm,
9093 uint16_t keyid, bool *has_algp, dns_diff_t *diff) {
9094 dns_rdata_rrsig_t rrsig;
9095 dns_rdataset_t rdataset;
9096 dns_rdatasetiter_t *iterator = NULL;
9097 isc_result_t result;
9098 bool alg_missed = false;
9099 bool alg_found = false;
9100
9101 char namebuf[DNS_NAME_FORMATSIZE];
9102 dns_name_format(name, namebuf, sizeof(namebuf));
9103
9104 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
9105 if (result != ISC_R_SUCCESS) {
9106 if (result == ISC_R_NOTFOUND) {
9107 result = ISC_R_SUCCESS;
9108 }
9109 return (result);
9110 }
9111
9112 dns_rdataset_init(&rdataset);
9113 for (result = dns_rdatasetiter_first(iterator); result == ISC_R_SUCCESS;
9114 result = dns_rdatasetiter_next(iterator))
9115 {
9116 bool has_alg = false;
9117 dns_rdatasetiter_current(iterator, &rdataset);
9118 if (nkeys == 0 && rdataset.type == dns_rdatatype_nsec) {
9119 for (result = dns_rdataset_first(&rdataset);
9120 result == ISC_R_SUCCESS;
9121 result = dns_rdataset_next(&rdataset))
9122 {
9123 dns_rdata_t rdata = DNS_RDATA_INIT;
9124 dns_rdataset_current(&rdataset, &rdata);
9125 CHECK(update_one_rr(db, version, diff,
9126 DNS_DIFFOP_DEL, name,
9127 rdataset.ttl, &rdata));
9128 }
9129 if (result != ISC_R_NOMORE) {
9130 goto failure;
9131 }
9132 dns_rdataset_disassociate(&rdataset);
9133 continue;
9134 }
9135 if (rdataset.type != dns_rdatatype_rrsig) {
9136 dns_rdataset_disassociate(&rdataset);
9137 continue;
9138 }
9139 for (result = dns_rdataset_first(&rdataset);
9140 result == ISC_R_SUCCESS;
9141 result = dns_rdataset_next(&rdataset))
9142 {
9143 dns_rdata_t rdata = DNS_RDATA_INIT;
9144 dns_rdataset_current(&rdataset, &rdata);
9145 CHECK(dns_rdata_tostruct(&rdata, &rrsig, NULL));
9146 if (nkeys != 0 && (rrsig.algorithm != algorithm ||
9147 rrsig.keyid != keyid)) {
9148 if (rrsig.algorithm == algorithm) {
9149 has_alg = true;
9150 }
9151 continue;
9152 }
9153 CHECK(update_one_rr(db, version, diff,
9154 DNS_DIFFOP_DELRESIGN, name,
9155 rdataset.ttl, &rdata));
9156 }
9157 dns_rdataset_disassociate(&rdataset);
9158 if (result != ISC_R_NOMORE) {
9159 break;
9160 }
9161
9162 /*
9163 * After deleting, if there's still a signature for
9164 * 'algorithm', set alg_found; if not, set alg_missed.
9165 */
9166 if (has_alg) {
9167 alg_found = true;
9168 } else {
9169 alg_missed = true;
9170 }
9171 }
9172 if (result == ISC_R_NOMORE) {
9173 result = ISC_R_SUCCESS;
9174 }
9175
9176 /*
9177 * Set `has_algp` if the algorithm was found in every RRset:
9178 * i.e., found in at least one, and not missing from any.
9179 */
9180 *has_algp = (alg_found && !alg_missed);
9181 failure:
9182 if (dns_rdataset_isassociated(&rdataset)) {
9183 dns_rdataset_disassociate(&rdataset);
9184 }
9185 dns_rdatasetiter_destroy(&iterator);
9186 return (result);
9187 }
9188
9189 /*
9190 * Incrementally sign the zone using the keys requested.
9191 * Builds the NSEC chain if required.
9192 */
9193 static void
9194 zone_sign(dns_zone_t *zone) {
9195 const char *me = "zone_sign";
9196 dns_db_t *db = NULL;
9197 dns_dbnode_t *node = NULL;
9198 dns_dbversion_t *version = NULL;
9199 dns_diff_t _sig_diff;
9200 dns_diff_t post_diff;
9201 dns__zonediff_t zonediff;
9202 dns_fixedname_t fixed;
9203 dns_fixedname_t nextfixed;
9204 dns_kasp_t *kasp;
9205 dns_name_t *name, *nextname;
9206 dns_rdataset_t rdataset;
9207 dns_signing_t *signing, *nextsigning;
9208 dns_signinglist_t cleanup;
9209 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
9210 int32_t signatures;
9211 bool check_ksk, keyset_kskonly, is_ksk, is_zsk;
9212 bool with_ksk, with_zsk;
9213 bool commit = false;
9214 bool is_bottom_of_zone;
9215 bool build_nsec = false;
9216 bool build_nsec3 = false;
9217 bool use_kasp = false;
9218 bool first;
9219 isc_result_t result;
9220 isc_stdtime_t now, inception, soaexpire, expire;
9221 uint32_t jitter, sigvalidityinterval, expiryinterval;
9222 unsigned int i, j;
9223 unsigned int nkeys = 0;
9224 uint32_t nodes;
9225
9226 ENTER;
9227
9228 dns_rdataset_init(&rdataset);
9229 name = dns_fixedname_initname(&fixed);
9230 nextname = dns_fixedname_initname(&nextfixed);
9231 dns_diff_init(zone->mctx, &_sig_diff);
9232 dns_diff_init(zone->mctx, &post_diff);
9233 zonediff_init(&zonediff, &_sig_diff);
9234 ISC_LIST_INIT(cleanup);
9235
9236 /*
9237 * Updates are disabled. Pause for 1 minute.
9238 */
9239 if (zone->update_disabled) {
9240 result = ISC_R_FAILURE;
9241 goto cleanup;
9242 }
9243
9244 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9245 if (zone->db != NULL) {
9246 dns_db_attach(zone->db, &db);
9247 }
9248 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9249 if (db == NULL) {
9250 result = ISC_R_FAILURE;
9251 goto cleanup;
9252 }
9253
9254 result = dns_db_newversion(db, &version);
9255 if (result != ISC_R_SUCCESS) {
9256 dnssec_log(zone, ISC_LOG_ERROR,
9257 "zone_sign:dns_db_newversion -> %s",
9258 dns_result_totext(result));
9259 goto cleanup;
9260 }
9261
9262 isc_stdtime_get(&now);
9263
9264 result = dns__zone_findkeys(zone, db, version, now, zone->mctx,
9265 DNS_MAXZONEKEYS, zone_keys, &nkeys);
9266 if (result != ISC_R_SUCCESS) {
9267 dnssec_log(zone, ISC_LOG_ERROR,
9268 "zone_sign:dns__zone_findkeys -> %s",
9269 dns_result_totext(result));
9270 goto cleanup;
9271 }
9272
9273 kasp = dns_zone_getkasp(zone);
9274 sigvalidityinterval = dns_zone_getsigvalidityinterval(zone);
9275 inception = now - 3600; /* Allow for clock skew. */
9276 soaexpire = now + sigvalidityinterval;
9277 expiryinterval = dns_zone_getsigresigninginterval(zone);
9278 if (expiryinterval > sigvalidityinterval) {
9279 expiryinterval = sigvalidityinterval;
9280 } else {
9281 expiryinterval = sigvalidityinterval - expiryinterval;
9282 }
9283
9284 /*
9285 * Spread out signatures over time if they happen to be
9286 * clumped. We don't do this for each add_sigs() call as
9287 * we still want some clustering to occur.
9288 */
9289 if (sigvalidityinterval >= 3600U) {
9290 if (sigvalidityinterval > 7200U) {
9291 jitter = isc_random_uniform(expiryinterval);
9292 } else {
9293 jitter = isc_random_uniform(1200);
9294 }
9295 expire = soaexpire - jitter - 1;
9296 } else {
9297 expire = soaexpire - 1;
9298 }
9299
9300 /*
9301 * We keep pulling nodes off each iterator in turn until
9302 * we have no more nodes to pull off or we reach the limits
9303 * for this quantum.
9304 */
9305 nodes = zone->nodes;
9306 signatures = zone->signatures;
9307 signing = ISC_LIST_HEAD(zone->signing);
9308 first = true;
9309
9310 if (dns_zone_use_kasp(zone)) {
9311 check_ksk = false;
9312 keyset_kskonly = true;
9313 use_kasp = true;
9314 } else {
9315 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
9316 keyset_kskonly = DNS_ZONE_OPTION(zone,
9317 DNS_ZONEOPT_DNSKEYKSKONLY);
9318 }
9319 dnssec_log(zone, ISC_LOG_DEBUG(3), "zone_sign:use kasp -> %s",
9320 use_kasp ? "yes" : "no");
9321
9322 /* Determine which type of chain to build */
9323 if (use_kasp) {
9324 build_nsec3 = dns_kasp_nsec3(kasp);
9325 build_nsec = !build_nsec3;
9326 } else {
9327 CHECK(dns_private_chains(db, version, zone->privatetype,
9328 &build_nsec, &build_nsec3));
9329 /* If neither chain is found, default to NSEC */
9330 if (!build_nsec && !build_nsec3) {
9331 build_nsec = true;
9332 }
9333 }
9334
9335 while (signing != NULL && nodes-- > 0 && signatures > 0) {
9336 bool has_alg = false;
9337
9338 dns_dbiterator_pause(signing->dbiterator);
9339 nextsigning = ISC_LIST_NEXT(signing, link);
9340
9341 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9342 if (signing->done || signing->db != zone->db) {
9343 /*
9344 * The zone has been reloaded. We will have to
9345 * created new signings as part of the reload
9346 * process so we can destroy this one.
9347 */
9348 ISC_LIST_UNLINK(zone->signing, signing, link);
9349 ISC_LIST_APPEND(cleanup, signing, link);
9350 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9351 goto next_signing;
9352 }
9353 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9354
9355 if (signing->db != db) {
9356 goto next_signing;
9357 }
9358
9359 is_bottom_of_zone = false;
9360
9361 if (first && signing->deleteit) {
9362 /*
9363 * Remove the key we are deleting from consideration.
9364 */
9365 for (i = 0, j = 0; i < nkeys; i++) {
9366 /*
9367 * Find the key we want to remove.
9368 */
9369 if (ALG(zone_keys[i]) == signing->algorithm &&
9370 dst_key_id(zone_keys[i]) == signing->keyid)
9371 {
9372 bool ksk = false;
9373 isc_result_t ret = dst_key_getbool(
9374 zone_keys[i], DST_BOOL_KSK,
9375 &ksk);
9376 if (ret != ISC_R_SUCCESS) {
9377 ksk = KSK(zone_keys[i]);
9378 }
9379 if (ksk) {
9380 dst_key_free(&zone_keys[i]);
9381 }
9382 continue;
9383 }
9384 zone_keys[j] = zone_keys[i];
9385 j++;
9386 }
9387 for (i = j; i < nkeys; i++) {
9388 zone_keys[i] = NULL;
9389 }
9390 nkeys = j;
9391 }
9392
9393 dns_dbiterator_current(signing->dbiterator, &node, name);
9394
9395 if (signing->deleteit) {
9396 dns_dbiterator_pause(signing->dbiterator);
9397 CHECK(del_sig(db, version, name, node, nkeys,
9398 signing->algorithm, signing->keyid,
9399 &has_alg, zonediff.diff));
9400 }
9401
9402 /*
9403 * On the first pass we need to check if the current node
9404 * has not been obscured.
9405 */
9406 if (first) {
9407 dns_fixedname_t ffound;
9408 dns_name_t *found;
9409 found = dns_fixedname_initname(&ffound);
9410 result = dns_db_find(
9411 db, name, version, dns_rdatatype_soa,
9412 DNS_DBFIND_NOWILD, 0, NULL, found, NULL, NULL);
9413 if ((result == DNS_R_DELEGATION ||
9414 result == DNS_R_DNAME) &&
9415 !dns_name_equal(name, found))
9416 {
9417 /*
9418 * Remember the obscuring name so that
9419 * we skip all obscured names.
9420 */
9421 dns_name_copynf(found, name);
9422 is_bottom_of_zone = true;
9423 goto next_node;
9424 }
9425 }
9426
9427 /*
9428 * Process one node.
9429 */
9430 with_ksk = false;
9431 with_zsk = false;
9432 dns_dbiterator_pause(signing->dbiterator);
9433
9434 CHECK(check_if_bottom_of_zone(db, node, version,
9435 &is_bottom_of_zone));
9436
9437 for (i = 0; !has_alg && i < nkeys; i++) {
9438 bool both = false;
9439
9440 /*
9441 * Find the keys we want to sign with.
9442 */
9443 if (!dst_key_isprivate(zone_keys[i])) {
9444 continue;
9445 }
9446 if (dst_key_inactive(zone_keys[i])) {
9447 continue;
9448 }
9449
9450 /*
9451 * When adding look for the specific key.
9452 */
9453 if (!signing->deleteit &&
9454 (dst_key_alg(zone_keys[i]) != signing->algorithm ||
9455 dst_key_id(zone_keys[i]) != signing->keyid))
9456 {
9457 continue;
9458 }
9459
9460 /*
9461 * When deleting make sure we are properly signed
9462 * with the algorithm that was being removed.
9463 */
9464 if (signing->deleteit &&
9465 ALG(zone_keys[i]) != signing->algorithm) {
9466 continue;
9467 }
9468
9469 /*
9470 * Do we do KSK processing?
9471 */
9472 if (check_ksk && !REVOKE(zone_keys[i])) {
9473 bool have_ksk, have_nonksk;
9474 if (KSK(zone_keys[i])) {
9475 have_ksk = true;
9476 have_nonksk = false;
9477 } else {
9478 have_ksk = false;
9479 have_nonksk = true;
9480 }
9481 for (j = 0; j < nkeys; j++) {
9482 if (j == i || (ALG(zone_keys[i]) !=
9483 ALG(zone_keys[j]))) {
9484 continue;
9485 }
9486 /* Don't consider inactive keys, however
9487 * the key may be temporary offline, so
9488 * do consider keys which private key
9489 * files are unavailable.
9490 */
9491 if (dst_key_inactive(zone_keys[j])) {
9492 continue;
9493 }
9494 if (REVOKE(zone_keys[j])) {
9495 continue;
9496 }
9497 if (KSK(zone_keys[j])) {
9498 have_ksk = true;
9499 } else {
9500 have_nonksk = true;
9501 }
9502 both = have_ksk && have_nonksk;
9503 if (both) {
9504 break;
9505 }
9506 }
9507 }
9508 if (use_kasp) {
9509 /*
9510 * A dnssec-policy is found. Check what
9511 * RRsets this key can sign.
9512 */
9513 isc_result_t kresult;
9514 is_ksk = false;
9515 kresult = dst_key_getbool(
9516 zone_keys[i], DST_BOOL_KSK, &is_ksk);
9517 if (kresult != ISC_R_SUCCESS) {
9518 if (KSK(zone_keys[i])) {
9519 is_ksk = true;
9520 }
9521 }
9522
9523 is_zsk = false;
9524 kresult = dst_key_getbool(
9525 zone_keys[i], DST_BOOL_ZSK, &is_zsk);
9526 if (kresult != ISC_R_SUCCESS) {
9527 if (!KSK(zone_keys[i])) {
9528 is_zsk = true;
9529 }
9530 }
9531 /* Treat as if we have both KSK and ZSK. */
9532 both = true;
9533 } else if (both || REVOKE(zone_keys[i])) {
9534 is_ksk = KSK(zone_keys[i]);
9535 is_zsk = !KSK(zone_keys[i]);
9536 } else {
9537 is_ksk = false;
9538 is_zsk = true;
9539 }
9540
9541 /*
9542 * If deleting signatures, we need to ensure that
9543 * the RRset is still signed at least once by a
9544 * KSK and a ZSK.
9545 */
9546 if (signing->deleteit && is_zsk && with_zsk) {
9547 continue;
9548 }
9549
9550 if (signing->deleteit && is_ksk && with_ksk) {
9551 continue;
9552 }
9553
9554 CHECK(sign_a_node(
9555 db, zone, name, node, version, build_nsec3,
9556 build_nsec, zone_keys[i], inception, expire,
9557 zone->minimum, is_ksk, is_zsk,
9558 (both && keyset_kskonly), is_bottom_of_zone,
9559 zonediff.diff, &signatures, zone->mctx));
9560 /*
9561 * If we are adding we are done. Look for other keys
9562 * of the same algorithm if deleting.
9563 */
9564 if (!signing->deleteit) {
9565 break;
9566 }
9567 if (is_zsk) {
9568 with_zsk = true;
9569 }
9570 if (is_ksk) {
9571 with_ksk = true;
9572 }
9573 }
9574
9575 /*
9576 * Go onto next node.
9577 */
9578 next_node:
9579 first = false;
9580 dns_db_detachnode(db, &node);
9581 do {
9582 result = dns_dbiterator_next(signing->dbiterator);
9583 if (result == ISC_R_NOMORE) {
9584 ISC_LIST_UNLINK(zone->signing, signing, link);
9585 ISC_LIST_APPEND(cleanup, signing, link);
9586 dns_dbiterator_pause(signing->dbiterator);
9587 if (nkeys != 0 && build_nsec) {
9588 /*
9589 * We have finished regenerating the
9590 * zone with a zone signing key.
9591 * The NSEC chain is now complete and
9592 * there is a full set of signatures
9593 * for the zone. We can now clear the
9594 * OPT bit from the NSEC record.
9595 */
9596 result = updatesecure(
9597 db, version, &zone->origin,
9598 zone->minimum, false,
9599 &post_diff);
9600 if (result != ISC_R_SUCCESS) {
9601 dnssec_log(zone, ISC_LOG_ERROR,
9602 "updatesecure -> %s",
9603 dns_result_totext(
9604 result));
9605 goto cleanup;
9606 }
9607 }
9608 result = updatesignwithkey(
9609 zone, signing, version, build_nsec3,
9610 zone->minimum, &post_diff);
9611 if (result != ISC_R_SUCCESS) {
9612 dnssec_log(zone, ISC_LOG_ERROR,
9613 "updatesignwithkey -> %s",
9614 dns_result_totext(result));
9615 goto cleanup;
9616 }
9617 build_nsec = false;
9618 goto next_signing;
9619 } else if (result != ISC_R_SUCCESS) {
9620 dnssec_log(zone, ISC_LOG_ERROR,
9621 "zone_sign:"
9622 "dns_dbiterator_next -> %s",
9623 dns_result_totext(result));
9624 goto cleanup;
9625 } else if (is_bottom_of_zone) {
9626 dns_dbiterator_current(signing->dbiterator,
9627 &node, nextname);
9628 dns_db_detachnode(db, &node);
9629 if (!dns_name_issubdomain(nextname, name)) {
9630 break;
9631 }
9632 } else {
9633 break;
9634 }
9635 } while (1);
9636 continue;
9637
9638 next_signing:
9639 dns_dbiterator_pause(signing->dbiterator);
9640 signing = nextsigning;
9641 first = true;
9642 }
9643
9644 if (ISC_LIST_HEAD(post_diff.tuples) != NULL) {
9645 result = dns__zone_updatesigs(&post_diff, db, version,
9646 zone_keys, nkeys, zone, inception,
9647 expire, 0, now, check_ksk,
9648 keyset_kskonly, &zonediff);
9649 if (result != ISC_R_SUCCESS) {
9650 dnssec_log(zone, ISC_LOG_ERROR,
9651 "zone_sign:dns__zone_updatesigs -> %s",
9652 dns_result_totext(result));
9653 goto cleanup;
9654 }
9655 }
9656
9657 /*
9658 * Have we changed anything?
9659 */
9660 if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
9661 if (zonediff.offline) {
9662 commit = true;
9663 }
9664 result = ISC_R_SUCCESS;
9665 goto pauseall;
9666 }
9667
9668 commit = true;
9669
9670 result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
9671 &zonediff, zone_keys, nkeys, now, false);
9672 if (result != ISC_R_SUCCESS) {
9673 dnssec_log(zone, ISC_LOG_ERROR, "zone_sign:del_sigs -> %s",
9674 dns_result_totext(result));
9675 goto cleanup;
9676 }
9677
9678 result = update_soa_serial(zone, db, version, zonediff.diff, zone->mctx,
9679 zone->updatemethod);
9680 if (result != ISC_R_SUCCESS) {
9681 dnssec_log(zone, ISC_LOG_ERROR,
9682 "zone_sign:update_soa_serial -> %s",
9683 dns_result_totext(result));
9684 goto cleanup;
9685 }
9686
9687 /*
9688 * Generate maximum life time signatures so that the above loop
9689 * termination is sensible.
9690 */
9691 result = add_sigs(db, version, &zone->origin, zone, dns_rdatatype_soa,
9692 zonediff.diff, zone_keys, nkeys, zone->mctx,
9693 inception, soaexpire, check_ksk, keyset_kskonly);
9694 if (result != ISC_R_SUCCESS) {
9695 dnssec_log(zone, ISC_LOG_ERROR, "zone_sign:add_sigs -> %s",
9696 dns_result_totext(result));
9697 goto cleanup;
9698 }
9699
9700 /*
9701 * Write changes to journal file.
9702 */
9703 CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_sign"));
9704
9705 pauseall:
9706 /*
9707 * Pause all iterators so that dns_db_closeversion() can succeed.
9708 */
9709 for (signing = ISC_LIST_HEAD(zone->signing); signing != NULL;
9710 signing = ISC_LIST_NEXT(signing, link))
9711 {
9712 dns_dbiterator_pause(signing->dbiterator);
9713 }
9714
9715 for (signing = ISC_LIST_HEAD(cleanup); signing != NULL;
9716 signing = ISC_LIST_NEXT(signing, link))
9717 {
9718 dns_dbiterator_pause(signing->dbiterator);
9719 }
9720
9721 /*
9722 * Everything has succeeded. Commit the changes.
9723 */
9724 dns_db_closeversion(db, &version, commit);
9725
9726 /*
9727 * Everything succeeded so we can clean these up now.
9728 */
9729 signing = ISC_LIST_HEAD(cleanup);
9730 while (signing != NULL) {
9731 ISC_LIST_UNLINK(cleanup, signing, link);
9732 dns_db_detach(&signing->db);
9733 dns_dbiterator_destroy(&signing->dbiterator);
9734 isc_mem_put(zone->mctx, signing, sizeof *signing);
9735 signing = ISC_LIST_HEAD(cleanup);
9736 }
9737
9738 LOCK_ZONE(zone);
9739 set_resigntime(zone);
9740 if (commit) {
9741 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
9742 zone_needdump(zone, DNS_DUMP_DELAY);
9743 }
9744 UNLOCK_ZONE(zone);
9745
9746 failure:
9747 if (result != ISC_R_SUCCESS) {
9748 dnssec_log(zone, ISC_LOG_ERROR, "zone_sign: failed: %s",
9749 dns_result_totext(result));
9750 }
9751
9752 cleanup:
9753 /*
9754 * Pause all dbiterators.
9755 */
9756 for (signing = ISC_LIST_HEAD(zone->signing); signing != NULL;
9757 signing = ISC_LIST_NEXT(signing, link))
9758 {
9759 dns_dbiterator_pause(signing->dbiterator);
9760 }
9761
9762 /*
9763 * Rollback the cleanup list.
9764 */
9765 signing = ISC_LIST_HEAD(cleanup);
9766 while (signing != NULL) {
9767 ISC_LIST_UNLINK(cleanup, signing, link);
9768 ISC_LIST_PREPEND(zone->signing, signing, link);
9769 dns_dbiterator_first(signing->dbiterator);
9770 dns_dbiterator_pause(signing->dbiterator);
9771 signing = ISC_LIST_HEAD(cleanup);
9772 }
9773
9774 dns_diff_clear(&_sig_diff);
9775
9776 for (i = 0; i < nkeys; i++) {
9777 dst_key_free(&zone_keys[i]);
9778 }
9779
9780 if (node != NULL) {
9781 dns_db_detachnode(db, &node);
9782 }
9783
9784 if (version != NULL) {
9785 dns_db_closeversion(db, &version, false);
9786 dns_db_detach(&db);
9787 } else if (db != NULL) {
9788 dns_db_detach(&db);
9789 }
9790
9791 LOCK_ZONE(zone);
9792 if (ISC_LIST_HEAD(zone->signing) != NULL) {
9793 isc_interval_t interval;
9794 if (zone->update_disabled || result != ISC_R_SUCCESS) {
9795 isc_interval_set(&interval, 60, 0); /* 1 minute */
9796 } else {
9797 isc_interval_set(&interval, 0, 10000000); /* 10 ms */
9798 }
9799 isc_time_nowplusinterval(&zone->signingtime, &interval);
9800 } else {
9801 isc_time_settoepoch(&zone->signingtime);
9802 }
9803 UNLOCK_ZONE(zone);
9804
9805 INSIST(version == NULL);
9806 }
9807
9808 static isc_result_t
9809 normalize_key(dns_rdata_t *rr, dns_rdata_t *target, unsigned char *data,
9810 int size) {
9811 dns_rdata_dnskey_t dnskey;
9812 dns_rdata_keydata_t keydata;
9813 isc_buffer_t buf;
9814 isc_result_t result;
9815
9816 dns_rdata_reset(target);
9817 isc_buffer_init(&buf, data, size);
9818
9819 switch (rr->type) {
9820 case dns_rdatatype_dnskey:
9821 result = dns_rdata_tostruct(rr, &dnskey, NULL);
9822 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9823 dnskey.flags &= ~DNS_KEYFLAG_REVOKE;
9824 dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
9825 &dnskey, &buf);
9826 break;
9827 case dns_rdatatype_keydata:
9828 result = dns_rdata_tostruct(rr, &keydata, NULL);
9829 if (result == ISC_R_UNEXPECTEDEND) {
9830 return (result);
9831 }
9832 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9833 dns_keydata_todnskey(&keydata, &dnskey, NULL);
9834 dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
9835 &dnskey, &buf);
9836 break;
9837 default:
9838 INSIST(0);
9839 ISC_UNREACHABLE();
9840 }
9841 return (ISC_R_SUCCESS);
9842 }
9843
9844 /*
9845 * 'rdset' contains either a DNSKEY rdataset from the zone apex, or
9846 * a KEYDATA rdataset from the key zone.
9847 *
9848 * 'rr' contains either a DNSKEY record, or a KEYDATA record
9849 *
9850 * After normalizing keys to the same format (DNSKEY, with revoke bit
9851 * cleared), return true if a key that matches 'rr' is found in
9852 * 'rdset', or false if not.
9853 */
9854
9855 static bool
9856 matchkey(dns_rdataset_t *rdset, dns_rdata_t *rr) {
9857 unsigned char data1[4096], data2[4096];
9858 dns_rdata_t rdata, rdata1, rdata2;
9859 isc_result_t result;
9860
9861 dns_rdata_init(&rdata);
9862 dns_rdata_init(&rdata1);
9863 dns_rdata_init(&rdata2);
9864
9865 result = normalize_key(rr, &rdata1, data1, sizeof(data1));
9866 if (result != ISC_R_SUCCESS) {
9867 return (false);
9868 }
9869
9870 for (result = dns_rdataset_first(rdset); result == ISC_R_SUCCESS;
9871 result = dns_rdataset_next(rdset))
9872 {
9873 dns_rdata_reset(&rdata);
9874 dns_rdataset_current(rdset, &rdata);
9875 result = normalize_key(&rdata, &rdata2, data2, sizeof(data2));
9876 if (result != ISC_R_SUCCESS) {
9877 continue;
9878 }
9879 if (dns_rdata_compare(&rdata1, &rdata2) == 0) {
9880 return (true);
9881 }
9882 }
9883
9884 return (false);
9885 }
9886
9887 /*
9888 * Calculate the refresh interval for a keydata zone, per
9889 * RFC5011: MAX(1 hr,
9890 * MIN(15 days,
9891 * 1/2 * OrigTTL,
9892 * 1/2 * RRSigExpirationInterval))
9893 * or for retries: MAX(1 hr,
9894 * MIN(1 day,
9895 * 1/10 * OrigTTL,
9896 * 1/10 * RRSigExpirationInterval))
9897 */
9898 static inline isc_stdtime_t
9899 refresh_time(dns_keyfetch_t *kfetch, bool retry) {
9900 isc_result_t result;
9901 uint32_t t;
9902 dns_rdataset_t *rdset;
9903 dns_rdata_t sigrr = DNS_RDATA_INIT;
9904 dns_rdata_sig_t sig;
9905 isc_stdtime_t now;
9906
9907 isc_stdtime_get(&now);
9908
9909 if (dns_rdataset_isassociated(&kfetch->dnskeysigset)) {
9910 rdset = &kfetch->dnskeysigset;
9911 } else {
9912 return (now + dns_zone_mkey_hour);
9913 }
9914
9915 result = dns_rdataset_first(rdset);
9916 if (result != ISC_R_SUCCESS) {
9917 return (now + dns_zone_mkey_hour);
9918 }
9919
9920 dns_rdataset_current(rdset, &sigrr);
9921 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
9922 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9923
9924 if (!retry) {
9925 t = sig.originalttl / 2;
9926
9927 if (isc_serial_gt(sig.timeexpire, now)) {
9928 uint32_t exp = (sig.timeexpire - now) / 2;
9929 if (t > exp) {
9930 t = exp;
9931 }
9932 }
9933
9934 if (t > (15 * dns_zone_mkey_day)) {
9935 t = (15 * dns_zone_mkey_day);
9936 }
9937
9938 if (t < dns_zone_mkey_hour) {
9939 t = dns_zone_mkey_hour;
9940 }
9941 } else {
9942 t = sig.originalttl / 10;
9943
9944 if (isc_serial_gt(sig.timeexpire, now)) {
9945 uint32_t exp = (sig.timeexpire - now) / 10;
9946 if (t > exp) {
9947 t = exp;
9948 }
9949 }
9950
9951 if (t > dns_zone_mkey_day) {
9952 t = dns_zone_mkey_day;
9953 }
9954
9955 if (t < dns_zone_mkey_hour) {
9956 t = dns_zone_mkey_hour;
9957 }
9958 }
9959
9960 return (now + t);
9961 }
9962
9963 /*
9964 * This routine is called when no changes are needed in a KEYDATA
9965 * record except to simply update the refresh timer. Caller should
9966 * hold zone lock.
9967 */
9968 static isc_result_t
9969 minimal_update(dns_keyfetch_t *kfetch, dns_dbversion_t *ver, dns_diff_t *diff) {
9970 isc_result_t result;
9971 isc_buffer_t keyb;
9972 unsigned char key_buf[4096];
9973 dns_rdata_t rdata = DNS_RDATA_INIT;
9974 dns_rdata_keydata_t keydata;
9975 dns_name_t *name;
9976 dns_zone_t *zone = kfetch->zone;
9977 isc_stdtime_t now;
9978
9979 name = dns_fixedname_name(&kfetch->name);
9980 isc_stdtime_get(&now);
9981
9982 for (result = dns_rdataset_first(&kfetch->keydataset);
9983 result == ISC_R_SUCCESS;
9984 result = dns_rdataset_next(&kfetch->keydataset))
9985 {
9986 dns_rdata_reset(&rdata);
9987 dns_rdataset_current(&kfetch->keydataset, &rdata);
9988
9989 /* Delete old version */
9990 CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_DEL, name,
9991 0, &rdata));
9992
9993 /* Update refresh timer */
9994 result = dns_rdata_tostruct(&rdata, &keydata, NULL);
9995 if (result == ISC_R_UNEXPECTEDEND) {
9996 continue;
9997 }
9998 if (result != ISC_R_SUCCESS) {
9999 goto failure;
10000 }
10001 keydata.refresh = refresh_time(kfetch, true);
10002 set_refreshkeytimer(zone, &keydata, now, false);
10003
10004 dns_rdata_reset(&rdata);
10005 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10006 CHECK(dns_rdata_fromstruct(&rdata, zone->rdclass,
10007 dns_rdatatype_keydata, &keydata,
10008 &keyb));
10009
10010 /* Insert updated version */
10011 CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_ADD, name,
10012 0, &rdata));
10013 }
10014 result = ISC_R_SUCCESS;
10015 failure:
10016 return (result);
10017 }
10018
10019 /*
10020 * Verify that DNSKEY set is signed by the key specified in 'keydata'.
10021 */
10022 static bool
10023 revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) {
10024 isc_result_t result;
10025 dns_name_t *keyname;
10026 isc_mem_t *mctx;
10027 dns_rdata_t sigrr = DNS_RDATA_INIT;
10028 dns_rdata_t rr = DNS_RDATA_INIT;
10029 dns_rdata_rrsig_t sig;
10030 dns_rdata_dnskey_t dnskey;
10031 dst_key_t *dstkey = NULL;
10032 unsigned char key_buf[4096];
10033 isc_buffer_t keyb;
10034 bool answer = false;
10035
10036 REQUIRE(kfetch != NULL && keydata != NULL);
10037 REQUIRE(dns_rdataset_isassociated(&kfetch->dnskeysigset));
10038
10039 keyname = dns_fixedname_name(&kfetch->name);
10040 mctx = kfetch->zone->view->mctx;
10041
10042 /* Generate a key from keydata */
10043 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10044 dns_keydata_todnskey(keydata, &dnskey, NULL);
10045 dns_rdata_fromstruct(&rr, keydata->common.rdclass, dns_rdatatype_dnskey,
10046 &dnskey, &keyb);
10047 result = dns_dnssec_keyfromrdata(keyname, &rr, mctx, &dstkey);
10048 if (result != ISC_R_SUCCESS) {
10049 return (false);
10050 }
10051
10052 /* See if that key generated any of the signatures */
10053 for (result = dns_rdataset_first(&kfetch->dnskeysigset);
10054 result == ISC_R_SUCCESS;
10055 result = dns_rdataset_next(&kfetch->dnskeysigset))
10056 {
10057 dns_fixedname_t fixed;
10058 dns_fixedname_init(&fixed);
10059
10060 dns_rdata_reset(&sigrr);
10061 dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
10062 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
10063 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10064
10065 if (dst_key_alg(dstkey) == sig.algorithm &&
10066 dst_key_rid(dstkey) == sig.keyid) {
10067 result = dns_dnssec_verify(
10068 keyname, &kfetch->dnskeyset, dstkey, false, 0,
10069 mctx, &sigrr, dns_fixedname_name(&fixed));
10070
10071 dnssec_log(kfetch->zone, ISC_LOG_DEBUG(3),
10072 "Confirm revoked DNSKEY is self-signed: %s",
10073 dns_result_totext(result));
10074
10075 if (result == ISC_R_SUCCESS) {
10076 answer = true;
10077 break;
10078 }
10079 }
10080 }
10081
10082 dst_key_free(&dstkey);
10083 return (answer);
10084 }
10085
10086 /*
10087 * A DNSKEY set has been fetched from the zone apex of a zone whose trust
10088 * anchors are being managed; scan the keyset, and update the key zone and the
10089 * local trust anchors according to RFC5011.
10090 */
10091 static void
10092 keyfetch_done(isc_task_t *task, isc_event_t *event) {
10093 isc_result_t result, eresult;
10094 dns_fetchevent_t *devent;
10095 dns_keyfetch_t *kfetch;
10096 dns_zone_t *zone;
10097 isc_mem_t *mctx = NULL;
10098 dns_keytable_t *secroots = NULL;
10099 dns_dbversion_t *ver = NULL;
10100 dns_diff_t diff;
10101 bool alldone = false;
10102 bool commit = false;
10103 dns_name_t *keyname = NULL;
10104 dns_rdata_t sigrr = DNS_RDATA_INIT;
10105 dns_rdata_t dnskeyrr = DNS_RDATA_INIT;
10106 dns_rdata_t keydatarr = DNS_RDATA_INIT;
10107 dns_rdata_rrsig_t sig;
10108 dns_rdata_dnskey_t dnskey;
10109 dns_rdata_keydata_t keydata;
10110 bool initializing;
10111 char namebuf[DNS_NAME_FORMATSIZE];
10112 unsigned char key_buf[4096];
10113 isc_buffer_t keyb;
10114 dst_key_t *dstkey = NULL;
10115 isc_stdtime_t now;
10116 int pending = 0;
10117 bool secure = false, initial = false;
10118 bool free_needed;
10119 dns_keynode_t *keynode = NULL;
10120 dns_rdataset_t *dnskeys = NULL, *dnskeysigs = NULL;
10121 dns_rdataset_t *keydataset = NULL, dsset;
10122
10123 UNUSED(task);
10124 INSIST(event != NULL && event->ev_type == DNS_EVENT_FETCHDONE);
10125 INSIST(event->ev_arg != NULL);
10126
10127 kfetch = event->ev_arg;
10128 zone = kfetch->zone;
10129 isc_mem_attach(zone->mctx, &mctx);
10130 keyname = dns_fixedname_name(&kfetch->name);
10131 dnskeys = &kfetch->dnskeyset;
10132 dnskeysigs = &kfetch->dnskeysigset;
10133 keydataset = &kfetch->keydataset;
10134
10135 devent = (dns_fetchevent_t *)event;
10136 eresult = devent->result;
10137
10138 /* Free resources which are not of interest */
10139 if (devent->node != NULL) {
10140 dns_db_detachnode(devent->db, &devent->node);
10141 }
10142 if (devent->db != NULL) {
10143 dns_db_detach(&devent->db);
10144 }
10145 isc_event_free(&event);
10146 dns_resolver_destroyfetch(&kfetch->fetch);
10147
10148 LOCK_ZONE(zone);
10149 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || zone->view == NULL) {
10150 goto cleanup;
10151 }
10152
10153 isc_stdtime_get(&now);
10154 dns_name_format(keyname, namebuf, sizeof(namebuf));
10155
10156 result = dns_view_getsecroots(zone->view, &secroots);
10157 INSIST(result == ISC_R_SUCCESS);
10158
10159 dns_diff_init(mctx, &diff);
10160
10161 CHECK(dns_db_newversion(kfetch->db, &ver));
10162
10163 zone->refreshkeycount--;
10164 alldone = (zone->refreshkeycount == 0);
10165
10166 if (alldone) {
10167 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
10168 }
10169
10170 dnssec_log(zone, ISC_LOG_DEBUG(3),
10171 "Returned from key fetch in keyfetch_done() for '%s': %s",
10172 namebuf, dns_result_totext(eresult));
10173
10174 /* Fetch failed */
10175 if (eresult != ISC_R_SUCCESS || !dns_rdataset_isassociated(dnskeys)) {
10176 dnssec_log(zone, ISC_LOG_WARNING,
10177 "Unable to fetch DNSKEY set '%s': %s", namebuf,
10178 dns_result_totext(eresult));
10179 CHECK(minimal_update(kfetch, ver, &diff));
10180 goto done;
10181 }
10182
10183 /* No RRSIGs found */
10184 if (!dns_rdataset_isassociated(dnskeysigs)) {
10185 dnssec_log(zone, ISC_LOG_WARNING,
10186 "No DNSKEY RRSIGs found for '%s': %s", namebuf,
10187 dns_result_totext(eresult));
10188 CHECK(minimal_update(kfetch, ver, &diff));
10189 goto done;
10190 }
10191
10192 /*
10193 * Clear any cached trust level, as we need to run validation
10194 * over again; trusted keys might have changed.
10195 */
10196 dnskeys->trust = dnskeysigs->trust = dns_trust_none;
10197
10198 /* Look up the trust anchor */
10199 result = dns_keytable_find(secroots, keyname, &keynode);
10200 if (result != ISC_R_SUCCESS) {
10201 goto anchors_done;
10202 }
10203
10204 /*
10205 * If the keynode has a DS trust anchor, use it for verification.
10206 */
10207 dns_rdataset_init(&dsset);
10208 if (dns_keynode_dsset(keynode, &dsset)) {
10209 for (result = dns_rdataset_first(dnskeysigs);
10210 result == ISC_R_SUCCESS;
10211 result = dns_rdataset_next(dnskeysigs))
10212 {
10213 isc_result_t tresult;
10214 dns_rdata_t keyrdata = DNS_RDATA_INIT;
10215
10216 dns_rdata_reset(&sigrr);
10217 dns_rdataset_current(dnskeysigs, &sigrr);
10218 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
10219 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10220
10221 for (tresult = dns_rdataset_first(&dsset);
10222 tresult == ISC_R_SUCCESS;
10223 tresult = dns_rdataset_next(&dsset))
10224 {
10225 dns_rdata_t dsrdata = DNS_RDATA_INIT;
10226 dns_rdata_ds_t ds;
10227
10228 dns_rdata_reset(&dsrdata);
10229 dns_rdataset_current(&dsset, &dsrdata);
10230 tresult = dns_rdata_tostruct(&dsrdata, &ds,
10231 NULL);
10232 RUNTIME_CHECK(tresult == ISC_R_SUCCESS);
10233
10234 if (ds.key_tag != sig.keyid ||
10235 ds.algorithm != sig.algorithm) {
10236 continue;
10237 }
10238
10239 result = dns_dnssec_matchdskey(
10240 keyname, &dsrdata, dnskeys, &keyrdata);
10241 if (result == ISC_R_SUCCESS) {
10242 break;
10243 }
10244 }
10245
10246 if (tresult == ISC_R_NOMORE) {
10247 continue;
10248 }
10249
10250 result = dns_dnssec_keyfromrdata(keyname, &keyrdata,
10251 mctx, &dstkey);
10252 if (result != ISC_R_SUCCESS) {
10253 continue;
10254 }
10255
10256 result = dns_dnssec_verify(keyname, dnskeys, dstkey,
10257 false, 0, mctx, &sigrr,
10258 NULL);
10259 dst_key_free(&dstkey);
10260
10261 dnssec_log(zone, ISC_LOG_DEBUG(3),
10262 "Verifying DNSKEY set for zone "
10263 "'%s' using DS %d/%d: %s",
10264 namebuf, sig.keyid, sig.algorithm,
10265 dns_result_totext(result));
10266
10267 if (result == ISC_R_SUCCESS) {
10268 dnskeys->trust = dns_trust_secure;
10269 dnskeysigs->trust = dns_trust_secure;
10270 initial = dns_keynode_initial(keynode);
10271 dns_keynode_trust(keynode);
10272 secure = true;
10273 break;
10274 }
10275 }
10276 dns_rdataset_disassociate(&dsset);
10277 }
10278
10279 anchors_done:
10280 if (keynode != NULL) {
10281 dns_keytable_detachkeynode(secroots, &keynode);
10282 }
10283
10284 /*
10285 * If we were not able to verify the answer using the current
10286 * trusted keys then all we can do is look at any revoked keys.
10287 */
10288 if (!secure) {
10289 dnssec_log(zone, ISC_LOG_INFO,
10290 "DNSKEY set for zone '%s' could not be verified "
10291 "with current keys",
10292 namebuf);
10293 }
10294
10295 /*
10296 * First scan keydataset to find keys that are not in dnskeyset
10297 * - Missing keys which are not scheduled for removal,
10298 * log a warning
10299 * - Missing keys which are scheduled for removal and
10300 * the remove hold-down timer has completed should
10301 * be removed from the key zone
10302 * - Missing keys whose acceptance timers have not yet
10303 * completed, log a warning and reset the acceptance
10304 * timer to 30 days in the future
10305 * - All keys not being removed have their refresh timers
10306 * updated
10307 */
10308 initializing = true;
10309 for (result = dns_rdataset_first(keydataset); result == ISC_R_SUCCESS;
10310 result = dns_rdataset_next(keydataset))
10311 {
10312 dns_keytag_t keytag;
10313
10314 dns_rdata_reset(&keydatarr);
10315 dns_rdataset_current(keydataset, &keydatarr);
10316 result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
10317 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10318
10319 dns_keydata_todnskey(&keydata, &dnskey, NULL);
10320 result = compute_tag(keyname, &dnskey, mctx, &keytag);
10321 if (result != ISC_R_SUCCESS) {
10322 /*
10323 * Skip if we cannot compute the key tag.
10324 * This may happen if the algorithm is unsupported
10325 */
10326 dns_zone_log(zone, ISC_LOG_ERROR,
10327 "Cannot compute tag for key in zone %s: "
10328 "%s "
10329 "(skipping)",
10330 namebuf, dns_result_totext(result));
10331 continue;
10332 }
10333 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10334
10335 /*
10336 * If any keydata record has a nonzero add holddown, then
10337 * there was a pre-existing trust anchor for this domain;
10338 * that means we are *not* initializing it and shouldn't
10339 * automatically trust all the keys we find at the zone apex.
10340 */
10341 initializing = initializing && (keydata.addhd == 0);
10342
10343 if (!matchkey(dnskeys, &keydatarr)) {
10344 bool deletekey = false;
10345
10346 if (!secure) {
10347 if (keydata.removehd != 0 &&
10348 keydata.removehd <= now) {
10349 deletekey = true;
10350 }
10351 } else if (keydata.addhd == 0) {
10352 deletekey = true;
10353 } else if (keydata.addhd > now) {
10354 dnssec_log(zone, ISC_LOG_INFO,
10355 "Pending key %d for zone %s "
10356 "unexpectedly missing "
10357 "restarting 30-day acceptance "
10358 "timer",
10359 keytag, namebuf);
10360 if (keydata.addhd < now + dns_zone_mkey_month) {
10361 keydata.addhd = now +
10362 dns_zone_mkey_month;
10363 }
10364 keydata.refresh = refresh_time(kfetch, false);
10365 } else if (keydata.removehd == 0) {
10366 dnssec_log(zone, ISC_LOG_INFO,
10367 "Active key %d for zone %s "
10368 "unexpectedly missing",
10369 keytag, namebuf);
10370 keydata.refresh = now + dns_zone_mkey_hour;
10371 } else if (keydata.removehd <= now) {
10372 deletekey = true;
10373 dnssec_log(zone, ISC_LOG_INFO,
10374 "Revoked key %d for zone %s "
10375 "missing: deleting from "
10376 "managed keys database",
10377 keytag, namebuf);
10378 } else {
10379 keydata.refresh = refresh_time(kfetch, false);
10380 }
10381
10382 if (secure || deletekey) {
10383 /* Delete old version */
10384 CHECK(update_one_rr(kfetch->db, ver, &diff,
10385 DNS_DIFFOP_DEL, keyname, 0,
10386 &keydatarr));
10387 }
10388
10389 if (!secure || deletekey) {
10390 continue;
10391 }
10392
10393 dns_rdata_reset(&keydatarr);
10394 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10395 dns_rdata_fromstruct(&keydatarr, zone->rdclass,
10396 dns_rdatatype_keydata, &keydata,
10397 &keyb);
10398
10399 /* Insert updated version */
10400 CHECK(update_one_rr(kfetch->db, ver, &diff,
10401 DNS_DIFFOP_ADD, keyname, 0,
10402 &keydatarr));
10403
10404 set_refreshkeytimer(zone, &keydata, now, false);
10405 }
10406 }
10407
10408 /*
10409 * Next scan dnskeyset:
10410 * - If new keys are found (i.e., lacking a match in keydataset)
10411 * add them to the key zone and set the acceptance timer
10412 * to 30 days in the future (or to immediately if we've
10413 * determined that we're initializing the zone for the
10414 * first time)
10415 * - Previously-known keys that have been revoked
10416 * must be scheduled for removal from the key zone (or,
10417 * if they hadn't been accepted as trust anchors yet
10418 * anyway, removed at once)
10419 * - Previously-known unrevoked keys whose acceptance timers
10420 * have completed are promoted to trust anchors
10421 * - All keys not being removed have their refresh
10422 * timers updated
10423 */
10424 for (result = dns_rdataset_first(dnskeys); result == ISC_R_SUCCESS;
10425 result = dns_rdataset_next(dnskeys))
10426 {
10427 bool revoked = false;
10428 bool newkey = false;
10429 bool updatekey = false;
10430 bool deletekey = false;
10431 bool trustkey = false;
10432 dns_keytag_t keytag;
10433
10434 dns_rdata_reset(&dnskeyrr);
10435 dns_rdataset_current(dnskeys, &dnskeyrr);
10436 result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
10437 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10438
10439 /* Skip ZSK's */
10440 if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0) {
10441 continue;
10442 }
10443
10444 result = compute_tag(keyname, &dnskey, mctx, &keytag);
10445 if (result != ISC_R_SUCCESS) {
10446 /*
10447 * Skip if we cannot compute the key tag.
10448 * This may happen if the algorithm is unsupported
10449 */
10450 dns_zone_log(zone, ISC_LOG_ERROR,
10451 "Cannot compute tag for key in zone %s: "
10452 "%s "
10453 "(skipping)",
10454 namebuf, dns_result_totext(result));
10455 continue;
10456 }
10457 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10458
10459 revoked = ((dnskey.flags & DNS_KEYFLAG_REVOKE) != 0);
10460
10461 if (matchkey(keydataset, &dnskeyrr)) {
10462 dns_rdata_reset(&keydatarr);
10463 dns_rdataset_current(keydataset, &keydatarr);
10464 result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
10465 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10466
10467 if (revoked && revocable(kfetch, &keydata)) {
10468 if (keydata.addhd > now) {
10469 /*
10470 * Key wasn't trusted yet, and now
10471 * it's been revoked? Just remove it
10472 */
10473 deletekey = true;
10474 dnssec_log(zone, ISC_LOG_INFO,
10475 "Pending key %d for "
10476 "zone %s is now revoked: "
10477 "deleting from the "
10478 "managed keys database",
10479 keytag, namebuf);
10480 } else if (keydata.removehd == 0) {
10481 /*
10482 * Remove key from secroots.
10483 */
10484 dns_view_untrust(zone->view, keyname,
10485 &dnskey);
10486
10487 /* If initializing, delete now */
10488 if (keydata.addhd == 0) {
10489 deletekey = true;
10490 } else {
10491 keydata.removehd =
10492 now +
10493 dns_zone_mkey_month;
10494 keydata.flags |=
10495 DNS_KEYFLAG_REVOKE;
10496 }
10497
10498 dnssec_log(zone, ISC_LOG_INFO,
10499 "Trusted key %d for "
10500 "zone %s is now revoked",
10501 keytag, namebuf);
10502 } else if (keydata.removehd < now) {
10503 /* Scheduled for removal */
10504 deletekey = true;
10505
10506 dnssec_log(zone, ISC_LOG_INFO,
10507 "Revoked key %d for "
10508 "zone %s removal timer "
10509 "complete: deleting from "
10510 "the managed keys database",
10511 keytag, namebuf);
10512 }
10513 } else if (revoked && keydata.removehd == 0) {
10514 dnssec_log(zone, ISC_LOG_WARNING,
10515 "Active key %d for zone "
10516 "%s is revoked but "
10517 "did not self-sign; "
10518 "ignoring",
10519 keytag, namebuf);
10520 continue;
10521 } else if (secure) {
10522 if (keydata.removehd != 0) {
10523 /*
10524 * Key isn't revoked--but it
10525 * seems it used to be.
10526 * Remove it now and add it
10527 * back as if it were a fresh key,
10528 * with a 30-day acceptance timer.
10529 */
10530 deletekey = true;
10531 newkey = true;
10532 keydata.removehd = 0;
10533 keydata.addhd = now +
10534 dns_zone_mkey_month;
10535
10536 dnssec_log(zone, ISC_LOG_INFO,
10537 "Revoked key %d for "
10538 "zone %s has returned: "
10539 "starting 30-day "
10540 "acceptance timer",
10541 keytag, namebuf);
10542 } else if (keydata.addhd > now) {
10543 pending++;
10544 } else if (keydata.addhd == 0) {
10545 keydata.addhd = now;
10546 }
10547
10548 if (keydata.addhd <= now) {
10549 trustkey = true;
10550 dnssec_log(zone, ISC_LOG_INFO,
10551 "Key %d for zone %s "
10552 "is now trusted (%s)",
10553 keytag, namebuf,
10554 initial ? "initializing key "
10555 "verified"
10556 : "acceptance timer "
10557 "complete");
10558 }
10559 } else if (keydata.addhd > now) {
10560 /*
10561 * Not secure, and key is pending:
10562 * reset the acceptance timer
10563 */
10564 pending++;
10565 keydata.addhd = now + dns_zone_mkey_month;
10566 dnssec_log(zone, ISC_LOG_INFO,
10567 "Pending key %d "
10568 "for zone %s was "
10569 "not validated: restarting "
10570 "30-day acceptance timer",
10571 keytag, namebuf);
10572 }
10573
10574 if (!deletekey && !newkey) {
10575 updatekey = true;
10576 }
10577 } else if (secure) {
10578 /*
10579 * Key wasn't in the key zone but it's
10580 * revoked now anyway, so just skip it
10581 */
10582 if (revoked) {
10583 continue;
10584 }
10585
10586 /* Key wasn't in the key zone: add it */
10587 newkey = true;
10588
10589 if (initializing) {
10590 dnssec_log(zone, ISC_LOG_WARNING,
10591 "Initializing automatic trust "
10592 "anchor management for zone '%s'; "
10593 "DNSKEY ID %d is now trusted, "
10594 "waiving the normal 30-day "
10595 "waiting period.",
10596 namebuf, keytag);
10597 trustkey = true;
10598 } else {
10599 dnssec_log(zone, ISC_LOG_INFO,
10600 "New key %d observed "
10601 "for zone '%s': "
10602 "starting 30-day "
10603 "acceptance timer",
10604 keytag, namebuf);
10605 }
10606 } else {
10607 /*
10608 * No previously known key, and the key is not
10609 * secure, so skip it.
10610 */
10611 continue;
10612 }
10613
10614 /* Delete old version */
10615 if (deletekey || !newkey) {
10616 CHECK(update_one_rr(kfetch->db, ver, &diff,
10617 DNS_DIFFOP_DEL, keyname, 0,
10618 &keydatarr));
10619 }
10620
10621 if (updatekey) {
10622 /* Set refresh timer */
10623 keydata.refresh = refresh_time(kfetch, false);
10624 dns_rdata_reset(&keydatarr);
10625 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10626 dns_rdata_fromstruct(&keydatarr, zone->rdclass,
10627 dns_rdatatype_keydata, &keydata,
10628 &keyb);
10629
10630 /* Insert updated version */
10631 CHECK(update_one_rr(kfetch->db, ver, &diff,
10632 DNS_DIFFOP_ADD, keyname, 0,
10633 &keydatarr));
10634 } else if (newkey) {
10635 /* Convert DNSKEY to KEYDATA */
10636 result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
10637 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10638 dns_keydata_fromdnskey(&keydata, &dnskey, 0, 0, 0,
10639 NULL);
10640 keydata.addhd = initializing
10641 ? now
10642 : now + dns_zone_mkey_month;
10643 keydata.refresh = refresh_time(kfetch, false);
10644 dns_rdata_reset(&keydatarr);
10645 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10646 dns_rdata_fromstruct(&keydatarr, zone->rdclass,
10647 dns_rdatatype_keydata, &keydata,
10648 &keyb);
10649
10650 /* Insert into key zone */
10651 CHECK(update_one_rr(kfetch->db, ver, &diff,
10652 DNS_DIFFOP_ADD, keyname, 0,
10653 &keydatarr));
10654 }
10655
10656 if (trustkey) {
10657 /* Trust this key. */
10658 result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
10659 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10660 trust_key(zone, keyname, &dnskey, false);
10661 }
10662
10663 if (secure && !deletekey) {
10664 INSIST(newkey || updatekey);
10665 set_refreshkeytimer(zone, &keydata, now, false);
10666 }
10667 }
10668
10669 /*
10670 * RFC5011 says, "A trust point that has all of its trust anchors
10671 * revoked is considered deleted and is treated as if the trust
10672 * point was never configured." But if someone revoked their
10673 * active key before the standby was trusted, that would mean the
10674 * zone would suddenly be nonsecured. We avoid this by checking to
10675 * see if there's pending keydata. If so, we put a null key in
10676 * the security roots; then all queries to the zone will fail.
10677 */
10678 if (pending != 0) {
10679 fail_secure(zone, keyname);
10680 }
10681
10682 done:
10683 if (!ISC_LIST_EMPTY(diff.tuples)) {
10684 /* Write changes to journal file. */
10685 CHECK(update_soa_serial(zone, kfetch->db, ver, &diff, mctx,
10686 zone->updatemethod));
10687 CHECK(zone_journal(zone, &diff, NULL, "keyfetch_done"));
10688 commit = true;
10689
10690 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
10691 zone_needdump(zone, 30);
10692 } else if (result == ISC_R_NOMORE) {
10693 /*
10694 * If "updatekey" was true for all keys found in the DNSKEY
10695 * response and the previous update of those keys happened
10696 * during the same second (only possible if a key refresh was
10697 * externally triggered), it may happen that all relevant
10698 * update_one_rr() calls will return ISC_R_SUCCESS, but
10699 * diff.tuples will remain empty. Reset result to
10700 * ISC_R_SUCCESS to prevent a bogus warning from being logged.
10701 */
10702 result = ISC_R_SUCCESS;
10703 }
10704
10705 failure:
10706 if (result != ISC_R_SUCCESS) {
10707 dnssec_log(zone, ISC_LOG_ERROR,
10708 "error during managed-keys processing (%s): "
10709 "DNSSEC validation may be at risk",
10710 isc_result_totext(result));
10711 }
10712 dns_diff_clear(&diff);
10713 if (ver != NULL) {
10714 dns_db_closeversion(kfetch->db, &ver, commit);
10715 }
10716
10717 cleanup:
10718 dns_db_detach(&kfetch->db);
10719
10720 isc_refcount_decrement(&zone->irefs);
10721
10722 kfetch->zone = NULL;
10723
10724 if (dns_rdataset_isassociated(keydataset)) {
10725 dns_rdataset_disassociate(keydataset);
10726 }
10727 if (dns_rdataset_isassociated(dnskeys)) {
10728 dns_rdataset_disassociate(dnskeys);
10729 }
10730 if (dns_rdataset_isassociated(dnskeysigs)) {
10731 dns_rdataset_disassociate(dnskeysigs);
10732 }
10733
10734 dns_name_free(keyname, mctx);
10735 isc_mem_putanddetach(&mctx, kfetch, sizeof(dns_keyfetch_t));
10736
10737 if (secroots != NULL) {
10738 dns_keytable_detach(&secroots);
10739 }
10740
10741 free_needed = exit_check(zone);
10742 UNLOCK_ZONE(zone);
10743 if (free_needed) {
10744 zone_free(zone);
10745 }
10746
10747 INSIST(ver == NULL);
10748 }
10749
10750 /*
10751 * Refresh the data in the key zone. Initiate a fetch to look up
10752 * DNSKEY records at the trust anchor name.
10753 */
10754 static void
10755 zone_refreshkeys(dns_zone_t *zone) {
10756 const char me[] = "zone_refreshkeys";
10757 isc_result_t result;
10758 dns_rriterator_t rrit;
10759 dns_db_t *db = NULL;
10760 dns_dbversion_t *ver = NULL;
10761 dns_diff_t diff;
10762 dns_rdata_t rdata = DNS_RDATA_INIT;
10763 dns_rdata_keydata_t kd;
10764 isc_stdtime_t now;
10765 bool commit = false;
10766 bool fetching = false, fetch_err = false;
10767 bool timerset = false;
10768
10769 ENTER;
10770 REQUIRE(zone->db != NULL);
10771
10772 isc_stdtime_get(&now);
10773
10774 LOCK_ZONE(zone);
10775 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
10776 isc_time_settoepoch(&zone->refreshkeytime);
10777 UNLOCK_ZONE(zone);
10778 return;
10779 }
10780
10781 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
10782 dns_db_attach(zone->db, &db);
10783 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
10784
10785 dns_diff_init(zone->mctx, &diff);
10786
10787 CHECK(dns_db_newversion(db, &ver));
10788
10789 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESHING);
10790
10791 dns_rriterator_init(&rrit, db, ver, 0);
10792 for (result = dns_rriterator_first(&rrit); result == ISC_R_SUCCESS;
10793 result = dns_rriterator_nextrrset(&rrit))
10794 {
10795 isc_stdtime_t timer = 0xffffffff;
10796 dns_name_t *name = NULL, *kname = NULL;
10797 dns_rdataset_t *kdset = NULL;
10798 dns_keyfetch_t *kfetch;
10799 uint32_t ttl;
10800
10801 dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL);
10802 if (kdset == NULL || kdset->type != dns_rdatatype_keydata ||
10803 !dns_rdataset_isassociated(kdset))
10804 {
10805 continue;
10806 }
10807
10808 /*
10809 * Scan the stored keys looking for ones that need
10810 * removal or refreshing
10811 */
10812 for (result = dns_rdataset_first(kdset);
10813 result == ISC_R_SUCCESS; result = dns_rdataset_next(kdset))
10814 {
10815 dns_rdata_reset(&rdata);
10816 dns_rdataset_current(kdset, &rdata);
10817 result = dns_rdata_tostruct(&rdata, &kd, NULL);
10818 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10819
10820 /* Removal timer expired? */
10821 if (kd.removehd != 0 && kd.removehd < now) {
10822 dns_rriterator_pause(&rrit);
10823 CHECK(update_one_rr(db, ver, &diff,
10824 DNS_DIFFOP_DEL, name, ttl,
10825 &rdata));
10826 continue;
10827 }
10828
10829 /* Acceptance timer expired? */
10830 if (kd.addhd <= now) {
10831 timer = kd.addhd;
10832 }
10833
10834 /* Or do we just need to refresh the keyset? */
10835 if (timer > kd.refresh) {
10836 timer = kd.refresh;
10837 }
10838
10839 dns_rriterator_pause(&rrit);
10840 set_refreshkeytimer(zone, &kd, now, false);
10841 timerset = true;
10842 }
10843
10844 if (timer > now) {
10845 continue;
10846 }
10847
10848 dns_rriterator_pause(&rrit);
10849
10850 kfetch = isc_mem_get(zone->mctx, sizeof(dns_keyfetch_t));
10851
10852 zone->refreshkeycount++;
10853 kfetch->zone = zone;
10854 isc_refcount_increment0(&zone->irefs);
10855 kname = dns_fixedname_initname(&kfetch->name);
10856 dns_name_dup(name, zone->mctx, kname);
10857 dns_rdataset_init(&kfetch->dnskeyset);
10858 dns_rdataset_init(&kfetch->dnskeysigset);
10859 dns_rdataset_init(&kfetch->keydataset);
10860 dns_rdataset_clone(kdset, &kfetch->keydataset);
10861 kfetch->db = NULL;
10862 dns_db_attach(db, &kfetch->db);
10863 kfetch->fetch = NULL;
10864
10865 if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
10866 char namebuf[DNS_NAME_FORMATSIZE];
10867 dns_name_format(kname, namebuf, sizeof(namebuf));
10868 dnssec_log(zone, ISC_LOG_DEBUG(3),
10869 "Creating key fetch in "
10870 "zone_refreshkeys() for '%s'",
10871 namebuf);
10872 }
10873
10874 /*
10875 * Use of DNS_FETCHOPT_NOCACHED is essential here. If it is
10876 * not set and the cache still holds a non-expired, validated
10877 * version of the RRset being queried for by the time the
10878 * response is received, the cached RRset will be passed to
10879 * keyfetch_done() instead of the one received in the response
10880 * as the latter will have a lower trust level due to not being
10881 * validated until keyfetch_done() is called.
10882 */
10883
10884 #ifdef ENABLE_AFL
10885 if (!dns_fuzzing_resolver) {
10886 #endif /* ifdef ENABLE_AFL */
10887 result = dns_resolver_createfetch(
10888 zone->view->resolver, kname,
10889 dns_rdatatype_dnskey, NULL, NULL, NULL, NULL, 0,
10890 DNS_FETCHOPT_NOVALIDATE |
10891 DNS_FETCHOPT_UNSHARED |
10892 DNS_FETCHOPT_NOCACHED,
10893 0, NULL, zone->task, keyfetch_done, kfetch,
10894 &kfetch->dnskeyset, &kfetch->dnskeysigset,
10895 &kfetch->fetch);
10896 #ifdef ENABLE_AFL
10897 } else {
10898 result = ISC_R_FAILURE;
10899 }
10900 #endif /* ifdef ENABLE_AFL */
10901 if (result == ISC_R_SUCCESS) {
10902 fetching = true;
10903 } else {
10904 zone->refreshkeycount--;
10905 isc_refcount_decrement(&zone->irefs);
10906 dns_db_detach(&kfetch->db);
10907 dns_rdataset_disassociate(&kfetch->keydataset);
10908 dns_name_free(kname, zone->mctx);
10909 isc_mem_put(zone->mctx, kfetch, sizeof(dns_keyfetch_t));
10910 dnssec_log(zone, ISC_LOG_WARNING,
10911 "Failed to create fetch for DNSKEY update");
10912 fetch_err = true;
10913 }
10914 }
10915 if (!ISC_LIST_EMPTY(diff.tuples)) {
10916 CHECK(update_soa_serial(zone, db, ver, &diff, zone->mctx,
10917 zone->updatemethod));
10918 CHECK(zone_journal(zone, &diff, NULL, "zone_refreshkeys"));
10919 commit = true;
10920 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
10921 zone_needdump(zone, 30);
10922 }
10923
10924 failure:
10925 if (fetch_err) {
10926 /*
10927 * Error during a key fetch; retry in an hour.
10928 */
10929 isc_time_t timenow, timethen;
10930 char timebuf[80];
10931
10932 TIME_NOW(&timenow);
10933 DNS_ZONE_TIME_ADD(&timenow, dns_zone_mkey_hour, &timethen);
10934 zone->refreshkeytime = timethen;
10935 zone_settimer(zone, &timenow);
10936
10937 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
10938 dnssec_log(zone, ISC_LOG_DEBUG(1), "retry key refresh: %s",
10939 timebuf);
10940 } else if (!timerset) {
10941 isc_time_settoepoch(&zone->refreshkeytime);
10942 }
10943
10944 if (!fetching) {
10945 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
10946 }
10947
10948 dns_diff_clear(&diff);
10949 if (ver != NULL) {
10950 dns_rriterator_destroy(&rrit);
10951 dns_db_closeversion(db, &ver, commit);
10952 }
10953 dns_db_detach(&db);
10954
10955 UNLOCK_ZONE(zone);
10956
10957 INSIST(ver == NULL);
10958 }
10959
10960 static void
10961 zone_maintenance(dns_zone_t *zone) {
10962 const char me[] = "zone_maintenance";
10963 isc_time_t now;
10964 isc_result_t result;
10965 bool dumping, load_pending, viewok;
10966
10967 REQUIRE(DNS_ZONE_VALID(zone));
10968 ENTER;
10969
10970 /*
10971 * Are we pending load/reload?
10972 */
10973 LOCK_ZONE(zone);
10974 load_pending = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING);
10975 UNLOCK_ZONE(zone);
10976
10977 if (load_pending) {
10978 return;
10979 }
10980
10981 /*
10982 * Configuring the view of this zone may have
10983 * failed, for example because the config file
10984 * had a syntax error. In that case, the view
10985 * adb or resolver will be NULL, and we had better not try
10986 * to do further maintenance on it.
10987 */
10988 LOCK_ZONE(zone);
10989 viewok = (zone->view != NULL && zone->view->adb != NULL);
10990 UNLOCK_ZONE(zone);
10991 if (!viewok) {
10992 return;
10993 }
10994
10995 TIME_NOW(&now);
10996
10997 /*
10998 * Expire check.
10999 */
11000 switch (zone->type) {
11001 case dns_zone_redirect:
11002 if (zone->masters == NULL) {
11003 break;
11004 }
11005 /* FALLTHROUGH */
11006 case dns_zone_slave:
11007 case dns_zone_mirror:
11008 case dns_zone_stub:
11009 LOCK_ZONE(zone);
11010 if (isc_time_compare(&now, &zone->expiretime) >= 0 &&
11011 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
11012 {
11013 zone_expire(zone);
11014 zone->refreshtime = now;
11015 }
11016 UNLOCK_ZONE(zone);
11017 break;
11018 default:
11019 break;
11020 }
11021
11022 /*
11023 * Up to date check.
11024 */
11025 switch (zone->type) {
11026 case dns_zone_redirect:
11027 if (zone->masters == NULL) {
11028 break;
11029 }
11030 /* FALLTHROUGH */
11031 case dns_zone_slave:
11032 case dns_zone_mirror:
11033 case dns_zone_stub:
11034 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
11035 isc_time_compare(&now, &zone->refreshtime) >= 0)
11036 {
11037 dns_zone_refresh(zone);
11038 }
11039 break;
11040 default:
11041 break;
11042 }
11043
11044 /*
11045 * Secondaries send notifies before backing up to disk,
11046 * primaries after.
11047 */
11048 if ((zone->type == dns_zone_slave || zone->type == dns_zone_mirror) &&
11049 (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
11050 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY)) &&
11051 isc_time_compare(&now, &zone->notifytime) >= 0)
11052 {
11053 zone_notify(zone, &now);
11054 }
11055
11056 /*
11057 * Do we need to consolidate the backing store?
11058 */
11059 switch (zone->type) {
11060 case dns_zone_master:
11061 case dns_zone_slave:
11062 case dns_zone_mirror:
11063 case dns_zone_key:
11064 case dns_zone_redirect:
11065 case dns_zone_stub:
11066 LOCK_ZONE(zone);
11067 if (zone->masterfile != NULL &&
11068 isc_time_compare(&now, &zone->dumptime) >= 0 &&
11069 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
11070 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP))
11071 {
11072 dumping = was_dumping(zone);
11073 } else {
11074 dumping = true;
11075 }
11076 UNLOCK_ZONE(zone);
11077 if (!dumping) {
11078 result = zone_dump(zone, true); /* task locked */
11079 if (result != ISC_R_SUCCESS) {
11080 dns_zone_log(zone, ISC_LOG_WARNING,
11081 "dump failed: %s",
11082 dns_result_totext(result));
11083 }
11084 }
11085 break;
11086 default:
11087 break;
11088 }
11089
11090 /*
11091 * Master/redirect zones send notifies now, if needed
11092 */
11093 switch (zone->type) {
11094 case dns_zone_master:
11095 case dns_zone_redirect:
11096 if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
11097 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY)) &&
11098 isc_time_compare(&now, &zone->notifytime) >= 0)
11099 {
11100 zone_notify(zone, &now);
11101 }
11102 default:
11103 break;
11104 }
11105
11106 /*
11107 * Do we need to refresh keys?
11108 */
11109 switch (zone->type) {
11110 case dns_zone_key:
11111 if (isc_time_compare(&now, &zone->refreshkeytime) >= 0) {
11112 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
11113 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING))
11114 {
11115 zone_refreshkeys(zone);
11116 }
11117 }
11118 break;
11119 case dns_zone_master:
11120 if (!isc_time_isepoch(&zone->refreshkeytime) &&
11121 isc_time_compare(&now, &zone->refreshkeytime) >= 0 &&
11122 zone->rss_event == NULL)
11123 {
11124 zone_rekey(zone);
11125 }
11126 default:
11127 break;
11128 }
11129
11130 switch (zone->type) {
11131 case dns_zone_master:
11132 case dns_zone_redirect:
11133 case dns_zone_slave:
11134 /*
11135 * Do we need to sign/resign some RRsets?
11136 */
11137 if (zone->rss_event != NULL) {
11138 break;
11139 }
11140 if (!isc_time_isepoch(&zone->signingtime) &&
11141 isc_time_compare(&now, &zone->signingtime) >= 0)
11142 {
11143 zone_sign(zone);
11144 } else if (!isc_time_isepoch(&zone->resigntime) &&
11145 isc_time_compare(&now, &zone->resigntime) >= 0)
11146 {
11147 zone_resigninc(zone);
11148 } else if (!isc_time_isepoch(&zone->nsec3chaintime) &&
11149 isc_time_compare(&now, &zone->nsec3chaintime) >= 0)
11150 {
11151 zone_nsec3chain(zone);
11152 }
11153 /*
11154 * Do we need to issue a key expiry warning?
11155 */
11156 if (!isc_time_isepoch(&zone->keywarntime) &&
11157 isc_time_compare(&now, &zone->keywarntime) >= 0)
11158 {
11159 set_key_expiry_warning(zone, zone->key_expiry,
11160 isc_time_seconds(&now));
11161 }
11162 break;
11163
11164 default:
11165 break;
11166 }
11167 LOCK_ZONE(zone);
11168 zone_settimer(zone, &now);
11169 UNLOCK_ZONE(zone);
11170 }
11171
11172 void
11173 dns_zone_markdirty(dns_zone_t *zone) {
11174 uint32_t serial;
11175 isc_result_t result = ISC_R_SUCCESS;
11176 dns_zone_t *secure = NULL;
11177
11178 /*
11179 * Obtaining a lock on the zone->secure (see zone_send_secureserial)
11180 * could result in a deadlock due to a LOR so we will spin if we
11181 * can't obtain the both locks.
11182 */
11183 again:
11184 LOCK_ZONE(zone);
11185 if (zone->type == dns_zone_master) {
11186 if (inline_raw(zone)) {
11187 unsigned int soacount;
11188 secure = zone->secure;
11189 INSIST(secure != zone);
11190 TRYLOCK_ZONE(result, secure);
11191 if (result != ISC_R_SUCCESS) {
11192 UNLOCK_ZONE(zone);
11193 secure = NULL;
11194 isc_thread_yield();
11195 goto again;
11196 }
11197
11198 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11199 if (zone->db != NULL) {
11200 result = zone_get_from_db(
11201 zone, zone->db, NULL, &soacount,
11202 &serial, NULL, NULL, NULL, NULL, NULL);
11203 } else {
11204 result = DNS_R_NOTLOADED;
11205 }
11206 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11207 if (result == ISC_R_SUCCESS && soacount > 0U) {
11208 zone_send_secureserial(zone, serial);
11209 }
11210 }
11211
11212 /* XXXMPA make separate call back */
11213 if (result == ISC_R_SUCCESS) {
11214 set_resigntime(zone);
11215 if (zone->task != NULL) {
11216 isc_time_t now;
11217 TIME_NOW(&now);
11218 zone_settimer(zone, &now);
11219 }
11220 }
11221 }
11222 if (secure != NULL) {
11223 UNLOCK_ZONE(secure);
11224 }
11225 zone_needdump(zone, DNS_DUMP_DELAY);
11226 UNLOCK_ZONE(zone);
11227 }
11228
11229 void
11230 dns_zone_expire(dns_zone_t *zone) {
11231 REQUIRE(DNS_ZONE_VALID(zone));
11232
11233 LOCK_ZONE(zone);
11234 zone_expire(zone);
11235 UNLOCK_ZONE(zone);
11236 }
11237
11238 static void
11239 zone_expire(dns_zone_t *zone) {
11240 dns_db_t *db = NULL;
11241
11242 /*
11243 * 'zone' locked by caller.
11244 */
11245
11246 REQUIRE(LOCKED_ZONE(zone));
11247
11248 dns_zone_log(zone, ISC_LOG_WARNING, "expired");
11249
11250 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXPIRED);
11251 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
11252 zone->retry = DNS_ZONE_DEFAULTRETRY;
11253 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
11254
11255 /*
11256 * An RPZ zone has expired; before unloading it, we must
11257 * first remove it from the RPZ summary database. The
11258 * easiest way to do this is "update" it with an empty
11259 * database so that the update callback synchronizes
11260 * the diff automatically.
11261 */
11262 if (zone->rpzs != NULL && zone->rpz_num != DNS_RPZ_INVALID_NUM) {
11263 isc_result_t result;
11264 dns_rpz_zone_t *rpz = zone->rpzs->zones[zone->rpz_num];
11265
11266 CHECK(dns_db_create(zone->mctx, "rbt", &zone->origin,
11267 dns_dbtype_zone, zone->rdclass, 0, NULL,
11268 &db));
11269 CHECK(dns_rpz_dbupdate_callback(db, rpz));
11270 dns_zone_log(zone, ISC_LOG_WARNING,
11271 "response-policy zone expired; "
11272 "policies unloaded");
11273 }
11274
11275 failure:
11276 if (db != NULL) {
11277 dns_db_detach(&db);
11278 }
11279
11280 zone_unload(zone);
11281 }
11282
11283 void
11284 dns_zone_refresh(dns_zone_t *zone) {
11285 isc_interval_t i;
11286 uint32_t oldflags;
11287 unsigned int j;
11288 isc_result_t result;
11289
11290 REQUIRE(DNS_ZONE_VALID(zone));
11291
11292 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
11293 return;
11294 }
11295
11296 /*
11297 * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation
11298 * in progress at a time.
11299 */
11300
11301 LOCK_ZONE(zone);
11302 oldflags = atomic_load(&zone->flags);
11303 if (zone->masterscnt == 0) {
11304 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOMASTERS);
11305 if ((oldflags & DNS_ZONEFLG_NOMASTERS) == 0) {
11306 dns_zone_log(zone, ISC_LOG_ERROR,
11307 "cannot refresh: no primaries");
11308 }
11309 goto unlock;
11310 }
11311 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
11312 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
11313 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
11314 if ((oldflags & (DNS_ZONEFLG_REFRESH | DNS_ZONEFLG_LOADING)) != 0) {
11315 goto unlock;
11316 }
11317
11318 /*
11319 * Set the next refresh time as if refresh check has failed.
11320 * Setting this to the retry time will do that. XXXMLG
11321 * If we are successful it will be reset using zone->refresh.
11322 */
11323 isc_interval_set(&i, zone->retry - isc_random_uniform(zone->retry / 4),
11324 0);
11325 result = isc_time_nowplusinterval(&zone->refreshtime, &i);
11326 if (result != ISC_R_SUCCESS) {
11327 dns_zone_log(zone, ISC_LOG_WARNING,
11328 "isc_time_nowplusinterval() failed: %s",
11329 dns_result_totext(result));
11330 }
11331
11332 /*
11333 * When lacking user-specified timer values from the SOA,
11334 * do exponential backoff of the retry time up to a
11335 * maximum of six hours.
11336 */
11337 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS)) {
11338 zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
11339 }
11340
11341 zone->curmaster = 0;
11342 for (j = 0; j < zone->masterscnt; j++) {
11343 zone->mastersok[j] = false;
11344 }
11345 /* initiate soa query */
11346 queue_soa_query(zone);
11347 unlock:
11348 UNLOCK_ZONE(zone);
11349 }
11350
11351 static void
11352 zone_journal_compact(dns_zone_t *zone, dns_db_t *db, uint32_t serial) {
11353 isc_result_t result;
11354 int32_t journalsize;
11355 dns_dbversion_t *ver = NULL;
11356 uint64_t dbsize;
11357
11358 INSIST(LOCKED_ZONE(zone));
11359 if (inline_raw(zone)) {
11360 INSIST(LOCKED_ZONE(zone->secure));
11361 }
11362
11363 journalsize = zone->journalsize;
11364 if (journalsize == -1) {
11365 journalsize = DNS_JOURNAL_SIZE_MAX;
11366 dns_db_currentversion(db, &ver);
11367 result = dns_db_getsize(db, ver, NULL, &dbsize);
11368 dns_db_closeversion(db, &ver, false);
11369 if (result != ISC_R_SUCCESS) {
11370 dns_zone_log(zone, ISC_LOG_ERROR,
11371 "zone_journal_compact: "
11372 "could not get zone size: %s",
11373 isc_result_totext(result));
11374 } else if (dbsize < DNS_JOURNAL_SIZE_MAX / 2) {
11375 journalsize = (int32_t)dbsize * 2;
11376 }
11377 }
11378 zone_debuglog(zone, "zone_journal_compact", 1, "target journal size %d",
11379 journalsize);
11380 result = dns_journal_compact(zone->mctx, zone->journal, serial,
11381 journalsize);
11382 switch (result) {
11383 case ISC_R_SUCCESS:
11384 case ISC_R_NOSPACE:
11385 case ISC_R_NOTFOUND:
11386 dns_zone_log(zone, ISC_LOG_DEBUG(3), "dns_journal_compact: %s",
11387 dns_result_totext(result));
11388 break;
11389 default:
11390 dns_zone_log(zone, ISC_LOG_ERROR,
11391 "dns_journal_compact failed: %s",
11392 dns_result_totext(result));
11393 break;
11394 }
11395 }
11396
11397 isc_result_t
11398 dns_zone_flush(dns_zone_t *zone) {
11399 isc_result_t result = ISC_R_SUCCESS;
11400 bool dumping;
11401
11402 REQUIRE(DNS_ZONE_VALID(zone));
11403
11404 LOCK_ZONE(zone);
11405 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FLUSH);
11406 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
11407 zone->masterfile != NULL) {
11408 result = ISC_R_ALREADYRUNNING;
11409 dumping = was_dumping(zone);
11410 } else {
11411 dumping = true;
11412 }
11413 UNLOCK_ZONE(zone);
11414 if (!dumping) {
11415 result = zone_dump(zone, true); /* Unknown task. */
11416 }
11417 return (result);
11418 }
11419
11420 isc_result_t
11421 dns_zone_dump(dns_zone_t *zone) {
11422 isc_result_t result = ISC_R_ALREADYRUNNING;
11423 bool dumping;
11424
11425 REQUIRE(DNS_ZONE_VALID(zone));
11426
11427 LOCK_ZONE(zone);
11428 dumping = was_dumping(zone);
11429 UNLOCK_ZONE(zone);
11430 if (!dumping) {
11431 result = zone_dump(zone, false); /* Unknown task. */
11432 }
11433 return (result);
11434 }
11435
11436 static void
11437 zone_needdump(dns_zone_t *zone, unsigned int delay) {
11438 const char me[] = "zone_needdump";
11439 isc_time_t dumptime;
11440 isc_time_t now;
11441
11442 /*
11443 * 'zone' locked by caller
11444 */
11445
11446 REQUIRE(DNS_ZONE_VALID(zone));
11447 REQUIRE(LOCKED_ZONE(zone));
11448 ENTER;
11449
11450 /*
11451 * Do we have a place to dump to and are we loaded?
11452 */
11453 if (zone->masterfile == NULL ||
11454 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0) {
11455 return;
11456 }
11457
11458 TIME_NOW(&now);
11459 /* add some noise */
11460 DNS_ZONE_JITTER_ADD(&now, delay, &dumptime);
11461
11462 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
11463 if (isc_time_isepoch(&zone->dumptime) ||
11464 isc_time_compare(&zone->dumptime, &dumptime) > 0)
11465 {
11466 zone->dumptime = dumptime;
11467 }
11468 if (zone->task != NULL) {
11469 zone_settimer(zone, &now);
11470 }
11471 }
11472
11473 static void
11474 dump_done(void *arg, isc_result_t result) {
11475 const char me[] = "dump_done";
11476 dns_zone_t *zone = arg;
11477 dns_zone_t *secure = NULL;
11478 dns_db_t *db;
11479 dns_dbversion_t *version;
11480 bool again = false;
11481 bool compact = false;
11482 uint32_t serial;
11483 isc_result_t tresult;
11484
11485 REQUIRE(DNS_ZONE_VALID(zone));
11486
11487 ENTER;
11488
11489 if (result == ISC_R_SUCCESS && zone->journal != NULL) {
11490 /*
11491 * We don't own these, zone->dctx must stay valid.
11492 */
11493 db = dns_dumpctx_db(zone->dctx);
11494 version = dns_dumpctx_version(zone->dctx);
11495 tresult = dns_db_getsoaserial(db, version, &serial);
11496
11497 /*
11498 * Handle lock order inversion.
11499 */
11500 again:
11501 LOCK_ZONE(zone);
11502 if (inline_raw(zone)) {
11503 secure = zone->secure;
11504 INSIST(secure != zone);
11505 TRYLOCK_ZONE(result, secure);
11506 if (result != ISC_R_SUCCESS) {
11507 UNLOCK_ZONE(zone);
11508 secure = NULL;
11509 isc_thread_yield();
11510 goto again;
11511 }
11512 }
11513
11514 /*
11515 * If there is a secure version of this zone
11516 * use its serial if it is less than ours.
11517 */
11518 if (tresult == ISC_R_SUCCESS && secure != NULL) {
11519 uint32_t sserial;
11520 isc_result_t mresult;
11521
11522 ZONEDB_LOCK(&secure->dblock, isc_rwlocktype_read);
11523 if (secure->db != NULL) {
11524 mresult = dns_db_getsoaserial(zone->secure->db,
11525 NULL, &sserial);
11526 if (mresult == ISC_R_SUCCESS &&
11527 isc_serial_lt(sserial, serial)) {
11528 serial = sserial;
11529 }
11530 }
11531 ZONEDB_UNLOCK(&secure->dblock, isc_rwlocktype_read);
11532 }
11533 if (tresult == ISC_R_SUCCESS && zone->xfr == NULL) {
11534 dns_db_t *zdb = NULL;
11535 if (dns_zone_getdb(zone, &zdb) == ISC_R_SUCCESS) {
11536 zone_journal_compact(zone, zdb, serial);
11537 dns_db_detach(&zdb);
11538 }
11539 } else if (tresult == ISC_R_SUCCESS) {
11540 compact = true;
11541 zone->compact_serial = serial;
11542 }
11543 if (secure != NULL) {
11544 UNLOCK_ZONE(secure);
11545 }
11546 UNLOCK_ZONE(zone);
11547 }
11548
11549 LOCK_ZONE(zone);
11550 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
11551 if (compact) {
11552 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
11553 }
11554 if (result != ISC_R_SUCCESS && result != ISC_R_CANCELED) {
11555 /*
11556 * Try again in a short while.
11557 */
11558 zone_needdump(zone, DNS_DUMP_DELAY);
11559 } else if (result == ISC_R_SUCCESS &&
11560 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
11561 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
11562 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
11563 {
11564 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
11565 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
11566 isc_time_settoepoch(&zone->dumptime);
11567 again = true;
11568 } else if (result == ISC_R_SUCCESS) {
11569 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
11570 }
11571
11572 if (zone->dctx != NULL) {
11573 dns_dumpctx_detach(&zone->dctx);
11574 }
11575 zonemgr_putio(&zone->writeio);
11576 UNLOCK_ZONE(zone);
11577 if (again) {
11578 (void)zone_dump(zone, false);
11579 }
11580 dns_zone_idetach(&zone);
11581 }
11582
11583 static isc_result_t
11584 zone_dump(dns_zone_t *zone, bool compact) {
11585 const char me[] = "zone_dump";
11586 isc_result_t result;
11587 dns_dbversion_t *version = NULL;
11588 bool again;
11589 dns_db_t *db = NULL;
11590 char *masterfile = NULL;
11591 dns_masterformat_t masterformat = dns_masterformat_none;
11592
11593 /*
11594 * 'compact' MUST only be set if we are task locked.
11595 */
11596
11597 REQUIRE(DNS_ZONE_VALID(zone));
11598 ENTER;
11599
11600 redo:
11601 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11602 if (zone->db != NULL) {
11603 dns_db_attach(zone->db, &db);
11604 }
11605 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11606 LOCK_ZONE(zone);
11607 if (zone->masterfile != NULL) {
11608 masterfile = isc_mem_strdup(zone->mctx, zone->masterfile);
11609 masterformat = zone->masterformat;
11610 }
11611 UNLOCK_ZONE(zone);
11612 if (db == NULL) {
11613 result = DNS_R_NOTLOADED;
11614 goto fail;
11615 }
11616 if (masterfile == NULL) {
11617 result = DNS_R_NOMASTERFILE;
11618 goto fail;
11619 }
11620
11621 if (compact && zone->type != dns_zone_stub) {
11622 dns_zone_t *dummy = NULL;
11623 LOCK_ZONE(zone);
11624 zone_iattach(zone, &dummy);
11625 result = zonemgr_getio(zone->zmgr, false, zone->task,
11626 zone_gotwritehandle, zone,
11627 &zone->writeio);
11628 if (result != ISC_R_SUCCESS) {
11629 zone_idetach(&dummy);
11630 } else {
11631 result = DNS_R_CONTINUE;
11632 }
11633 UNLOCK_ZONE(zone);
11634 } else {
11635 const dns_master_style_t *output_style;
11636
11637 dns_masterrawheader_t rawdata;
11638 dns_db_currentversion(db, &version);
11639 dns_master_initrawheader(&rawdata);
11640 if (inline_secure(zone)) {
11641 get_raw_serial(zone->raw, &rawdata);
11642 }
11643 if (zone->type == dns_zone_key) {
11644 output_style = &dns_master_style_keyzone;
11645 } else {
11646 output_style = &dns_master_style_default;
11647 }
11648 result = dns_master_dump(zone->mctx, db, version, output_style,
11649 masterfile, masterformat, &rawdata);
11650 dns_db_closeversion(db, &version, false);
11651 }
11652 fail:
11653 if (db != NULL) {
11654 dns_db_detach(&db);
11655 }
11656 if (masterfile != NULL) {
11657 isc_mem_free(zone->mctx, masterfile);
11658 }
11659 masterfile = NULL;
11660
11661 if (result == DNS_R_CONTINUE) {
11662 return (ISC_R_SUCCESS); /* XXXMPA */
11663 }
11664
11665 again = false;
11666 LOCK_ZONE(zone);
11667 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
11668 if (result != ISC_R_SUCCESS) {
11669 /*
11670 * Try again in a short while.
11671 */
11672 zone_needdump(zone, DNS_DUMP_DELAY);
11673 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
11674 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
11675 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
11676 {
11677 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
11678 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
11679 isc_time_settoepoch(&zone->dumptime);
11680 again = true;
11681 } else {
11682 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
11683 }
11684 UNLOCK_ZONE(zone);
11685 if (again) {
11686 goto redo;
11687 }
11688
11689 return (result);
11690 }
11691
11692 static isc_result_t
11693 dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style,
11694 dns_masterformat_t format, const uint32_t rawversion) {
11695 isc_result_t result;
11696 dns_dbversion_t *version = NULL;
11697 dns_db_t *db = NULL;
11698 dns_masterrawheader_t rawdata;
11699
11700 REQUIRE(DNS_ZONE_VALID(zone));
11701
11702 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11703 if (zone->db != NULL) {
11704 dns_db_attach(zone->db, &db);
11705 }
11706 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11707 if (db == NULL) {
11708 return (DNS_R_NOTLOADED);
11709 }
11710
11711 dns_db_currentversion(db, &version);
11712 dns_master_initrawheader(&rawdata);
11713 if (rawversion == 0) {
11714 rawdata.flags |= DNS_MASTERRAW_COMPAT;
11715 } else if (inline_secure(zone)) {
11716 get_raw_serial(zone->raw, &rawdata);
11717 } else if (zone->sourceserialset) {
11718 rawdata.flags = DNS_MASTERRAW_SOURCESERIALSET;
11719 rawdata.sourceserial = zone->sourceserial;
11720 }
11721 result = dns_master_dumptostream(zone->mctx, db, version, style, format,
11722 &rawdata, fd);
11723 dns_db_closeversion(db, &version, false);
11724 dns_db_detach(&db);
11725 return (result);
11726 }
11727
11728 isc_result_t
11729 dns_zone_dumptostream(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
11730 const dns_master_style_t *style,
11731 const uint32_t rawversion) {
11732 return (dumptostream(zone, fd, style, format, rawversion));
11733 }
11734
11735 void
11736 dns_zone_unload(dns_zone_t *zone) {
11737 REQUIRE(DNS_ZONE_VALID(zone));
11738
11739 LOCK_ZONE(zone);
11740 zone_unload(zone);
11741 UNLOCK_ZONE(zone);
11742 }
11743
11744 static void
11745 notify_cancel(dns_zone_t *zone) {
11746 dns_notify_t *notify;
11747
11748 /*
11749 * 'zone' locked by caller.
11750 */
11751
11752 REQUIRE(LOCKED_ZONE(zone));
11753
11754 for (notify = ISC_LIST_HEAD(zone->notifies); notify != NULL;
11755 notify = ISC_LIST_NEXT(notify, link))
11756 {
11757 if (notify->find != NULL) {
11758 dns_adb_cancelfind(notify->find);
11759 }
11760 if (notify->request != NULL) {
11761 dns_request_cancel(notify->request);
11762 }
11763 }
11764 }
11765
11766 static void
11767 forward_cancel(dns_zone_t *zone) {
11768 dns_forward_t *forward;
11769
11770 /*
11771 * 'zone' locked by caller.
11772 */
11773
11774 REQUIRE(LOCKED_ZONE(zone));
11775
11776 for (forward = ISC_LIST_HEAD(zone->forwards); forward != NULL;
11777 forward = ISC_LIST_NEXT(forward, link))
11778 {
11779 if (forward->request != NULL) {
11780 dns_request_cancel(forward->request);
11781 }
11782 }
11783 }
11784
11785 static void
11786 zone_unload(dns_zone_t *zone) {
11787 /*
11788 * 'zone' locked by caller.
11789 */
11790
11791 REQUIRE(LOCKED_ZONE(zone));
11792
11793 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
11794 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
11795 {
11796 if (zone->writeio != NULL) {
11797 zonemgr_cancelio(zone->writeio);
11798 }
11799
11800 if (zone->dctx != NULL) {
11801 dns_dumpctx_cancel(zone->dctx);
11802 }
11803 }
11804 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
11805 zone_detachdb(zone);
11806 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
11807 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
11808 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
11809
11810 if (zone->type == dns_zone_mirror) {
11811 dns_zone_log(zone, ISC_LOG_INFO,
11812 "mirror zone is no longer in use; "
11813 "reverting to normal recursion");
11814 }
11815 }
11816
11817 void
11818 dns_zone_setminrefreshtime(dns_zone_t *zone, uint32_t val) {
11819 REQUIRE(DNS_ZONE_VALID(zone));
11820 REQUIRE(val > 0);
11821
11822 zone->minrefresh = val;
11823 }
11824
11825 void
11826 dns_zone_setmaxrefreshtime(dns_zone_t *zone, uint32_t val) {
11827 REQUIRE(DNS_ZONE_VALID(zone));
11828 REQUIRE(val > 0);
11829
11830 zone->maxrefresh = val;
11831 }
11832
11833 void
11834 dns_zone_setminretrytime(dns_zone_t *zone, uint32_t val) {
11835 REQUIRE(DNS_ZONE_VALID(zone));
11836 REQUIRE(val > 0);
11837
11838 zone->minretry = val;
11839 }
11840
11841 void
11842 dns_zone_setmaxretrytime(dns_zone_t *zone, uint32_t val) {
11843 REQUIRE(DNS_ZONE_VALID(zone));
11844 REQUIRE(val > 0);
11845
11846 zone->maxretry = val;
11847 }
11848
11849 uint32_t
11850 dns_zone_getmaxrecords(dns_zone_t *zone) {
11851 REQUIRE(DNS_ZONE_VALID(zone));
11852
11853 return (zone->maxrecords);
11854 }
11855
11856 void
11857 dns_zone_setmaxrecords(dns_zone_t *zone, uint32_t val) {
11858 REQUIRE(DNS_ZONE_VALID(zone));
11859
11860 zone->maxrecords = val;
11861 }
11862
11863 static bool
11864 notify_isqueued(dns_zone_t *zone, unsigned int flags, dns_name_t *name,
11865 isc_sockaddr_t *addr, dns_tsigkey_t *key) {
11866 dns_notify_t *notify;
11867 dns_zonemgr_t *zmgr;
11868 isc_result_t result;
11869
11870 for (notify = ISC_LIST_HEAD(zone->notifies); notify != NULL;
11871 notify = ISC_LIST_NEXT(notify, link))
11872 {
11873 if (notify->request != NULL) {
11874 continue;
11875 }
11876 if (name != NULL && dns_name_dynamic(¬ify->ns) &&
11877 dns_name_equal(name, ¬ify->ns))
11878 {
11879 goto requeue;
11880 }
11881 if (addr != NULL && isc_sockaddr_equal(addr, ¬ify->dst) &&
11882 notify->key == key)
11883 {
11884 goto requeue;
11885 }
11886 }
11887 return (false);
11888
11889 requeue:
11890 /*
11891 * If we are enqueued on the startup ratelimiter and this is
11892 * not a startup notify, re-enqueue on the normal notify
11893 * ratelimiter.
11894 */
11895 if (notify->event != NULL && (flags & DNS_NOTIFY_STARTUP) == 0 &&
11896 (notify->flags & DNS_NOTIFY_STARTUP) != 0)
11897 {
11898 zmgr = notify->zone->zmgr;
11899 result = isc_ratelimiter_dequeue(zmgr->startupnotifyrl,
11900 notify->event);
11901 if (result != ISC_R_SUCCESS) {
11902 return (true);
11903 }
11904
11905 notify->flags &= ~DNS_NOTIFY_STARTUP;
11906 result = isc_ratelimiter_enqueue(notify->zone->zmgr->notifyrl,
11907 notify->zone->task,
11908 ¬ify->event);
11909 if (result != ISC_R_SUCCESS) {
11910 isc_event_free(¬ify->event);
11911 return (false);
11912 }
11913 }
11914
11915 return (true);
11916 }
11917
11918 static bool
11919 notify_isself(dns_zone_t *zone, isc_sockaddr_t *dst) {
11920 dns_tsigkey_t *key = NULL;
11921 isc_sockaddr_t src;
11922 isc_sockaddr_t any;
11923 bool isself;
11924 isc_netaddr_t dstaddr;
11925 isc_result_t result;
11926
11927 if (zone->view == NULL || zone->isself == NULL) {
11928 return (false);
11929 }
11930
11931 switch (isc_sockaddr_pf(dst)) {
11932 case PF_INET:
11933 src = zone->notifysrc4;
11934 isc_sockaddr_any(&any);
11935 break;
11936 case PF_INET6:
11937 src = zone->notifysrc6;
11938 isc_sockaddr_any6(&any);
11939 break;
11940 default:
11941 return (false);
11942 }
11943
11944 /*
11945 * When sending from any the kernel will assign a source address
11946 * that matches the destination address.
11947 */
11948 if (isc_sockaddr_eqaddr(&any, &src)) {
11949 src = *dst;
11950 }
11951
11952 isc_netaddr_fromsockaddr(&dstaddr, dst);
11953 result = dns_view_getpeertsig(zone->view, &dstaddr, &key);
11954 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
11955 return (false);
11956 }
11957 isself = (zone->isself)(zone->view, key, &src, dst, zone->rdclass,
11958 zone->isselfarg);
11959 if (key != NULL) {
11960 dns_tsigkey_detach(&key);
11961 }
11962 return (isself);
11963 }
11964
11965 static void
11966 notify_destroy(dns_notify_t *notify, bool locked) {
11967 isc_mem_t *mctx;
11968
11969 REQUIRE(DNS_NOTIFY_VALID(notify));
11970
11971 if (notify->zone != NULL) {
11972 if (!locked) {
11973 LOCK_ZONE(notify->zone);
11974 }
11975 REQUIRE(LOCKED_ZONE(notify->zone));
11976 if (ISC_LINK_LINKED(notify, link)) {
11977 ISC_LIST_UNLINK(notify->zone->notifies, notify, link);
11978 }
11979 if (!locked) {
11980 UNLOCK_ZONE(notify->zone);
11981 }
11982 if (locked) {
11983 zone_idetach(¬ify->zone);
11984 } else {
11985 dns_zone_idetach(¬ify->zone);
11986 }
11987 }
11988 if (notify->find != NULL) {
11989 dns_adb_destroyfind(¬ify->find);
11990 }
11991 if (notify->request != NULL) {
11992 dns_request_destroy(¬ify->request);
11993 }
11994 if (dns_name_dynamic(¬ify->ns)) {
11995 dns_name_free(¬ify->ns, notify->mctx);
11996 }
11997 if (notify->key != NULL) {
11998 dns_tsigkey_detach(¬ify->key);
11999 }
12000 mctx = notify->mctx;
12001 isc_mem_put(notify->mctx, notify, sizeof(*notify));
12002 isc_mem_detach(&mctx);
12003 }
12004
12005 static isc_result_t
12006 notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
12007 dns_notify_t *notify;
12008
12009 REQUIRE(notifyp != NULL && *notifyp == NULL);
12010
12011 notify = isc_mem_get(mctx, sizeof(*notify));
12012
12013 notify->mctx = NULL;
12014 isc_mem_attach(mctx, ¬ify->mctx);
12015 notify->flags = flags;
12016 notify->zone = NULL;
12017 notify->find = NULL;
12018 notify->request = NULL;
12019 notify->key = NULL;
12020 notify->event = NULL;
12021 isc_sockaddr_any(¬ify->dst);
12022 dns_name_init(¬ify->ns, NULL);
12023 ISC_LINK_INIT(notify, link);
12024 notify->magic = NOTIFY_MAGIC;
12025 *notifyp = notify;
12026 return (ISC_R_SUCCESS);
12027 }
12028
12029 /*
12030 * XXXAG should check for DNS_ZONEFLG_EXITING
12031 */
12032 static void
12033 process_adb_event(isc_task_t *task, isc_event_t *ev) {
12034 dns_notify_t *notify;
12035 isc_eventtype_t result;
12036
12037 UNUSED(task);
12038
12039 notify = ev->ev_arg;
12040 REQUIRE(DNS_NOTIFY_VALID(notify));
12041 INSIST(task == notify->zone->task);
12042 result = ev->ev_type;
12043 isc_event_free(&ev);
12044 if (result == DNS_EVENT_ADBMOREADDRESSES) {
12045 dns_adb_destroyfind(¬ify->find);
12046 notify_find_address(notify);
12047 return;
12048 }
12049 if (result == DNS_EVENT_ADBNOMOREADDRESSES) {
12050 LOCK_ZONE(notify->zone);
12051 notify_send(notify);
12052 UNLOCK_ZONE(notify->zone);
12053 }
12054 notify_destroy(notify, false);
12055 }
12056
12057 static void
12058 notify_find_address(dns_notify_t *notify) {
12059 isc_result_t result;
12060 unsigned int options;
12061
12062 REQUIRE(DNS_NOTIFY_VALID(notify));
12063 options = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_INET | DNS_ADBFIND_INET6 |
12064 DNS_ADBFIND_RETURNLAME;
12065
12066 if (notify->zone->view->adb == NULL) {
12067 goto destroy;
12068 }
12069
12070 result = dns_adb_createfind(
12071 notify->zone->view->adb, notify->zone->task, process_adb_event,
12072 notify, ¬ify->ns, dns_rootname, 0, options, 0, NULL,
12073 notify->zone->view->dstport, 0, NULL, ¬ify->find);
12074
12075 /* Something failed? */
12076 if (result != ISC_R_SUCCESS) {
12077 goto destroy;
12078 }
12079
12080 /* More addresses pending? */
12081 if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0) {
12082 return;
12083 }
12084
12085 /* We have as many addresses as we can get. */
12086 LOCK_ZONE(notify->zone);
12087 notify_send(notify);
12088 UNLOCK_ZONE(notify->zone);
12089
12090 destroy:
12091 notify_destroy(notify, false);
12092 }
12093
12094 static isc_result_t
12095 notify_send_queue(dns_notify_t *notify, bool startup) {
12096 isc_event_t *e;
12097 isc_result_t result;
12098
12099 INSIST(notify->event == NULL);
12100 e = isc_event_allocate(notify->mctx, NULL, DNS_EVENT_NOTIFYSENDTOADDR,
12101 notify_send_toaddr, notify, sizeof(isc_event_t));
12102 if (startup) {
12103 notify->event = e;
12104 }
12105 e->ev_arg = notify;
12106 e->ev_sender = NULL;
12107 result = isc_ratelimiter_enqueue(
12108 startup ? notify->zone->zmgr->startupnotifyrl
12109 : notify->zone->zmgr->notifyrl,
12110 notify->zone->task, &e);
12111 if (result != ISC_R_SUCCESS) {
12112 isc_event_free(&e);
12113 notify->event = NULL;
12114 }
12115 return (result);
12116 }
12117
12118 static void
12119 notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
12120 dns_notify_t *notify;
12121 isc_result_t result;
12122 dns_message_t *message = NULL;
12123 isc_netaddr_t dstip;
12124 dns_tsigkey_t *key = NULL;
12125 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
12126 isc_sockaddr_t src;
12127 unsigned int options, timeout;
12128 bool have_notifysource = false;
12129 bool have_notifydscp = false;
12130 isc_dscp_t dscp = -1;
12131
12132 notify = event->ev_arg;
12133 REQUIRE(DNS_NOTIFY_VALID(notify));
12134
12135 UNUSED(task);
12136
12137 LOCK_ZONE(notify->zone);
12138
12139 notify->event = NULL;
12140
12141 if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0) {
12142 result = ISC_R_CANCELED;
12143 goto cleanup;
12144 }
12145
12146 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
12147 DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) ||
12148 notify->zone->view->requestmgr == NULL || notify->zone->db == NULL)
12149 {
12150 result = ISC_R_CANCELED;
12151 goto cleanup;
12152 }
12153
12154 /*
12155 * The raw IPv4 address should also exist. Don't send to the
12156 * mapped form.
12157 */
12158 if (isc_sockaddr_pf(¬ify->dst) == PF_INET6 &&
12159 IN6_IS_ADDR_V4MAPPED(¬ify->dst.type.sin6.sin6_addr))
12160 {
12161 isc_sockaddr_format(¬ify->dst, addrbuf, sizeof(addrbuf));
12162 notify_log(notify->zone, ISC_LOG_DEBUG(3),
12163 "notify: ignoring IPv6 mapped IPV4 address: %s",
12164 addrbuf);
12165 result = ISC_R_CANCELED;
12166 goto cleanup;
12167 }
12168
12169 result = notify_createmessage(notify->zone, notify->flags, &message);
12170 if (result != ISC_R_SUCCESS) {
12171 goto cleanup;
12172 }
12173
12174 isc_sockaddr_format(¬ify->dst, addrbuf, sizeof(addrbuf));
12175 if (notify->key != NULL) {
12176 /* Transfer ownership of key */
12177 key = notify->key;
12178 notify->key = NULL;
12179 } else {
12180 isc_netaddr_fromsockaddr(&dstip, ¬ify->dst);
12181 result = dns_view_getpeertsig(notify->zone->view, &dstip, &key);
12182 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
12183 notify_log(notify->zone, ISC_LOG_ERROR,
12184 "NOTIFY to %s not sent. "
12185 "Peer TSIG key lookup failure.",
12186 addrbuf);
12187 goto cleanup_message;
12188 }
12189 }
12190
12191 if (key != NULL) {
12192 char namebuf[DNS_NAME_FORMATSIZE];
12193
12194 dns_name_format(&key->name, namebuf, sizeof(namebuf));
12195 notify_log(notify->zone, ISC_LOG_DEBUG(3),
12196 "sending notify to %s : TSIG (%s)", addrbuf,
12197 namebuf);
12198 } else {
12199 notify_log(notify->zone, ISC_LOG_DEBUG(3),
12200 "sending notify to %s", addrbuf);
12201 }
12202 options = 0;
12203 if (notify->zone->view->peers != NULL) {
12204 dns_peer_t *peer = NULL;
12205 bool usetcp = false;
12206 result = dns_peerlist_peerbyaddr(notify->zone->view->peers,
12207 &dstip, &peer);
12208 if (result == ISC_R_SUCCESS) {
12209 result = dns_peer_getnotifysource(peer, &src);
12210 if (result == ISC_R_SUCCESS) {
12211 have_notifysource = true;
12212 }
12213 dns_peer_getnotifydscp(peer, &dscp);
12214 if (dscp != -1) {
12215 have_notifydscp = true;
12216 }
12217 result = dns_peer_getforcetcp(peer, &usetcp);
12218 if (result == ISC_R_SUCCESS && usetcp) {
12219 options |= DNS_FETCHOPT_TCP;
12220 }
12221 }
12222 }
12223 switch (isc_sockaddr_pf(¬ify->dst)) {
12224 case PF_INET:
12225 if (!have_notifysource) {
12226 src = notify->zone->notifysrc4;
12227 }
12228 if (!have_notifydscp) {
12229 dscp = notify->zone->notifysrc4dscp;
12230 }
12231 break;
12232 case PF_INET6:
12233 if (!have_notifysource) {
12234 src = notify->zone->notifysrc6;
12235 }
12236 if (!have_notifydscp) {
12237 dscp = notify->zone->notifysrc6dscp;
12238 }
12239 break;
12240 default:
12241 result = ISC_R_NOTIMPLEMENTED;
12242 goto cleanup_key;
12243 }
12244 timeout = 15;
12245 if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY)) {
12246 timeout = 30;
12247 }
12248 result = dns_request_createvia(
12249 notify->zone->view->requestmgr, message, &src, ¬ify->dst,
12250 dscp, options, key, timeout * 3, timeout, 0, notify->zone->task,
12251 notify_done, notify, ¬ify->request);
12252 if (result == ISC_R_SUCCESS) {
12253 if (isc_sockaddr_pf(¬ify->dst) == AF_INET) {
12254 inc_stats(notify->zone,
12255 dns_zonestatscounter_notifyoutv4);
12256 } else {
12257 inc_stats(notify->zone,
12258 dns_zonestatscounter_notifyoutv6);
12259 }
12260 }
12261
12262 cleanup_key:
12263 if (key != NULL) {
12264 dns_tsigkey_detach(&key);
12265 }
12266 cleanup_message:
12267 dns_message_detach(&message);
12268 cleanup:
12269 UNLOCK_ZONE(notify->zone);
12270 isc_event_free(&event);
12271 if (result != ISC_R_SUCCESS) {
12272 notify_destroy(notify, false);
12273 }
12274 }
12275
12276 static void
12277 notify_send(dns_notify_t *notify) {
12278 dns_adbaddrinfo_t *ai;
12279 isc_sockaddr_t dst;
12280 isc_result_t result;
12281 dns_notify_t *newnotify = NULL;
12282 unsigned int flags;
12283 bool startup;
12284
12285 /*
12286 * Zone lock held by caller.
12287 */
12288 REQUIRE(DNS_NOTIFY_VALID(notify));
12289 REQUIRE(LOCKED_ZONE(notify->zone));
12290
12291 if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING)) {
12292 return;
12293 }
12294
12295 for (ai = ISC_LIST_HEAD(notify->find->list); ai != NULL;
12296 ai = ISC_LIST_NEXT(ai, publink))
12297 {
12298 dst = ai->sockaddr;
12299 if (notify_isqueued(notify->zone, notify->flags, NULL, &dst,
12300 NULL)) {
12301 continue;
12302 }
12303 if (notify_isself(notify->zone, &dst)) {
12304 continue;
12305 }
12306 newnotify = NULL;
12307 flags = notify->flags & DNS_NOTIFY_NOSOA;
12308 result = notify_create(notify->mctx, flags, &newnotify);
12309 if (result != ISC_R_SUCCESS) {
12310 goto cleanup;
12311 }
12312 zone_iattach(notify->zone, &newnotify->zone);
12313 ISC_LIST_APPEND(newnotify->zone->notifies, newnotify, link);
12314 newnotify->dst = dst;
12315 startup = ((notify->flags & DNS_NOTIFY_STARTUP) != 0);
12316 result = notify_send_queue(newnotify, startup);
12317 if (result != ISC_R_SUCCESS) {
12318 goto cleanup;
12319 }
12320 newnotify = NULL;
12321 }
12322
12323 cleanup:
12324 if (newnotify != NULL) {
12325 notify_destroy(newnotify, true);
12326 }
12327 }
12328
12329 void
12330 dns_zone_notify(dns_zone_t *zone) {
12331 isc_time_t now;
12332
12333 REQUIRE(DNS_ZONE_VALID(zone));
12334
12335 LOCK_ZONE(zone);
12336 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
12337
12338 TIME_NOW(&now);
12339 zone_settimer(zone, &now);
12340 UNLOCK_ZONE(zone);
12341 }
12342
12343 static void
12344 zone_notify(dns_zone_t *zone, isc_time_t *now) {
12345 dns_dbnode_t *node = NULL;
12346 dns_db_t *zonedb = NULL;
12347 dns_dbversion_t *version = NULL;
12348 dns_name_t *origin = NULL;
12349 dns_name_t master;
12350 dns_rdata_ns_t ns;
12351 dns_rdata_soa_t soa;
12352 uint32_t serial;
12353 dns_rdata_t rdata = DNS_RDATA_INIT;
12354 dns_rdataset_t nsrdset;
12355 dns_rdataset_t soardset;
12356 isc_result_t result;
12357 unsigned int i;
12358 isc_sockaddr_t dst;
12359 bool isqueued;
12360 dns_notifytype_t notifytype;
12361 unsigned int flags = 0;
12362 bool loggednotify = false;
12363 bool startup;
12364
12365 REQUIRE(DNS_ZONE_VALID(zone));
12366
12367 LOCK_ZONE(zone);
12368 startup = !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
12369 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
12370 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY);
12371 notifytype = zone->notifytype;
12372 DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime);
12373 UNLOCK_ZONE(zone);
12374
12375 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
12376 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
12377 {
12378 return;
12379 }
12380
12381 if (notifytype == dns_notifytype_no) {
12382 return;
12383 }
12384
12385 if (notifytype == dns_notifytype_masteronly &&
12386 zone->type != dns_zone_master) {
12387 return;
12388 }
12389
12390 origin = &zone->origin;
12391
12392 /*
12393 * If the zone is dialup we are done as we don't want to send
12394 * the current soa so as to force a refresh query.
12395 */
12396 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY)) {
12397 flags |= DNS_NOTIFY_NOSOA;
12398 }
12399
12400 /*
12401 * Record that this was a notify due to starting up.
12402 */
12403 if (startup) {
12404 flags |= DNS_NOTIFY_STARTUP;
12405 }
12406
12407 /*
12408 * Get SOA RRset.
12409 */
12410 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
12411 if (zone->db != NULL) {
12412 dns_db_attach(zone->db, &zonedb);
12413 }
12414 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12415 if (zonedb == NULL) {
12416 return;
12417 }
12418 dns_db_currentversion(zonedb, &version);
12419 result = dns_db_findnode(zonedb, origin, false, &node);
12420 if (result != ISC_R_SUCCESS) {
12421 goto cleanup1;
12422 }
12423
12424 dns_rdataset_init(&soardset);
12425 result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
12426 dns_rdatatype_none, 0, &soardset, NULL);
12427 if (result != ISC_R_SUCCESS) {
12428 goto cleanup2;
12429 }
12430
12431 /*
12432 * Find serial and master server's name.
12433 */
12434 dns_name_init(&master, NULL);
12435 result = dns_rdataset_first(&soardset);
12436 if (result != ISC_R_SUCCESS) {
12437 goto cleanup3;
12438 }
12439 dns_rdataset_current(&soardset, &rdata);
12440 result = dns_rdata_tostruct(&rdata, &soa, NULL);
12441 RUNTIME_CHECK(result == ISC_R_SUCCESS);
12442 dns_rdata_reset(&rdata);
12443 dns_name_dup(&soa.origin, zone->mctx, &master);
12444 serial = soa.serial;
12445 dns_rdataset_disassociate(&soardset);
12446
12447 /*
12448 * Enqueue notify requests for 'also-notify' servers.
12449 */
12450 LOCK_ZONE(zone);
12451 for (i = 0; i < zone->notifycnt; i++) {
12452 dns_tsigkey_t *key = NULL;
12453 dns_notify_t *notify = NULL;
12454
12455 if ((zone->notifykeynames != NULL) &&
12456 (zone->notifykeynames[i] != NULL)) {
12457 dns_view_t *view = dns_zone_getview(zone);
12458 dns_name_t *keyname = zone->notifykeynames[i];
12459 (void)dns_view_gettsig(view, keyname, &key);
12460 }
12461
12462 dst = zone->notify[i];
12463 if (notify_isqueued(zone, flags, NULL, &dst, key)) {
12464 if (key != NULL) {
12465 dns_tsigkey_detach(&key);
12466 }
12467 continue;
12468 }
12469
12470 result = notify_create(zone->mctx, flags, ¬ify);
12471 if (result != ISC_R_SUCCESS) {
12472 if (key != NULL) {
12473 dns_tsigkey_detach(&key);
12474 }
12475 continue;
12476 }
12477
12478 zone_iattach(zone, ¬ify->zone);
12479 notify->dst = dst;
12480
12481 INSIST(notify->key == NULL);
12482
12483 if (key != NULL) {
12484 notify->key = key;
12485 key = NULL;
12486 }
12487
12488 ISC_LIST_APPEND(zone->notifies, notify, link);
12489 result = notify_send_queue(notify, startup);
12490 if (result != ISC_R_SUCCESS) {
12491 notify_destroy(notify, true);
12492 }
12493 if (!loggednotify) {
12494 notify_log(zone, ISC_LOG_INFO,
12495 "sending notifies (serial %u)", serial);
12496 loggednotify = true;
12497 }
12498 }
12499 UNLOCK_ZONE(zone);
12500
12501 if (notifytype == dns_notifytype_explicit) {
12502 goto cleanup3;
12503 }
12504
12505 /*
12506 * Process NS RRset to generate notifies.
12507 */
12508
12509 dns_rdataset_init(&nsrdset);
12510 result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_ns,
12511 dns_rdatatype_none, 0, &nsrdset, NULL);
12512 if (result != ISC_R_SUCCESS) {
12513 goto cleanup3;
12514 }
12515
12516 result = dns_rdataset_first(&nsrdset);
12517 while (result == ISC_R_SUCCESS) {
12518 dns_notify_t *notify = NULL;
12519
12520 dns_rdataset_current(&nsrdset, &rdata);
12521 result = dns_rdata_tostruct(&rdata, &ns, NULL);
12522 RUNTIME_CHECK(result == ISC_R_SUCCESS);
12523 dns_rdata_reset(&rdata);
12524 /*
12525 * Don't notify the master server unless explicitly
12526 * configured to do so.
12527 */
12528 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOTIFYTOSOA) &&
12529 dns_name_compare(&master, &ns.name) == 0)
12530 {
12531 result = dns_rdataset_next(&nsrdset);
12532 continue;
12533 }
12534
12535 if (!loggednotify) {
12536 notify_log(zone, ISC_LOG_INFO,
12537 "sending notifies (serial %u)", serial);
12538 loggednotify = true;
12539 }
12540
12541 LOCK_ZONE(zone);
12542 isqueued = notify_isqueued(zone, flags, &ns.name, NULL, NULL);
12543 UNLOCK_ZONE(zone);
12544 if (isqueued) {
12545 result = dns_rdataset_next(&nsrdset);
12546 continue;
12547 }
12548 result = notify_create(zone->mctx, flags, ¬ify);
12549 if (result != ISC_R_SUCCESS) {
12550 continue;
12551 }
12552 dns_zone_iattach(zone, ¬ify->zone);
12553 dns_name_dup(&ns.name, zone->mctx, ¬ify->ns);
12554 LOCK_ZONE(zone);
12555 ISC_LIST_APPEND(zone->notifies, notify, link);
12556 UNLOCK_ZONE(zone);
12557 notify_find_address(notify);
12558 result = dns_rdataset_next(&nsrdset);
12559 }
12560 dns_rdataset_disassociate(&nsrdset);
12561
12562 cleanup3:
12563 if (dns_name_dynamic(&master)) {
12564 dns_name_free(&master, zone->mctx);
12565 }
12566 cleanup2:
12567 dns_db_detachnode(zonedb, &node);
12568 cleanup1:
12569 dns_db_closeversion(zonedb, &version, false);
12570 dns_db_detach(&zonedb);
12571 }
12572
12573 /***
12574 *** Private
12575 ***/
12576 static inline isc_result_t
12577 create_query(dns_zone_t *zone, dns_rdatatype_t rdtype, dns_name_t *name,
12578 dns_message_t **messagep) {
12579 dns_message_t *message = NULL;
12580 dns_name_t *qname = NULL;
12581 dns_rdataset_t *qrdataset = NULL;
12582 isc_result_t result;
12583
12584 dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER, &message);
12585
12586 message->opcode = dns_opcode_query;
12587 message->rdclass = zone->rdclass;
12588
12589 result = dns_message_gettempname(message, &qname);
12590 if (result != ISC_R_SUCCESS) {
12591 goto cleanup;
12592 }
12593
12594 result = dns_message_gettemprdataset(message, &qrdataset);
12595 if (result != ISC_R_SUCCESS) {
12596 goto cleanup;
12597 }
12598
12599 /*
12600 * Make question.
12601 */
12602 dns_name_init(qname, NULL);
12603 dns_name_clone(name, qname);
12604 dns_rdataset_makequestion(qrdataset, zone->rdclass, rdtype);
12605 ISC_LIST_APPEND(qname->list, qrdataset, link);
12606 dns_message_addname(message, qname, DNS_SECTION_QUESTION);
12607
12608 *messagep = message;
12609 return (ISC_R_SUCCESS);
12610
12611 cleanup:
12612 if (qname != NULL) {
12613 dns_message_puttempname(message, &qname);
12614 }
12615 if (qrdataset != NULL) {
12616 dns_message_puttemprdataset(message, &qrdataset);
12617 }
12618 dns_message_detach(&message);
12619 return (result);
12620 }
12621
12622 static isc_result_t
12623 add_opt(dns_message_t *message, uint16_t udpsize, bool reqnsid,
12624 bool reqexpire) {
12625 isc_result_t result;
12626 dns_rdataset_t *rdataset = NULL;
12627 dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS];
12628 int count = 0;
12629
12630 /* Set EDNS options if applicable. */
12631 if (reqnsid) {
12632 INSIST(count < DNS_EDNSOPTIONS);
12633 ednsopts[count].code = DNS_OPT_NSID;
12634 ednsopts[count].length = 0;
12635 ednsopts[count].value = NULL;
12636 count++;
12637 }
12638 if (reqexpire) {
12639 INSIST(count < DNS_EDNSOPTIONS);
12640 ednsopts[count].code = DNS_OPT_EXPIRE;
12641 ednsopts[count].length = 0;
12642 ednsopts[count].value = NULL;
12643 count++;
12644 }
12645 result = dns_message_buildopt(message, &rdataset, 0, udpsize, 0,
12646 ednsopts, count);
12647 if (result != ISC_R_SUCCESS) {
12648 return (result);
12649 }
12650
12651 return (dns_message_setopt(message, rdataset));
12652 }
12653
12654 /*
12655 * Called when stub zone update is finished.
12656 * Update zone refresh, retry, expire values accordingly with
12657 * SOA received from master, sync database to file, restart
12658 * zone management timer.
12659 */
12660 static void
12661 stub_finish_zone_update(dns_stub_t *stub, isc_time_t now) {
12662 uint32_t refresh, retry, expire;
12663 isc_result_t result;
12664 isc_interval_t i;
12665 unsigned int soacount;
12666 dns_zone_t *zone = stub->zone;
12667
12668 /*
12669 * Tidy up.
12670 */
12671 dns_db_closeversion(stub->db, &stub->version, true);
12672 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
12673 if (zone->db == NULL) {
12674 zone_attachdb(zone, stub->db);
12675 }
12676 result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL,
12677 &refresh, &retry, &expire, NULL, NULL);
12678 if (result == ISC_R_SUCCESS && soacount > 0U) {
12679 zone->refresh = RANGE(refresh, zone->minrefresh,
12680 zone->maxrefresh);
12681 zone->retry = RANGE(retry, zone->minretry, zone->maxretry);
12682 zone->expire = RANGE(expire, zone->refresh + zone->retry,
12683 DNS_MAX_EXPIRE);
12684 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
12685 }
12686 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
12687 dns_db_detach(&stub->db);
12688
12689 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
12690 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
12691 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
12692 isc_interval_set(&i, zone->expire, 0);
12693 DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
12694
12695 if (zone->masterfile != NULL) {
12696 zone_needdump(zone, 0);
12697 }
12698
12699 zone_settimer(zone, &now);
12700 }
12701
12702 /*
12703 * Process answers for A and AAAA queries when
12704 * resolving nameserver addresses for which glue
12705 * was missing in a previous answer for a NS query.
12706 */
12707 static void
12708 stub_glue_response_cb(isc_task_t *task, isc_event_t *event) {
12709 const char me[] = "stub_glue_response_cb";
12710 dns_requestevent_t *revent = (dns_requestevent_t *)event;
12711 dns_stub_t *stub = NULL;
12712 dns_message_t *msg = NULL;
12713 dns_zone_t *zone = NULL;
12714 char master[ISC_SOCKADDR_FORMATSIZE];
12715 char source[ISC_SOCKADDR_FORMATSIZE];
12716 uint32_t addr_count, cnamecnt;
12717 isc_result_t result;
12718 isc_time_t now;
12719 struct stub_glue_request *request;
12720 struct stub_cb_args *cb_args;
12721 dns_rdataset_t *addr_rdataset = NULL;
12722 dns_dbnode_t *node = NULL;
12723
12724 UNUSED(task);
12725
12726 request = revent->ev_arg;
12727 cb_args = request->args;
12728 stub = cb_args->stub;
12729 INSIST(DNS_STUB_VALID(stub));
12730
12731 zone = stub->zone;
12732
12733 ENTER;
12734
12735 TIME_NOW(&now);
12736
12737 LOCK_ZONE(zone);
12738
12739 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
12740 zone_debuglog(zone, me, 1, "exiting");
12741 goto cleanup;
12742 }
12743
12744 isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
12745 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
12746
12747 if (revent->result != ISC_R_SUCCESS) {
12748 dns_zonemgr_unreachableadd(zone->zmgr, &zone->masteraddr,
12749 &zone->sourceaddr, &now);
12750 dns_zone_log(zone, ISC_LOG_INFO,
12751 "could not refresh stub from master %s"
12752 " (source %s): %s",
12753 master, source, dns_result_totext(revent->result));
12754 goto cleanup;
12755 }
12756
12757 dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
12758 result = dns_request_getresponse(revent->request, msg, 0);
12759 if (result != ISC_R_SUCCESS) {
12760 dns_zone_log(zone, ISC_LOG_INFO,
12761 "refreshing stub: unable to parse response (%s)",
12762 isc_result_totext(result));
12763 goto cleanup;
12764 }
12765
12766 /*
12767 * Unexpected rcode.
12768 */
12769 if (msg->rcode != dns_rcode_noerror) {
12770 char rcode[128];
12771 isc_buffer_t rb;
12772
12773 isc_buffer_init(&rb, rcode, sizeof(rcode));
12774 (void)dns_rcode_totext(msg->rcode, &rb);
12775
12776 dns_zone_log(zone, ISC_LOG_INFO,
12777 "refreshing stub: "
12778 "unexpected rcode (%.*s) from %s (source %s)",
12779 (int)rb.used, rcode, master, source);
12780 goto cleanup;
12781 }
12782
12783 /*
12784 * We need complete messages.
12785 */
12786 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
12787 if (dns_request_usedtcp(revent->request)) {
12788 dns_zone_log(zone, ISC_LOG_INFO,
12789 "refreshing stub: truncated TCP "
12790 "response from master %s (source %s)",
12791 master, source);
12792 }
12793 goto cleanup;
12794 }
12795
12796 /*
12797 * If non-auth log.
12798 */
12799 if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
12800 dns_zone_log(zone, ISC_LOG_INFO,
12801 "refreshing stub: "
12802 "non-authoritative answer from "
12803 "master %s (source %s)",
12804 master, source);
12805 goto cleanup;
12806 }
12807
12808 /*
12809 * Sanity checks.
12810 */
12811 cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
12812 addr_count = message_count(msg, DNS_SECTION_ANSWER,
12813 request->ipv4 ? dns_rdatatype_a
12814 : dns_rdatatype_aaaa);
12815
12816 if (cnamecnt != 0) {
12817 dns_zone_log(zone, ISC_LOG_INFO,
12818 "refreshing stub: unexpected CNAME response "
12819 "from master %s (source %s)",
12820 master, source);
12821 goto cleanup;
12822 }
12823
12824 if (addr_count == 0) {
12825 dns_zone_log(zone, ISC_LOG_INFO,
12826 "refreshing stub: no %s records in response "
12827 "from master %s (source %s)",
12828 request->ipv4 ? "A" : "AAAA", master, source);
12829 goto cleanup;
12830 }
12831 /*
12832 * Extract A or AAAA RRset from message.
12833 */
12834 result = dns_message_findname(msg, DNS_SECTION_ANSWER, &request->name,
12835 request->ipv4 ? dns_rdatatype_a
12836 : dns_rdatatype_aaaa,
12837 dns_rdatatype_none, NULL, &addr_rdataset);
12838 if (result != ISC_R_SUCCESS) {
12839 if (result != DNS_R_NXDOMAIN && result != DNS_R_NXRRSET) {
12840 char namebuf[DNS_NAME_FORMATSIZE];
12841 dns_name_format(&request->name, namebuf,
12842 sizeof(namebuf));
12843 dns_zone_log(
12844 zone, ISC_LOG_INFO,
12845 "refreshing stub: dns_message_findname(%s/%s) "
12846 "failed (%s)",
12847 namebuf, request->ipv4 ? "A" : "AAAA",
12848 isc_result_totext(result));
12849 }
12850 goto cleanup;
12851 }
12852
12853 result = dns_db_findnode(stub->db, &request->name, true, &node);
12854 if (result != ISC_R_SUCCESS) {
12855 dns_zone_log(zone, ISC_LOG_INFO,
12856 "refreshing stub: "
12857 "dns_db_findnode() failed: %s",
12858 dns_result_totext(result));
12859 goto cleanup;
12860 }
12861
12862 result = dns_db_addrdataset(stub->db, node, stub->version, 0,
12863 addr_rdataset, 0, NULL);
12864 if (result != ISC_R_SUCCESS) {
12865 dns_zone_log(zone, ISC_LOG_INFO,
12866 "refreshing stub: "
12867 "dns_db_addrdataset() failed: %s",
12868 dns_result_totext(result));
12869 }
12870 dns_db_detachnode(stub->db, &node);
12871
12872 cleanup:
12873 if (msg != NULL) {
12874 dns_message_detach(&msg);
12875 }
12876 isc_event_free(&event);
12877 dns_name_free(&request->name, zone->mctx);
12878 dns_request_destroy(&request->request);
12879 isc_mem_put(zone->mctx, request, sizeof(*request));
12880
12881 /* If last request, release all related resources */
12882 if (atomic_fetch_sub_release(&stub->pending_requests, 1) == 1) {
12883 isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
12884 stub_finish_zone_update(stub, now);
12885 UNLOCK_ZONE(zone);
12886 stub->magic = 0;
12887 dns_zone_idetach(&stub->zone);
12888 INSIST(stub->db == NULL);
12889 INSIST(stub->version == NULL);
12890 isc_mem_put(stub->mctx, stub, sizeof(*stub));
12891 } else {
12892 UNLOCK_ZONE(zone);
12893 }
12894 }
12895
12896 /*
12897 * Create and send an A or AAAA query to the master
12898 * server of the stub zone given.
12899 */
12900 static isc_result_t
12901 stub_request_nameserver_address(struct stub_cb_args *args, bool ipv4,
12902 const dns_name_t *name) {
12903 dns_message_t *message = NULL;
12904 dns_zone_t *zone;
12905 isc_result_t result;
12906 struct stub_glue_request *request;
12907
12908 zone = args->stub->zone;
12909 request = isc_mem_get(zone->mctx, sizeof(*request));
12910 request->request = NULL;
12911 request->args = args;
12912 request->name = (dns_name_t)DNS_NAME_INITEMPTY;
12913 request->ipv4 = ipv4;
12914 dns_name_dup(name, zone->mctx, &request->name);
12915
12916 result = create_query(zone, ipv4 ? dns_rdatatype_a : dns_rdatatype_aaaa,
12917 &request->name, &message);
12918 INSIST(result == ISC_R_SUCCESS);
12919
12920 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
12921 result = add_opt(message, args->udpsize, args->reqnsid, false);
12922 if (result != ISC_R_SUCCESS) {
12923 zone_debuglog(zone, "stub_send_query", 1,
12924 "unable to add opt record: %s",
12925 dns_result_totext(result));
12926 goto fail;
12927 }
12928 }
12929
12930 atomic_fetch_add_release(&args->stub->pending_requests, 1);
12931
12932 result = dns_request_createvia(
12933 zone->view->requestmgr, message, &zone->sourceaddr,
12934 &zone->masteraddr, args->dscp, DNS_REQUESTOPT_TCP,
12935 args->tsig_key, args->timeout * 3, args->timeout, 0, zone->task,
12936 stub_glue_response_cb, request, &request->request);
12937
12938 if (result != ISC_R_SUCCESS) {
12939 INSIST(atomic_fetch_sub_release(&args->stub->pending_requests,
12940 1) > 1);
12941 zone_debuglog(zone, "stub_send_query", 1,
12942 "dns_request_createvia() failed: %s",
12943 dns_result_totext(result));
12944 goto fail;
12945 }
12946
12947 dns_message_detach(&message);
12948
12949 return (ISC_R_SUCCESS);
12950
12951 fail:
12952 dns_name_free(&request->name, zone->mctx);
12953 isc_mem_put(zone->mctx, request, sizeof(*request));
12954
12955 if (message != NULL) {
12956 dns_message_detach(&message);
12957 }
12958
12959 return (result);
12960 }
12961
12962 static inline isc_result_t
12963 save_nsrrset(dns_message_t *message, dns_name_t *name,
12964 struct stub_cb_args *cb_args, dns_db_t *db,
12965 dns_dbversion_t *version) {
12966 dns_rdataset_t *nsrdataset = NULL;
12967 dns_rdataset_t *rdataset = NULL;
12968 dns_dbnode_t *node = NULL;
12969 dns_rdata_ns_t ns;
12970 isc_result_t result;
12971 dns_rdata_t rdata = DNS_RDATA_INIT;
12972 bool has_glue = false;
12973 dns_name_t *ns_name;
12974 /*
12975 * List of NS entries in answer, keep names that will be used
12976 * to resolve missing A/AAAA glue for each entry.
12977 */
12978 dns_namelist_t ns_list;
12979 ISC_LIST_INIT(ns_list);
12980
12981 /*
12982 * Extract NS RRset from message.
12983 */
12984 result = dns_message_findname(message, DNS_SECTION_ANSWER, name,
12985 dns_rdatatype_ns, dns_rdatatype_none,
12986 NULL, &nsrdataset);
12987 if (result != ISC_R_SUCCESS) {
12988 goto done;
12989 }
12990
12991 /*
12992 * Add NS rdataset.
12993 */
12994 result = dns_db_findnode(db, name, true, &node);
12995 if (result != ISC_R_SUCCESS) {
12996 goto done;
12997 }
12998 result = dns_db_addrdataset(db, node, version, 0, nsrdataset, 0, NULL);
12999 dns_db_detachnode(db, &node);
13000 if (result != ISC_R_SUCCESS) {
13001 goto done;
13002 }
13003 /*
13004 * Add glue rdatasets.
13005 */
13006 for (result = dns_rdataset_first(nsrdataset); result == ISC_R_SUCCESS;
13007 result = dns_rdataset_next(nsrdataset))
13008 {
13009 dns_rdataset_current(nsrdataset, &rdata);
13010 result = dns_rdata_tostruct(&rdata, &ns, NULL);
13011 RUNTIME_CHECK(result == ISC_R_SUCCESS);
13012 dns_rdata_reset(&rdata);
13013
13014 if (!dns_name_issubdomain(&ns.name, name)) {
13015 continue;
13016 }
13017 rdataset = NULL;
13018 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
13019 &ns.name, dns_rdatatype_aaaa,
13020 dns_rdatatype_none, NULL,
13021 &rdataset);
13022 if (result == ISC_R_SUCCESS) {
13023 has_glue = true;
13024 result = dns_db_findnode(db, &ns.name, true, &node);
13025 if (result != ISC_R_SUCCESS) {
13026 goto done;
13027 }
13028 result = dns_db_addrdataset(db, node, version, 0,
13029 rdataset, 0, NULL);
13030 dns_db_detachnode(db, &node);
13031 if (result != ISC_R_SUCCESS) {
13032 goto done;
13033 }
13034 }
13035
13036 rdataset = NULL;
13037 result = dns_message_findname(
13038 message, DNS_SECTION_ADDITIONAL, &ns.name,
13039 dns_rdatatype_a, dns_rdatatype_none, NULL, &rdataset);
13040 if (result == ISC_R_SUCCESS) {
13041 has_glue = true;
13042 result = dns_db_findnode(db, &ns.name, true, &node);
13043 if (result != ISC_R_SUCCESS) {
13044 goto done;
13045 }
13046 result = dns_db_addrdataset(db, node, version, 0,
13047 rdataset, 0, NULL);
13048 dns_db_detachnode(db, &node);
13049 if (result != ISC_R_SUCCESS) {
13050 goto done;
13051 }
13052 }
13053
13054 /*
13055 * If no glue is found so far, we add the name to the list to
13056 * resolve the A/AAAA glue later. If any glue is found in any
13057 * iteration step, this list will be discarded and only the glue
13058 * provided in this message will be used.
13059 */
13060 if (!has_glue && dns_name_issubdomain(&ns.name, name)) {
13061 dns_name_t *tmp_name;
13062 tmp_name = isc_mem_get(cb_args->stub->mctx,
13063 sizeof(*tmp_name));
13064 dns_name_init(tmp_name, NULL);
13065 dns_name_dup(&ns.name, cb_args->stub->mctx, tmp_name);
13066 ISC_LIST_APPEND(ns_list, tmp_name, link);
13067 }
13068 }
13069
13070 if (result != ISC_R_NOMORE) {
13071 goto done;
13072 }
13073
13074 /*
13075 * If no glue records were found, we attempt to resolve A/AAAA
13076 * for each NS entry found in the answer.
13077 */
13078 if (!has_glue) {
13079 for (ns_name = ISC_LIST_HEAD(ns_list); ns_name != NULL;
13080 ns_name = ISC_LIST_NEXT(ns_name, link))
13081 {
13082 /*
13083 * Resolve NS IPv4 address/A.
13084 */
13085 result = stub_request_nameserver_address(cb_args, true,
13086 ns_name);
13087 if (result != ISC_R_SUCCESS) {
13088 goto done;
13089 }
13090 /*
13091 * Resolve NS IPv6 address/AAAA.
13092 */
13093 result = stub_request_nameserver_address(cb_args, false,
13094 ns_name);
13095 if (result != ISC_R_SUCCESS) {
13096 goto done;
13097 }
13098 }
13099 }
13100
13101 result = ISC_R_SUCCESS;
13102
13103 done:
13104 while ((ns_name = ISC_LIST_HEAD(ns_list)) != NULL) {
13105 ISC_LIST_UNLINK(ns_list, ns_name, link);
13106 dns_name_free(ns_name, cb_args->stub->mctx);
13107 isc_mem_put(cb_args->stub->mctx, ns_name, sizeof(*ns_name));
13108 }
13109 return (result);
13110 }
13111
13112 static void
13113 stub_callback(isc_task_t *task, isc_event_t *event) {
13114 const char me[] = "stub_callback";
13115 dns_requestevent_t *revent = (dns_requestevent_t *)event;
13116 dns_stub_t *stub = NULL;
13117 dns_message_t *msg = NULL;
13118 dns_zone_t *zone = NULL;
13119 char master[ISC_SOCKADDR_FORMATSIZE];
13120 char source[ISC_SOCKADDR_FORMATSIZE];
13121 uint32_t nscnt, cnamecnt;
13122 isc_result_t result;
13123 isc_time_t now;
13124 bool exiting = false;
13125 unsigned int j;
13126 struct stub_cb_args *cb_args;
13127
13128 cb_args = revent->ev_arg;
13129 stub = cb_args->stub;
13130 INSIST(DNS_STUB_VALID(stub));
13131
13132 UNUSED(task);
13133
13134 zone = stub->zone;
13135
13136 ENTER;
13137
13138 TIME_NOW(&now);
13139
13140 LOCK_ZONE(zone);
13141
13142 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
13143 zone_debuglog(zone, me, 1, "exiting");
13144 exiting = true;
13145 goto next_master;
13146 }
13147
13148 isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
13149 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
13150
13151 if (revent->result != ISC_R_SUCCESS) {
13152 if (revent->result == ISC_R_TIMEDOUT &&
13153 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS))
13154 {
13155 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
13156 dns_zone_log(zone, ISC_LOG_DEBUG(1),
13157 "refreshing stub: timeout retrying "
13158 " without EDNS master %s (source %s)",
13159 master, source);
13160 goto same_master;
13161 }
13162 dns_zonemgr_unreachableadd(zone->zmgr, &zone->masteraddr,
13163 &zone->sourceaddr, &now);
13164 dns_zone_log(zone, ISC_LOG_INFO,
13165 "could not refresh stub from master %s"
13166 " (source %s): %s",
13167 master, source, dns_result_totext(revent->result));
13168 goto next_master;
13169 }
13170
13171 dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
13172
13173 result = dns_request_getresponse(revent->request, msg, 0);
13174 if (result != ISC_R_SUCCESS) {
13175 goto next_master;
13176 }
13177
13178 /*
13179 * Unexpected rcode.
13180 */
13181 if (msg->rcode != dns_rcode_noerror) {
13182 char rcode[128];
13183 isc_buffer_t rb;
13184
13185 isc_buffer_init(&rb, rcode, sizeof(rcode));
13186 (void)dns_rcode_totext(msg->rcode, &rb);
13187
13188 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
13189 (msg->rcode == dns_rcode_servfail ||
13190 msg->rcode == dns_rcode_notimp ||
13191 msg->rcode == dns_rcode_formerr))
13192 {
13193 dns_zone_log(zone, ISC_LOG_DEBUG(1),
13194 "refreshing stub: rcode (%.*s) retrying "
13195 "without EDNS master %s (source %s)",
13196 (int)rb.used, rcode, master, source);
13197 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
13198 goto same_master;
13199 }
13200
13201 dns_zone_log(zone, ISC_LOG_INFO,
13202 "refreshing stub: "
13203 "unexpected rcode (%.*s) from %s (source %s)",
13204 (int)rb.used, rcode, master, source);
13205 goto next_master;
13206 }
13207
13208 /*
13209 * We need complete messages.
13210 */
13211 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
13212 if (dns_request_usedtcp(revent->request)) {
13213 dns_zone_log(zone, ISC_LOG_INFO,
13214 "refreshing stub: truncated TCP "
13215 "response from master %s (source %s)",
13216 master, source);
13217 goto next_master;
13218 }
13219 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
13220 goto same_master;
13221 }
13222
13223 /*
13224 * If non-auth log and next master.
13225 */
13226 if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
13227 dns_zone_log(zone, ISC_LOG_INFO,
13228 "refreshing stub: "
13229 "non-authoritative answer from "
13230 "master %s (source %s)",
13231 master, source);
13232 goto next_master;
13233 }
13234
13235 /*
13236 * Sanity checks.
13237 */
13238 cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
13239 nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns);
13240
13241 if (cnamecnt != 0) {
13242 dns_zone_log(zone, ISC_LOG_INFO,
13243 "refreshing stub: unexpected CNAME response "
13244 "from master %s (source %s)",
13245 master, source);
13246 goto next_master;
13247 }
13248
13249 if (nscnt == 0) {
13250 dns_zone_log(zone, ISC_LOG_INFO,
13251 "refreshing stub: no NS records in response "
13252 "from master %s (source %s)",
13253 master, source);
13254 goto next_master;
13255 }
13256
13257 atomic_fetch_add(&stub->pending_requests, 1);
13258
13259 /*
13260 * Save answer.
13261 */
13262 result = save_nsrrset(msg, &zone->origin, cb_args, stub->db,
13263 stub->version);
13264 if (result != ISC_R_SUCCESS) {
13265 dns_zone_log(zone, ISC_LOG_INFO,
13266 "refreshing stub: unable to save NS records "
13267 "from master %s (source %s)",
13268 master, source);
13269 goto next_master;
13270 }
13271
13272 dns_message_detach(&msg);
13273 isc_event_free(&event);
13274 dns_request_destroy(&zone->request);
13275
13276 /*
13277 * Check to see if there are no outstanding requests and
13278 * finish off if that is so.
13279 */
13280 if (atomic_fetch_sub(&stub->pending_requests, 1) == 1) {
13281 isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
13282 stub_finish_zone_update(stub, now);
13283 goto free_stub;
13284 }
13285
13286 UNLOCK_ZONE(zone);
13287 return;
13288
13289 next_master:
13290 isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
13291 if (stub->version != NULL) {
13292 dns_db_closeversion(stub->db, &stub->version, false);
13293 }
13294 if (stub->db != NULL) {
13295 dns_db_detach(&stub->db);
13296 }
13297 if (msg != NULL) {
13298 dns_message_detach(&msg);
13299 }
13300 isc_event_free(&event);
13301 dns_request_destroy(&zone->request);
13302 /*
13303 * Skip to next failed / untried master.
13304 */
13305 do {
13306 zone->curmaster++;
13307 } while (zone->curmaster < zone->masterscnt &&
13308 zone->mastersok[zone->curmaster]);
13309 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
13310 if (exiting || zone->curmaster >= zone->masterscnt) {
13311 bool done = true;
13312 if (!exiting &&
13313 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
13314 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
13315 {
13316 /*
13317 * Did we get a good answer from all the primaries?
13318 */
13319 for (j = 0; j < zone->masterscnt; j++) {
13320 if (!zone->mastersok[j]) {
13321 {
13322 done = false;
13323 break;
13324 }
13325 }
13326 }
13327 } else {
13328 done = true;
13329 }
13330 if (!done) {
13331 zone->curmaster = 0;
13332 /*
13333 * Find the next failed master.
13334 */
13335 while (zone->curmaster < zone->masterscnt &&
13336 zone->mastersok[zone->curmaster]) {
13337 zone->curmaster++;
13338 }
13339 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
13340 } else {
13341 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
13342
13343 zone_settimer(zone, &now);
13344 goto free_stub;
13345 }
13346 }
13347 queue_soa_query(zone);
13348 goto free_stub;
13349
13350 same_master:
13351 isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
13352 if (msg != NULL) {
13353 dns_message_detach(&msg);
13354 }
13355 isc_event_free(&event);
13356 dns_request_destroy(&zone->request);
13357 ns_query(zone, NULL, stub);
13358 UNLOCK_ZONE(zone);
13359 goto done;
13360
13361 free_stub:
13362 UNLOCK_ZONE(zone);
13363 stub->magic = 0;
13364 dns_zone_idetach(&stub->zone);
13365 INSIST(stub->db == NULL);
13366 INSIST(stub->version == NULL);
13367 isc_mem_put(stub->mctx, stub, sizeof(*stub));
13368
13369 done:
13370 INSIST(event == NULL);
13371 return;
13372 }
13373
13374 /*
13375 * Get the EDNS EXPIRE option from the response and if it exists trim
13376 * expire to be not more than it.
13377 */
13378 static void
13379 get_edns_expire(dns_zone_t *zone, dns_message_t *message, uint32_t *expirep) {
13380 isc_result_t result;
13381 uint32_t expire;
13382 dns_rdata_t rdata = DNS_RDATA_INIT;
13383 isc_buffer_t optbuf;
13384 uint16_t optcode;
13385 uint16_t optlen;
13386
13387 REQUIRE(expirep != NULL);
13388 REQUIRE(message != NULL);
13389
13390 if (message->opt == NULL) {
13391 return;
13392 }
13393
13394 result = dns_rdataset_first(message->opt);
13395 if (result == ISC_R_SUCCESS) {
13396 dns_rdataset_current(message->opt, &rdata);
13397 isc_buffer_init(&optbuf, rdata.data, rdata.length);
13398 isc_buffer_add(&optbuf, rdata.length);
13399 while (isc_buffer_remaininglength(&optbuf) >= 4) {
13400 optcode = isc_buffer_getuint16(&optbuf);
13401 optlen = isc_buffer_getuint16(&optbuf);
13402 /*
13403 * A EDNS EXPIRE response has a length of 4.
13404 */
13405 if (optcode != DNS_OPT_EXPIRE || optlen != 4) {
13406 isc_buffer_forward(&optbuf, optlen);
13407 continue;
13408 }
13409 expire = isc_buffer_getuint32(&optbuf);
13410 dns_zone_log(zone, ISC_LOG_DEBUG(1),
13411 "got EDNS EXPIRE of %u", expire);
13412 /*
13413 * Trim *expirep?
13414 */
13415 if (expire < *expirep) {
13416 *expirep = expire;
13417 }
13418 break;
13419 }
13420 }
13421 }
13422
13423 /*
13424 * Set the file modification time zone->expire seconds before expiretime.
13425 */
13426 static void
13427 setmodtime(dns_zone_t *zone, isc_time_t *expiretime) {
13428 isc_result_t result;
13429 isc_time_t when;
13430 isc_interval_t i;
13431
13432 isc_interval_set(&i, zone->expire, 0);
13433 result = isc_time_subtract(expiretime, &i, &when);
13434 if (result != ISC_R_SUCCESS) {
13435 return;
13436 }
13437
13438 result = ISC_R_FAILURE;
13439 if (zone->journal != NULL) {
13440 result = isc_file_settime(zone->journal, &when);
13441 }
13442 if (result == ISC_R_SUCCESS &&
13443 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
13444 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP))
13445 {
13446 result = isc_file_settime(zone->masterfile, &when);
13447 } else if (result != ISC_R_SUCCESS) {
13448 result = isc_file_settime(zone->masterfile, &when);
13449 }
13450
13451 /*
13452 * Someone removed the file from underneath us!
13453 */
13454 if (result == ISC_R_FILENOTFOUND) {
13455 zone_needdump(zone, DNS_DUMP_DELAY);
13456 } else if (result != ISC_R_SUCCESS) {
13457 dns_zone_log(zone, ISC_LOG_ERROR,
13458 "refresh: could not set "
13459 "file modification time of '%s': %s",
13460 zone->masterfile, dns_result_totext(result));
13461 }
13462 }
13463
13464 /*
13465 * An SOA query has finished (successfully or not).
13466 */
13467 static void
13468 refresh_callback(isc_task_t *task, isc_event_t *event) {
13469 const char me[] = "refresh_callback";
13470 dns_requestevent_t *revent = (dns_requestevent_t *)event;
13471 dns_zone_t *zone;
13472 dns_message_t *msg = NULL;
13473 uint32_t soacnt, cnamecnt, soacount, nscount;
13474 isc_time_t now;
13475 char master[ISC_SOCKADDR_FORMATSIZE];
13476 char source[ISC_SOCKADDR_FORMATSIZE];
13477 dns_rdataset_t *rdataset = NULL;
13478 dns_rdata_t rdata = DNS_RDATA_INIT;
13479 dns_rdata_soa_t soa;
13480 isc_result_t result;
13481 uint32_t serial, oldserial = 0;
13482 unsigned int j;
13483 bool do_queue_xfrin = false;
13484
13485 zone = revent->ev_arg;
13486 INSIST(DNS_ZONE_VALID(zone));
13487
13488 UNUSED(task);
13489
13490 ENTER;
13491
13492 TIME_NOW(&now);
13493
13494 LOCK_ZONE(zone);
13495
13496 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
13497 isc_event_free(&event);
13498 dns_request_destroy(&zone->request);
13499 goto detach;
13500 }
13501
13502 /*
13503 * if timeout log and next master;
13504 */
13505
13506 isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
13507 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
13508
13509 if (revent->result != ISC_R_SUCCESS) {
13510 if (revent->result == ISC_R_TIMEDOUT &&
13511 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS))
13512 {
13513 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
13514 dns_zone_log(zone, ISC_LOG_DEBUG(1),
13515 "refresh: timeout retrying without EDNS "
13516 "master %s (source %s)",
13517 master, source);
13518 goto same_master;
13519 }
13520 if (revent->result == ISC_R_TIMEDOUT &&
13521 !dns_request_usedtcp(revent->request)) {
13522 dns_zone_log(zone, ISC_LOG_INFO,
13523 "refresh: retry limit for "
13524 "master %s exceeded (source %s)",
13525 master, source);
13526 /* Try with slave with TCP. */
13527 if ((zone->type == dns_zone_slave ||
13528 zone->type == dns_zone_mirror ||
13529 zone->type == dns_zone_redirect) &&
13530 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH))
13531 {
13532 if (!dns_zonemgr_unreachable(
13533 zone->zmgr, &zone->masteraddr,
13534 &zone->sourceaddr, &now))
13535 {
13536 DNS_ZONE_SETFLAG(
13537 zone,
13538 DNS_ZONEFLG_SOABEFOREAXFR);
13539 goto tcp_transfer;
13540 }
13541 dns_zone_log(zone, ISC_LOG_DEBUG(1),
13542 "refresh: skipped tcp fallback "
13543 "as master %s (source %s) is "
13544 "unreachable (cached)",
13545 master, source);
13546 }
13547 } else {
13548 dns_zone_log(zone, ISC_LOG_INFO,
13549 "refresh: failure trying master "
13550 "%s (source %s): %s",
13551 master, source,
13552 dns_result_totext(revent->result));
13553 }
13554 goto next_master;
13555 }
13556
13557 dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
13558 result = dns_request_getresponse(revent->request, msg, 0);
13559 if (result != ISC_R_SUCCESS) {
13560 dns_zone_log(zone, ISC_LOG_INFO,
13561 "refresh: failure trying master "
13562 "%s (source %s): %s",
13563 master, source, dns_result_totext(result));
13564 goto next_master;
13565 }
13566
13567 /*
13568 * Unexpected rcode.
13569 */
13570 if (msg->rcode != dns_rcode_noerror) {
13571 char rcode[128];
13572 isc_buffer_t rb;
13573
13574 isc_buffer_init(&rb, rcode, sizeof(rcode));
13575 (void)dns_rcode_totext(msg->rcode, &rb);
13576
13577 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
13578 (msg->rcode == dns_rcode_servfail ||
13579 msg->rcode == dns_rcode_notimp ||
13580 msg->rcode == dns_rcode_formerr))
13581 {
13582 dns_zone_log(zone, ISC_LOG_DEBUG(1),
13583 "refresh: rcode (%.*s) retrying without "
13584 "EDNS master %s (source %s)",
13585 (int)rb.used, rcode, master, source);
13586 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
13587 goto same_master;
13588 }
13589 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
13590 msg->rcode == dns_rcode_badvers) {
13591 dns_zone_log(zone, ISC_LOG_DEBUG(1),
13592 "refresh: rcode (%.*s) retrying without "
13593 "EDNS EXPIRE OPTION master %s (source %s)",
13594 (int)rb.used, rcode, master, source);
13595 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
13596 goto same_master;
13597 }
13598 dns_zone_log(zone, ISC_LOG_INFO,
13599 "refresh: unexpected rcode (%.*s) from "
13600 "master %s (source %s)",
13601 (int)rb.used, rcode, master, source);
13602 /*
13603 * Perhaps AXFR/IXFR is allowed even if SOA queries aren't.
13604 */
13605 if (msg->rcode == dns_rcode_refused &&
13606 (zone->type == dns_zone_slave ||
13607 zone->type == dns_zone_mirror ||
13608 zone->type == dns_zone_redirect))
13609 {
13610 goto tcp_transfer;
13611 }
13612 goto next_master;
13613 }
13614
13615 /*
13616 * If truncated punt to zone transfer which will query again.
13617 */
13618 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
13619 if (zone->type == dns_zone_slave ||
13620 zone->type == dns_zone_mirror ||
13621 zone->type == dns_zone_redirect)
13622 {
13623 dns_zone_log(zone, ISC_LOG_INFO,
13624 "refresh: truncated UDP answer, "
13625 "initiating TCP zone xfer "
13626 "for master %s (source %s)",
13627 master, source);
13628 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
13629 goto tcp_transfer;
13630 } else {
13631 INSIST(zone->type == dns_zone_stub);
13632 if (dns_request_usedtcp(revent->request)) {
13633 dns_zone_log(zone, ISC_LOG_INFO,
13634 "refresh: truncated TCP response "
13635 "from master %s (source %s)",
13636 master, source);
13637 goto next_master;
13638 }
13639 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
13640 goto same_master;
13641 }
13642 }
13643
13644 /*
13645 * if non-auth log and next master;
13646 */
13647 if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
13648 dns_zone_log(zone, ISC_LOG_INFO,
13649 "refresh: non-authoritative answer from "
13650 "master %s (source %s)",
13651 master, source);
13652 goto next_master;
13653 }
13654
13655 cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
13656 soacnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_soa);
13657 nscount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_ns);
13658 soacount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_soa);
13659
13660 /*
13661 * There should not be a CNAME record at top of zone.
13662 */
13663 if (cnamecnt != 0) {
13664 dns_zone_log(zone, ISC_LOG_INFO,
13665 "refresh: CNAME at top of zone "
13666 "in master %s (source %s)",
13667 master, source);
13668 goto next_master;
13669 }
13670
13671 /*
13672 * if referral log and next master;
13673 */
13674 if (soacnt == 0 && soacount == 0 && nscount != 0) {
13675 dns_zone_log(zone, ISC_LOG_INFO,
13676 "refresh: referral response "
13677 "from master %s (source %s)",
13678 master, source);
13679 goto next_master;
13680 }
13681
13682 /*
13683 * if nodata log and next master;
13684 */
13685 if (soacnt == 0 && (nscount == 0 || soacount != 0)) {
13686 dns_zone_log(zone, ISC_LOG_INFO,
13687 "refresh: NODATA response "
13688 "from master %s (source %s)",
13689 master, source);
13690 goto next_master;
13691 }
13692
13693 /*
13694 * Only one soa at top of zone.
13695 */
13696 if (soacnt != 1) {
13697 dns_zone_log(zone, ISC_LOG_INFO,
13698 "refresh: answer SOA count (%d) != 1 "
13699 "from master %s (source %s)",
13700 soacnt, master, source);
13701 goto next_master;
13702 }
13703
13704 /*
13705 * Extract serial
13706 */
13707 rdataset = NULL;
13708 result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin,
13709 dns_rdatatype_soa, dns_rdatatype_none,
13710 NULL, &rdataset);
13711 if (result != ISC_R_SUCCESS) {
13712 dns_zone_log(zone, ISC_LOG_INFO,
13713 "refresh: unable to get SOA record "
13714 "from master %s (source %s)",
13715 master, source);
13716 goto next_master;
13717 }
13718
13719 result = dns_rdataset_first(rdataset);
13720 if (result != ISC_R_SUCCESS) {
13721 dns_zone_log(zone, ISC_LOG_INFO,
13722 "refresh: dns_rdataset_first() failed");
13723 goto next_master;
13724 }
13725
13726 dns_rdataset_current(rdataset, &rdata);
13727 result = dns_rdata_tostruct(&rdata, &soa, NULL);
13728 RUNTIME_CHECK(result == ISC_R_SUCCESS);
13729
13730 serial = soa.serial;
13731 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
13732 unsigned int dbsoacount;
13733 result = zone_get_from_db(zone, zone->db, NULL, &dbsoacount,
13734 &oldserial, NULL, NULL, NULL, NULL,
13735 NULL);
13736 RUNTIME_CHECK(result == ISC_R_SUCCESS);
13737 RUNTIME_CHECK(dbsoacount > 0U);
13738 zone_debuglog(zone, me, 1, "serial: new %u, old %u", serial,
13739 oldserial);
13740 } else {
13741 zone_debuglog(zone, me, 1, "serial: new %u, old not loaded",
13742 serial);
13743 }
13744
13745 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
13746 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
13747 isc_serial_gt(serial, oldserial))
13748 {
13749 if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
13750 &zone->sourceaddr, &now))
13751 {
13752 dns_zone_log(zone, ISC_LOG_INFO,
13753 "refresh: skipping %s as master %s "
13754 "(source %s) is unreachable (cached)",
13755 (zone->type == dns_zone_slave ||
13756 zone->type == dns_zone_mirror ||
13757 zone->type == dns_zone_redirect)
13758 ? "zone transfer"
13759 : "NS query",
13760 master, source);
13761 goto next_master;
13762 }
13763 tcp_transfer:
13764 isc_event_free(&event);
13765 dns_request_destroy(&zone->request);
13766 if (zone->type == dns_zone_slave ||
13767 zone->type == dns_zone_mirror ||
13768 zone->type == dns_zone_redirect)
13769 {
13770 do_queue_xfrin = true;
13771 } else {
13772 INSIST(zone->type == dns_zone_stub);
13773 ns_query(zone, rdataset, NULL);
13774 }
13775 if (msg != NULL) {
13776 dns_message_detach(&msg);
13777 }
13778 } else if (isc_serial_eq(soa.serial, oldserial)) {
13779 isc_time_t expiretime;
13780 uint32_t expire;
13781
13782 /*
13783 * Compute the new expire time based on this response.
13784 */
13785 expire = zone->expire;
13786 get_edns_expire(zone, msg, &expire);
13787 DNS_ZONE_TIME_ADD(&now, expire, &expiretime);
13788
13789 /*
13790 * Has the expire time improved?
13791 */
13792 if (isc_time_compare(&expiretime, &zone->expiretime) > 0) {
13793 zone->expiretime = expiretime;
13794 if (zone->masterfile != NULL) {
13795 setmodtime(zone, &expiretime);
13796 }
13797 }
13798
13799 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
13800 zone->mastersok[zone->curmaster] = true;
13801 goto next_master;
13802 } else {
13803 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER)) {
13804 dns_zone_log(zone, ISC_LOG_INFO,
13805 "serial number (%u) "
13806 "received from master %s < ours (%u)",
13807 soa.serial, master, oldserial);
13808 } else {
13809 zone_debuglog(zone, me, 1, "ahead");
13810 }
13811 zone->mastersok[zone->curmaster] = true;
13812 goto next_master;
13813 }
13814 if (msg != NULL) {
13815 dns_message_detach(&msg);
13816 }
13817 goto detach;
13818
13819 next_master:
13820 if (msg != NULL) {
13821 dns_message_detach(&msg);
13822 }
13823 isc_event_free(&event);
13824 dns_request_destroy(&zone->request);
13825 /*
13826 * Skip to next failed / untried master.
13827 */
13828 do {
13829 zone->curmaster++;
13830 } while (zone->curmaster < zone->masterscnt &&
13831 zone->mastersok[zone->curmaster]);
13832 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
13833 if (zone->curmaster >= zone->masterscnt) {
13834 bool done = true;
13835 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
13836 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
13837 {
13838 /*
13839 * Did we get a good answer from all the primaries?
13840 */
13841 for (j = 0; j < zone->masterscnt; j++) {
13842 if (!zone->mastersok[j]) {
13843 {
13844 done = false;
13845 break;
13846 }
13847 }
13848 }
13849 } else {
13850 done = true;
13851 }
13852 if (!done) {
13853 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
13854 zone->curmaster = 0;
13855 /*
13856 * Find the next failed master.
13857 */
13858 while (zone->curmaster < zone->masterscnt &&
13859 zone->mastersok[zone->curmaster]) {
13860 zone->curmaster++;
13861 }
13862 goto requeue;
13863 }
13864 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
13865 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
13866 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
13867 zone->refreshtime = now;
13868 }
13869 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
13870 zone_settimer(zone, &now);
13871 goto detach;
13872 }
13873
13874 requeue:
13875 queue_soa_query(zone);
13876 goto detach;
13877
13878 same_master:
13879 if (msg != NULL) {
13880 dns_message_detach(&msg);
13881 }
13882 isc_event_free(&event);
13883 dns_request_destroy(&zone->request);
13884 queue_soa_query(zone);
13885
13886 detach:
13887 UNLOCK_ZONE(zone);
13888 if (do_queue_xfrin) {
13889 queue_xfrin(zone);
13890 }
13891 dns_zone_idetach(&zone);
13892 return;
13893 }
13894
13895 static void
13896 queue_soa_query(dns_zone_t *zone) {
13897 const char me[] = "queue_soa_query";
13898 isc_event_t *e;
13899 dns_zone_t *dummy = NULL;
13900 isc_result_t result;
13901
13902 ENTER;
13903 /*
13904 * Locked by caller
13905 */
13906 REQUIRE(LOCKED_ZONE(zone));
13907
13908 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
13909 cancel_refresh(zone);
13910 return;
13911 }
13912
13913 e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE, soa_query,
13914 zone, sizeof(isc_event_t));
13915
13916 /*
13917 * Attach so that we won't clean up
13918 * until the event is delivered.
13919 */
13920 zone_iattach(zone, &dummy);
13921
13922 e->ev_arg = zone;
13923 e->ev_sender = NULL;
13924 result = isc_ratelimiter_enqueue(zone->zmgr->refreshrl, zone->task, &e);
13925 if (result != ISC_R_SUCCESS) {
13926 zone_idetach(&dummy);
13927 isc_event_free(&e);
13928 cancel_refresh(zone);
13929 }
13930 }
13931
13932 static void
13933 soa_query(isc_task_t *task, isc_event_t *event) {
13934 const char me[] = "soa_query";
13935 isc_result_t result = ISC_R_FAILURE;
13936 dns_message_t *message = NULL;
13937 dns_zone_t *zone = event->ev_arg;
13938 dns_zone_t *dummy = NULL;
13939 isc_netaddr_t masterip;
13940 dns_tsigkey_t *key = NULL;
13941 uint32_t options;
13942 bool cancel = true;
13943 int timeout;
13944 bool have_xfrsource, have_xfrdscp, reqnsid, reqexpire;
13945 uint16_t udpsize = SEND_BUFFER_SIZE;
13946 isc_dscp_t dscp = -1;
13947
13948 REQUIRE(DNS_ZONE_VALID(zone));
13949
13950 UNUSED(task);
13951
13952 ENTER;
13953
13954 LOCK_ZONE(zone);
13955 if (((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) ||
13956 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
13957 zone->view->requestmgr == NULL)
13958 {
13959 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
13960 cancel = false;
13961 }
13962 goto cleanup;
13963 }
13964
13965 again:
13966 result = create_query(zone, dns_rdatatype_soa, &zone->origin, &message);
13967 if (result != ISC_R_SUCCESS) {
13968 goto cleanup;
13969 }
13970
13971 INSIST(zone->masterscnt > 0);
13972 INSIST(zone->curmaster < zone->masterscnt);
13973
13974 zone->masteraddr = zone->masters[zone->curmaster];
13975
13976 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
13977 /*
13978 * First, look for a tsig key in the master statement, then
13979 * try for a server key.
13980 */
13981 if ((zone->masterkeynames != NULL) &&
13982 (zone->masterkeynames[zone->curmaster] != NULL))
13983 {
13984 dns_view_t *view = dns_zone_getview(zone);
13985 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
13986 result = dns_view_gettsig(view, keyname, &key);
13987 if (result != ISC_R_SUCCESS) {
13988 char namebuf[DNS_NAME_FORMATSIZE];
13989 dns_name_format(keyname, namebuf, sizeof(namebuf));
13990 dns_zone_log(zone, ISC_LOG_ERROR,
13991 "unable to find key: %s", namebuf);
13992 goto skip_master;
13993 }
13994 }
13995 if (key == NULL) {
13996 result = dns_view_getpeertsig(zone->view, &masterip, &key);
13997 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
13998 char addrbuf[ISC_NETADDR_FORMATSIZE];
13999 isc_netaddr_format(&masterip, addrbuf, sizeof(addrbuf));
14000 dns_zone_log(zone, ISC_LOG_ERROR,
14001 "unable to find TSIG key for %s", addrbuf);
14002 goto skip_master;
14003 }
14004 }
14005
14006 options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ? DNS_REQUESTOPT_TCP
14007 : 0;
14008 have_xfrsource = have_xfrdscp = false;
14009 reqnsid = zone->view->requestnsid;
14010 reqexpire = zone->requestexpire;
14011 if (zone->view->peers != NULL) {
14012 dns_peer_t *peer = NULL;
14013 bool edns, usetcp;
14014 result = dns_peerlist_peerbyaddr(zone->view->peers, &masterip,
14015 &peer);
14016 if (result == ISC_R_SUCCESS) {
14017 result = dns_peer_getsupportedns(peer, &edns);
14018 if (result == ISC_R_SUCCESS && !edns) {
14019 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
14020 }
14021 result = dns_peer_gettransfersource(peer,
14022 &zone->sourceaddr);
14023 if (result == ISC_R_SUCCESS) {
14024 have_xfrsource = true;
14025 }
14026 (void)dns_peer_gettransferdscp(peer, &dscp);
14027 if (dscp != -1) {
14028 have_xfrdscp = true;
14029 }
14030 if (zone->view->resolver != NULL) {
14031 udpsize = dns_resolver_getudpsize(
14032 zone->view->resolver);
14033 }
14034 (void)dns_peer_getudpsize(peer, &udpsize);
14035 (void)dns_peer_getrequestnsid(peer, &reqnsid);
14036 (void)dns_peer_getrequestexpire(peer, &reqexpire);
14037 result = dns_peer_getforcetcp(peer, &usetcp);
14038 if (result == ISC_R_SUCCESS && usetcp) {
14039 options |= DNS_REQUESTOPT_TCP;
14040 }
14041 }
14042 }
14043
14044 switch (isc_sockaddr_pf(&zone->masteraddr)) {
14045 case PF_INET:
14046 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
14047 if (isc_sockaddr_equal(&zone->altxfrsource4,
14048 &zone->xfrsource4)) {
14049 goto skip_master;
14050 }
14051 zone->sourceaddr = zone->altxfrsource4;
14052 if (!have_xfrdscp) {
14053 dscp = zone->altxfrsource4dscp;
14054 }
14055 } else if (!have_xfrsource) {
14056 zone->sourceaddr = zone->xfrsource4;
14057 if (!have_xfrdscp) {
14058 dscp = zone->xfrsource4dscp;
14059 }
14060 }
14061 break;
14062 case PF_INET6:
14063 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
14064 if (isc_sockaddr_equal(&zone->altxfrsource6,
14065 &zone->xfrsource6)) {
14066 goto skip_master;
14067 }
14068 zone->sourceaddr = zone->altxfrsource6;
14069 if (!have_xfrdscp) {
14070 dscp = zone->altxfrsource6dscp;
14071 }
14072 } else if (!have_xfrsource) {
14073 zone->sourceaddr = zone->xfrsource6;
14074 if (!have_xfrdscp) {
14075 dscp = zone->xfrsource6dscp;
14076 }
14077 }
14078 break;
14079 default:
14080 result = ISC_R_NOTIMPLEMENTED;
14081 goto cleanup;
14082 }
14083
14084 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
14085 result = add_opt(message, udpsize, reqnsid, reqexpire);
14086 if (result != ISC_R_SUCCESS) {
14087 zone_debuglog(zone, me, 1,
14088 "unable to add opt record: %s",
14089 dns_result_totext(result));
14090 }
14091 }
14092
14093 zone_iattach(zone, &dummy);
14094 timeout = 15;
14095 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH)) {
14096 timeout = 30;
14097 }
14098 result = dns_request_createvia(
14099 zone->view->requestmgr, message, &zone->sourceaddr,
14100 &zone->masteraddr, dscp, options, key, timeout * 3, timeout, 0,
14101 zone->task, refresh_callback, zone, &zone->request);
14102 if (result != ISC_R_SUCCESS) {
14103 zone_idetach(&dummy);
14104 zone_debuglog(zone, me, 1,
14105 "dns_request_createvia4() failed: %s",
14106 dns_result_totext(result));
14107 goto skip_master;
14108 } else {
14109 if (isc_sockaddr_pf(&zone->masteraddr) == PF_INET) {
14110 inc_stats(zone, dns_zonestatscounter_soaoutv4);
14111 } else {
14112 inc_stats(zone, dns_zonestatscounter_soaoutv6);
14113 }
14114 }
14115 cancel = false;
14116
14117 cleanup:
14118 if (key != NULL) {
14119 dns_tsigkey_detach(&key);
14120 }
14121 if (result != ISC_R_SUCCESS) {
14122 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
14123 }
14124 if (message != NULL) {
14125 dns_message_detach(&message);
14126 }
14127 if (cancel) {
14128 cancel_refresh(zone);
14129 }
14130 isc_event_free(&event);
14131 UNLOCK_ZONE(zone);
14132 dns_zone_idetach(&zone);
14133 return;
14134
14135 skip_master:
14136 if (key != NULL) {
14137 dns_tsigkey_detach(&key);
14138 }
14139 dns_message_detach(&message);
14140 /*
14141 * Skip to next failed / untried master.
14142 */
14143 do {
14144 zone->curmaster++;
14145 } while (zone->curmaster < zone->masterscnt &&
14146 zone->mastersok[zone->curmaster]);
14147 if (zone->curmaster < zone->masterscnt) {
14148 goto again;
14149 }
14150 zone->curmaster = 0;
14151 goto cleanup;
14152 }
14153
14154 static void
14155 ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
14156 const char me[] = "ns_query";
14157 isc_result_t result;
14158 dns_message_t *message = NULL;
14159 isc_netaddr_t masterip;
14160 dns_tsigkey_t *key = NULL;
14161 dns_dbnode_t *node = NULL;
14162 int timeout;
14163 bool have_xfrsource = false, have_xfrdscp = false;
14164 bool reqnsid;
14165 uint16_t udpsize = SEND_BUFFER_SIZE;
14166 isc_dscp_t dscp = -1;
14167 struct stub_cb_args *cb_args;
14168
14169 REQUIRE(DNS_ZONE_VALID(zone));
14170 REQUIRE(LOCKED_ZONE(zone));
14171 REQUIRE((soardataset != NULL && stub == NULL) ||
14172 (soardataset == NULL && stub != NULL));
14173 REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
14174
14175 ENTER;
14176
14177 if (stub == NULL) {
14178 stub = isc_mem_get(zone->mctx, sizeof(*stub));
14179 stub->magic = STUB_MAGIC;
14180 stub->mctx = zone->mctx;
14181 stub->zone = NULL;
14182 stub->db = NULL;
14183 stub->version = NULL;
14184 atomic_init(&stub->pending_requests, 0);
14185
14186 /*
14187 * Attach so that the zone won't disappear from under us.
14188 */
14189 zone_iattach(zone, &stub->zone);
14190
14191 /*
14192 * If a db exists we will update it, otherwise we create a
14193 * new one and attach it to the zone once we have the NS
14194 * RRset and glue.
14195 */
14196 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
14197 if (zone->db != NULL) {
14198 dns_db_attach(zone->db, &stub->db);
14199 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
14200 } else {
14201 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
14202
14203 INSIST(zone->db_argc >= 1);
14204 result = dns_db_create(zone->mctx, zone->db_argv[0],
14205 &zone->origin, dns_dbtype_stub,
14206 zone->rdclass, zone->db_argc - 1,
14207 zone->db_argv + 1, &stub->db);
14208 if (result != ISC_R_SUCCESS) {
14209 dns_zone_log(zone, ISC_LOG_ERROR,
14210 "refreshing stub: "
14211 "could not create "
14212 "database: %s",
14213 dns_result_totext(result));
14214 goto cleanup;
14215 }
14216 dns_db_settask(stub->db, zone->task);
14217 }
14218
14219 result = dns_db_newversion(stub->db, &stub->version);
14220 if (result != ISC_R_SUCCESS) {
14221 dns_zone_log(zone, ISC_LOG_INFO,
14222 "refreshing stub: "
14223 "dns_db_newversion() failed: %s",
14224 dns_result_totext(result));
14225 goto cleanup;
14226 }
14227
14228 /*
14229 * Update SOA record.
14230 */
14231 result = dns_db_findnode(stub->db, &zone->origin, true, &node);
14232 if (result != ISC_R_SUCCESS) {
14233 dns_zone_log(zone, ISC_LOG_INFO,
14234 "refreshing stub: "
14235 "dns_db_findnode() failed: %s",
14236 dns_result_totext(result));
14237 goto cleanup;
14238 }
14239
14240 result = dns_db_addrdataset(stub->db, node, stub->version, 0,
14241 soardataset, 0, NULL);
14242 dns_db_detachnode(stub->db, &node);
14243 if (result != ISC_R_SUCCESS) {
14244 dns_zone_log(zone, ISC_LOG_INFO,
14245 "refreshing stub: "
14246 "dns_db_addrdataset() failed: %s",
14247 dns_result_totext(result));
14248 goto cleanup;
14249 }
14250 }
14251
14252 /*
14253 * XXX Optimisation: Create message when zone is setup and reuse.
14254 */
14255 result = create_query(zone, dns_rdatatype_ns, &zone->origin, &message);
14256 INSIST(result == ISC_R_SUCCESS);
14257
14258 INSIST(zone->masterscnt > 0);
14259 INSIST(zone->curmaster < zone->masterscnt);
14260 zone->masteraddr = zone->masters[zone->curmaster];
14261
14262 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
14263 /*
14264 * First, look for a tsig key in the master statement, then
14265 * try for a server key.
14266 */
14267 if ((zone->masterkeynames != NULL) &&
14268 (zone->masterkeynames[zone->curmaster] != NULL))
14269 {
14270 dns_view_t *view = dns_zone_getview(zone);
14271 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
14272 result = dns_view_gettsig(view, keyname, &key);
14273 if (result != ISC_R_SUCCESS) {
14274 char namebuf[DNS_NAME_FORMATSIZE];
14275 dns_name_format(keyname, namebuf, sizeof(namebuf));
14276 dns_zone_log(zone, ISC_LOG_ERROR,
14277 "unable to find key: %s", namebuf);
14278 }
14279 }
14280 if (key == NULL) {
14281 (void)dns_view_getpeertsig(zone->view, &masterip, &key);
14282 }
14283
14284 reqnsid = zone->view->requestnsid;
14285 if (zone->view->peers != NULL) {
14286 dns_peer_t *peer = NULL;
14287 bool edns;
14288 result = dns_peerlist_peerbyaddr(zone->view->peers, &masterip,
14289 &peer);
14290 if (result == ISC_R_SUCCESS) {
14291 result = dns_peer_getsupportedns(peer, &edns);
14292 if (result == ISC_R_SUCCESS && !edns) {
14293 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
14294 }
14295 result = dns_peer_gettransfersource(peer,
14296 &zone->sourceaddr);
14297 if (result == ISC_R_SUCCESS) {
14298 have_xfrsource = true;
14299 }
14300 result = dns_peer_gettransferdscp(peer, &dscp);
14301 if (result == ISC_R_SUCCESS && dscp != -1) {
14302 have_xfrdscp = true;
14303 }
14304 if (zone->view->resolver != NULL) {
14305 udpsize = dns_resolver_getudpsize(
14306 zone->view->resolver);
14307 }
14308 (void)dns_peer_getudpsize(peer, &udpsize);
14309 (void)dns_peer_getrequestnsid(peer, &reqnsid);
14310 }
14311 }
14312 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
14313 result = add_opt(message, udpsize, reqnsid, false);
14314 if (result != ISC_R_SUCCESS) {
14315 zone_debuglog(zone, me, 1,
14316 "unable to add opt record: %s",
14317 dns_result_totext(result));
14318 }
14319 }
14320
14321 /*
14322 * Always use TCP so that we shouldn't truncate in additional section.
14323 */
14324 switch (isc_sockaddr_pf(&zone->masteraddr)) {
14325 case PF_INET:
14326 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
14327 zone->sourceaddr = zone->altxfrsource4;
14328 if (!have_xfrdscp) {
14329 dscp = zone->altxfrsource4dscp;
14330 }
14331 } else if (!have_xfrsource) {
14332 zone->sourceaddr = zone->xfrsource4;
14333 if (!have_xfrdscp) {
14334 dscp = zone->xfrsource4dscp;
14335 }
14336 }
14337 break;
14338 case PF_INET6:
14339 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
14340 zone->sourceaddr = zone->altxfrsource6;
14341 if (!have_xfrdscp) {
14342 dscp = zone->altxfrsource6dscp;
14343 }
14344 } else if (!have_xfrsource) {
14345 zone->sourceaddr = zone->xfrsource6;
14346 if (!have_xfrdscp) {
14347 dscp = zone->xfrsource6dscp;
14348 }
14349 }
14350 break;
14351 default:
14352 result = ISC_R_NOTIMPLEMENTED;
14353 POST(result);
14354 goto cleanup;
14355 }
14356 timeout = 15;
14357 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH)) {
14358 timeout = 30;
14359 }
14360
14361 /* Save request parameters so we can reuse them later on
14362 for resolving missing glue A/AAAA records. */
14363 cb_args = isc_mem_get(zone->mctx, sizeof(*cb_args));
14364 cb_args->stub = stub;
14365 cb_args->tsig_key = key;
14366 cb_args->dscp = dscp;
14367 cb_args->udpsize = udpsize;
14368 cb_args->timeout = timeout;
14369 cb_args->reqnsid = reqnsid;
14370
14371 result = dns_request_createvia(
14372 zone->view->requestmgr, message, &zone->sourceaddr,
14373 &zone->masteraddr, dscp, DNS_REQUESTOPT_TCP, key, timeout * 3,
14374 timeout, 0, zone->task, stub_callback, cb_args, &zone->request);
14375 if (result != ISC_R_SUCCESS) {
14376 zone_debuglog(zone, me, 1, "dns_request_createvia() failed: %s",
14377 dns_result_totext(result));
14378 goto cleanup;
14379 }
14380 dns_message_detach(&message);
14381 goto unlock;
14382
14383 cleanup:
14384 cancel_refresh(zone);
14385 stub->magic = 0;
14386 if (stub->version != NULL) {
14387 dns_db_closeversion(stub->db, &stub->version, false);
14388 }
14389 if (stub->db != NULL) {
14390 dns_db_detach(&stub->db);
14391 }
14392 if (stub->zone != NULL) {
14393 zone_idetach(&stub->zone);
14394 }
14395 isc_mem_put(stub->mctx, stub, sizeof(*stub));
14396 if (message != NULL) {
14397 dns_message_detach(&message);
14398 }
14399 unlock:
14400 if (key != NULL) {
14401 dns_tsigkey_detach(&key);
14402 }
14403 return;
14404 }
14405
14406 /*
14407 * Handle the control event. Note that although this event causes the zone
14408 * to shut down, it is not a shutdown event in the sense of the task library.
14409 */
14410 static void
14411 zone_shutdown(isc_task_t *task, isc_event_t *event) {
14412 dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
14413 bool free_needed, linked = false;
14414 dns_zone_t *raw = NULL, *secure = NULL;
14415
14416 UNUSED(task);
14417 REQUIRE(DNS_ZONE_VALID(zone));
14418 INSIST(event->ev_type == DNS_EVENT_ZONECONTROL);
14419 INSIST(isc_refcount_current(&zone->erefs) == 0);
14420
14421 zone_debuglog(zone, "zone_shutdown", 3, "shutting down");
14422
14423 /*
14424 * Stop things being restarted after we cancel them below.
14425 */
14426 LOCK_ZONE(zone);
14427 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
14428 UNLOCK_ZONE(zone);
14429
14430 /*
14431 * If we were waiting for xfrin quota, step out of
14432 * the queue.
14433 * If there's no zone manager, we can't be waiting for the
14434 * xfrin quota
14435 */
14436 if (zone->zmgr != NULL) {
14437 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
14438 if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
14439 ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone,
14440 statelink);
14441 linked = true;
14442 zone->statelist = NULL;
14443 }
14444 if (zone->statelist == &zone->zmgr->xfrin_in_progress) {
14445 ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone,
14446 statelink);
14447 zone->statelist = NULL;
14448 zmgr_resume_xfrs(zone->zmgr, false);
14449 }
14450 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
14451 }
14452
14453 /*
14454 * In task context, no locking required. See zone_xfrdone().
14455 */
14456 if (zone->xfr != NULL) {
14457 dns_xfrin_shutdown(zone->xfr);
14458 }
14459
14460 /* Safe to release the zone now */
14461 if (zone->zmgr != NULL) {
14462 dns_zonemgr_releasezone(zone->zmgr, zone);
14463 }
14464
14465 LOCK_ZONE(zone);
14466 INSIST(zone != zone->raw);
14467 if (linked) {
14468 isc_refcount_decrement(&zone->irefs);
14469 }
14470 if (zone->request != NULL) {
14471 dns_request_cancel(zone->request);
14472 }
14473
14474 if (zone->readio != NULL) {
14475 zonemgr_cancelio(zone->readio);
14476 }
14477
14478 if (zone->lctx != NULL) {
14479 dns_loadctx_cancel(zone->lctx);
14480 }
14481
14482 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
14483 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
14484 {
14485 if (zone->writeio != NULL) {
14486 zonemgr_cancelio(zone->writeio);
14487 }
14488
14489 if (zone->dctx != NULL) {
14490 dns_dumpctx_cancel(zone->dctx);
14491 }
14492 }
14493
14494 notify_cancel(zone);
14495
14496 forward_cancel(zone);
14497
14498 if (zone->timer != NULL) {
14499 isc_timer_detach(&zone->timer);
14500 isc_refcount_decrement(&zone->irefs);
14501 }
14502
14503 /*
14504 * We have now canceled everything set the flag to allow exit_check()
14505 * to succeed. We must not unlock between setting this flag and
14506 * calling exit_check().
14507 */
14508 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN);
14509 free_needed = exit_check(zone);
14510 if (inline_secure(zone)) {
14511 raw = zone->raw;
14512 zone->raw = NULL;
14513 }
14514 if (inline_raw(zone)) {
14515 secure = zone->secure;
14516 zone->secure = NULL;
14517 }
14518 UNLOCK_ZONE(zone);
14519 if (raw != NULL) {
14520 dns_zone_detach(&raw);
14521 }
14522 if (secure != NULL) {
14523 dns_zone_idetach(&secure);
14524 }
14525 if (free_needed) {
14526 zone_free(zone);
14527 }
14528 }
14529
14530 static void
14531 zone_timer(isc_task_t *task, isc_event_t *event) {
14532 const char me[] = "zone_timer";
14533 dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
14534
14535 UNUSED(task);
14536 REQUIRE(DNS_ZONE_VALID(zone));
14537
14538 ENTER;
14539
14540 zone_maintenance(zone);
14541
14542 isc_event_free(&event);
14543 }
14544
14545 static void
14546 zone_settimer(dns_zone_t *zone, isc_time_t *now) {
14547 const char me[] = "zone_settimer";
14548 isc_time_t next;
14549 isc_result_t result;
14550
14551 REQUIRE(DNS_ZONE_VALID(zone));
14552 REQUIRE(LOCKED_ZONE(zone));
14553 ENTER;
14554
14555 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
14556 return;
14557 }
14558
14559 isc_time_settoepoch(&next);
14560
14561 switch (zone->type) {
14562 case dns_zone_redirect:
14563 if (zone->masters != NULL) {
14564 goto treat_as_slave;
14565 }
14566 /* FALLTHROUGH */
14567
14568 case dns_zone_master:
14569 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
14570 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))
14571 {
14572 next = zone->notifytime;
14573 }
14574 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
14575 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
14576 {
14577 INSIST(!isc_time_isepoch(&zone->dumptime));
14578 if (isc_time_isepoch(&next) ||
14579 isc_time_compare(&zone->dumptime, &next) < 0) {
14580 next = zone->dumptime;
14581 }
14582 }
14583 if (zone->type == dns_zone_redirect) {
14584 break;
14585 }
14586 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING) &&
14587 !isc_time_isepoch(&zone->refreshkeytime))
14588 {
14589 if (isc_time_isepoch(&next) ||
14590 isc_time_compare(&zone->refreshkeytime, &next) < 0)
14591 {
14592 next = zone->refreshkeytime;
14593 }
14594 }
14595 if (!isc_time_isepoch(&zone->resigntime)) {
14596 if (isc_time_isepoch(&next) ||
14597 isc_time_compare(&zone->resigntime, &next) < 0) {
14598 next = zone->resigntime;
14599 }
14600 }
14601 if (!isc_time_isepoch(&zone->keywarntime)) {
14602 if (isc_time_isepoch(&next) ||
14603 isc_time_compare(&zone->keywarntime, &next) < 0) {
14604 next = zone->keywarntime;
14605 }
14606 }
14607 if (!isc_time_isepoch(&zone->signingtime)) {
14608 if (isc_time_isepoch(&next) ||
14609 isc_time_compare(&zone->signingtime, &next) < 0) {
14610 next = zone->signingtime;
14611 }
14612 }
14613 if (!isc_time_isepoch(&zone->nsec3chaintime)) {
14614 if (isc_time_isepoch(&next) ||
14615 isc_time_compare(&zone->nsec3chaintime, &next) < 0)
14616 {
14617 next = zone->nsec3chaintime;
14618 }
14619 }
14620 break;
14621
14622 case dns_zone_slave:
14623 case dns_zone_mirror:
14624 treat_as_slave:
14625 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
14626 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))
14627 {
14628 next = zone->notifytime;
14629 }
14630 /* FALLTHROUGH */
14631
14632 case dns_zone_stub:
14633 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) &&
14634 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOMASTERS) &&
14635 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH) &&
14636 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING) &&
14637 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING) &&
14638 !isc_time_isepoch(&zone->refreshtime) &&
14639 (isc_time_isepoch(&next) ||
14640 isc_time_compare(&zone->refreshtime, &next) < 0))
14641 {
14642 next = zone->refreshtime;
14643 }
14644 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
14645 !isc_time_isepoch(&zone->expiretime))
14646 {
14647 if (isc_time_isepoch(&next) ||
14648 isc_time_compare(&zone->expiretime, &next) < 0) {
14649 next = zone->expiretime;
14650 }
14651 }
14652 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
14653 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
14654 {
14655 INSIST(!isc_time_isepoch(&zone->dumptime));
14656 if (isc_time_isepoch(&next) ||
14657 isc_time_compare(&zone->dumptime, &next) < 0) {
14658 next = zone->dumptime;
14659 }
14660 }
14661 break;
14662
14663 case dns_zone_key:
14664 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
14665 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
14666 {
14667 INSIST(!isc_time_isepoch(&zone->dumptime));
14668 if (isc_time_isepoch(&next) ||
14669 isc_time_compare(&zone->dumptime, &next) < 0) {
14670 next = zone->dumptime;
14671 }
14672 }
14673 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
14674 if (isc_time_isepoch(&next) ||
14675 (!isc_time_isepoch(&zone->refreshkeytime) &&
14676 isc_time_compare(&zone->refreshkeytime, &next) <
14677 0))
14678 {
14679 next = zone->refreshkeytime;
14680 }
14681 }
14682 break;
14683
14684 default:
14685 break;
14686 }
14687
14688 if (isc_time_isepoch(&next)) {
14689 zone_debuglog(zone, me, 10, "settimer inactive");
14690 result = isc_timer_reset(zone->timer, isc_timertype_inactive,
14691 NULL, NULL, true);
14692 if (result != ISC_R_SUCCESS) {
14693 dns_zone_log(zone, ISC_LOG_ERROR,
14694 "could not deactivate zone timer: %s",
14695 isc_result_totext(result));
14696 }
14697 } else {
14698 if (isc_time_compare(&next, now) <= 0) {
14699 next = *now;
14700 }
14701 result = isc_timer_reset(zone->timer, isc_timertype_once, &next,
14702 NULL, true);
14703 if (result != ISC_R_SUCCESS) {
14704 dns_zone_log(zone, ISC_LOG_ERROR,
14705 "could not reset zone timer: %s",
14706 isc_result_totext(result));
14707 }
14708 }
14709 }
14710
14711 static void
14712 cancel_refresh(dns_zone_t *zone) {
14713 const char me[] = "cancel_refresh";
14714 isc_time_t now;
14715
14716 /*
14717 * 'zone' locked by caller.
14718 */
14719
14720 REQUIRE(DNS_ZONE_VALID(zone));
14721 REQUIRE(LOCKED_ZONE(zone));
14722
14723 ENTER;
14724
14725 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
14726 TIME_NOW(&now);
14727 zone_settimer(zone, &now);
14728 }
14729
14730 static isc_result_t
14731 notify_createmessage(dns_zone_t *zone, unsigned int flags,
14732 dns_message_t **messagep) {
14733 dns_db_t *zonedb = NULL;
14734 dns_dbnode_t *node = NULL;
14735 dns_dbversion_t *version = NULL;
14736 dns_message_t *message = NULL;
14737 dns_rdataset_t rdataset;
14738 dns_rdata_t rdata = DNS_RDATA_INIT;
14739
14740 dns_name_t *tempname = NULL;
14741 dns_rdata_t *temprdata = NULL;
14742 dns_rdatalist_t *temprdatalist = NULL;
14743 dns_rdataset_t *temprdataset = NULL;
14744
14745 isc_result_t result;
14746 isc_region_t r;
14747 isc_buffer_t *b = NULL;
14748
14749 REQUIRE(DNS_ZONE_VALID(zone));
14750 REQUIRE(messagep != NULL && *messagep == NULL);
14751
14752 dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER, &message);
14753
14754 message->opcode = dns_opcode_notify;
14755 message->flags |= DNS_MESSAGEFLAG_AA;
14756 message->rdclass = zone->rdclass;
14757
14758 result = dns_message_gettempname(message, &tempname);
14759 if (result != ISC_R_SUCCESS) {
14760 goto cleanup;
14761 }
14762
14763 result = dns_message_gettemprdataset(message, &temprdataset);
14764 if (result != ISC_R_SUCCESS) {
14765 goto cleanup;
14766 }
14767
14768 /*
14769 * Make question.
14770 */
14771 dns_name_init(tempname, NULL);
14772 dns_name_clone(&zone->origin, tempname);
14773 dns_rdataset_makequestion(temprdataset, zone->rdclass,
14774 dns_rdatatype_soa);
14775 ISC_LIST_APPEND(tempname->list, temprdataset, link);
14776 dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
14777 tempname = NULL;
14778 temprdataset = NULL;
14779
14780 if ((flags & DNS_NOTIFY_NOSOA) != 0) {
14781 goto done;
14782 }
14783
14784 result = dns_message_gettempname(message, &tempname);
14785 if (result != ISC_R_SUCCESS) {
14786 goto soa_cleanup;
14787 }
14788 result = dns_message_gettemprdata(message, &temprdata);
14789 if (result != ISC_R_SUCCESS) {
14790 goto soa_cleanup;
14791 }
14792 result = dns_message_gettemprdataset(message, &temprdataset);
14793 if (result != ISC_R_SUCCESS) {
14794 goto soa_cleanup;
14795 }
14796 result = dns_message_gettemprdatalist(message, &temprdatalist);
14797 if (result != ISC_R_SUCCESS) {
14798 goto soa_cleanup;
14799 }
14800
14801 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
14802 INSIST(zone->db != NULL); /* XXXJT: is this assumption correct? */
14803 dns_db_attach(zone->db, &zonedb);
14804 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
14805
14806 dns_name_init(tempname, NULL);
14807 dns_name_clone(&zone->origin, tempname);
14808 dns_db_currentversion(zonedb, &version);
14809 result = dns_db_findnode(zonedb, tempname, false, &node);
14810 if (result != ISC_R_SUCCESS) {
14811 goto soa_cleanup;
14812 }
14813
14814 dns_rdataset_init(&rdataset);
14815 result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
14816 dns_rdatatype_none, 0, &rdataset, NULL);
14817 if (result != ISC_R_SUCCESS) {
14818 goto soa_cleanup;
14819 }
14820 result = dns_rdataset_first(&rdataset);
14821 if (result != ISC_R_SUCCESS) {
14822 goto soa_cleanup;
14823 }
14824 dns_rdataset_current(&rdataset, &rdata);
14825 dns_rdata_toregion(&rdata, &r);
14826 isc_buffer_allocate(zone->mctx, &b, r.length);
14827 isc_buffer_putmem(b, r.base, r.length);
14828 isc_buffer_usedregion(b, &r);
14829 dns_rdata_init(temprdata);
14830 dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r);
14831 dns_message_takebuffer(message, &b);
14832 result = dns_rdataset_next(&rdataset);
14833 dns_rdataset_disassociate(&rdataset);
14834 if (result != ISC_R_NOMORE) {
14835 goto soa_cleanup;
14836 }
14837 temprdatalist->rdclass = rdata.rdclass;
14838 temprdatalist->type = rdata.type;
14839 temprdatalist->ttl = rdataset.ttl;
14840 ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link);
14841
14842 result = dns_rdatalist_tordataset(temprdatalist, temprdataset);
14843 if (result != ISC_R_SUCCESS) {
14844 goto soa_cleanup;
14845 }
14846
14847 ISC_LIST_APPEND(tempname->list, temprdataset, link);
14848 dns_message_addname(message, tempname, DNS_SECTION_ANSWER);
14849 temprdatalist = NULL;
14850 temprdataset = NULL;
14851 temprdata = NULL;
14852 tempname = NULL;
14853
14854 soa_cleanup:
14855 if (node != NULL) {
14856 dns_db_detachnode(zonedb, &node);
14857 }
14858 if (version != NULL) {
14859 dns_db_closeversion(zonedb, &version, false);
14860 }
14861 if (zonedb != NULL) {
14862 dns_db_detach(&zonedb);
14863 }
14864 if (tempname != NULL) {
14865 dns_message_puttempname(message, &tempname);
14866 }
14867 if (temprdata != NULL) {
14868 dns_message_puttemprdata(message, &temprdata);
14869 }
14870 if (temprdataset != NULL) {
14871 dns_message_puttemprdataset(message, &temprdataset);
14872 }
14873 if (temprdatalist != NULL) {
14874 dns_message_puttemprdatalist(message, &temprdatalist);
14875 }
14876
14877 done:
14878 *messagep = message;
14879 return (ISC_R_SUCCESS);
14880
14881 cleanup:
14882 if (tempname != NULL) {
14883 dns_message_puttempname(message, &tempname);
14884 }
14885 if (temprdataset != NULL) {
14886 dns_message_puttemprdataset(message, &temprdataset);
14887 }
14888 dns_message_detach(&message);
14889 return (result);
14890 }
14891
14892 isc_result_t
14893 dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
14894 isc_sockaddr_t *to, dns_message_t *msg) {
14895 unsigned int i;
14896 dns_rdata_soa_t soa;
14897 dns_rdataset_t *rdataset = NULL;
14898 dns_rdata_t rdata = DNS_RDATA_INIT;
14899 isc_result_t result;
14900 char fromtext[ISC_SOCKADDR_FORMATSIZE];
14901 int match = 0;
14902 isc_netaddr_t netaddr;
14903 uint32_t serial = 0;
14904 bool have_serial = false;
14905 dns_tsigkey_t *tsigkey;
14906 const dns_name_t *tsig;
14907
14908 REQUIRE(DNS_ZONE_VALID(zone));
14909
14910 /*
14911 * If type != T_SOA return DNS_R_NOTIMP. We don't yet support
14912 * ROLLOVER.
14913 *
14914 * SOA: RFC1996
14915 * Check that 'from' is a valid notify source, (zone->masters).
14916 * Return DNS_R_REFUSED if not.
14917 *
14918 * If the notify message contains a serial number check it
14919 * against the zones serial and return if <= current serial
14920 *
14921 * If a refresh check is progress, if so just record the
14922 * fact we received a NOTIFY and from where and return.
14923 * We will perform a new refresh check when the current one
14924 * completes. Return ISC_R_SUCCESS.
14925 *
14926 * Otherwise initiate a refresh check using 'from' as the
14927 * first address to check. Return ISC_R_SUCCESS.
14928 */
14929
14930 isc_sockaddr_format(from, fromtext, sizeof(fromtext));
14931
14932 /*
14933 * Notify messages are processed by the raw zone.
14934 */
14935 LOCK_ZONE(zone);
14936 INSIST(zone != zone->raw);
14937 if (inline_secure(zone)) {
14938 result = dns_zone_notifyreceive(zone->raw, from, to, msg);
14939 UNLOCK_ZONE(zone);
14940 return (result);
14941 }
14942 /*
14943 * We only handle NOTIFY (SOA) at the present.
14944 */
14945 if (isc_sockaddr_pf(from) == PF_INET) {
14946 inc_stats(zone, dns_zonestatscounter_notifyinv4);
14947 } else {
14948 inc_stats(zone, dns_zonestatscounter_notifyinv6);
14949 }
14950 if (msg->counts[DNS_SECTION_QUESTION] == 0 ||
14951 dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin,
14952 dns_rdatatype_soa, dns_rdatatype_none, NULL,
14953 NULL) != ISC_R_SUCCESS)
14954 {
14955 UNLOCK_ZONE(zone);
14956 if (msg->counts[DNS_SECTION_QUESTION] == 0) {
14957 dns_zone_log(zone, ISC_LOG_NOTICE,
14958 "NOTIFY with no "
14959 "question section from: %s",
14960 fromtext);
14961 return (DNS_R_FORMERR);
14962 }
14963 dns_zone_log(zone, ISC_LOG_NOTICE,
14964 "NOTIFY zone does not match");
14965 return (DNS_R_NOTIMP);
14966 }
14967
14968 /*
14969 * If we are a master zone just succeed.
14970 */
14971 if (zone->type == dns_zone_master) {
14972 UNLOCK_ZONE(zone);
14973 return (ISC_R_SUCCESS);
14974 }
14975
14976 isc_netaddr_fromsockaddr(&netaddr, from);
14977 for (i = 0; i < zone->masterscnt; i++) {
14978 if (isc_sockaddr_eqaddr(from, &zone->masters[i])) {
14979 break;
14980 }
14981 if (zone->view->aclenv.match_mapped &&
14982 IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) &&
14983 isc_sockaddr_pf(&zone->masters[i]) == AF_INET)
14984 {
14985 isc_netaddr_t na1, na2;
14986 isc_netaddr_fromv4mapped(&na1, &netaddr);
14987 isc_netaddr_fromsockaddr(&na2, &zone->masters[i]);
14988 if (isc_netaddr_equal(&na1, &na2)) {
14989 break;
14990 }
14991 }
14992 }
14993
14994 /*
14995 * Accept notify requests from non masters if they are on
14996 * 'zone->notify_acl'.
14997 */
14998 tsigkey = dns_message_gettsigkey(msg);
14999 tsig = dns_tsigkey_identity(tsigkey);
15000 if (i >= zone->masterscnt && zone->notify_acl != NULL &&
15001 (dns_acl_match(&netaddr, tsig, zone->notify_acl,
15002 &zone->view->aclenv, &match,
15003 NULL) == ISC_R_SUCCESS) &&
15004 match > 0)
15005 {
15006 /* Accept notify. */
15007 } else if (i >= zone->masterscnt) {
15008 UNLOCK_ZONE(zone);
15009 dns_zone_log(zone, ISC_LOG_INFO,
15010 "refused notify from non-master: %s", fromtext);
15011 inc_stats(zone, dns_zonestatscounter_notifyrej);
15012 return (DNS_R_REFUSED);
15013 }
15014
15015 /*
15016 * If the zone is loaded and there are answers check the serial
15017 * to see if we need to do a refresh. Do not worry about this
15018 * check if we are a dialup zone as we use the notify request
15019 * to trigger a refresh check.
15020 */
15021 if (msg->counts[DNS_SECTION_ANSWER] > 0 &&
15022 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
15023 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH))
15024 {
15025 result = dns_message_findname(
15026 msg, DNS_SECTION_ANSWER, &zone->origin,
15027 dns_rdatatype_soa, dns_rdatatype_none, NULL, &rdataset);
15028 if (result == ISC_R_SUCCESS) {
15029 result = dns_rdataset_first(rdataset);
15030 }
15031 if (result == ISC_R_SUCCESS) {
15032 uint32_t oldserial;
15033 unsigned int soacount;
15034
15035 dns_rdataset_current(rdataset, &rdata);
15036 result = dns_rdata_tostruct(&rdata, &soa, NULL);
15037 RUNTIME_CHECK(result == ISC_R_SUCCESS);
15038 serial = soa.serial;
15039 have_serial = true;
15040 /*
15041 * The following should safely be performed without DB
15042 * lock and succeed in this context.
15043 */
15044 result = zone_get_from_db(zone, zone->db, NULL,
15045 &soacount, &oldserial, NULL,
15046 NULL, NULL, NULL, NULL);
15047 RUNTIME_CHECK(result == ISC_R_SUCCESS);
15048 RUNTIME_CHECK(soacount > 0U);
15049 if (isc_serial_le(serial, oldserial)) {
15050 dns_zone_log(zone, ISC_LOG_INFO,
15051 "notify from %s: "
15052 "zone is up to date",
15053 fromtext);
15054 UNLOCK_ZONE(zone);
15055 return (ISC_R_SUCCESS);
15056 }
15057 }
15058 }
15059
15060 /*
15061 * If we got this far and there was a refresh in progress just
15062 * let it complete. Record where we got the notify from so we
15063 * can perform a refresh check when the current one completes
15064 */
15065 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
15066 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
15067 zone->notifyfrom = *from;
15068 UNLOCK_ZONE(zone);
15069 if (have_serial) {
15070 dns_zone_log(zone, ISC_LOG_INFO,
15071 "notify from %s: serial %u: refresh in "
15072 "progress, refresh check queued",
15073 fromtext, serial);
15074 } else {
15075 dns_zone_log(zone, ISC_LOG_INFO,
15076 "notify from %s: refresh in progress, "
15077 "refresh check queued",
15078 fromtext);
15079 }
15080 return (ISC_R_SUCCESS);
15081 }
15082 if (have_serial) {
15083 dns_zone_log(zone, ISC_LOG_INFO, "notify from %s: serial %u",
15084 fromtext, serial);
15085 } else {
15086 dns_zone_log(zone, ISC_LOG_INFO, "notify from %s: no serial",
15087 fromtext);
15088 }
15089 zone->notifyfrom = *from;
15090 UNLOCK_ZONE(zone);
15091
15092 if (to != NULL) {
15093 dns_zonemgr_unreachabledel(zone->zmgr, from, to);
15094 }
15095 dns_zone_refresh(zone);
15096 return (ISC_R_SUCCESS);
15097 }
15098
15099 void
15100 dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
15101 REQUIRE(DNS_ZONE_VALID(zone));
15102
15103 LOCK_ZONE(zone);
15104 if (zone->notify_acl != NULL) {
15105 dns_acl_detach(&zone->notify_acl);
15106 }
15107 dns_acl_attach(acl, &zone->notify_acl);
15108 UNLOCK_ZONE(zone);
15109 }
15110
15111 void
15112 dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
15113 REQUIRE(DNS_ZONE_VALID(zone));
15114
15115 LOCK_ZONE(zone);
15116 if (zone->query_acl != NULL) {
15117 dns_acl_detach(&zone->query_acl);
15118 }
15119 dns_acl_attach(acl, &zone->query_acl);
15120 UNLOCK_ZONE(zone);
15121 }
15122
15123 void
15124 dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl) {
15125 REQUIRE(DNS_ZONE_VALID(zone));
15126
15127 LOCK_ZONE(zone);
15128 if (zone->queryon_acl != NULL) {
15129 dns_acl_detach(&zone->queryon_acl);
15130 }
15131 dns_acl_attach(acl, &zone->queryon_acl);
15132 UNLOCK_ZONE(zone);
15133 }
15134
15135 void
15136 dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
15137 REQUIRE(DNS_ZONE_VALID(zone));
15138
15139 LOCK_ZONE(zone);
15140 if (zone->update_acl != NULL) {
15141 dns_acl_detach(&zone->update_acl);
15142 }
15143 dns_acl_attach(acl, &zone->update_acl);
15144 UNLOCK_ZONE(zone);
15145 }
15146
15147 void
15148 dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
15149 REQUIRE(DNS_ZONE_VALID(zone));
15150
15151 LOCK_ZONE(zone);
15152 if (zone->forward_acl != NULL) {
15153 dns_acl_detach(&zone->forward_acl);
15154 }
15155 dns_acl_attach(acl, &zone->forward_acl);
15156 UNLOCK_ZONE(zone);
15157 }
15158
15159 void
15160 dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
15161 REQUIRE(DNS_ZONE_VALID(zone));
15162
15163 LOCK_ZONE(zone);
15164 if (zone->xfr_acl != NULL) {
15165 dns_acl_detach(&zone->xfr_acl);
15166 }
15167 dns_acl_attach(acl, &zone->xfr_acl);
15168 UNLOCK_ZONE(zone);
15169 }
15170
15171 dns_acl_t *
15172 dns_zone_getnotifyacl(dns_zone_t *zone) {
15173 REQUIRE(DNS_ZONE_VALID(zone));
15174
15175 return (zone->notify_acl);
15176 }
15177
15178 dns_acl_t *
15179 dns_zone_getqueryacl(dns_zone_t *zone) {
15180 REQUIRE(DNS_ZONE_VALID(zone));
15181
15182 return (zone->query_acl);
15183 }
15184
15185 dns_acl_t *
15186 dns_zone_getqueryonacl(dns_zone_t *zone) {
15187 REQUIRE(DNS_ZONE_VALID(zone));
15188
15189 return (zone->queryon_acl);
15190 }
15191
15192 dns_acl_t *
15193 dns_zone_getupdateacl(dns_zone_t *zone) {
15194 REQUIRE(DNS_ZONE_VALID(zone));
15195
15196 return (zone->update_acl);
15197 }
15198
15199 dns_acl_t *
15200 dns_zone_getforwardacl(dns_zone_t *zone) {
15201 REQUIRE(DNS_ZONE_VALID(zone));
15202
15203 return (zone->forward_acl);
15204 }
15205
15206 dns_acl_t *
15207 dns_zone_getxfracl(dns_zone_t *zone) {
15208 REQUIRE(DNS_ZONE_VALID(zone));
15209
15210 return (zone->xfr_acl);
15211 }
15212
15213 void
15214 dns_zone_clearupdateacl(dns_zone_t *zone) {
15215 REQUIRE(DNS_ZONE_VALID(zone));
15216
15217 LOCK_ZONE(zone);
15218 if (zone->update_acl != NULL) {
15219 dns_acl_detach(&zone->update_acl);
15220 }
15221 UNLOCK_ZONE(zone);
15222 }
15223
15224 void
15225 dns_zone_clearforwardacl(dns_zone_t *zone) {
15226 REQUIRE(DNS_ZONE_VALID(zone));
15227
15228 LOCK_ZONE(zone);
15229 if (zone->forward_acl != NULL) {
15230 dns_acl_detach(&zone->forward_acl);
15231 }
15232 UNLOCK_ZONE(zone);
15233 }
15234
15235 void
15236 dns_zone_clearnotifyacl(dns_zone_t *zone) {
15237 REQUIRE(DNS_ZONE_VALID(zone));
15238
15239 LOCK_ZONE(zone);
15240 if (zone->notify_acl != NULL) {
15241 dns_acl_detach(&zone->notify_acl);
15242 }
15243 UNLOCK_ZONE(zone);
15244 }
15245
15246 void
15247 dns_zone_clearqueryacl(dns_zone_t *zone) {
15248 REQUIRE(DNS_ZONE_VALID(zone));
15249
15250 LOCK_ZONE(zone);
15251 if (zone->query_acl != NULL) {
15252 dns_acl_detach(&zone->query_acl);
15253 }
15254 UNLOCK_ZONE(zone);
15255 }
15256
15257 void
15258 dns_zone_clearqueryonacl(dns_zone_t *zone) {
15259 REQUIRE(DNS_ZONE_VALID(zone));
15260
15261 LOCK_ZONE(zone);
15262 if (zone->queryon_acl != NULL) {
15263 dns_acl_detach(&zone->queryon_acl);
15264 }
15265 UNLOCK_ZONE(zone);
15266 }
15267
15268 void
15269 dns_zone_clearxfracl(dns_zone_t *zone) {
15270 REQUIRE(DNS_ZONE_VALID(zone));
15271
15272 LOCK_ZONE(zone);
15273 if (zone->xfr_acl != NULL) {
15274 dns_acl_detach(&zone->xfr_acl);
15275 }
15276 UNLOCK_ZONE(zone);
15277 }
15278
15279 bool
15280 dns_zone_getupdatedisabled(dns_zone_t *zone) {
15281 REQUIRE(DNS_ZONE_VALID(zone));
15282 return (zone->update_disabled);
15283 }
15284
15285 void
15286 dns_zone_setupdatedisabled(dns_zone_t *zone, bool state) {
15287 REQUIRE(DNS_ZONE_VALID(zone));
15288 zone->update_disabled = state;
15289 }
15290
15291 bool
15292 dns_zone_getzeronosoattl(dns_zone_t *zone) {
15293 REQUIRE(DNS_ZONE_VALID(zone));
15294 return (zone->zero_no_soa_ttl);
15295 }
15296
15297 void
15298 dns_zone_setzeronosoattl(dns_zone_t *zone, bool state) {
15299 REQUIRE(DNS_ZONE_VALID(zone));
15300 zone->zero_no_soa_ttl = state;
15301 }
15302
15303 void
15304 dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
15305 REQUIRE(DNS_ZONE_VALID(zone));
15306
15307 zone->check_names = severity;
15308 }
15309
15310 dns_severity_t
15311 dns_zone_getchecknames(dns_zone_t *zone) {
15312 REQUIRE(DNS_ZONE_VALID(zone));
15313
15314 return (zone->check_names);
15315 }
15316
15317 void
15318 dns_zone_setjournalsize(dns_zone_t *zone, int32_t size) {
15319 REQUIRE(DNS_ZONE_VALID(zone));
15320
15321 zone->journalsize = size;
15322 }
15323
15324 int32_t
15325 dns_zone_getjournalsize(dns_zone_t *zone) {
15326 REQUIRE(DNS_ZONE_VALID(zone));
15327
15328 return (zone->journalsize);
15329 }
15330
15331 static void
15332 zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) {
15333 isc_result_t result = ISC_R_FAILURE;
15334 isc_buffer_t buffer;
15335
15336 REQUIRE(buf != NULL);
15337 REQUIRE(length > 1U);
15338
15339 /*
15340 * Leave space for terminating '\0'.
15341 */
15342 isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
15343 if (zone->type != dns_zone_redirect && zone->type != dns_zone_key) {
15344 if (dns_name_dynamic(&zone->origin)) {
15345 result = dns_name_totext(&zone->origin, true, &buffer);
15346 }
15347 if (result != ISC_R_SUCCESS &&
15348 isc_buffer_availablelength(&buffer) >=
15349 (sizeof("<UNKNOWN>") - 1))
15350 {
15351 isc_buffer_putstr(&buffer, "<UNKNOWN>");
15352 }
15353
15354 if (isc_buffer_availablelength(&buffer) > 0) {
15355 isc_buffer_putstr(&buffer, "/");
15356 }
15357 (void)dns_rdataclass_totext(zone->rdclass, &buffer);
15358 }
15359
15360 if (zone->view != NULL && strcmp(zone->view->name, "_bind") != 0 &&
15361 strcmp(zone->view->name, "_default") != 0 &&
15362 strlen(zone->view->name) < isc_buffer_availablelength(&buffer))
15363 {
15364 isc_buffer_putstr(&buffer, "/");
15365 isc_buffer_putstr(&buffer, zone->view->name);
15366 }
15367 if (inline_secure(zone) && 9U < isc_buffer_availablelength(&buffer)) {
15368 isc_buffer_putstr(&buffer, " (signed)");
15369 }
15370 if (inline_raw(zone) && 11U < isc_buffer_availablelength(&buffer)) {
15371 isc_buffer_putstr(&buffer, " (unsigned)");
15372 }
15373
15374 buf[isc_buffer_usedlength(&buffer)] = '\0';
15375 }
15376
15377 static void
15378 zone_name_tostr(dns_zone_t *zone, char *buf, size_t length) {
15379 isc_result_t result = ISC_R_FAILURE;
15380 isc_buffer_t buffer;
15381
15382 REQUIRE(buf != NULL);
15383 REQUIRE(length > 1U);
15384
15385 /*
15386 * Leave space for terminating '\0'.
15387 */
15388 isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
15389 if (dns_name_dynamic(&zone->origin)) {
15390 result = dns_name_totext(&zone->origin, true, &buffer);
15391 }
15392 if (result != ISC_R_SUCCESS &&
15393 isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
15394 {
15395 isc_buffer_putstr(&buffer, "<UNKNOWN>");
15396 }
15397
15398 buf[isc_buffer_usedlength(&buffer)] = '\0';
15399 }
15400
15401 static void
15402 zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length) {
15403 isc_buffer_t buffer;
15404
15405 REQUIRE(buf != NULL);
15406 REQUIRE(length > 1U);
15407
15408 /*
15409 * Leave space for terminating '\0'.
15410 */
15411 isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
15412 (void)dns_rdataclass_totext(zone->rdclass, &buffer);
15413
15414 buf[isc_buffer_usedlength(&buffer)] = '\0';
15415 }
15416
15417 static void
15418 zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length) {
15419 isc_buffer_t buffer;
15420
15421 REQUIRE(buf != NULL);
15422 REQUIRE(length > 1U);
15423
15424 /*
15425 * Leave space for terminating '\0'.
15426 */
15427 isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
15428
15429 if (zone->view == NULL) {
15430 isc_buffer_putstr(&buffer, "_none");
15431 } else if (strlen(zone->view->name) <
15432 isc_buffer_availablelength(&buffer)) {
15433 isc_buffer_putstr(&buffer, zone->view->name);
15434 } else {
15435 isc_buffer_putstr(&buffer, "_toolong");
15436 }
15437
15438 buf[isc_buffer_usedlength(&buffer)] = '\0';
15439 }
15440
15441 void
15442 dns_zone_name(dns_zone_t *zone, char *buf, size_t length) {
15443 REQUIRE(DNS_ZONE_VALID(zone));
15444 REQUIRE(buf != NULL);
15445
15446 LOCK_ZONE(zone);
15447 zone_namerd_tostr(zone, buf, length);
15448 UNLOCK_ZONE(zone);
15449 }
15450
15451 void
15452 dns_zone_nameonly(dns_zone_t *zone, char *buf, size_t length) {
15453 REQUIRE(DNS_ZONE_VALID(zone));
15454 REQUIRE(buf != NULL);
15455 zone_name_tostr(zone, buf, length);
15456 }
15457
15458 void
15459 dns_zone_logv(dns_zone_t *zone, isc_logcategory_t *category, int level,
15460 const char *prefix, const char *fmt, va_list ap) {
15461 char message[4096];
15462 const char *zstr;
15463
15464 REQUIRE(DNS_ZONE_VALID(zone));
15465
15466 if (!isc_log_wouldlog(dns_lctx, level)) {
15467 return;
15468 }
15469
15470 vsnprintf(message, sizeof(message), fmt, ap);
15471
15472 switch (zone->type) {
15473 case dns_zone_key:
15474 zstr = "managed-keys-zone";
15475 break;
15476 case dns_zone_redirect:
15477 zstr = "redirect-zone";
15478 break;
15479 default:
15480 zstr = "zone ";
15481 }
15482
15483 isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE, level,
15484 "%s%s%s%s: %s", (prefix != NULL ? prefix : ""),
15485 (prefix != NULL ? ": " : ""), zstr, zone->strnamerd,
15486 message);
15487 }
15488
15489 static void
15490 notify_log(dns_zone_t *zone, int level, const char *fmt, ...) {
15491 va_list ap;
15492
15493 va_start(ap, fmt);
15494 dns_zone_logv(zone, DNS_LOGCATEGORY_NOTIFY, level, NULL, fmt, ap);
15495 va_end(ap);
15496 }
15497
15498 void
15499 dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category, int level,
15500 const char *fmt, ...) {
15501 va_list ap;
15502
15503 va_start(ap, fmt);
15504 dns_zone_logv(zone, category, level, NULL, fmt, ap);
15505 va_end(ap);
15506 }
15507
15508 void
15509 dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) {
15510 va_list ap;
15511
15512 va_start(ap, fmt);
15513 dns_zone_logv(zone, DNS_LOGCATEGORY_GENERAL, level, NULL, fmt, ap);
15514 va_end(ap);
15515 }
15516
15517 static void
15518 zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel, const char *fmt,
15519 ...) {
15520 int level = ISC_LOG_DEBUG(debuglevel);
15521 va_list ap;
15522
15523 va_start(ap, fmt);
15524 dns_zone_logv(zone, DNS_LOGCATEGORY_GENERAL, level, me, fmt, ap);
15525 va_end(ap);
15526 }
15527
15528 static void
15529 dnssec_log(dns_zone_t *zone, int level, const char *fmt, ...) {
15530 va_list ap;
15531
15532 va_start(ap, fmt);
15533 dns_zone_logv(zone, DNS_LOGCATEGORY_DNSSEC, level, NULL, fmt, ap);
15534 va_end(ap);
15535 }
15536
15537 static int
15538 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type) {
15539 isc_result_t result;
15540 dns_name_t *name;
15541 dns_rdataset_t *curr;
15542 int count = 0;
15543
15544 result = dns_message_firstname(msg, section);
15545 while (result == ISC_R_SUCCESS) {
15546 name = NULL;
15547 dns_message_currentname(msg, section, &name);
15548
15549 for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
15550 curr = ISC_LIST_PREV(curr, link))
15551 {
15552 if (curr->type == type) {
15553 count++;
15554 }
15555 }
15556 result = dns_message_nextname(msg, section);
15557 }
15558
15559 return (count);
15560 }
15561
15562 void
15563 dns_zone_setmaxxfrin(dns_zone_t *zone, uint32_t maxxfrin) {
15564 REQUIRE(DNS_ZONE_VALID(zone));
15565
15566 zone->maxxfrin = maxxfrin;
15567 }
15568
15569 uint32_t
15570 dns_zone_getmaxxfrin(dns_zone_t *zone) {
15571 REQUIRE(DNS_ZONE_VALID(zone));
15572
15573 return (zone->maxxfrin);
15574 }
15575
15576 void
15577 dns_zone_setmaxxfrout(dns_zone_t *zone, uint32_t maxxfrout) {
15578 REQUIRE(DNS_ZONE_VALID(zone));
15579 zone->maxxfrout = maxxfrout;
15580 }
15581
15582 uint32_t
15583 dns_zone_getmaxxfrout(dns_zone_t *zone) {
15584 REQUIRE(DNS_ZONE_VALID(zone));
15585
15586 return (zone->maxxfrout);
15587 }
15588
15589 dns_zonetype_t
15590 dns_zone_gettype(dns_zone_t *zone) {
15591 REQUIRE(DNS_ZONE_VALID(zone));
15592
15593 return (zone->type);
15594 }
15595
15596 const char *
15597 dns_zonetype_name(dns_zonetype_t type) {
15598 switch (type) {
15599 case dns_zone_none:
15600 return ("none");
15601 case dns_zone_master:
15602 return ("primary");
15603 case dns_zone_slave:
15604 return ("secondary");
15605 case dns_zone_mirror:
15606 return ("mirror");
15607 case dns_zone_stub:
15608 return ("stub");
15609 case dns_zone_staticstub:
15610 return ("static-stub");
15611 case dns_zone_key:
15612 return ("key");
15613 case dns_zone_dlz:
15614 return ("dlz");
15615 case dns_zone_redirect:
15616 return ("redirect");
15617 default:
15618 return ("unknown");
15619 }
15620 }
15621
15622 dns_zonetype_t
15623 dns_zone_getredirecttype(dns_zone_t *zone) {
15624 REQUIRE(DNS_ZONE_VALID(zone));
15625 REQUIRE(zone->type == dns_zone_redirect);
15626
15627 return (zone->masters == NULL ? dns_zone_master : dns_zone_slave);
15628 }
15629
15630 dns_name_t *
15631 dns_zone_getorigin(dns_zone_t *zone) {
15632 REQUIRE(DNS_ZONE_VALID(zone));
15633
15634 return (&zone->origin);
15635 }
15636
15637 void
15638 dns_zone_settask(dns_zone_t *zone, isc_task_t *task) {
15639 REQUIRE(DNS_ZONE_VALID(zone));
15640
15641 LOCK_ZONE(zone);
15642 if (zone->task != NULL) {
15643 isc_task_detach(&zone->task);
15644 }
15645 isc_task_attach(task, &zone->task);
15646 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
15647 if (zone->db != NULL) {
15648 dns_db_settask(zone->db, zone->task);
15649 }
15650 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
15651 UNLOCK_ZONE(zone);
15652 }
15653
15654 void
15655 dns_zone_gettask(dns_zone_t *zone, isc_task_t **target) {
15656 REQUIRE(DNS_ZONE_VALID(zone));
15657 isc_task_attach(zone->task, target);
15658 }
15659
15660 void
15661 dns_zone_setidlein(dns_zone_t *zone, uint32_t idlein) {
15662 REQUIRE(DNS_ZONE_VALID(zone));
15663
15664 if (idlein == 0) {
15665 idlein = DNS_DEFAULT_IDLEIN;
15666 }
15667 zone->idlein = idlein;
15668 }
15669
15670 uint32_t
15671 dns_zone_getidlein(dns_zone_t *zone) {
15672 REQUIRE(DNS_ZONE_VALID(zone));
15673
15674 return (zone->idlein);
15675 }
15676
15677 void
15678 dns_zone_setidleout(dns_zone_t *zone, uint32_t idleout) {
15679 REQUIRE(DNS_ZONE_VALID(zone));
15680
15681 zone->idleout = idleout;
15682 }
15683
15684 uint32_t
15685 dns_zone_getidleout(dns_zone_t *zone) {
15686 REQUIRE(DNS_ZONE_VALID(zone));
15687
15688 return (zone->idleout);
15689 }
15690
15691 static void
15692 notify_done(isc_task_t *task, isc_event_t *event) {
15693 dns_requestevent_t *revent = (dns_requestevent_t *)event;
15694 dns_notify_t *notify;
15695 isc_result_t result;
15696 dns_message_t *message = NULL;
15697 isc_buffer_t buf;
15698 char rcode[128];
15699 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
15700
15701 UNUSED(task);
15702
15703 notify = event->ev_arg;
15704 REQUIRE(DNS_NOTIFY_VALID(notify));
15705 INSIST(task == notify->zone->task);
15706
15707 isc_buffer_init(&buf, rcode, sizeof(rcode));
15708 isc_sockaddr_format(¬ify->dst, addrbuf, sizeof(addrbuf));
15709 dns_message_create(notify->zone->mctx, DNS_MESSAGE_INTENTPARSE,
15710 &message);
15711
15712 result = revent->result;
15713 if (result == ISC_R_SUCCESS) {
15714 result =
15715 dns_request_getresponse(revent->request, message,
15716 DNS_MESSAGEPARSE_PRESERVEORDER);
15717 }
15718 if (result == ISC_R_SUCCESS) {
15719 result = dns_rcode_totext(message->rcode, &buf);
15720 }
15721 if (result == ISC_R_SUCCESS) {
15722 notify_log(notify->zone, ISC_LOG_DEBUG(3),
15723 "notify response from %s: %.*s", addrbuf,
15724 (int)buf.used, rcode);
15725 } else {
15726 notify_log(notify->zone, ISC_LOG_DEBUG(2),
15727 "notify to %s failed: %s", addrbuf,
15728 dns_result_totext(result));
15729 }
15730
15731 /*
15732 * Old bind's return formerr if they see a soa record. Retry w/o
15733 * the soa if we see a formerr and had sent a SOA.
15734 */
15735 isc_event_free(&event);
15736 if (message->rcode == dns_rcode_formerr &&
15737 (notify->flags & DNS_NOTIFY_NOSOA) == 0)
15738 {
15739 bool startup;
15740
15741 notify->flags |= DNS_NOTIFY_NOSOA;
15742 dns_request_destroy(¬ify->request);
15743 startup = (notify->flags & DNS_NOTIFY_STARTUP);
15744 result = notify_send_queue(notify, startup);
15745 if (result != ISC_R_SUCCESS) {
15746 notify_destroy(notify, false);
15747 }
15748 } else {
15749 if (result == ISC_R_TIMEDOUT) {
15750 notify_log(notify->zone, ISC_LOG_DEBUG(1),
15751 "notify to %s: retries exceeded", addrbuf);
15752 }
15753 notify_destroy(notify, false);
15754 }
15755 dns_message_detach(&message);
15756 }
15757
15758 struct secure_event {
15759 isc_event_t e;
15760 dns_db_t *db;
15761 uint32_t serial;
15762 };
15763
15764 static void
15765 update_log_cb(void *arg, dns_zone_t *zone, int level, const char *message) {
15766 UNUSED(arg);
15767 dns_zone_log(zone, level, "%s", message);
15768 }
15769
15770 static isc_result_t
15771 sync_secure_journal(dns_zone_t *zone, dns_zone_t *raw, dns_journal_t *journal,
15772 uint32_t start, uint32_t end, dns_difftuple_t **soatuplep,
15773 dns_diff_t *diff) {
15774 isc_result_t result;
15775 dns_difftuple_t *tuple = NULL;
15776 dns_diffop_t op = DNS_DIFFOP_ADD;
15777 int n_soa = 0;
15778
15779 REQUIRE(soatuplep != NULL);
15780
15781 if (start == end) {
15782 return (DNS_R_UNCHANGED);
15783 }
15784
15785 CHECK(dns_journal_iter_init(journal, start, end, NULL));
15786 for (result = dns_journal_first_rr(journal); result == ISC_R_SUCCESS;
15787 result = dns_journal_next_rr(journal))
15788 {
15789 dns_name_t *name = NULL;
15790 uint32_t ttl;
15791 dns_rdata_t *rdata = NULL;
15792 dns_journal_current_rr(journal, &name, &ttl, &rdata);
15793
15794 if (rdata->type == dns_rdatatype_soa) {
15795 n_soa++;
15796 if (n_soa == 2) {
15797 /*
15798 * Save the latest raw SOA record.
15799 */
15800 if (*soatuplep != NULL) {
15801 dns_difftuple_free(soatuplep);
15802 }
15803 CHECK(dns_difftuple_create(
15804 diff->mctx, DNS_DIFFOP_ADD, name, ttl,
15805 rdata, soatuplep));
15806 }
15807 if (n_soa == 3) {
15808 n_soa = 1;
15809 }
15810 continue;
15811 }
15812
15813 /* Sanity. */
15814 if (n_soa == 0) {
15815 dns_zone_log(raw, ISC_LOG_ERROR,
15816 "corrupt journal file: '%s'\n",
15817 raw->journal);
15818 return (ISC_R_FAILURE);
15819 }
15820
15821 if (zone->privatetype != 0 && rdata->type == zone->privatetype)
15822 {
15823 continue;
15824 }
15825
15826 if (rdata->type == dns_rdatatype_nsec ||
15827 rdata->type == dns_rdatatype_rrsig ||
15828 rdata->type == dns_rdatatype_nsec3 ||
15829 rdata->type == dns_rdatatype_dnskey ||
15830 rdata->type == dns_rdatatype_nsec3param)
15831 {
15832 continue;
15833 }
15834
15835 op = (n_soa == 1) ? DNS_DIFFOP_DEL : DNS_DIFFOP_ADD;
15836
15837 CHECK(dns_difftuple_create(diff->mctx, op, name, ttl, rdata,
15838 &tuple));
15839 dns_diff_appendminimal(diff, &tuple);
15840 }
15841 if (result == ISC_R_NOMORE) {
15842 result = ISC_R_SUCCESS;
15843 }
15844
15845 failure:
15846 return (result);
15847 }
15848
15849 static isc_result_t
15850 sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb,
15851 dns_dbversion_t *secver, dns_difftuple_t **soatuple,
15852 dns_diff_t *diff) {
15853 isc_result_t result;
15854 dns_db_t *rawdb = NULL;
15855 dns_dbversion_t *rawver = NULL;
15856 dns_difftuple_t *tuple = NULL, *next;
15857 dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
15858 dns_rdata_soa_t oldsoa, newsoa;
15859
15860 REQUIRE(DNS_ZONE_VALID(seczone));
15861 REQUIRE(soatuple != NULL && *soatuple == NULL);
15862
15863 if (!seczone->sourceserialset) {
15864 return (DNS_R_UNCHANGED);
15865 }
15866
15867 dns_db_attach(raw->db, &rawdb);
15868 dns_db_currentversion(rawdb, &rawver);
15869 result = dns_db_diffx(diff, rawdb, rawver, secdb, secver, NULL);
15870 dns_db_closeversion(rawdb, &rawver, false);
15871 dns_db_detach(&rawdb);
15872
15873 if (result != ISC_R_SUCCESS) {
15874 return (result);
15875 }
15876
15877 for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL; tuple = next) {
15878 next = ISC_LIST_NEXT(tuple, link);
15879 if (tuple->rdata.type == dns_rdatatype_nsec ||
15880 tuple->rdata.type == dns_rdatatype_rrsig ||
15881 tuple->rdata.type == dns_rdatatype_dnskey ||
15882 tuple->rdata.type == dns_rdatatype_nsec3 ||
15883 tuple->rdata.type == dns_rdatatype_nsec3param)
15884 {
15885 ISC_LIST_UNLINK(diff->tuples, tuple, link);
15886 dns_difftuple_free(&tuple);
15887 continue;
15888 }
15889 if (tuple->rdata.type == dns_rdatatype_soa) {
15890 if (tuple->op == DNS_DIFFOP_DEL) {
15891 INSIST(oldtuple == NULL);
15892 oldtuple = tuple;
15893 }
15894 if (tuple->op == DNS_DIFFOP_ADD) {
15895 INSIST(newtuple == NULL);
15896 newtuple = tuple;
15897 }
15898 }
15899 }
15900
15901 if (oldtuple != NULL && newtuple != NULL) {
15902 result = dns_rdata_tostruct(&oldtuple->rdata, &oldsoa, NULL);
15903 RUNTIME_CHECK(result == ISC_R_SUCCESS);
15904
15905 result = dns_rdata_tostruct(&newtuple->rdata, &newsoa, NULL);
15906 RUNTIME_CHECK(result == ISC_R_SUCCESS);
15907
15908 /*
15909 * If the SOA records are the same except for the serial
15910 * remove them from the diff.
15911 */
15912 if (oldsoa.refresh == newsoa.refresh &&
15913 oldsoa.retry == newsoa.retry &&
15914 oldsoa.minimum == newsoa.minimum &&
15915 oldsoa.expire == newsoa.expire &&
15916 dns_name_equal(&oldsoa.origin, &newsoa.origin) &&
15917 dns_name_equal(&oldsoa.contact, &newsoa.contact))
15918 {
15919 ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
15920 dns_difftuple_free(&oldtuple);
15921 ISC_LIST_UNLINK(diff->tuples, newtuple, link);
15922 dns_difftuple_free(&newtuple);
15923 }
15924 }
15925
15926 if (ISC_LIST_EMPTY(diff->tuples)) {
15927 return (DNS_R_UNCHANGED);
15928 }
15929
15930 /*
15931 * If there are still SOA records in the diff they can now be removed
15932 * saving the new SOA record.
15933 */
15934 if (oldtuple != NULL) {
15935 ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
15936 dns_difftuple_free(&oldtuple);
15937 }
15938
15939 if (newtuple != NULL) {
15940 ISC_LIST_UNLINK(diff->tuples, newtuple, link);
15941 *soatuple = newtuple;
15942 }
15943
15944 return (ISC_R_SUCCESS);
15945 }
15946
15947 static void
15948 receive_secure_serial(isc_task_t *task, isc_event_t *event) {
15949 static char me[] = "receive_secure_serial";
15950 isc_result_t result = ISC_R_SUCCESS;
15951 dns_journal_t *rjournal = NULL;
15952 dns_journal_t *sjournal = NULL;
15953 uint32_t start, end;
15954 dns_zone_t *zone;
15955 dns_difftuple_t *tuple = NULL, *soatuple = NULL;
15956 dns_update_log_t log = { update_log_cb, NULL };
15957 uint32_t newserial = 0, desired = 0;
15958 isc_time_t timenow;
15959 int level = ISC_LOG_ERROR;
15960
15961 UNUSED(task);
15962
15963 zone = event->ev_arg;
15964 end = ((struct secure_event *)event)->serial;
15965
15966 ENTER;
15967
15968 LOCK_ZONE(zone);
15969
15970 /*
15971 * If we are already processing a receive secure serial event
15972 * for the zone, just queue the new one and exit.
15973 */
15974 if (zone->rss_event != NULL && zone->rss_event != event) {
15975 ISC_LIST_APPEND(zone->rss_events, event, ev_link);
15976 UNLOCK_ZONE(zone);
15977 return;
15978 }
15979
15980 nextevent:
15981 if (zone->rss_event != NULL) {
15982 INSIST(zone->rss_event == event);
15983 UNLOCK_ZONE(zone);
15984 } else {
15985 zone->rss_event = event;
15986 dns_diff_init(zone->mctx, &zone->rss_diff);
15987
15988 /*
15989 * zone->db may be NULL, if the load from disk failed.
15990 */
15991 result = ISC_R_SUCCESS;
15992 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
15993 if (zone->db != NULL) {
15994 dns_db_attach(zone->db, &zone->rss_db);
15995 } else {
15996 result = ISC_R_FAILURE;
15997 }
15998 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
15999
16000 if (result == ISC_R_SUCCESS && zone->raw != NULL) {
16001 dns_zone_attach(zone->raw, &zone->rss_raw);
16002 } else {
16003 result = ISC_R_FAILURE;
16004 }
16005
16006 UNLOCK_ZONE(zone);
16007
16008 CHECK(result);
16009
16010 /*
16011 * We first attempt to sync the raw zone to the secure zone
16012 * by using the raw zone's journal, applying all the deltas
16013 * from the latest source-serial of the secure zone up to
16014 * the current serial number of the raw zone.
16015 *
16016 * If that fails, then we'll fall back to a direct comparison
16017 * between raw and secure zones.
16018 */
16019 CHECK(dns_journal_open(zone->rss_raw->mctx,
16020 zone->rss_raw->journal,
16021 DNS_JOURNAL_WRITE, &rjournal));
16022
16023 result = dns_journal_open(zone->mctx, zone->journal,
16024 DNS_JOURNAL_READ, &sjournal);
16025 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
16026 goto failure;
16027 }
16028
16029 if (!dns_journal_get_sourceserial(rjournal, &start)) {
16030 start = dns_journal_first_serial(rjournal);
16031 dns_journal_set_sourceserial(rjournal, start);
16032 }
16033 if (sjournal != NULL) {
16034 uint32_t serial;
16035 /*
16036 * We read the secure journal first, if that
16037 * exists use its value provided it is greater
16038 * that from the raw journal.
16039 */
16040 if (dns_journal_get_sourceserial(sjournal, &serial)) {
16041 if (isc_serial_gt(serial, start)) {
16042 start = serial;
16043 }
16044 }
16045 dns_journal_destroy(&sjournal);
16046 }
16047
16048 dns_db_currentversion(zone->rss_db, &zone->rss_oldver);
16049 CHECK(dns_db_newversion(zone->rss_db, &zone->rss_newver));
16050
16051 /*
16052 * Try to apply diffs from the raw zone's journal to the secure
16053 * zone. If that fails, we recover by syncing up the databases
16054 * directly.
16055 */
16056 result = sync_secure_journal(zone, zone->rss_raw, rjournal,
16057 start, end, &soatuple,
16058 &zone->rss_diff);
16059 if (result == DNS_R_UNCHANGED) {
16060 level = ISC_LOG_INFO;
16061 goto failure;
16062 } else if (result != ISC_R_SUCCESS) {
16063 CHECK(sync_secure_db(zone, zone->rss_raw, zone->rss_db,
16064 zone->rss_oldver, &soatuple,
16065 &zone->rss_diff));
16066 }
16067
16068 CHECK(dns_diff_apply(&zone->rss_diff, zone->rss_db,
16069 zone->rss_newver));
16070
16071 if (soatuple != NULL) {
16072 uint32_t oldserial;
16073
16074 CHECK(dns_db_createsoatuple(
16075 zone->rss_db, zone->rss_oldver,
16076 zone->rss_diff.mctx, DNS_DIFFOP_DEL, &tuple));
16077 oldserial = dns_soa_getserial(&tuple->rdata);
16078 newserial = desired =
16079 dns_soa_getserial(&soatuple->rdata);
16080 if (!isc_serial_gt(newserial, oldserial)) {
16081 newserial = oldserial + 1;
16082 if (newserial == 0) {
16083 newserial++;
16084 }
16085 dns_soa_setserial(newserial, &soatuple->rdata);
16086 }
16087 CHECK(do_one_tuple(&tuple, zone->rss_db,
16088 zone->rss_newver, &zone->rss_diff));
16089 CHECK(do_one_tuple(&soatuple, zone->rss_db,
16090 zone->rss_newver, &zone->rss_diff));
16091 } else {
16092 CHECK(update_soa_serial(zone, zone->rss_db,
16093 zone->rss_newver,
16094 &zone->rss_diff, zone->mctx,
16095 zone->updatemethod));
16096 }
16097 }
16098 result = dns_update_signaturesinc(
16099 &log, zone, zone->rss_db, zone->rss_oldver, zone->rss_newver,
16100 &zone->rss_diff, zone->sigvalidityinterval, &zone->rss_state);
16101 if (result == DNS_R_CONTINUE) {
16102 if (rjournal != NULL) {
16103 dns_journal_destroy(&rjournal);
16104 }
16105 isc_task_send(task, &event);
16106 return;
16107 }
16108 /*
16109 * If something went wrong while trying to update the secure zone and
16110 * the latter was already signed before, do not apply raw zone deltas
16111 * to it as that would break existing DNSSEC signatures. However, if
16112 * the secure zone was not yet signed (e.g. because no signing keys
16113 * were created for it), commence applying raw zone deltas to it so
16114 * that contents of the raw zone and the secure zone are kept in sync.
16115 */
16116 if (result != ISC_R_SUCCESS && dns_db_issecure(zone->rss_db)) {
16117 goto failure;
16118 }
16119
16120 if (rjournal == NULL) {
16121 CHECK(dns_journal_open(zone->rss_raw->mctx,
16122 zone->rss_raw->journal,
16123 DNS_JOURNAL_WRITE, &rjournal));
16124 }
16125 CHECK(zone_journal(zone, &zone->rss_diff, &end,
16126 "receive_secure_serial"));
16127
16128 dns_journal_set_sourceserial(rjournal, end);
16129 dns_journal_commit(rjournal);
16130
16131 LOCK_ZONE(zone);
16132 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
16133
16134 zone->sourceserial = end;
16135 zone->sourceserialset = true;
16136 zone_needdump(zone, DNS_DUMP_DELAY);
16137
16138 /*
16139 * Set resign time to make sure it is set to the earliest
16140 * signature expiration.
16141 */
16142 set_resigntime(zone);
16143 TIME_NOW(&timenow);
16144 zone_settimer(zone, &timenow);
16145 UNLOCK_ZONE(zone);
16146
16147 dns_db_closeversion(zone->rss_db, &zone->rss_oldver, false);
16148 dns_db_closeversion(zone->rss_db, &zone->rss_newver, true);
16149
16150 if (newserial != 0) {
16151 dns_zone_log(zone, ISC_LOG_INFO, "serial %u (unsigned %u)",
16152 newserial, desired);
16153 }
16154
16155 failure:
16156 isc_event_free(&zone->rss_event);
16157 event = ISC_LIST_HEAD(zone->rss_events);
16158
16159 if (zone->rss_raw != NULL) {
16160 dns_zone_detach(&zone->rss_raw);
16161 }
16162 if (result != ISC_R_SUCCESS) {
16163 LOCK_ZONE(zone);
16164 set_resigntime(zone);
16165 TIME_NOW(&timenow);
16166 zone_settimer(zone, &timenow);
16167 UNLOCK_ZONE(zone);
16168 dns_zone_log(zone, level, "receive_secure_serial: %s",
16169 dns_result_totext(result));
16170 }
16171 if (tuple != NULL) {
16172 dns_difftuple_free(&tuple);
16173 }
16174 if (soatuple != NULL) {
16175 dns_difftuple_free(&soatuple);
16176 }
16177 if (zone->rss_db != NULL) {
16178 if (zone->rss_oldver != NULL) {
16179 dns_db_closeversion(zone->rss_db, &zone->rss_oldver,
16180 false);
16181 }
16182 if (zone->rss_newver != NULL) {
16183 dns_db_closeversion(zone->rss_db, &zone->rss_newver,
16184 false);
16185 }
16186 dns_db_detach(&zone->rss_db);
16187 }
16188 INSIST(zone->rss_oldver == NULL);
16189 INSIST(zone->rss_newver == NULL);
16190 if (rjournal != NULL) {
16191 dns_journal_destroy(&rjournal);
16192 }
16193 dns_diff_clear(&zone->rss_diff);
16194
16195 if (event != NULL) {
16196 LOCK_ZONE(zone);
16197 isc_refcount_decrement(&zone->irefs);
16198 ISC_LIST_UNLINK(zone->rss_events, event, ev_link);
16199 goto nextevent;
16200 }
16201
16202 event = ISC_LIST_HEAD(zone->rss_post);
16203 while (event != NULL) {
16204 ISC_LIST_UNLINK(zone->rss_post, event, ev_link);
16205 rss_post(zone, event);
16206 event = ISC_LIST_HEAD(zone->rss_post);
16207 }
16208
16209 dns_zone_idetach(&zone);
16210 }
16211
16212 static isc_result_t
16213 zone_send_secureserial(dns_zone_t *zone, uint32_t serial) {
16214 isc_event_t *e;
16215 dns_zone_t *dummy = NULL;
16216
16217 e = isc_event_allocate(zone->secure->mctx, zone,
16218 DNS_EVENT_ZONESECURESERIAL,
16219 receive_secure_serial, zone->secure,
16220 sizeof(struct secure_event));
16221 ((struct secure_event *)e)->serial = serial;
16222 INSIST(LOCKED_ZONE(zone->secure));
16223 zone_iattach(zone->secure, &dummy);
16224 isc_task_send(zone->secure->task, &e);
16225
16226 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
16227 return (ISC_R_SUCCESS);
16228 }
16229
16230 static isc_result_t
16231 checkandaddsoa(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
16232 dns_rdataset_t *rdataset, uint32_t oldserial) {
16233 dns_rdata_soa_t soa;
16234 dns_rdata_t rdata = DNS_RDATA_INIT;
16235 dns_rdatalist_t temprdatalist;
16236 dns_rdataset_t temprdataset;
16237 isc_buffer_t b;
16238 isc_result_t result;
16239 unsigned char buf[DNS_SOA_BUFFERSIZE];
16240 dns_fixedname_t fixed;
16241 dns_name_t *name;
16242
16243 result = dns_rdataset_first(rdataset);
16244 RUNTIME_CHECK(result == ISC_R_SUCCESS);
16245 dns_rdataset_current(rdataset, &rdata);
16246 result = dns_rdata_tostruct(&rdata, &soa, NULL);
16247 RUNTIME_CHECK(result == ISC_R_SUCCESS);
16248
16249 if (isc_serial_gt(soa.serial, oldserial)) {
16250 return (dns_db_addrdataset(db, node, version, 0, rdataset, 0,
16251 NULL));
16252 }
16253 /*
16254 * Always bump the serial.
16255 */
16256 oldserial++;
16257 if (oldserial == 0) {
16258 oldserial++;
16259 }
16260 soa.serial = oldserial;
16261
16262 /*
16263 * Construct a replacement rdataset.
16264 */
16265 dns_rdata_reset(&rdata);
16266 isc_buffer_init(&b, buf, sizeof(buf));
16267 result = dns_rdata_fromstruct(&rdata, rdataset->rdclass,
16268 dns_rdatatype_soa, &soa, &b);
16269 RUNTIME_CHECK(result == ISC_R_SUCCESS);
16270 dns_rdatalist_init(&temprdatalist);
16271 temprdatalist.rdclass = rdata.rdclass;
16272 temprdatalist.type = rdata.type;
16273 temprdatalist.ttl = rdataset->ttl;
16274 ISC_LIST_APPEND(temprdatalist.rdata, &rdata, link);
16275
16276 dns_rdataset_init(&temprdataset);
16277 result = dns_rdatalist_tordataset(&temprdatalist, &temprdataset);
16278 RUNTIME_CHECK(result == ISC_R_SUCCESS);
16279
16280 name = dns_fixedname_initname(&fixed);
16281 result = dns_db_nodefullname(db, node, name);
16282 RUNTIME_CHECK(result == ISC_R_SUCCESS);
16283 dns_rdataset_getownercase(rdataset, name);
16284 dns_rdataset_setownercase(&temprdataset, name);
16285 return (dns_db_addrdataset(db, node, version, 0, &temprdataset, 0,
16286 NULL));
16287 }
16288
16289 /*
16290 * This function should populate an nsec3paramlist_t with the
16291 * nsecparam_t data from a zone.
16292 */
16293 static isc_result_t
16294 save_nsec3param(dns_zone_t *zone, nsec3paramlist_t *nsec3list) {
16295 isc_result_t result;
16296 dns_dbnode_t *node = NULL;
16297 dns_rdataset_t rdataset, prdataset;
16298 dns_dbversion_t *version = NULL;
16299 nsec3param_t *nsec3param = NULL;
16300 nsec3param_t *nsec3p = NULL;
16301 nsec3param_t *next;
16302 dns_db_t *db = NULL;
16303 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
16304
16305 REQUIRE(DNS_ZONE_VALID(zone));
16306 REQUIRE(nsec3list != NULL);
16307 REQUIRE(ISC_LIST_EMPTY(*nsec3list));
16308
16309 dns_rdataset_init(&rdataset);
16310 dns_rdataset_init(&prdataset);
16311
16312 dns_db_attach(zone->db, &db);
16313 CHECK(dns_db_getoriginnode(db, &node));
16314
16315 dns_db_currentversion(db, &version);
16316 result = dns_db_findrdataset(db, node, version,
16317 dns_rdatatype_nsec3param,
16318 dns_rdatatype_none, 0, &rdataset, NULL);
16319
16320 if (result != ISC_R_SUCCESS) {
16321 goto getprivate;
16322 }
16323
16324 /*
16325 * Walk nsec3param rdataset making a list of parameters (note that
16326 * multiple simultaneous nsec3 chains are annoyingly legal -- this
16327 * is why we use an nsec3list, even though we will usually only
16328 * have one).
16329 */
16330 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
16331 result = dns_rdataset_next(&rdataset))
16332 {
16333 dns_rdata_t rdata = DNS_RDATA_INIT;
16334 dns_rdata_t private = DNS_RDATA_INIT;
16335
16336 dns_rdataset_current(&rdataset, &rdata);
16337 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
16338 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
16339 "looping through nsec3param data");
16340 nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
16341 ISC_LINK_INIT(nsec3param, link);
16342
16343 /*
16344 * now transfer the data from the rdata to
16345 * the nsec3param
16346 */
16347 dns_nsec3param_toprivate(&rdata, &private, zone->privatetype,
16348 nsec3param->data,
16349 sizeof(nsec3param->data));
16350 nsec3param->length = private.length;
16351 ISC_LIST_APPEND(*nsec3list, nsec3param, link);
16352 }
16353
16354 getprivate:
16355 result = dns_db_findrdataset(db, node, version, zone->privatetype,
16356 dns_rdatatype_none, 0, &prdataset, NULL);
16357 if (result != ISC_R_SUCCESS) {
16358 goto done;
16359 }
16360
16361 /*
16362 * walk private type records, converting them to nsec3 parameters
16363 * using dns_nsec3param_fromprivate(), do the right thing based on
16364 * CREATE and REMOVE flags
16365 */
16366 for (result = dns_rdataset_first(&prdataset); result == ISC_R_SUCCESS;
16367 result = dns_rdataset_next(&prdataset))
16368 {
16369 dns_rdata_t rdata = DNS_RDATA_INIT;
16370 dns_rdata_t private = DNS_RDATA_INIT;
16371
16372 dns_rdataset_current(&prdataset, &private);
16373 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
16374 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
16375 "looping through nsec3param private data");
16376
16377 /*
16378 * Do we have a valid private record?
16379 */
16380 if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
16381 sizeof(buf))) {
16382 continue;
16383 }
16384
16385 /*
16386 * Remove any NSEC3PARAM records scheduled to be removed.
16387 */
16388 if (NSEC3REMOVE(rdata.data[1])) {
16389 /*
16390 * Zero out the flags.
16391 */
16392 rdata.data[1] = 0;
16393
16394 for (nsec3p = ISC_LIST_HEAD(*nsec3list); nsec3p != NULL;
16395 nsec3p = next) {
16396 next = ISC_LIST_NEXT(nsec3p, link);
16397
16398 if (nsec3p->length == rdata.length + 1 &&
16399 memcmp(rdata.data, nsec3p->data + 1,
16400 nsec3p->length - 1) == 0)
16401 {
16402 ISC_LIST_UNLINK(*nsec3list, nsec3p,
16403 link);
16404 isc_mem_put(zone->mctx, nsec3p,
16405 sizeof(nsec3param_t));
16406 }
16407 }
16408 continue;
16409 }
16410
16411 nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
16412 ISC_LINK_INIT(nsec3param, link);
16413
16414 /*
16415 * Copy the remaining private records so the nsec/nsec3
16416 * chain gets created.
16417 */
16418 INSIST(private.length <= sizeof(nsec3param->data));
16419 memmove(nsec3param->data, private.data, private.length);
16420 nsec3param->length = private.length;
16421 ISC_LIST_APPEND(*nsec3list, nsec3param, link);
16422 }
16423
16424 done:
16425 if (result == ISC_R_NOMORE || result == ISC_R_NOTFOUND) {
16426 result = ISC_R_SUCCESS;
16427 }
16428
16429 failure:
16430 if (node != NULL) {
16431 dns_db_detachnode(db, &node);
16432 }
16433 if (version != NULL) {
16434 dns_db_closeversion(db, &version, false);
16435 }
16436 if (db != NULL) {
16437 dns_db_detach(&db);
16438 }
16439 if (dns_rdataset_isassociated(&rdataset)) {
16440 dns_rdataset_disassociate(&rdataset);
16441 }
16442 if (dns_rdataset_isassociated(&prdataset)) {
16443 dns_rdataset_disassociate(&prdataset);
16444 }
16445 return (result);
16446 }
16447
16448 /*
16449 * Populate new zone db with private type records found by save_nsec3param().
16450 */
16451 static isc_result_t
16452 restore_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
16453 nsec3paramlist_t *nsec3list) {
16454 isc_result_t result = ISC_R_SUCCESS;
16455 dns_diff_t diff;
16456 dns_rdata_t rdata;
16457 nsec3param_t *nsec3p = NULL;
16458 nsec3param_t *next;
16459
16460 REQUIRE(DNS_ZONE_VALID(zone));
16461 REQUIRE(!ISC_LIST_EMPTY(*nsec3list));
16462
16463 dns_diff_init(zone->mctx, &diff);
16464
16465 /*
16466 * Loop through the list of private-type records, set the INITIAL
16467 * and CREATE flags, and the add the record to the apex of the tree
16468 * in db.
16469 */
16470 for (nsec3p = ISC_LIST_HEAD(*nsec3list); nsec3p != NULL; nsec3p = next)
16471 {
16472 next = ISC_LIST_NEXT(nsec3p, link);
16473 dns_rdata_init(&rdata);
16474 nsec3p->data[2] = DNS_NSEC3FLAG_CREATE | DNS_NSEC3FLAG_INITIAL;
16475 rdata.length = nsec3p->length;
16476 rdata.data = nsec3p->data;
16477 rdata.type = zone->privatetype;
16478 rdata.rdclass = zone->rdclass;
16479 result = update_one_rr(db, version, &diff, DNS_DIFFOP_ADD,
16480 &zone->origin, 0, &rdata);
16481 if (result != ISC_R_SUCCESS) {
16482 break;
16483 }
16484 }
16485
16486 dns_diff_clear(&diff);
16487 return (result);
16488 }
16489
16490 static isc_result_t
16491 copy_non_dnssec_records(dns_zone_t *zone, dns_db_t *db, dns_db_t *version,
16492 dns_db_t *rawdb, dns_dbiterator_t *dbiterator,
16493 unsigned int *oldserial) {
16494 dns_dbnode_t *rawnode = NULL, *node = NULL;
16495 dns_fixedname_t fixed;
16496 dns_name_t *name = dns_fixedname_initname(&fixed);
16497 dns_rdataset_t rdataset;
16498 dns_rdatasetiter_t *rdsit = NULL;
16499 isc_result_t result;
16500
16501 result = dns_dbiterator_current(dbiterator, &rawnode, name);
16502 if (result != ISC_R_SUCCESS) {
16503 return (ISC_R_SUCCESS);
16504 }
16505
16506 dns_dbiterator_pause(dbiterator);
16507
16508 result = dns_db_findnode(db, name, true, &node);
16509 if (result != ISC_R_SUCCESS) {
16510 goto cleanup;
16511 }
16512
16513 result = dns_db_allrdatasets(rawdb, rawnode, NULL, 0, &rdsit);
16514 if (result != ISC_R_SUCCESS) {
16515 goto cleanup;
16516 }
16517
16518 dns_rdataset_init(&rdataset);
16519
16520 for (result = dns_rdatasetiter_first(rdsit); result == ISC_R_SUCCESS;
16521 result = dns_rdatasetiter_next(rdsit))
16522 {
16523 dns_rdatasetiter_current(rdsit, &rdataset);
16524 if (rdataset.type == dns_rdatatype_nsec ||
16525 rdataset.type == dns_rdatatype_rrsig ||
16526 rdataset.type == dns_rdatatype_nsec3 ||
16527 rdataset.type == dns_rdatatype_dnskey ||
16528 rdataset.type == dns_rdatatype_nsec3param)
16529 {
16530 /*
16531 * Allow DNSSEC records with dnssec-policy.
16532 * WMM: Perhaps add config option for it.
16533 */
16534 if (!dns_zone_use_kasp(zone)) {
16535 dns_rdataset_disassociate(&rdataset);
16536 continue;
16537 }
16538 }
16539 if (rdataset.type == dns_rdatatype_soa && oldserial != NULL) {
16540 result = checkandaddsoa(db, node, version, &rdataset,
16541 *oldserial);
16542 } else {
16543 result = dns_db_addrdataset(db, node, version, 0,
16544 &rdataset, 0, NULL);
16545 }
16546 dns_rdataset_disassociate(&rdataset);
16547 if (result != ISC_R_SUCCESS) {
16548 goto cleanup;
16549 }
16550 }
16551 if (result == ISC_R_NOMORE) {
16552 result = ISC_R_SUCCESS;
16553 }
16554
16555 cleanup:
16556 if (rdsit != NULL) {
16557 dns_rdatasetiter_destroy(&rdsit);
16558 }
16559 if (rawnode) {
16560 dns_db_detachnode(rawdb, &rawnode);
16561 }
16562 if (node) {
16563 dns_db_detachnode(db, &node);
16564 }
16565 return (result);
16566 }
16567
16568 static void
16569 receive_secure_db(isc_task_t *task, isc_event_t *event) {
16570 isc_result_t result;
16571 dns_zone_t *zone;
16572 dns_db_t *rawdb, *db = NULL;
16573 dns_dbiterator_t *dbiterator = NULL;
16574 dns_dbversion_t *version = NULL;
16575 isc_time_t loadtime;
16576 unsigned int oldserial = 0, *oldserialp = NULL;
16577 nsec3paramlist_t nsec3list;
16578 isc_event_t *setnsec3param_event;
16579 dns_zone_t *dummy;
16580
16581 UNUSED(task);
16582
16583 ISC_LIST_INIT(nsec3list);
16584
16585 zone = event->ev_arg;
16586 rawdb = ((struct secure_event *)event)->db;
16587 isc_event_free(&event);
16588
16589 LOCK_ZONE(zone);
16590 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || !inline_secure(zone)) {
16591 result = ISC_R_SHUTTINGDOWN;
16592 goto failure;
16593 }
16594
16595 TIME_NOW(&loadtime);
16596 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
16597 if (zone->db != NULL) {
16598 result = dns_db_getsoaserial(zone->db, NULL, &oldserial);
16599 if (result == ISC_R_SUCCESS) {
16600 oldserialp = &oldserial;
16601 }
16602
16603 /*
16604 * assemble nsec3parameters from the old zone, and set a flag
16605 * if any are found
16606 */
16607 result = save_nsec3param(zone, &nsec3list);
16608 if (result != ISC_R_SUCCESS) {
16609 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
16610 goto failure;
16611 }
16612 }
16613 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
16614
16615 result = dns_db_create(zone->mctx, zone->db_argv[0], &zone->origin,
16616 dns_dbtype_zone, zone->rdclass,
16617 zone->db_argc - 1, zone->db_argv + 1, &db);
16618 if (result != ISC_R_SUCCESS) {
16619 goto failure;
16620 }
16621
16622 result = dns_db_setgluecachestats(db, zone->gluecachestats);
16623 if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) {
16624 goto failure;
16625 }
16626
16627 result = dns_db_newversion(db, &version);
16628 if (result != ISC_R_SUCCESS) {
16629 goto failure;
16630 }
16631
16632 result = dns_db_createiterator(rawdb, 0, &dbiterator);
16633 if (result != ISC_R_SUCCESS) {
16634 goto failure;
16635 }
16636
16637 for (result = dns_dbiterator_first(dbiterator); result == ISC_R_SUCCESS;
16638 result = dns_dbiterator_next(dbiterator))
16639 {
16640 result = copy_non_dnssec_records(zone, db, version, rawdb,
16641 dbiterator, oldserialp);
16642 if (result != ISC_R_SUCCESS) {
16643 goto failure;
16644 }
16645 }
16646 dns_dbiterator_destroy(&dbiterator);
16647 if (result != ISC_R_NOMORE) {
16648 goto failure;
16649 }
16650
16651 /*
16652 * Call restore_nsec3param() to create private-type records from
16653 * the old nsec3 parameters and insert them into db
16654 */
16655 if (!ISC_LIST_EMPTY(nsec3list)) {
16656 result = restore_nsec3param(zone, db, version, &nsec3list);
16657 if (result != ISC_R_SUCCESS) {
16658 goto failure;
16659 }
16660 }
16661
16662 dns_db_closeversion(db, &version, true);
16663
16664 /*
16665 * Lock hierarchy: zmgr, zone, raw.
16666 */
16667 INSIST(zone != zone->raw);
16668 LOCK_ZONE(zone->raw);
16669 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
16670 result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
16671 zone_needdump(zone, 0); /* XXXMPA */
16672 UNLOCK_ZONE(zone->raw);
16673
16674 /*
16675 * Process any queued NSEC3PARAM change requests.
16676 */
16677 while (!ISC_LIST_EMPTY(zone->setnsec3param_queue)) {
16678 setnsec3param_event = ISC_LIST_HEAD(zone->setnsec3param_queue);
16679 ISC_LIST_UNLINK(zone->setnsec3param_queue, setnsec3param_event,
16680 ev_link);
16681 dummy = NULL;
16682 zone_iattach(zone, &dummy);
16683 isc_task_send(zone->task, &setnsec3param_event);
16684 }
16685
16686 failure:
16687 UNLOCK_ZONE(zone);
16688 if (dbiterator != NULL) {
16689 dns_dbiterator_destroy(&dbiterator);
16690 }
16691 if (result != ISC_R_SUCCESS) {
16692 dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_db: %s",
16693 dns_result_totext(result));
16694 }
16695
16696 while (!ISC_LIST_EMPTY(nsec3list)) {
16697 nsec3param_t *nsec3p;
16698 nsec3p = ISC_LIST_HEAD(nsec3list);
16699 ISC_LIST_UNLINK(nsec3list, nsec3p, link);
16700 isc_mem_put(zone->mctx, nsec3p, sizeof(nsec3param_t));
16701 }
16702 if (db != NULL) {
16703 if (version != NULL) {
16704 dns_db_closeversion(db, &version, false);
16705 }
16706 dns_db_detach(&db);
16707 }
16708 dns_db_detach(&rawdb);
16709 dns_zone_idetach(&zone);
16710
16711 INSIST(version == NULL);
16712 }
16713
16714 static isc_result_t
16715 zone_send_securedb(dns_zone_t *zone, dns_db_t *db) {
16716 isc_event_t *e;
16717 dns_db_t *dummy = NULL;
16718 dns_zone_t *secure = NULL;
16719
16720 e = isc_event_allocate(zone->secure->mctx, zone, DNS_EVENT_ZONESECUREDB,
16721 receive_secure_db, zone->secure,
16722 sizeof(struct secure_event));
16723 dns_db_attach(db, &dummy);
16724 ((struct secure_event *)e)->db = dummy;
16725 INSIST(LOCKED_ZONE(zone->secure));
16726 zone_iattach(zone->secure, &secure);
16727 isc_task_send(zone->secure->task, &e);
16728 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
16729 return (ISC_R_SUCCESS);
16730 }
16731
16732 isc_result_t
16733 dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump) {
16734 isc_result_t result;
16735 dns_zone_t *secure = NULL;
16736
16737 REQUIRE(DNS_ZONE_VALID(zone));
16738 again:
16739 LOCK_ZONE(zone);
16740 if (inline_raw(zone)) {
16741 secure = zone->secure;
16742 INSIST(secure != zone);
16743 TRYLOCK_ZONE(result, secure);
16744 if (result != ISC_R_SUCCESS) {
16745 UNLOCK_ZONE(zone);
16746 secure = NULL;
16747 isc_thread_yield();
16748 goto again;
16749 }
16750 }
16751 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
16752 result = zone_replacedb(zone, db, dump);
16753 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
16754 if (secure != NULL) {
16755 UNLOCK_ZONE(secure);
16756 }
16757 UNLOCK_ZONE(zone);
16758 return (result);
16759 }
16760
16761 static isc_result_t
16762 zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump) {
16763 dns_dbversion_t *ver;
16764 isc_result_t result;
16765 unsigned int soacount = 0;
16766 unsigned int nscount = 0;
16767
16768 /*
16769 * 'zone' and 'zone->db' locked by caller.
16770 */
16771 REQUIRE(DNS_ZONE_VALID(zone));
16772 REQUIRE(LOCKED_ZONE(zone));
16773 if (inline_raw(zone)) {
16774 REQUIRE(LOCKED_ZONE(zone->secure));
16775 }
16776
16777 result = zone_get_from_db(zone, db, &nscount, &soacount, NULL, NULL,
16778 NULL, NULL, NULL, NULL);
16779 if (result == ISC_R_SUCCESS) {
16780 if (soacount != 1) {
16781 dns_zone_log(zone, ISC_LOG_ERROR, "has %d SOA records",
16782 soacount);
16783 result = DNS_R_BADZONE;
16784 }
16785 if (nscount == 0 && zone->type != dns_zone_key) {
16786 dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records");
16787 result = DNS_R_BADZONE;
16788 }
16789 if (result != ISC_R_SUCCESS) {
16790 return (result);
16791 }
16792 } else {
16793 dns_zone_log(zone, ISC_LOG_ERROR,
16794 "retrieving SOA and NS records failed: %s",
16795 dns_result_totext(result));
16796 return (result);
16797 }
16798
16799 result = check_nsec3param(zone, db);
16800 if (result != ISC_R_SUCCESS) {
16801 return (result);
16802 }
16803
16804 ver = NULL;
16805 dns_db_currentversion(db, &ver);
16806
16807 /*
16808 * The initial version of a slave zone is always dumped;
16809 * subsequent versions may be journaled instead if this
16810 * is enabled in the configuration.
16811 */
16812 if (zone->db != NULL && zone->journal != NULL &&
16813 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
16814 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER))
16815 {
16816 uint32_t serial, oldserial;
16817
16818 dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
16819
16820 result = dns_db_getsoaserial(db, ver, &serial);
16821 if (result != ISC_R_SUCCESS) {
16822 dns_zone_log(zone, ISC_LOG_ERROR,
16823 "ixfr-from-differences: unable to get "
16824 "new serial");
16825 goto fail;
16826 }
16827
16828 /*
16829 * This is checked in zone_postload() for master zones.
16830 */
16831 result = zone_get_from_db(zone, zone->db, NULL, &soacount,
16832 &oldserial, NULL, NULL, NULL, NULL,
16833 NULL);
16834 RUNTIME_CHECK(result == ISC_R_SUCCESS);
16835 RUNTIME_CHECK(soacount > 0U);
16836 if ((zone->type == dns_zone_slave ||
16837 (zone->type == dns_zone_redirect &&
16838 zone->masters != NULL)) &&
16839 !isc_serial_gt(serial, oldserial))
16840 {
16841 uint32_t serialmin, serialmax;
16842 serialmin = (oldserial + 1) & 0xffffffffU;
16843 serialmax = (oldserial + 0x7fffffffU) & 0xffffffffU;
16844 dns_zone_log(zone, ISC_LOG_ERROR,
16845 "ixfr-from-differences: failed: "
16846 "new serial (%u) out of range [%u - %u]",
16847 serial, serialmin, serialmax);
16848 result = ISC_R_RANGE;
16849 goto fail;
16850 }
16851
16852 result = dns_db_diff(zone->mctx, db, ver, zone->db, NULL,
16853 zone->journal);
16854 if (result != ISC_R_SUCCESS) {
16855 char strbuf[ISC_STRERRORSIZE];
16856 strerror_r(errno, strbuf, sizeof(strbuf));
16857 dns_zone_log(zone, ISC_LOG_ERROR,
16858 "ixfr-from-differences: failed: "
16859 "%s",
16860 strbuf);
16861 goto fallback;
16862 }
16863 if (dump) {
16864 zone_needdump(zone, DNS_DUMP_DELAY);
16865 } else {
16866 zone_journal_compact(zone, zone->db, serial);
16867 }
16868 if (zone->type == dns_zone_master && inline_raw(zone)) {
16869 zone_send_secureserial(zone, serial);
16870 }
16871 } else {
16872 fallback:
16873 if (dump && zone->masterfile != NULL) {
16874 /*
16875 * If DNS_ZONEFLG_FORCEXFER was set we don't want
16876 * to keep the old masterfile.
16877 */
16878 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) &&
16879 remove(zone->masterfile) < 0 && errno != ENOENT)
16880 {
16881 char strbuf[ISC_STRERRORSIZE];
16882 strerror_r(errno, strbuf, sizeof(strbuf));
16883 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
16884 DNS_LOGMODULE_ZONE,
16885 ISC_LOG_WARNING,
16886 "unable to remove masterfile "
16887 "'%s': '%s'",
16888 zone->masterfile, strbuf);
16889 }
16890 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0) {
16891 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NODELAY);
16892 } else {
16893 zone_needdump(zone, 0);
16894 }
16895 }
16896 if (dump && zone->journal != NULL) {
16897 /*
16898 * The in-memory database just changed, and
16899 * because 'dump' is set, it didn't change by
16900 * being loaded from disk. Also, we have not
16901 * journaled diffs for this change.
16902 * Therefore, the on-disk journal is missing
16903 * the deltas for this change. Since it can
16904 * no longer be used to bring the zone
16905 * up-to-date, it is useless and should be
16906 * removed.
16907 */
16908 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
16909 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
16910 "removing journal file");
16911 if (remove(zone->journal) < 0 && errno != ENOENT) {
16912 char strbuf[ISC_STRERRORSIZE];
16913 strerror_r(errno, strbuf, sizeof(strbuf));
16914 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
16915 DNS_LOGMODULE_ZONE,
16916 ISC_LOG_WARNING,
16917 "unable to remove journal "
16918 "'%s': '%s'",
16919 zone->journal, strbuf);
16920 }
16921 }
16922
16923 if (inline_raw(zone)) {
16924 zone_send_securedb(zone, db);
16925 }
16926 }
16927
16928 dns_db_closeversion(db, &ver, false);
16929
16930 dns_zone_log(zone, ISC_LOG_DEBUG(3), "replacing zone database");
16931
16932 if (zone->db != NULL) {
16933 zone_detachdb(zone);
16934 }
16935 zone_attachdb(zone, db);
16936 dns_db_settask(zone->db, zone->task);
16937 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED | DNS_ZONEFLG_NEEDNOTIFY);
16938 return (ISC_R_SUCCESS);
16939
16940 fail:
16941 dns_db_closeversion(db, &ver, false);
16942 return (result);
16943 }
16944
16945 /* The caller must hold the dblock as a writer. */
16946 static inline void
16947 zone_attachdb(dns_zone_t *zone, dns_db_t *db) {
16948 REQUIRE(zone->db == NULL && db != NULL);
16949
16950 dns_db_attach(db, &zone->db);
16951 }
16952
16953 /* The caller must hold the dblock as a writer. */
16954 static inline void
16955 zone_detachdb(dns_zone_t *zone) {
16956 REQUIRE(zone->db != NULL);
16957
16958 dns_db_detach(&zone->db);
16959 }
16960
16961 static void
16962 zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
16963 isc_time_t now;
16964 bool again = false;
16965 unsigned int soacount;
16966 unsigned int nscount;
16967 uint32_t serial, refresh, retry, expire, minimum;
16968 isc_result_t xfrresult = result;
16969 bool free_needed;
16970 dns_zone_t *secure = NULL;
16971
16972 REQUIRE(DNS_ZONE_VALID(zone));
16973
16974 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(1),
16975 "zone transfer finished: %s", dns_result_totext(result));
16976
16977 /*
16978 * Obtaining a lock on the zone->secure (see zone_send_secureserial)
16979 * could result in a deadlock due to a LOR so we will spin if we
16980 * can't obtain the both locks.
16981 */
16982 again:
16983 LOCK_ZONE(zone);
16984 if (inline_raw(zone)) {
16985 secure = zone->secure;
16986 INSIST(secure != zone);
16987 TRYLOCK_ZONE(result, secure);
16988 if (result != ISC_R_SUCCESS) {
16989 UNLOCK_ZONE(zone);
16990 secure = NULL;
16991 isc_thread_yield();
16992 goto again;
16993 }
16994 }
16995
16996 INSIST(DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH));
16997 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
16998 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
16999
17000 TIME_NOW(&now);
17001 switch (xfrresult) {
17002 case ISC_R_SUCCESS:
17003 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
17004 /* FALLTHROUGH */
17005 case DNS_R_UPTODATE:
17006 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FORCEXFER);
17007 /*
17008 * Has the zone expired underneath us?
17009 */
17010 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
17011 if (zone->db == NULL) {
17012 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17013 goto same_master;
17014 }
17015
17016 /*
17017 * Update the zone structure's data from the actual
17018 * SOA received.
17019 */
17020 nscount = 0;
17021 soacount = 0;
17022 INSIST(zone->db != NULL);
17023 result = zone_get_from_db(zone, zone->db, &nscount, &soacount,
17024 &serial, &refresh, &retry, &expire,
17025 &minimum, NULL);
17026 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17027 if (result == ISC_R_SUCCESS) {
17028 if (soacount != 1) {
17029 dns_zone_log(zone, ISC_LOG_ERROR,
17030 "transferred zone "
17031 "has %d SOA record%s",
17032 soacount,
17033 (soacount != 0) ? "s" : "");
17034 }
17035 if (nscount == 0) {
17036 dns_zone_log(zone, ISC_LOG_ERROR,
17037 "transferred zone "
17038 "has no NS records");
17039 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
17040 {
17041 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
17042 zone->retry = DNS_ZONE_DEFAULTRETRY;
17043 }
17044 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
17045 zone_unload(zone);
17046 goto next_master;
17047 }
17048 zone->refresh = RANGE(refresh, zone->minrefresh,
17049 zone->maxrefresh);
17050 zone->retry = RANGE(retry, zone->minretry,
17051 zone->maxretry);
17052 zone->expire = RANGE(expire,
17053 zone->refresh + zone->retry,
17054 DNS_MAX_EXPIRE);
17055 zone->minimum = minimum;
17056 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
17057 }
17058
17059 /*
17060 * Set our next update/expire times.
17061 */
17062 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
17063 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
17064 zone->refreshtime = now;
17065 DNS_ZONE_TIME_ADD(&now, zone->expire,
17066 &zone->expiretime);
17067 } else {
17068 DNS_ZONE_JITTER_ADD(&now, zone->refresh,
17069 &zone->refreshtime);
17070 DNS_ZONE_TIME_ADD(&now, zone->expire,
17071 &zone->expiretime);
17072 }
17073 if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS) {
17074 char buf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
17075 if (zone->tsigkey != NULL) {
17076 char namebuf[DNS_NAME_FORMATSIZE];
17077 dns_name_format(&zone->tsigkey->name, namebuf,
17078 sizeof(namebuf));
17079 snprintf(buf, sizeof(buf), ": TSIG '%s'",
17080 namebuf);
17081 } else {
17082 buf[0] = '\0';
17083 }
17084 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
17085 ISC_LOG_INFO, "transferred serial %u%s",
17086 serial, buf);
17087 if (inline_raw(zone)) {
17088 zone_send_secureserial(zone, serial);
17089 }
17090 }
17091
17092 /*
17093 * This is not necessary if we just performed a AXFR
17094 * however it is necessary for an IXFR / UPTODATE and
17095 * won't hurt with an AXFR.
17096 */
17097 if (zone->masterfile != NULL || zone->journal != NULL) {
17098 unsigned int delay = DNS_DUMP_DELAY;
17099
17100 result = ISC_R_FAILURE;
17101 if (zone->journal != NULL) {
17102 result = isc_file_settime(zone->journal, &now);
17103 }
17104 if (result != ISC_R_SUCCESS && zone->masterfile != NULL)
17105 {
17106 result = isc_file_settime(zone->masterfile,
17107 &now);
17108 }
17109
17110 if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NODELAY) != 0) ||
17111 result == ISC_R_FILENOTFOUND)
17112 {
17113 delay = 0;
17114 }
17115
17116 if ((result == ISC_R_SUCCESS ||
17117 result == ISC_R_FILENOTFOUND) &&
17118 zone->masterfile != NULL)
17119 {
17120 zone_needdump(zone, delay);
17121 } else if (result != ISC_R_SUCCESS) {
17122 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
17123 ISC_LOG_ERROR,
17124 "transfer: could not set file "
17125 "modification time of '%s': %s",
17126 zone->masterfile,
17127 dns_result_totext(result));
17128 }
17129 }
17130 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NODELAY);
17131 inc_stats(zone, dns_zonestatscounter_xfrsuccess);
17132 break;
17133
17134 case DNS_R_BADIXFR:
17135 /* Force retry with AXFR. */
17136 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOIXFR);
17137 goto same_master;
17138
17139 case DNS_R_TOOMANYRECORDS:
17140 case DNS_R_VERIFYFAILURE:
17141 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
17142 inc_stats(zone, dns_zonestatscounter_xfrfail);
17143 break;
17144
17145 default:
17146 next_master:
17147 /*
17148 * Skip to next failed / untried master.
17149 */
17150 do {
17151 zone->curmaster++;
17152 } while (zone->curmaster < zone->masterscnt &&
17153 zone->mastersok[zone->curmaster]);
17154 /* FALLTHROUGH */
17155 same_master:
17156 if (zone->curmaster >= zone->masterscnt) {
17157 zone->curmaster = 0;
17158 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
17159 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
17160 {
17161 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
17162 DNS_ZONE_SETFLAG(zone,
17163 DNS_ZONEFLG_USEALTXFRSRC);
17164 while (zone->curmaster < zone->masterscnt &&
17165 zone->mastersok[zone->curmaster]) {
17166 zone->curmaster++;
17167 }
17168 again = true;
17169 } else {
17170 DNS_ZONE_CLRFLAG(zone,
17171 DNS_ZONEFLG_USEALTXFRSRC);
17172 }
17173 } else {
17174 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
17175 again = true;
17176 }
17177 inc_stats(zone, dns_zonestatscounter_xfrfail);
17178 break;
17179 }
17180 zone_settimer(zone, &now);
17181
17182 /*
17183 * If creating the transfer object failed, zone->xfr is NULL.
17184 * Otherwise, we are called as the done callback of a zone
17185 * transfer object that just entered its shutting-down
17186 * state. Since we are no longer responsible for shutting
17187 * it down, we can detach our reference.
17188 */
17189 if (zone->xfr != NULL) {
17190 dns_xfrin_detach(&zone->xfr);
17191 }
17192
17193 if (zone->tsigkey != NULL) {
17194 dns_tsigkey_detach(&zone->tsigkey);
17195 }
17196
17197 /*
17198 * Handle any deferred journal compaction.
17199 */
17200 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDCOMPACT)) {
17201 dns_db_t *db = NULL;
17202 if (dns_zone_getdb(zone, &db) == ISC_R_SUCCESS) {
17203 zone_journal_compact(zone, db, zone->compact_serial);
17204 dns_db_detach(&db);
17205 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
17206 }
17207 }
17208
17209 if (secure != NULL) {
17210 UNLOCK_ZONE(secure);
17211 }
17212 /*
17213 * This transfer finishing freed up a transfer quota slot.
17214 * Let any other zones waiting for quota have it.
17215 */
17216 if (zone->zmgr != NULL &&
17217 zone->statelist == &zone->zmgr->xfrin_in_progress) {
17218 UNLOCK_ZONE(zone);
17219 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
17220 ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
17221 zone->statelist = NULL;
17222 zmgr_resume_xfrs(zone->zmgr, false);
17223 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
17224 LOCK_ZONE(zone);
17225 }
17226
17227 /*
17228 * Retry with a different server if necessary.
17229 */
17230 if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
17231 queue_soa_query(zone);
17232 }
17233
17234 isc_refcount_decrement(&zone->irefs);
17235 free_needed = exit_check(zone);
17236 UNLOCK_ZONE(zone);
17237 if (free_needed) {
17238 zone_free(zone);
17239 }
17240 }
17241
17242 static void
17243 zone_loaddone(void *arg, isc_result_t result) {
17244 static char me[] = "zone_loaddone";
17245 dns_load_t *load = arg;
17246 dns_zone_t *zone;
17247 isc_result_t tresult;
17248 dns_zone_t *secure = NULL;
17249
17250 REQUIRE(DNS_LOAD_VALID(load));
17251 zone = load->zone;
17252
17253 ENTER;
17254
17255 /*
17256 * If zone loading failed, remove the update db callbacks prior
17257 * to calling the list of callbacks in the zone load structure.
17258 */
17259 if (result != ISC_R_SUCCESS) {
17260 dns_zone_rpz_disable_db(zone, load->db);
17261 dns_zone_catz_disable_db(zone, load->db);
17262 }
17263
17264 tresult = dns_db_endload(load->db, &load->callbacks);
17265 if (tresult != ISC_R_SUCCESS &&
17266 (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
17267 {
17268 result = tresult;
17269 }
17270
17271 /*
17272 * Lock hierarchy: zmgr, zone, raw.
17273 */
17274 again:
17275 LOCK_ZONE(zone);
17276 INSIST(zone != zone->raw);
17277 if (inline_secure(zone)) {
17278 LOCK_ZONE(zone->raw);
17279 } else if (inline_raw(zone)) {
17280 secure = zone->secure;
17281 TRYLOCK_ZONE(tresult, secure);
17282 if (tresult != ISC_R_SUCCESS) {
17283 UNLOCK_ZONE(zone);
17284 secure = NULL;
17285 isc_thread_yield();
17286 goto again;
17287 }
17288 }
17289 (void)zone_postload(zone, load->db, load->loadtime, result);
17290 zonemgr_putio(&zone->readio);
17291 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADING);
17292 zone_idetach(&load->callbacks.zone);
17293 /*
17294 * Leave the zone frozen if the reload fails.
17295 */
17296 if ((result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) &&
17297 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_THAW))
17298 {
17299 zone->update_disabled = false;
17300 }
17301 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_THAW);
17302 if (inline_secure(zone)) {
17303 UNLOCK_ZONE(zone->raw);
17304 } else if (secure != NULL) {
17305 UNLOCK_ZONE(secure);
17306 }
17307 UNLOCK_ZONE(zone);
17308
17309 load->magic = 0;
17310 dns_db_detach(&load->db);
17311 if (load->zone->lctx != NULL) {
17312 dns_loadctx_detach(&load->zone->lctx);
17313 }
17314 dns_zone_idetach(&load->zone);
17315 isc_mem_putanddetach(&load->mctx, load, sizeof(*load));
17316 }
17317
17318 void
17319 dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) {
17320 REQUIRE(DNS_ZONE_VALID(zone));
17321 REQUIRE(table != NULL);
17322 REQUIRE(*table == NULL);
17323
17324 LOCK_ZONE(zone);
17325 if (zone->ssutable != NULL) {
17326 dns_ssutable_attach(zone->ssutable, table);
17327 }
17328 UNLOCK_ZONE(zone);
17329 }
17330
17331 void
17332 dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
17333 REQUIRE(DNS_ZONE_VALID(zone));
17334
17335 LOCK_ZONE(zone);
17336 if (zone->ssutable != NULL) {
17337 dns_ssutable_detach(&zone->ssutable);
17338 }
17339 if (table != NULL) {
17340 dns_ssutable_attach(table, &zone->ssutable);
17341 }
17342 UNLOCK_ZONE(zone);
17343 }
17344
17345 void
17346 dns_zone_setsigvalidityinterval(dns_zone_t *zone, uint32_t interval) {
17347 REQUIRE(DNS_ZONE_VALID(zone));
17348
17349 zone->sigvalidityinterval = interval;
17350 }
17351
17352 uint32_t
17353 dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
17354 REQUIRE(DNS_ZONE_VALID(zone));
17355
17356 return (zone->sigvalidityinterval);
17357 }
17358
17359 void
17360 dns_zone_setkeyvalidityinterval(dns_zone_t *zone, uint32_t interval) {
17361 REQUIRE(DNS_ZONE_VALID(zone));
17362
17363 zone->keyvalidityinterval = interval;
17364 }
17365
17366 uint32_t
17367 dns_zone_getkeyvalidityinterval(dns_zone_t *zone) {
17368 REQUIRE(DNS_ZONE_VALID(zone));
17369
17370 return (zone->keyvalidityinterval);
17371 }
17372
17373 void
17374 dns_zone_setsigresigninginterval(dns_zone_t *zone, uint32_t interval) {
17375 isc_time_t now;
17376
17377 REQUIRE(DNS_ZONE_VALID(zone));
17378
17379 LOCK_ZONE(zone);
17380 zone->sigresigninginterval = interval;
17381 set_resigntime(zone);
17382 if (zone->task != NULL) {
17383 TIME_NOW(&now);
17384 zone_settimer(zone, &now);
17385 }
17386 UNLOCK_ZONE(zone);
17387 }
17388
17389 uint32_t
17390 dns_zone_getsigresigninginterval(dns_zone_t *zone) {
17391 REQUIRE(DNS_ZONE_VALID(zone));
17392
17393 return (zone->sigresigninginterval);
17394 }
17395
17396 static void
17397 queue_xfrin(dns_zone_t *zone) {
17398 const char me[] = "queue_xfrin";
17399 isc_result_t result;
17400 dns_zonemgr_t *zmgr = zone->zmgr;
17401
17402 ENTER;
17403
17404 INSIST(zone->statelist == NULL);
17405
17406 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
17407 ISC_LIST_APPEND(zmgr->waiting_for_xfrin, zone, statelink);
17408 isc_refcount_increment0(&zone->irefs);
17409 zone->statelist = &zmgr->waiting_for_xfrin;
17410 result = zmgr_start_xfrin_ifquota(zmgr, zone);
17411 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
17412
17413 if (result == ISC_R_QUOTA) {
17414 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
17415 "zone transfer deferred due to quota");
17416 } else if (result != ISC_R_SUCCESS) {
17417 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
17418 "starting zone transfer: %s",
17419 isc_result_totext(result));
17420 }
17421 }
17422
17423 /*
17424 * This event callback is called when a zone has received
17425 * any necessary zone transfer quota. This is the time
17426 * to go ahead and start the transfer.
17427 */
17428 static void
17429 got_transfer_quota(isc_task_t *task, isc_event_t *event) {
17430 isc_result_t result = ISC_R_SUCCESS;
17431 dns_peer_t *peer = NULL;
17432 char master[ISC_SOCKADDR_FORMATSIZE];
17433 char source[ISC_SOCKADDR_FORMATSIZE];
17434 dns_rdatatype_t xfrtype;
17435 dns_zone_t *zone = event->ev_arg;
17436 isc_netaddr_t masterip;
17437 isc_sockaddr_t sourceaddr;
17438 isc_sockaddr_t masteraddr;
17439 isc_time_t now;
17440 const char *soa_before = "";
17441 isc_dscp_t dscp = -1;
17442 bool loaded;
17443
17444 UNUSED(task);
17445
17446 INSIST(task == zone->task);
17447
17448 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
17449 result = ISC_R_CANCELED;
17450 goto cleanup;
17451 }
17452
17453 TIME_NOW(&now);
17454
17455 isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
17456 if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
17457 &zone->sourceaddr, &now))
17458 {
17459 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
17460 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
17461 "got_transfer_quota: skipping zone transfer as "
17462 "master %s (source %s) is unreachable (cached)",
17463 master, source);
17464 result = ISC_R_CANCELED;
17465 goto cleanup;
17466 }
17467
17468 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
17469 (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
17470
17471 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR)) {
17472 soa_before = "SOA before ";
17473 }
17474 /*
17475 * Decide whether we should request IXFR or AXFR.
17476 */
17477 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
17478 loaded = (zone->db != NULL);
17479 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17480
17481 if (!loaded) {
17482 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(1),
17483 "no database exists yet, requesting AXFR of "
17484 "initial version from %s",
17485 master);
17486 xfrtype = dns_rdatatype_axfr;
17487 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
17488 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(1),
17489 "forced reload, requesting AXFR of "
17490 "initial version from %s",
17491 master);
17492 xfrtype = dns_rdatatype_axfr;
17493 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOIXFR)) {
17494 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(1),
17495 "retrying with AXFR from %s due to "
17496 "previous IXFR failure",
17497 master);
17498 xfrtype = dns_rdatatype_axfr;
17499 LOCK_ZONE(zone);
17500 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOIXFR);
17501 UNLOCK_ZONE(zone);
17502 } else {
17503 bool use_ixfr = true;
17504 if (peer != NULL) {
17505 result = dns_peer_getrequestixfr(peer, &use_ixfr);
17506 }
17507 if (peer == NULL || result != ISC_R_SUCCESS) {
17508 use_ixfr = zone->requestixfr;
17509 }
17510 if (!use_ixfr) {
17511 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
17512 ISC_LOG_DEBUG(1),
17513 "IXFR disabled, "
17514 "requesting %sAXFR from %s",
17515 soa_before, master);
17516 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR)) {
17517 xfrtype = dns_rdatatype_soa;
17518 } else {
17519 xfrtype = dns_rdatatype_axfr;
17520 }
17521 } else {
17522 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
17523 ISC_LOG_DEBUG(1),
17524 "requesting IXFR from %s", master);
17525 xfrtype = dns_rdatatype_ixfr;
17526 }
17527 }
17528
17529 /*
17530 * Determine if we should attempt to sign the request with TSIG.
17531 */
17532 result = ISC_R_NOTFOUND;
17533
17534 /*
17535 * First, look for a tsig key in the master statement, then
17536 * try for a server key.
17537 */
17538 if ((zone->masterkeynames != NULL) &&
17539 (zone->masterkeynames[zone->curmaster] != NULL))
17540 {
17541 dns_view_t *view = dns_zone_getview(zone);
17542 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
17543 result = dns_view_gettsig(view, keyname, &zone->tsigkey);
17544 }
17545 if (zone->tsigkey == NULL) {
17546 result = dns_view_getpeertsig(zone->view, &masterip,
17547 &zone->tsigkey);
17548 }
17549
17550 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
17551 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
17552 "could not get TSIG key for zone transfer: %s",
17553 isc_result_totext(result));
17554 }
17555
17556 if (zone->masterdscps != NULL) {
17557 dscp = zone->masterdscps[zone->curmaster];
17558 }
17559
17560 LOCK_ZONE(zone);
17561 masteraddr = zone->masteraddr;
17562 sourceaddr = zone->sourceaddr;
17563 switch (isc_sockaddr_pf(&masteraddr)) {
17564 case PF_INET:
17565 if (dscp == -1) {
17566 dscp = zone->xfrsource4dscp;
17567 }
17568 break;
17569 case PF_INET6:
17570 if (dscp == -1) {
17571 dscp = zone->xfrsource6dscp;
17572 }
17573 break;
17574 default:
17575 INSIST(0);
17576 ISC_UNREACHABLE();
17577 }
17578 UNLOCK_ZONE(zone);
17579 INSIST(isc_sockaddr_pf(&masteraddr) == isc_sockaddr_pf(&sourceaddr));
17580 result = dns_xfrin_create(zone, xfrtype, &masteraddr, &sourceaddr, dscp,
17581 zone->tsigkey, zone->mctx,
17582 zone->zmgr->timermgr, zone->zmgr->socketmgr,
17583 zone->task, zone_xfrdone, &zone->xfr);
17584 if (result == ISC_R_SUCCESS) {
17585 LOCK_ZONE(zone);
17586 if (xfrtype == dns_rdatatype_axfr) {
17587 if (isc_sockaddr_pf(&masteraddr) == PF_INET) {
17588 inc_stats(zone, dns_zonestatscounter_axfrreqv4);
17589 } else {
17590 inc_stats(zone, dns_zonestatscounter_axfrreqv6);
17591 }
17592 } else if (xfrtype == dns_rdatatype_ixfr) {
17593 if (isc_sockaddr_pf(&masteraddr) == PF_INET) {
17594 inc_stats(zone, dns_zonestatscounter_ixfrreqv4);
17595 } else {
17596 inc_stats(zone, dns_zonestatscounter_ixfrreqv6);
17597 }
17598 }
17599 UNLOCK_ZONE(zone);
17600 }
17601 cleanup:
17602 /*
17603 * Any failure in this function is handled like a failed
17604 * zone transfer. This ensures that we get removed from
17605 * zmgr->xfrin_in_progress.
17606 */
17607 if (result != ISC_R_SUCCESS) {
17608 zone_xfrdone(zone, result);
17609 }
17610
17611 isc_event_free(&event);
17612 }
17613
17614 /*
17615 * Update forwarding support.
17616 */
17617
17618 static void
17619 forward_destroy(dns_forward_t *forward) {
17620 forward->magic = 0;
17621 if (forward->request != NULL) {
17622 dns_request_destroy(&forward->request);
17623 }
17624 if (forward->msgbuf != NULL) {
17625 isc_buffer_free(&forward->msgbuf);
17626 }
17627 if (forward->zone != NULL) {
17628 LOCK(&forward->zone->lock);
17629 if (ISC_LINK_LINKED(forward, link)) {
17630 ISC_LIST_UNLINK(forward->zone->forwards, forward, link);
17631 }
17632 UNLOCK(&forward->zone->lock);
17633 dns_zone_idetach(&forward->zone);
17634 }
17635 isc_mem_putanddetach(&forward->mctx, forward, sizeof(*forward));
17636 }
17637
17638 static isc_result_t
17639 sendtomaster(dns_forward_t *forward) {
17640 isc_result_t result;
17641 isc_sockaddr_t src;
17642 isc_dscp_t dscp = -1;
17643
17644 LOCK_ZONE(forward->zone);
17645
17646 if (DNS_ZONE_FLAG(forward->zone, DNS_ZONEFLG_EXITING)) {
17647 UNLOCK_ZONE(forward->zone);
17648 return (ISC_R_CANCELED);
17649 }
17650
17651 if (forward->which >= forward->zone->masterscnt) {
17652 UNLOCK_ZONE(forward->zone);
17653 return (ISC_R_NOMORE);
17654 }
17655
17656 forward->addr = forward->zone->masters[forward->which];
17657 /*
17658 * Always use TCP regardless of whether the original update
17659 * used TCP.
17660 * XXX The timeout may but a bit small if we are far down a
17661 * transfer graph and the master has to try several masters.
17662 */
17663 switch (isc_sockaddr_pf(&forward->addr)) {
17664 case PF_INET:
17665 src = forward->zone->xfrsource4;
17666 dscp = forward->zone->xfrsource4dscp;
17667 break;
17668 case PF_INET6:
17669 src = forward->zone->xfrsource6;
17670 dscp = forward->zone->xfrsource6dscp;
17671 break;
17672 default:
17673 result = ISC_R_NOTIMPLEMENTED;
17674 goto unlock;
17675 }
17676 result = dns_request_createraw(forward->zone->view->requestmgr,
17677 forward->msgbuf, &src, &forward->addr,
17678 dscp, forward->options, 15 /* XXX */, 0,
17679 0, forward->zone->task, forward_callback,
17680 forward, &forward->request);
17681 if (result == ISC_R_SUCCESS) {
17682 if (!ISC_LINK_LINKED(forward, link)) {
17683 ISC_LIST_APPEND(forward->zone->forwards, forward, link);
17684 }
17685 }
17686
17687 unlock:
17688 UNLOCK_ZONE(forward->zone);
17689 return (result);
17690 }
17691
17692 static void
17693 forward_callback(isc_task_t *task, isc_event_t *event) {
17694 const char me[] = "forward_callback";
17695 dns_requestevent_t *revent = (dns_requestevent_t *)event;
17696 dns_message_t *msg = NULL;
17697 char master[ISC_SOCKADDR_FORMATSIZE];
17698 isc_result_t result;
17699 dns_forward_t *forward;
17700 dns_zone_t *zone;
17701
17702 UNUSED(task);
17703
17704 forward = revent->ev_arg;
17705 INSIST(DNS_FORWARD_VALID(forward));
17706 zone = forward->zone;
17707 INSIST(DNS_ZONE_VALID(zone));
17708
17709 ENTER;
17710
17711 isc_sockaddr_format(&forward->addr, master, sizeof(master));
17712
17713 if (revent->result != ISC_R_SUCCESS) {
17714 dns_zone_log(zone, ISC_LOG_INFO,
17715 "could not forward dynamic update to %s: %s",
17716 master, dns_result_totext(revent->result));
17717 goto next_master;
17718 }
17719
17720 dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
17721
17722 result = dns_request_getresponse(revent->request, msg,
17723 DNS_MESSAGEPARSE_PRESERVEORDER |
17724 DNS_MESSAGEPARSE_CLONEBUFFER);
17725 if (result != ISC_R_SUCCESS) {
17726 goto next_master;
17727 }
17728
17729 switch (msg->rcode) {
17730 /*
17731 * Pass these rcodes back to client.
17732 */
17733 case dns_rcode_noerror:
17734 case dns_rcode_yxdomain:
17735 case dns_rcode_yxrrset:
17736 case dns_rcode_nxrrset:
17737 case dns_rcode_refused:
17738 case dns_rcode_nxdomain: {
17739 char rcode[128];
17740 isc_buffer_t rb;
17741
17742 isc_buffer_init(&rb, rcode, sizeof(rcode));
17743 (void)dns_rcode_totext(msg->rcode, &rb);
17744 dns_zone_log(zone, ISC_LOG_INFO,
17745 "forwarded dynamic update: "
17746 "master %s returned: %.*s",
17747 master, (int)rb.used, rcode);
17748 break;
17749 }
17750
17751 /* These should not occur if the primaries/zone are valid. */
17752 case dns_rcode_notzone:
17753 case dns_rcode_notauth: {
17754 char rcode[128];
17755 isc_buffer_t rb;
17756
17757 isc_buffer_init(&rb, rcode, sizeof(rcode));
17758 (void)dns_rcode_totext(msg->rcode, &rb);
17759 dns_zone_log(zone, ISC_LOG_WARNING,
17760 "forwarding dynamic update: "
17761 "unexpected response: master %s returned: %.*s",
17762 master, (int)rb.used, rcode);
17763 goto next_master;
17764 }
17765
17766 /* Try another server for these rcodes. */
17767 case dns_rcode_formerr:
17768 case dns_rcode_servfail:
17769 case dns_rcode_notimp:
17770 case dns_rcode_badvers:
17771 default:
17772 goto next_master;
17773 }
17774
17775 /* call callback */
17776 (forward->callback)(forward->callback_arg, ISC_R_SUCCESS, msg);
17777 msg = NULL;
17778 dns_request_destroy(&forward->request);
17779 forward_destroy(forward);
17780 isc_event_free(&event);
17781 return;
17782
17783 next_master:
17784 if (msg != NULL) {
17785 dns_message_detach(&msg);
17786 }
17787 isc_event_free(&event);
17788 forward->which++;
17789 dns_request_destroy(&forward->request);
17790 result = sendtomaster(forward);
17791 if (result != ISC_R_SUCCESS) {
17792 /* call callback */
17793 dns_zone_log(zone, ISC_LOG_DEBUG(3),
17794 "exhausted dynamic update forwarder list");
17795 (forward->callback)(forward->callback_arg, result, NULL);
17796 forward_destroy(forward);
17797 }
17798 }
17799
17800 isc_result_t
17801 dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
17802 dns_updatecallback_t callback, void *callback_arg) {
17803 dns_forward_t *forward;
17804 isc_result_t result;
17805 isc_region_t *mr;
17806
17807 REQUIRE(DNS_ZONE_VALID(zone));
17808 REQUIRE(msg != NULL);
17809 REQUIRE(callback != NULL);
17810
17811 forward = isc_mem_get(zone->mctx, sizeof(*forward));
17812
17813 forward->request = NULL;
17814 forward->zone = NULL;
17815 forward->msgbuf = NULL;
17816 forward->which = 0;
17817 forward->mctx = 0;
17818 forward->callback = callback;
17819 forward->callback_arg = callback_arg;
17820 ISC_LINK_INIT(forward, link);
17821 forward->magic = FORWARD_MAGIC;
17822 forward->options = DNS_REQUESTOPT_TCP;
17823 /*
17824 * If we have a SIG(0) signed message we need to preserve the
17825 * query id as that is included in the SIG(0) computation.
17826 */
17827 if (msg->sig0 != NULL) {
17828 forward->options |= DNS_REQUESTOPT_FIXEDID;
17829 }
17830
17831 mr = dns_message_getrawmessage(msg);
17832 if (mr == NULL) {
17833 result = ISC_R_UNEXPECTEDEND;
17834 goto cleanup;
17835 }
17836
17837 isc_buffer_allocate(zone->mctx, &forward->msgbuf, mr->length);
17838 result = isc_buffer_copyregion(forward->msgbuf, mr);
17839 if (result != ISC_R_SUCCESS) {
17840 goto cleanup;
17841 }
17842
17843 isc_mem_attach(zone->mctx, &forward->mctx);
17844 dns_zone_iattach(zone, &forward->zone);
17845 result = sendtomaster(forward);
17846
17847 cleanup:
17848 if (result != ISC_R_SUCCESS) {
17849 forward_destroy(forward);
17850 }
17851 return (result);
17852 }
17853
17854 isc_result_t
17855 dns_zone_next(dns_zone_t *zone, dns_zone_t **next) {
17856 REQUIRE(DNS_ZONE_VALID(zone));
17857 REQUIRE(next != NULL && *next == NULL);
17858
17859 *next = ISC_LIST_NEXT(zone, link);
17860 if (*next == NULL) {
17861 return (ISC_R_NOMORE);
17862 } else {
17863 return (ISC_R_SUCCESS);
17864 }
17865 }
17866
17867 isc_result_t
17868 dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) {
17869 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17870 REQUIRE(first != NULL && *first == NULL);
17871
17872 *first = ISC_LIST_HEAD(zmgr->zones);
17873 if (*first == NULL) {
17874 return (ISC_R_NOMORE);
17875 } else {
17876 return (ISC_R_SUCCESS);
17877 }
17878 }
17879
17880 /***
17881 *** Zone manager.
17882 ***/
17883
17884 isc_result_t
17885 dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
17886 isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
17887 dns_zonemgr_t **zmgrp) {
17888 dns_zonemgr_t *zmgr;
17889 isc_result_t result;
17890
17891 zmgr = isc_mem_get(mctx, sizeof(*zmgr));
17892 zmgr->mctx = NULL;
17893 isc_refcount_init(&zmgr->refs, 1);
17894 isc_mem_attach(mctx, &zmgr->mctx);
17895 zmgr->taskmgr = taskmgr;
17896 zmgr->timermgr = timermgr;
17897 zmgr->socketmgr = socketmgr;
17898 zmgr->zonetasks = NULL;
17899 zmgr->loadtasks = NULL;
17900 zmgr->mctxpool = NULL;
17901 zmgr->task = NULL;
17902 zmgr->notifyrl = NULL;
17903 zmgr->refreshrl = NULL;
17904 zmgr->startupnotifyrl = NULL;
17905 zmgr->startuprefreshrl = NULL;
17906 ISC_LIST_INIT(zmgr->zones);
17907 ISC_LIST_INIT(zmgr->waiting_for_xfrin);
17908 ISC_LIST_INIT(zmgr->xfrin_in_progress);
17909 memset(zmgr->unreachable, 0, sizeof(zmgr->unreachable));
17910 result = isc_rwlock_init(&zmgr->rwlock, 0, 0);
17911 if (result != ISC_R_SUCCESS) {
17912 goto free_mem;
17913 }
17914
17915 zmgr->transfersin = 10;
17916 zmgr->transfersperns = 2;
17917
17918 /* Unreachable lock. */
17919 result = isc_rwlock_init(&zmgr->urlock, 0, 0);
17920 if (result != ISC_R_SUCCESS) {
17921 goto free_rwlock;
17922 }
17923
17924 /* Create a single task for queueing of SOA queries. */
17925 result = isc_task_create(taskmgr, 1, &zmgr->task);
17926 if (result != ISC_R_SUCCESS) {
17927 goto free_urlock;
17928 }
17929
17930 isc_task_setname(zmgr->task, "zmgr", zmgr);
17931 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
17932 &zmgr->notifyrl);
17933 if (result != ISC_R_SUCCESS) {
17934 goto free_task;
17935 }
17936
17937 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
17938 &zmgr->refreshrl);
17939 if (result != ISC_R_SUCCESS) {
17940 goto free_notifyrl;
17941 }
17942
17943 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
17944 &zmgr->startupnotifyrl);
17945 if (result != ISC_R_SUCCESS) {
17946 goto free_refreshrl;
17947 }
17948
17949 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
17950 &zmgr->startuprefreshrl);
17951 if (result != ISC_R_SUCCESS) {
17952 goto free_startupnotifyrl;
17953 }
17954
17955 /* default to 20 refresh queries / notifies per second. */
17956 setrl(zmgr->notifyrl, &zmgr->notifyrate, 20);
17957 setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, 20);
17958 setrl(zmgr->refreshrl, &zmgr->serialqueryrate, 20);
17959 setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, 20);
17960 isc_ratelimiter_setpushpop(zmgr->startupnotifyrl, true);
17961 isc_ratelimiter_setpushpop(zmgr->startuprefreshrl, true);
17962
17963 zmgr->iolimit = 1;
17964 zmgr->ioactive = 0;
17965 ISC_LIST_INIT(zmgr->high);
17966 ISC_LIST_INIT(zmgr->low);
17967
17968 isc_mutex_init(&zmgr->iolock);
17969
17970 zmgr->magic = ZONEMGR_MAGIC;
17971
17972 *zmgrp = zmgr;
17973 return (ISC_R_SUCCESS);
17974
17975 #if 0
17976 free_iolock:
17977 isc_mutex_destroy(&zmgr->iolock);
17978 #endif /* if 0 */
17979 free_startupnotifyrl:
17980 isc_ratelimiter_detach(&zmgr->startupnotifyrl);
17981 free_refreshrl:
17982 isc_ratelimiter_detach(&zmgr->refreshrl);
17983 free_notifyrl:
17984 isc_ratelimiter_detach(&zmgr->notifyrl);
17985 free_task:
17986 isc_task_detach(&zmgr->task);
17987 free_urlock:
17988 isc_rwlock_destroy(&zmgr->urlock);
17989 free_rwlock:
17990 isc_rwlock_destroy(&zmgr->rwlock);
17991 free_mem:
17992 isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
17993 isc_mem_detach(&mctx);
17994 return (result);
17995 }
17996
17997 isc_result_t
17998 dns_zonemgr_createzone(dns_zonemgr_t *zmgr, dns_zone_t **zonep) {
17999 isc_result_t result;
18000 isc_mem_t *mctx = NULL;
18001 dns_zone_t *zone = NULL;
18002 void *item;
18003
18004 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18005 REQUIRE(zonep != NULL && *zonep == NULL);
18006
18007 if (zmgr->mctxpool == NULL) {
18008 return (ISC_R_FAILURE);
18009 }
18010
18011 item = isc_pool_get(zmgr->mctxpool);
18012 if (item == NULL) {
18013 return (ISC_R_FAILURE);
18014 }
18015
18016 isc_mem_attach((isc_mem_t *)item, &mctx);
18017 result = dns_zone_create(&zone, mctx);
18018 isc_mem_detach(&mctx);
18019
18020 if (result == ISC_R_SUCCESS) {
18021 *zonep = zone;
18022 }
18023
18024 return (result);
18025 }
18026
18027 isc_result_t
18028 dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
18029 isc_result_t result;
18030
18031 REQUIRE(DNS_ZONE_VALID(zone));
18032 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18033
18034 if (zmgr->zonetasks == NULL) {
18035 return (ISC_R_FAILURE);
18036 }
18037
18038 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18039 LOCK_ZONE(zone);
18040 REQUIRE(zone->task == NULL);
18041 REQUIRE(zone->timer == NULL);
18042 REQUIRE(zone->zmgr == NULL);
18043
18044 isc_taskpool_gettask(zmgr->zonetasks, &zone->task);
18045 isc_taskpool_gettask(zmgr->loadtasks, &zone->loadtask);
18046
18047 /*
18048 * Set the task name. The tag will arbitrarily point to one
18049 * of the zones sharing the task (in practice, the one
18050 * to be managed last).
18051 */
18052 isc_task_setname(zone->task, "zone", zone);
18053 isc_task_setname(zone->loadtask, "loadzone", zone);
18054
18055 result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive, NULL,
18056 NULL, zone->task, zone_timer, zone,
18057 &zone->timer);
18058
18059 if (result != ISC_R_SUCCESS) {
18060 goto cleanup_tasks;
18061 }
18062
18063 /*
18064 * The timer "holds" a iref.
18065 */
18066 isc_refcount_increment0(&zone->irefs);
18067
18068 ISC_LIST_APPEND(zmgr->zones, zone, link);
18069 zone->zmgr = zmgr;
18070 isc_refcount_increment(&zmgr->refs);
18071
18072 goto unlock;
18073
18074 cleanup_tasks:
18075 isc_task_detach(&zone->loadtask);
18076 isc_task_detach(&zone->task);
18077
18078 unlock:
18079 UNLOCK_ZONE(zone);
18080 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18081 return (result);
18082 }
18083
18084 void
18085 dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
18086 bool free_now = false;
18087
18088 REQUIRE(DNS_ZONE_VALID(zone));
18089 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18090 REQUIRE(zone->zmgr == zmgr);
18091
18092 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18093 LOCK_ZONE(zone);
18094
18095 ISC_LIST_UNLINK(zmgr->zones, zone, link);
18096 zone->zmgr = NULL;
18097
18098 if (isc_refcount_decrement(&zmgr->refs) == 1) {
18099 free_now = true;
18100 }
18101
18102 UNLOCK_ZONE(zone);
18103 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18104
18105 if (free_now) {
18106 zonemgr_free(zmgr);
18107 }
18108 ENSURE(zone->zmgr == NULL);
18109 }
18110
18111 void
18112 dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) {
18113 REQUIRE(DNS_ZONEMGR_VALID(source));
18114 REQUIRE(target != NULL && *target == NULL);
18115
18116 isc_refcount_increment(&source->refs);
18117
18118 *target = source;
18119 }
18120
18121 void
18122 dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
18123 dns_zonemgr_t *zmgr;
18124
18125 REQUIRE(zmgrp != NULL);
18126 zmgr = *zmgrp;
18127 *zmgrp = NULL;
18128 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18129
18130 if (isc_refcount_decrement(&zmgr->refs) == 1) {
18131 zonemgr_free(zmgr);
18132 }
18133 }
18134
18135 isc_result_t
18136 dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
18137 dns_zone_t *p;
18138
18139 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18140
18141 RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
18142 for (p = ISC_LIST_HEAD(zmgr->zones); p != NULL;
18143 p = ISC_LIST_NEXT(p, link)) {
18144 dns_zone_maintenance(p);
18145 }
18146 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
18147
18148 /*
18149 * Recent configuration changes may have increased the
18150 * amount of available transfers quota. Make sure any
18151 * transfers currently blocked on quota get started if
18152 * possible.
18153 */
18154 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18155 zmgr_resume_xfrs(zmgr, true);
18156 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18157 return (ISC_R_SUCCESS);
18158 }
18159
18160 void
18161 dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) {
18162 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18163
18164 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18165 zmgr_resume_xfrs(zmgr, true);
18166 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18167 }
18168
18169 void
18170 dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
18171 dns_zone_t *zone;
18172
18173 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18174
18175 isc_ratelimiter_shutdown(zmgr->notifyrl);
18176 isc_ratelimiter_shutdown(zmgr->refreshrl);
18177 isc_ratelimiter_shutdown(zmgr->startupnotifyrl);
18178 isc_ratelimiter_shutdown(zmgr->startuprefreshrl);
18179
18180 if (zmgr->task != NULL) {
18181 isc_task_destroy(&zmgr->task);
18182 }
18183 if (zmgr->zonetasks != NULL) {
18184 isc_taskpool_destroy(&zmgr->zonetasks);
18185 }
18186 if (zmgr->loadtasks != NULL) {
18187 isc_taskpool_destroy(&zmgr->loadtasks);
18188 }
18189 if (zmgr->mctxpool != NULL) {
18190 isc_pool_destroy(&zmgr->mctxpool);
18191 }
18192
18193 RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
18194 for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
18195 zone = ISC_LIST_NEXT(zone, link))
18196 {
18197 LOCK_ZONE(zone);
18198 forward_cancel(zone);
18199 UNLOCK_ZONE(zone);
18200 }
18201 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
18202 }
18203
18204 static isc_result_t
18205 mctxinit(void **target, void *arg) {
18206 isc_mem_t *mctx = NULL;
18207
18208 UNUSED(arg);
18209
18210 REQUIRE(target != NULL && *target == NULL);
18211
18212 isc_mem_create(&mctx);
18213 isc_mem_setname(mctx, "zonemgr-pool", NULL);
18214
18215 *target = mctx;
18216 return (ISC_R_SUCCESS);
18217 }
18218
18219 static void
18220 mctxfree(void **target) {
18221 isc_mem_t *mctx = *(isc_mem_t **)target;
18222 isc_mem_detach(&mctx);
18223 *target = NULL;
18224 }
18225
18226 #define ZONES_PER_TASK 100
18227 #define ZONES_PER_MCTX 1000
18228
18229 isc_result_t
18230 dns_zonemgr_setsize(dns_zonemgr_t *zmgr, int num_zones) {
18231 isc_result_t result;
18232 int ntasks = num_zones / ZONES_PER_TASK;
18233 int nmctx = num_zones / ZONES_PER_MCTX;
18234 isc_taskpool_t *pool = NULL;
18235 isc_pool_t *mctxpool = NULL;
18236
18237 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18238
18239 /*
18240 * For anything fewer than 1000 zones we use 10 tasks in
18241 * the task pools. More than that, and we'll scale at one
18242 * task per 100 zones. Similarly, for anything smaller than
18243 * 2000 zones we use 2 memory contexts, then scale at 1:1000.
18244 */
18245 if (ntasks < 10) {
18246 ntasks = 10;
18247 }
18248 if (nmctx < 2) {
18249 nmctx = 2;
18250 }
18251
18252 /* Create or resize the zone task pools. */
18253 if (zmgr->zonetasks == NULL) {
18254 result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx, ntasks,
18255 2, &pool);
18256 } else {
18257 result = isc_taskpool_expand(&zmgr->zonetasks, ntasks, &pool);
18258 }
18259
18260 if (result == ISC_R_SUCCESS) {
18261 zmgr->zonetasks = pool;
18262 }
18263
18264 pool = NULL;
18265 if (zmgr->loadtasks == NULL) {
18266 result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx, ntasks,
18267 2, &pool);
18268 } else {
18269 result = isc_taskpool_expand(&zmgr->loadtasks, ntasks, &pool);
18270 }
18271
18272 if (result == ISC_R_SUCCESS) {
18273 zmgr->loadtasks = pool;
18274 }
18275
18276 /*
18277 * We always set all tasks in the zone-load task pool to
18278 * privileged. This prevents other tasks in the system from
18279 * running while the server task manager is in privileged
18280 * mode.
18281 *
18282 * NOTE: If we start using task privileges for any other
18283 * part of the system than zone tasks, then this will need to be
18284 * revisted. In that case we'd want to turn on privileges for
18285 * zone tasks only when we were loading, and turn them off the
18286 * rest of the time. For now, however, it's okay to just
18287 * set it and forget it.
18288 */
18289 isc_taskpool_setprivilege(zmgr->loadtasks, true);
18290
18291 /* Create or resize the zone memory context pool. */
18292 if (zmgr->mctxpool == NULL) {
18293 result = isc_pool_create(zmgr->mctx, nmctx, mctxfree, mctxinit,
18294 NULL, &mctxpool);
18295 } else {
18296 result = isc_pool_expand(&zmgr->mctxpool, nmctx, &mctxpool);
18297 }
18298
18299 if (result == ISC_R_SUCCESS) {
18300 zmgr->mctxpool = mctxpool;
18301 }
18302
18303 return (result);
18304 }
18305
18306 static void
18307 zonemgr_free(dns_zonemgr_t *zmgr) {
18308 isc_mem_t *mctx;
18309
18310 INSIST(ISC_LIST_EMPTY(zmgr->zones));
18311
18312 zmgr->magic = 0;
18313
18314 isc_refcount_destroy(&zmgr->refs);
18315 isc_mutex_destroy(&zmgr->iolock);
18316 isc_ratelimiter_detach(&zmgr->notifyrl);
18317 isc_ratelimiter_detach(&zmgr->refreshrl);
18318 isc_ratelimiter_detach(&zmgr->startupnotifyrl);
18319 isc_ratelimiter_detach(&zmgr->startuprefreshrl);
18320
18321 isc_rwlock_destroy(&zmgr->urlock);
18322 isc_rwlock_destroy(&zmgr->rwlock);
18323 mctx = zmgr->mctx;
18324 isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
18325 isc_mem_detach(&mctx);
18326 }
18327
18328 void
18329 dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, uint32_t value) {
18330 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18331
18332 zmgr->transfersin = value;
18333 }
18334
18335 uint32_t
18336 dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) {
18337 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18338
18339 return (zmgr->transfersin);
18340 }
18341
18342 void
18343 dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, uint32_t value) {
18344 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18345
18346 zmgr->transfersperns = value;
18347 }
18348
18349 uint32_t
18350 dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr) {
18351 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18352
18353 return (zmgr->transfersperns);
18354 }
18355
18356 /*
18357 * Try to start a new incoming zone transfer to fill a quota
18358 * slot that was just vacated.
18359 *
18360 * Requires:
18361 * The zone manager is locked by the caller.
18362 */
18363 static void
18364 zmgr_resume_xfrs(dns_zonemgr_t *zmgr, bool multi) {
18365 dns_zone_t *zone;
18366 dns_zone_t *next;
18367
18368 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin); zone != NULL;
18369 zone = next) {
18370 isc_result_t result;
18371 next = ISC_LIST_NEXT(zone, statelink);
18372 result = zmgr_start_xfrin_ifquota(zmgr, zone);
18373 if (result == ISC_R_SUCCESS) {
18374 if (multi) {
18375 continue;
18376 }
18377 /*
18378 * We successfully filled the slot. We're done.
18379 */
18380 break;
18381 } else if (result == ISC_R_QUOTA) {
18382 /*
18383 * Not enough quota. This is probably the per-server
18384 * quota, because we usually get called when a unit of
18385 * global quota has just been freed. Try the next
18386 * zone, it may succeed if it uses another master.
18387 */
18388 continue;
18389 } else {
18390 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
18391 ISC_LOG_DEBUG(1),
18392 "starting zone transfer: %s",
18393 isc_result_totext(result));
18394 break;
18395 }
18396 }
18397 }
18398
18399 /*
18400 * Try to start an incoming zone transfer for 'zone', quota permitting.
18401 *
18402 * Requires:
18403 * The zone manager is locked by the caller.
18404 *
18405 * Returns:
18406 * ISC_R_SUCCESS There was enough quota and we attempted to
18407 * start a transfer. zone_xfrdone() has been or will
18408 * be called.
18409 * ISC_R_QUOTA Not enough quota.
18410 * Others Failure.
18411 */
18412 static isc_result_t
18413 zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
18414 dns_peer_t *peer = NULL;
18415 isc_netaddr_t masterip;
18416 uint32_t nxfrsin, nxfrsperns;
18417 dns_zone_t *x;
18418 uint32_t maxtransfersin, maxtransfersperns;
18419 isc_event_t *e;
18420
18421 /*
18422 * If we are exiting just pretend we got quota so the zone will
18423 * be cleaned up in the zone's task context.
18424 */
18425 LOCK_ZONE(zone);
18426 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
18427 UNLOCK_ZONE(zone);
18428 goto gotquota;
18429 }
18430
18431 /*
18432 * Find any configured information about the server we'd
18433 * like to transfer this zone from.
18434 */
18435 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
18436 (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
18437 UNLOCK_ZONE(zone);
18438
18439 /*
18440 * Determine the total maximum number of simultaneous
18441 * transfers allowed, and the maximum for this specific
18442 * master.
18443 */
18444 maxtransfersin = zmgr->transfersin;
18445 maxtransfersperns = zmgr->transfersperns;
18446 if (peer != NULL) {
18447 (void)dns_peer_gettransfers(peer, &maxtransfersperns);
18448 }
18449
18450 /*
18451 * Count the total number of transfers that are in progress,
18452 * and the number of transfers in progress from this master.
18453 * We linearly scan a list of all transfers; if this turns
18454 * out to be too slow, we could hash on the master address.
18455 */
18456 nxfrsin = nxfrsperns = 0;
18457 for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress); x != NULL;
18458 x = ISC_LIST_NEXT(x, statelink))
18459 {
18460 isc_netaddr_t xip;
18461
18462 LOCK_ZONE(x);
18463 isc_netaddr_fromsockaddr(&xip, &x->masteraddr);
18464 UNLOCK_ZONE(x);
18465
18466 nxfrsin++;
18467 if (isc_netaddr_equal(&xip, &masterip)) {
18468 nxfrsperns++;
18469 }
18470 }
18471
18472 /* Enforce quota. */
18473 if (nxfrsin >= maxtransfersin) {
18474 return (ISC_R_QUOTA);
18475 }
18476
18477 if (nxfrsperns >= maxtransfersperns) {
18478 return (ISC_R_QUOTA);
18479 }
18480
18481 gotquota:
18482 /*
18483 * We have sufficient quota. Move the zone to the "xfrin_in_progress"
18484 * list and send it an event to let it start the actual transfer in the
18485 * context of its own task.
18486 */
18487 e = isc_event_allocate(zmgr->mctx, zmgr, DNS_EVENT_ZONESTARTXFRIN,
18488 got_transfer_quota, zone, sizeof(isc_event_t));
18489
18490 LOCK_ZONE(zone);
18491 INSIST(zone->statelist == &zmgr->waiting_for_xfrin);
18492 ISC_LIST_UNLINK(zmgr->waiting_for_xfrin, zone, statelink);
18493 ISC_LIST_APPEND(zmgr->xfrin_in_progress, zone, statelink);
18494 zone->statelist = &zmgr->xfrin_in_progress;
18495 isc_task_send(zone->task, &e);
18496 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
18497 "Transfer started.");
18498 UNLOCK_ZONE(zone);
18499
18500 return (ISC_R_SUCCESS);
18501 }
18502
18503 void
18504 dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, uint32_t iolimit) {
18505 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18506 REQUIRE(iolimit > 0);
18507
18508 zmgr->iolimit = iolimit;
18509 }
18510
18511 uint32_t
18512 dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr) {
18513 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18514
18515 return (zmgr->iolimit);
18516 }
18517
18518 /*
18519 * Get permission to request a file handle from the OS.
18520 * An event will be sent to action when one is available.
18521 * There are two queues available (high and low), the high
18522 * queue will be serviced before the low one.
18523 *
18524 * zonemgr_putio() must be called after the event is delivered to
18525 * 'action'.
18526 */
18527
18528 static isc_result_t
18529 zonemgr_getio(dns_zonemgr_t *zmgr, bool high, isc_task_t *task,
18530 isc_taskaction_t action, void *arg, dns_io_t **iop) {
18531 dns_io_t *io;
18532 bool queue;
18533
18534 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18535 REQUIRE(iop != NULL && *iop == NULL);
18536
18537 io = isc_mem_get(zmgr->mctx, sizeof(*io));
18538
18539 io->event = isc_event_allocate(zmgr->mctx, task, DNS_EVENT_IOREADY,
18540 action, arg, sizeof(*io->event));
18541
18542 io->zmgr = zmgr;
18543 io->high = high;
18544 io->task = NULL;
18545 isc_task_attach(task, &io->task);
18546 ISC_LINK_INIT(io, link);
18547 io->magic = IO_MAGIC;
18548
18549 LOCK(&zmgr->iolock);
18550 zmgr->ioactive++;
18551 queue = (zmgr->ioactive > zmgr->iolimit);
18552 if (queue) {
18553 if (io->high) {
18554 ISC_LIST_APPEND(zmgr->high, io, link);
18555 } else {
18556 ISC_LIST_APPEND(zmgr->low, io, link);
18557 }
18558 }
18559 UNLOCK(&zmgr->iolock);
18560 *iop = io;
18561
18562 if (!queue) {
18563 isc_task_send(io->task, &io->event);
18564 }
18565 return (ISC_R_SUCCESS);
18566 }
18567
18568 static void
18569 zonemgr_putio(dns_io_t **iop) {
18570 dns_io_t *io;
18571 dns_io_t *next;
18572 dns_zonemgr_t *zmgr;
18573
18574 REQUIRE(iop != NULL);
18575 io = *iop;
18576 *iop = NULL;
18577 REQUIRE(DNS_IO_VALID(io));
18578
18579 INSIST(!ISC_LINK_LINKED(io, link));
18580 INSIST(io->event == NULL);
18581
18582 zmgr = io->zmgr;
18583 isc_task_detach(&io->task);
18584 io->magic = 0;
18585 isc_mem_put(zmgr->mctx, io, sizeof(*io));
18586
18587 LOCK(&zmgr->iolock);
18588 INSIST(zmgr->ioactive > 0);
18589 zmgr->ioactive--;
18590 next = HEAD(zmgr->high);
18591 if (next == NULL) {
18592 next = HEAD(zmgr->low);
18593 }
18594 if (next != NULL) {
18595 if (next->high) {
18596 ISC_LIST_UNLINK(zmgr->high, next, link);
18597 } else {
18598 ISC_LIST_UNLINK(zmgr->low, next, link);
18599 }
18600 INSIST(next->event != NULL);
18601 }
18602 UNLOCK(&zmgr->iolock);
18603 if (next != NULL) {
18604 isc_task_send(next->task, &next->event);
18605 }
18606 }
18607
18608 static void
18609 zonemgr_cancelio(dns_io_t *io) {
18610 bool send_event = false;
18611
18612 REQUIRE(DNS_IO_VALID(io));
18613
18614 /*
18615 * If we are queued to be run then dequeue.
18616 */
18617 LOCK(&io->zmgr->iolock);
18618 if (ISC_LINK_LINKED(io, link)) {
18619 if (io->high) {
18620 ISC_LIST_UNLINK(io->zmgr->high, io, link);
18621 } else {
18622 ISC_LIST_UNLINK(io->zmgr->low, io, link);
18623 }
18624
18625 send_event = true;
18626 INSIST(io->event != NULL);
18627 }
18628 UNLOCK(&io->zmgr->iolock);
18629 if (send_event) {
18630 io->event->ev_attributes |= ISC_EVENTATTR_CANCELED;
18631 isc_task_send(io->task, &io->event);
18632 }
18633 }
18634
18635 static void
18636 zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
18637 char *buf;
18638 int buflen;
18639 isc_result_t result;
18640
18641 buflen = strlen(path) + strlen(templat) + 2;
18642
18643 buf = isc_mem_get(zone->mctx, buflen);
18644
18645 result = isc_file_template(path, templat, buf, buflen);
18646 if (result != ISC_R_SUCCESS) {
18647 goto cleanup;
18648 }
18649
18650 result = isc_file_renameunique(path, buf);
18651 if (result != ISC_R_SUCCESS) {
18652 goto cleanup;
18653 }
18654
18655 dns_zone_log(zone, ISC_LOG_WARNING,
18656 "unable to load from '%s'; "
18657 "renaming file to '%s' for failure analysis and "
18658 "retransferring.",
18659 path, buf);
18660
18661 cleanup:
18662 isc_mem_put(zone->mctx, buf, buflen);
18663 }
18664
18665 static void
18666 setrl(isc_ratelimiter_t *rl, unsigned int *rate, unsigned int value) {
18667 isc_interval_t interval;
18668 uint32_t s, ns;
18669 uint32_t pertic;
18670 isc_result_t result;
18671
18672 if (value == 0) {
18673 value = 1;
18674 }
18675
18676 if (value == 1) {
18677 s = 1;
18678 ns = 0;
18679 pertic = 1;
18680 } else if (value <= 10) {
18681 s = 0;
18682 ns = 1000000000 / value;
18683 pertic = 1;
18684 } else {
18685 s = 0;
18686 ns = (1000000000 / value) * 10;
18687 pertic = 10;
18688 }
18689
18690 isc_interval_set(&interval, s, ns);
18691
18692 result = isc_ratelimiter_setinterval(rl, &interval);
18693 RUNTIME_CHECK(result == ISC_R_SUCCESS);
18694 isc_ratelimiter_setpertic(rl, pertic);
18695
18696 *rate = value;
18697 }
18698
18699 void
18700 dns_zonemgr_setnotifyrate(dns_zonemgr_t *zmgr, unsigned int value) {
18701 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18702
18703 setrl(zmgr->notifyrl, &zmgr->notifyrate, value);
18704 }
18705
18706 void
18707 dns_zonemgr_setstartupnotifyrate(dns_zonemgr_t *zmgr, unsigned int value) {
18708 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18709
18710 setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, value);
18711 }
18712
18713 void
18714 dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) {
18715 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18716
18717 setrl(zmgr->refreshrl, &zmgr->serialqueryrate, value);
18718 /* XXXMPA separate out once we have the code to support this. */
18719 setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, value);
18720 }
18721
18722 unsigned int
18723 dns_zonemgr_getnotifyrate(dns_zonemgr_t *zmgr) {
18724 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18725
18726 return (zmgr->notifyrate);
18727 }
18728
18729 unsigned int
18730 dns_zonemgr_getstartupnotifyrate(dns_zonemgr_t *zmgr) {
18731 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18732
18733 return (zmgr->startupnotifyrate);
18734 }
18735
18736 unsigned int
18737 dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
18738 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18739
18740 return (zmgr->serialqueryrate);
18741 }
18742
18743 bool
18744 dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
18745 isc_sockaddr_t *local, isc_time_t *now) {
18746 unsigned int i;
18747 uint32_t seconds = isc_time_seconds(now);
18748 uint32_t count = 0;
18749
18750 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18751
18752 RWLOCK(&zmgr->urlock, isc_rwlocktype_read);
18753 for (i = 0; i < UNREACH_CACHE_SIZE; i++) {
18754 if (atomic_load(&zmgr->unreachable[i].expire) >= seconds &&
18755 isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
18756 isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
18757 {
18758 atomic_store_relaxed(&zmgr->unreachable[i].last,
18759 seconds);
18760 count = zmgr->unreachable[i].count;
18761 break;
18762 }
18763 }
18764 RWUNLOCK(&zmgr->urlock, isc_rwlocktype_read);
18765 return (i < UNREACH_CACHE_SIZE && count > 1U);
18766 }
18767
18768 void
18769 dns_zonemgr_unreachabledel(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
18770 isc_sockaddr_t *local) {
18771 unsigned int i;
18772 char master[ISC_SOCKADDR_FORMATSIZE];
18773 char source[ISC_SOCKADDR_FORMATSIZE];
18774
18775 isc_sockaddr_format(remote, master, sizeof(master));
18776 isc_sockaddr_format(local, source, sizeof(source));
18777
18778 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18779
18780 RWLOCK(&zmgr->urlock, isc_rwlocktype_read);
18781 for (i = 0; i < UNREACH_CACHE_SIZE; i++) {
18782 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
18783 isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
18784 {
18785 atomic_store_relaxed(&zmgr->unreachable[i].expire, 0);
18786 break;
18787 }
18788 }
18789 RWUNLOCK(&zmgr->urlock, isc_rwlocktype_read);
18790 }
18791
18792 void
18793 dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
18794 isc_sockaddr_t *local, isc_time_t *now) {
18795 uint32_t seconds = isc_time_seconds(now);
18796 uint32_t expire = 0, last = seconds;
18797 unsigned int slot = UNREACH_CACHE_SIZE, oldest = 0;
18798 bool update_entry = true;
18799 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18800
18801 RWLOCK(&zmgr->urlock, isc_rwlocktype_write);
18802 for (unsigned int i = 0; i < UNREACH_CACHE_SIZE; i++) {
18803 /* Existing entry? */
18804 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
18805 isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
18806 {
18807 update_entry = false;
18808 slot = i;
18809 expire = atomic_load_relaxed(
18810 &zmgr->unreachable[i].expire);
18811 break;
18812 }
18813 /* Pick first empty slot? */
18814 if (atomic_load_relaxed(&zmgr->unreachable[i].expire) < seconds)
18815 {
18816 slot = i;
18817 break;
18818 }
18819 /* The worst case, least recently used slot? */
18820 if (atomic_load_relaxed(&zmgr->unreachable[i].last) < last) {
18821 last = atomic_load_relaxed(&zmgr->unreachable[i].last);
18822 oldest = i;
18823 }
18824 }
18825
18826 /* We haven't found any existing or free slots, use the oldest */
18827 if (slot == UNREACH_CACHE_SIZE) {
18828 slot = oldest;
18829 }
18830
18831 if (expire < seconds) {
18832 /* Expired or new entry, reset count to 1 */
18833 zmgr->unreachable[slot].count = 1;
18834 } else {
18835 zmgr->unreachable[slot].count++;
18836 }
18837 atomic_store_relaxed(&zmgr->unreachable[slot].expire,
18838 seconds + UNREACH_HOLD_TIME);
18839 atomic_store_relaxed(&zmgr->unreachable[slot].last, seconds);
18840 if (update_entry) {
18841 zmgr->unreachable[slot].remote = *remote;
18842 zmgr->unreachable[slot].local = *local;
18843 }
18844
18845 RWUNLOCK(&zmgr->urlock, isc_rwlocktype_write);
18846 }
18847
18848 void
18849 dns_zone_forcereload(dns_zone_t *zone) {
18850 REQUIRE(DNS_ZONE_VALID(zone));
18851
18852 if (zone->type == dns_zone_master ||
18853 (zone->type == dns_zone_redirect && zone->masters == NULL))
18854 {
18855 return;
18856 }
18857
18858 LOCK_ZONE(zone);
18859 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
18860 UNLOCK_ZONE(zone);
18861 dns_zone_refresh(zone);
18862 }
18863
18864 bool
18865 dns_zone_isforced(dns_zone_t *zone) {
18866 REQUIRE(DNS_ZONE_VALID(zone));
18867
18868 return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER));
18869 }
18870
18871 isc_result_t
18872 dns_zone_setstatistics(dns_zone_t *zone, bool on) {
18873 /*
18874 * This function is obsoleted.
18875 */
18876 UNUSED(zone);
18877 UNUSED(on);
18878 return (ISC_R_NOTIMPLEMENTED);
18879 }
18880
18881 uint64_t *
18882 dns_zone_getstatscounters(dns_zone_t *zone) {
18883 /*
18884 * This function is obsoleted.
18885 */
18886 UNUSED(zone);
18887 return (NULL);
18888 }
18889
18890 void
18891 dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats) {
18892 REQUIRE(DNS_ZONE_VALID(zone));
18893 REQUIRE(zone->stats == NULL);
18894
18895 LOCK_ZONE(zone);
18896 zone->stats = NULL;
18897 isc_stats_attach(stats, &zone->stats);
18898 UNLOCK_ZONE(zone);
18899 }
18900
18901 void
18902 dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats) {
18903 REQUIRE(DNS_ZONE_VALID(zone));
18904
18905 LOCK_ZONE(zone);
18906 if (zone->requeststats_on && stats == NULL) {
18907 zone->requeststats_on = false;
18908 } else if (!zone->requeststats_on && stats != NULL) {
18909 if (zone->requeststats == NULL) {
18910 isc_stats_attach(stats, &zone->requeststats);
18911 zone->requeststats_on = true;
18912 }
18913 }
18914 UNLOCK_ZONE(zone);
18915 }
18916
18917 void
18918 dns_zone_setrcvquerystats(dns_zone_t *zone, dns_stats_t *stats) {
18919 REQUIRE(DNS_ZONE_VALID(zone));
18920
18921 LOCK_ZONE(zone);
18922 if (zone->requeststats_on && stats != NULL) {
18923 if (zone->rcvquerystats == NULL) {
18924 dns_stats_attach(stats, &zone->rcvquerystats);
18925 zone->requeststats_on = true;
18926 }
18927 }
18928 UNLOCK_ZONE(zone);
18929 }
18930
18931 void
18932 dns_zone_setdnssecsignstats(dns_zone_t *zone, dns_stats_t *stats) {
18933 REQUIRE(DNS_ZONE_VALID(zone));
18934
18935 LOCK_ZONE(zone);
18936 if (stats != NULL && zone->dnssecsignstats == NULL) {
18937 dns_stats_attach(stats, &zone->dnssecsignstats);
18938 }
18939 UNLOCK_ZONE(zone);
18940 }
18941
18942 dns_stats_t *
18943 dns_zone_getdnssecsignstats(dns_zone_t *zone) {
18944 REQUIRE(DNS_ZONE_VALID(zone));
18945
18946 return (zone->dnssecsignstats);
18947 }
18948
18949 isc_stats_t *
18950 dns_zone_getrequeststats(dns_zone_t *zone) {
18951 /*
18952 * We don't lock zone for efficiency reason. This is not catastrophic
18953 * because requeststats must always be valid when requeststats_on is
18954 * true.
18955 * Some counters may be incremented while requeststats_on is becoming
18956 * false, or some cannot be incremented just after the statistics are
18957 * installed, but it shouldn't matter much in practice.
18958 */
18959 if (zone->requeststats_on) {
18960 return (zone->requeststats);
18961 } else {
18962 return (NULL);
18963 }
18964 }
18965
18966 /*
18967 * Return the received query stats bucket
18968 * see note from dns_zone_getrequeststats()
18969 */
18970 dns_stats_t *
18971 dns_zone_getrcvquerystats(dns_zone_t *zone) {
18972 if (zone->requeststats_on) {
18973 return (zone->rcvquerystats);
18974 } else {
18975 return (NULL);
18976 }
18977 }
18978
18979 void
18980 dns_zone_dialup(dns_zone_t *zone) {
18981 REQUIRE(DNS_ZONE_VALID(zone));
18982
18983 zone_debuglog(zone, "dns_zone_dialup", 3, "notify = %d, refresh = %d",
18984 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY),
18985 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH));
18986
18987 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY)) {
18988 dns_zone_notify(zone);
18989 }
18990 if (zone->type != dns_zone_master && zone->masters != NULL &&
18991 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
18992 {
18993 dns_zone_refresh(zone);
18994 }
18995 }
18996
18997 void
18998 dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
18999 REQUIRE(DNS_ZONE_VALID(zone));
19000
19001 LOCK_ZONE(zone);
19002 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
19003 DNS_ZONEFLG_DIALREFRESH |
19004 DNS_ZONEFLG_NOREFRESH);
19005 switch (dialup) {
19006 case dns_dialuptype_no:
19007 break;
19008 case dns_dialuptype_yes:
19009 DNS_ZONE_SETFLAG(zone, (DNS_ZONEFLG_DIALNOTIFY |
19010 DNS_ZONEFLG_DIALREFRESH |
19011 DNS_ZONEFLG_NOREFRESH));
19012 break;
19013 case dns_dialuptype_notify:
19014 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
19015 break;
19016 case dns_dialuptype_notifypassive:
19017 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
19018 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
19019 break;
19020 case dns_dialuptype_refresh:
19021 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALREFRESH);
19022 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
19023 break;
19024 case dns_dialuptype_passive:
19025 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
19026 break;
19027 default:
19028 INSIST(0);
19029 ISC_UNREACHABLE();
19030 }
19031 UNLOCK_ZONE(zone);
19032 }
19033
19034 isc_result_t
19035 dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory) {
19036 isc_result_t result = ISC_R_SUCCESS;
19037
19038 REQUIRE(DNS_ZONE_VALID(zone));
19039
19040 LOCK_ZONE(zone);
19041 result = dns_zone_setstring(zone, &zone->keydirectory, directory);
19042 UNLOCK_ZONE(zone);
19043
19044 return (result);
19045 }
19046
19047 const char *
19048 dns_zone_getkeydirectory(dns_zone_t *zone) {
19049 REQUIRE(DNS_ZONE_VALID(zone));
19050
19051 return (zone->keydirectory);
19052 }
19053
19054 unsigned int
19055 dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state) {
19056 dns_zone_t *zone;
19057 unsigned int count = 0;
19058
19059 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19060
19061 RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
19062 switch (state) {
19063 case DNS_ZONESTATE_XFERRUNNING:
19064 for (zone = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
19065 zone != NULL; zone = ISC_LIST_NEXT(zone, statelink))
19066 {
19067 count++;
19068 }
19069 break;
19070 case DNS_ZONESTATE_XFERDEFERRED:
19071 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
19072 zone != NULL; zone = ISC_LIST_NEXT(zone, statelink))
19073 {
19074 count++;
19075 }
19076 break;
19077 case DNS_ZONESTATE_SOAQUERY:
19078 for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
19079 zone = ISC_LIST_NEXT(zone, link))
19080 {
19081 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
19082 count++;
19083 }
19084 }
19085 break;
19086 case DNS_ZONESTATE_ANY:
19087 for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
19088 zone = ISC_LIST_NEXT(zone, link))
19089 {
19090 dns_view_t *view = zone->view;
19091 if (view != NULL && strcmp(view->name, "_bind") == 0) {
19092 continue;
19093 }
19094 count++;
19095 }
19096 break;
19097 case DNS_ZONESTATE_AUTOMATIC:
19098 for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
19099 zone = ISC_LIST_NEXT(zone, link))
19100 {
19101 dns_view_t *view = zone->view;
19102 if (view != NULL && strcmp(view->name, "_bind") == 0) {
19103 continue;
19104 }
19105 if (zone->automatic) {
19106 count++;
19107 }
19108 }
19109 break;
19110 default:
19111 INSIST(0);
19112 ISC_UNREACHABLE();
19113 }
19114
19115 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
19116
19117 return (count);
19118 }
19119
19120 isc_result_t
19121 dns_zone_checknames(dns_zone_t *zone, const dns_name_t *name,
19122 dns_rdata_t *rdata) {
19123 bool ok = true;
19124 bool fail = false;
19125 char namebuf[DNS_NAME_FORMATSIZE];
19126 char namebuf2[DNS_NAME_FORMATSIZE];
19127 char typebuf[DNS_RDATATYPE_FORMATSIZE];
19128 int level = ISC_LOG_WARNING;
19129 dns_name_t bad;
19130
19131 REQUIRE(DNS_ZONE_VALID(zone));
19132
19133 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES) &&
19134 rdata->type != dns_rdatatype_nsec3)
19135 {
19136 return (ISC_R_SUCCESS);
19137 }
19138
19139 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL) ||
19140 rdata->type == dns_rdatatype_nsec3)
19141 {
19142 level = ISC_LOG_ERROR;
19143 fail = true;
19144 }
19145
19146 ok = dns_rdata_checkowner(name, rdata->rdclass, rdata->type, true);
19147 if (!ok) {
19148 dns_name_format(name, namebuf, sizeof(namebuf));
19149 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
19150 dns_zone_log(zone, level, "%s/%s: %s", namebuf, typebuf,
19151 dns_result_totext(DNS_R_BADOWNERNAME));
19152 if (fail) {
19153 return (DNS_R_BADOWNERNAME);
19154 }
19155 }
19156
19157 dns_name_init(&bad, NULL);
19158 ok = dns_rdata_checknames(rdata, name, &bad);
19159 if (!ok) {
19160 dns_name_format(name, namebuf, sizeof(namebuf));
19161 dns_name_format(&bad, namebuf2, sizeof(namebuf2));
19162 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
19163 dns_zone_log(zone, level, "%s/%s: %s: %s ", namebuf, typebuf,
19164 namebuf2, dns_result_totext(DNS_R_BADNAME));
19165 if (fail) {
19166 return (DNS_R_BADNAME);
19167 }
19168 }
19169
19170 return (ISC_R_SUCCESS);
19171 }
19172
19173 void
19174 dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx) {
19175 REQUIRE(DNS_ZONE_VALID(zone));
19176 zone->checkmx = checkmx;
19177 }
19178
19179 void
19180 dns_zone_setchecksrv(dns_zone_t *zone, dns_checksrvfunc_t checksrv) {
19181 REQUIRE(DNS_ZONE_VALID(zone));
19182 zone->checksrv = checksrv;
19183 }
19184
19185 void
19186 dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns) {
19187 REQUIRE(DNS_ZONE_VALID(zone));
19188 zone->checkns = checkns;
19189 }
19190
19191 void
19192 dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg) {
19193 REQUIRE(DNS_ZONE_VALID(zone));
19194
19195 LOCK_ZONE(zone);
19196 zone->isself = isself;
19197 zone->isselfarg = arg;
19198 UNLOCK_ZONE(zone);
19199 }
19200
19201 void
19202 dns_zone_setnotifydelay(dns_zone_t *zone, uint32_t delay) {
19203 REQUIRE(DNS_ZONE_VALID(zone));
19204
19205 LOCK_ZONE(zone);
19206 zone->notifydelay = delay;
19207 UNLOCK_ZONE(zone);
19208 }
19209
19210 uint32_t
19211 dns_zone_getnotifydelay(dns_zone_t *zone) {
19212 REQUIRE(DNS_ZONE_VALID(zone));
19213
19214 return (zone->notifydelay);
19215 }
19216
19217 isc_result_t
19218 dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid,
19219 bool deleteit) {
19220 isc_result_t result;
19221 REQUIRE(DNS_ZONE_VALID(zone));
19222
19223 dnssec_log(zone, ISC_LOG_NOTICE,
19224 "dns_zone_signwithkey(algorithm=%u, keyid=%u)", algorithm,
19225 keyid);
19226 LOCK_ZONE(zone);
19227 result = zone_signwithkey(zone, algorithm, keyid, deleteit);
19228 UNLOCK_ZONE(zone);
19229
19230 return (result);
19231 }
19232
19233 /*
19234 * Called when a dynamic update for an NSEC3PARAM record is received.
19235 *
19236 * If set, transform the NSEC3 salt into human-readable form so that it can be
19237 * logged. Then call zone_addnsec3chain(), passing NSEC3PARAM RDATA to it.
19238 */
19239 isc_result_t
19240 dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
19241 isc_result_t result;
19242 char salt[255 * 2 + 1];
19243
19244 REQUIRE(DNS_ZONE_VALID(zone));
19245
19246 result = dns_nsec3param_salttotext(nsec3param, salt, sizeof(salt));
19247 RUNTIME_CHECK(result == ISC_R_SUCCESS);
19248 dnssec_log(zone, ISC_LOG_NOTICE,
19249 "dns_zone_addnsec3chain(hash=%u, iterations=%u, salt=%s)",
19250 nsec3param->hash, nsec3param->iterations, salt);
19251 LOCK_ZONE(zone);
19252 result = zone_addnsec3chain(zone, nsec3param);
19253 UNLOCK_ZONE(zone);
19254
19255 return (result);
19256 }
19257
19258 void
19259 dns_zone_setnodes(dns_zone_t *zone, uint32_t nodes) {
19260 REQUIRE(DNS_ZONE_VALID(zone));
19261
19262 if (nodes == 0) {
19263 nodes = 1;
19264 }
19265 zone->nodes = nodes;
19266 }
19267
19268 void
19269 dns_zone_setsignatures(dns_zone_t *zone, uint32_t signatures) {
19270 REQUIRE(DNS_ZONE_VALID(zone));
19271
19272 /*
19273 * We treat signatures as a signed value so explicitly
19274 * limit its range here.
19275 */
19276 if (signatures > INT32_MAX) {
19277 signatures = INT32_MAX;
19278 } else if (signatures == 0) {
19279 signatures = 1;
19280 }
19281 zone->signatures = signatures;
19282 }
19283
19284 uint32_t
19285 dns_zone_getsignatures(dns_zone_t *zone) {
19286 REQUIRE(DNS_ZONE_VALID(zone));
19287 return (zone->signatures);
19288 }
19289
19290 void
19291 dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type) {
19292 REQUIRE(DNS_ZONE_VALID(zone));
19293 zone->privatetype = type;
19294 }
19295
19296 dns_rdatatype_t
19297 dns_zone_getprivatetype(dns_zone_t *zone) {
19298 REQUIRE(DNS_ZONE_VALID(zone));
19299 return (zone->privatetype);
19300 }
19301
19302 static isc_result_t
19303 zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid,
19304 bool deleteit) {
19305 dns_signing_t *signing;
19306 dns_signing_t *current;
19307 isc_result_t result = ISC_R_SUCCESS;
19308 isc_time_t now;
19309 dns_db_t *db = NULL;
19310
19311 signing = isc_mem_get(zone->mctx, sizeof *signing);
19312
19313 signing->magic = 0;
19314 signing->db = NULL;
19315 signing->dbiterator = NULL;
19316 signing->algorithm = algorithm;
19317 signing->keyid = keyid;
19318 signing->deleteit = deleteit;
19319 signing->done = false;
19320
19321 TIME_NOW(&now);
19322
19323 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
19324 if (zone->db != NULL) {
19325 dns_db_attach(zone->db, &db);
19326 }
19327 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
19328
19329 if (db == NULL) {
19330 result = ISC_R_NOTFOUND;
19331 goto cleanup;
19332 }
19333
19334 dns_db_attach(db, &signing->db);
19335
19336 for (current = ISC_LIST_HEAD(zone->signing); current != NULL;
19337 current = ISC_LIST_NEXT(current, link))
19338 {
19339 if (current->db == signing->db &&
19340 current->algorithm == signing->algorithm &&
19341 current->keyid == signing->keyid)
19342 {
19343 if (current->deleteit != signing->deleteit) {
19344 current->done = true;
19345 } else {
19346 goto cleanup;
19347 }
19348 }
19349 }
19350
19351 result = dns_db_createiterator(signing->db, 0, &signing->dbiterator);
19352
19353 if (result == ISC_R_SUCCESS) {
19354 result = dns_dbiterator_first(signing->dbiterator);
19355 }
19356 if (result == ISC_R_SUCCESS) {
19357 dns_dbiterator_pause(signing->dbiterator);
19358 ISC_LIST_INITANDAPPEND(zone->signing, signing, link);
19359 signing = NULL;
19360 if (isc_time_isepoch(&zone->signingtime)) {
19361 zone->signingtime = now;
19362 if (zone->task != NULL) {
19363 zone_settimer(zone, &now);
19364 }
19365 }
19366 }
19367
19368 cleanup:
19369 if (signing != NULL) {
19370 if (signing->db != NULL) {
19371 dns_db_detach(&signing->db);
19372 }
19373 if (signing->dbiterator != NULL) {
19374 dns_dbiterator_destroy(&signing->dbiterator);
19375 }
19376 isc_mem_put(zone->mctx, signing, sizeof *signing);
19377 }
19378 if (db != NULL) {
19379 dns_db_detach(&db);
19380 }
19381 return (result);
19382 }
19383
19384 static void
19385 clear_keylist(dns_dnsseckeylist_t *list, isc_mem_t *mctx) {
19386 dns_dnsseckey_t *key;
19387 while (!ISC_LIST_EMPTY(*list)) {
19388 key = ISC_LIST_HEAD(*list);
19389 ISC_LIST_UNLINK(*list, key, link);
19390 dns_dnsseckey_destroy(mctx, &key);
19391 }
19392 }
19393
19394 /* Called once; *timep should be set to the current time. */
19395 static isc_result_t
19396 next_keyevent(dst_key_t *key, isc_stdtime_t *timep) {
19397 isc_result_t result;
19398 isc_stdtime_t now, then = 0, event;
19399 int i;
19400
19401 now = *timep;
19402
19403 for (i = 0; i <= DST_MAX_TIMES; i++) {
19404 result = dst_key_gettime(key, i, &event);
19405 if (result == ISC_R_SUCCESS && event > now &&
19406 (then == 0 || event < then)) {
19407 then = event;
19408 }
19409 }
19410
19411 if (then != 0) {
19412 *timep = then;
19413 return (ISC_R_SUCCESS);
19414 }
19415
19416 return (ISC_R_NOTFOUND);
19417 }
19418
19419 static isc_result_t
19420 rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
19421 const dns_rdata_t *rdata, bool *flag) {
19422 dns_rdataset_t rdataset;
19423 dns_dbnode_t *node = NULL;
19424 isc_result_t result;
19425
19426 dns_rdataset_init(&rdataset);
19427 if (rdata->type == dns_rdatatype_nsec3) {
19428 CHECK(dns_db_findnsec3node(db, name, false, &node));
19429 } else {
19430 CHECK(dns_db_findnode(db, name, false, &node));
19431 }
19432 result = dns_db_findrdataset(db, node, ver, rdata->type, 0,
19433 (isc_stdtime_t)0, &rdataset, NULL);
19434 if (result == ISC_R_NOTFOUND) {
19435 *flag = false;
19436 result = ISC_R_SUCCESS;
19437 goto failure;
19438 }
19439
19440 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
19441 result = dns_rdataset_next(&rdataset))
19442 {
19443 dns_rdata_t myrdata = DNS_RDATA_INIT;
19444 dns_rdataset_current(&rdataset, &myrdata);
19445 if (!dns_rdata_compare(&myrdata, rdata)) {
19446 break;
19447 }
19448 }
19449 dns_rdataset_disassociate(&rdataset);
19450 if (result == ISC_R_SUCCESS) {
19451 *flag = true;
19452 } else if (result == ISC_R_NOMORE) {
19453 *flag = false;
19454 result = ISC_R_SUCCESS;
19455 }
19456
19457 failure:
19458 if (node != NULL) {
19459 dns_db_detachnode(db, &node);
19460 }
19461 return (result);
19462 }
19463
19464 /*
19465 * Add records to signal the state of signing or of key removal.
19466 */
19467 static isc_result_t
19468 add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
19469 dns_dbversion_t *ver, dns_diff_t *diff, bool sign_all) {
19470 dns_difftuple_t *tuple, *newtuple = NULL;
19471 dns_rdata_dnskey_t dnskey;
19472 dns_rdata_t rdata = DNS_RDATA_INIT;
19473 bool flag;
19474 isc_region_t r;
19475 isc_result_t result = ISC_R_SUCCESS;
19476 uint16_t keyid;
19477 unsigned char buf[5];
19478 dns_name_t *name = dns_db_origin(db);
19479
19480 for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL;
19481 tuple = ISC_LIST_NEXT(tuple, link))
19482 {
19483 if (tuple->rdata.type != dns_rdatatype_dnskey) {
19484 continue;
19485 }
19486
19487 result = dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
19488 RUNTIME_CHECK(result == ISC_R_SUCCESS);
19489 if ((dnskey.flags & (DNS_KEYFLAG_OWNERMASK |
19490 DNS_KEYTYPE_NOAUTH)) != DNS_KEYOWNER_ZONE)
19491 {
19492 continue;
19493 }
19494
19495 dns_rdata_toregion(&tuple->rdata, &r);
19496
19497 keyid = dst_region_computeid(&r);
19498
19499 buf[0] = dnskey.algorithm;
19500 buf[1] = (keyid & 0xff00) >> 8;
19501 buf[2] = (keyid & 0xff);
19502 buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1;
19503 buf[4] = 0;
19504 rdata.data = buf;
19505 rdata.length = sizeof(buf);
19506 rdata.type = privatetype;
19507 rdata.rdclass = tuple->rdata.rdclass;
19508
19509 if (sign_all || tuple->op == DNS_DIFFOP_DEL) {
19510 CHECK(rr_exists(db, ver, name, &rdata, &flag));
19511 if (flag) {
19512 continue;
19513 }
19514
19515 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
19516 name, 0, &rdata, &newtuple));
19517 CHECK(do_one_tuple(&newtuple, db, ver, diff));
19518 INSIST(newtuple == NULL);
19519 }
19520
19521 /*
19522 * Remove any record which says this operation has already
19523 * completed.
19524 */
19525 buf[4] = 1;
19526 CHECK(rr_exists(db, ver, name, &rdata, &flag));
19527 if (flag) {
19528 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL,
19529 name, 0, &rdata, &newtuple));
19530 CHECK(do_one_tuple(&newtuple, db, ver, diff));
19531 INSIST(newtuple == NULL);
19532 }
19533 }
19534 failure:
19535 return (result);
19536 }
19537
19538 /*
19539 * See if dns__zone_updatesigs() will update signature for RRset 'rrtype' at
19540 * the apex, and if not tickle them and cause to sign so that newly activated
19541 * keys are used.
19542 */
19543 static isc_result_t
19544 tickle_apex_rrset(dns_rdatatype_t rrtype, dns_zone_t *zone, dns_db_t *db,
19545 dns_dbversion_t *ver, isc_stdtime_t now, dns_diff_t *diff,
19546 dns__zonediff_t *zonediff, dst_key_t **keys,
19547 unsigned int nkeys, isc_stdtime_t inception,
19548 isc_stdtime_t keyexpire, bool check_ksk,
19549 bool keyset_kskonly) {
19550 dns_difftuple_t *tuple;
19551 isc_result_t result;
19552
19553 for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL;
19554 tuple = ISC_LIST_NEXT(tuple, link))
19555 {
19556 if (tuple->rdata.type == rrtype &&
19557 dns_name_equal(&tuple->name, &zone->origin)) {
19558 break;
19559 }
19560 }
19561
19562 if (tuple == NULL) {
19563 result = del_sigs(zone, db, ver, &zone->origin, rrtype,
19564 zonediff, keys, nkeys, now, false);
19565 if (result != ISC_R_SUCCESS) {
19566 dnssec_log(zone, ISC_LOG_ERROR,
19567 "sign_apex:del_sigs -> %s",
19568 dns_result_totext(result));
19569 return (result);
19570 }
19571 result = add_sigs(db, ver, &zone->origin, zone, rrtype,
19572 zonediff->diff, keys, nkeys, zone->mctx,
19573 inception, keyexpire, check_ksk,
19574 keyset_kskonly);
19575 if (result != ISC_R_SUCCESS) {
19576 dnssec_log(zone, ISC_LOG_ERROR,
19577 "sign_apex:add_sigs -> %s",
19578 dns_result_totext(result));
19579 return (result);
19580 }
19581 }
19582
19583 return (ISC_R_SUCCESS);
19584 }
19585
19586 static isc_result_t
19587 sign_apex(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
19588 isc_stdtime_t now, dns_diff_t *diff, dns__zonediff_t *zonediff) {
19589 isc_result_t result;
19590 isc_stdtime_t inception, soaexpire, keyexpire;
19591 bool check_ksk, keyset_kskonly;
19592 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
19593 unsigned int nkeys = 0, i;
19594
19595 result = dns__zone_findkeys(zone, db, ver, now, zone->mctx,
19596 DNS_MAXZONEKEYS, zone_keys, &nkeys);
19597 if (result != ISC_R_SUCCESS) {
19598 dnssec_log(zone, ISC_LOG_ERROR,
19599 "sign_apex:dns__zone_findkeys -> %s",
19600 dns_result_totext(result));
19601 return (result);
19602 }
19603
19604 inception = now - 3600; /* Allow for clock skew. */
19605 soaexpire = now + dns_zone_getsigvalidityinterval(zone);
19606
19607 keyexpire = dns_zone_getkeyvalidityinterval(zone);
19608 if (keyexpire == 0) {
19609 keyexpire = soaexpire - 1;
19610 } else {
19611 keyexpire += now;
19612 }
19613
19614 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
19615 keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
19616
19617 /*
19618 * See if dns__zone_updatesigs() will update DNSKEY/CDS/CDNSKEY
19619 * signature and if not cause them to sign so that newly activated
19620 * keys are used.
19621 */
19622 result = tickle_apex_rrset(dns_rdatatype_dnskey, zone, db, ver, now,
19623 diff, zonediff, zone_keys, nkeys, inception,
19624 keyexpire, check_ksk, keyset_kskonly);
19625 if (result != ISC_R_SUCCESS) {
19626 goto failure;
19627 }
19628 result = tickle_apex_rrset(dns_rdatatype_cds, zone, db, ver, now, diff,
19629 zonediff, zone_keys, nkeys, inception,
19630 keyexpire, check_ksk, keyset_kskonly);
19631 if (result != ISC_R_SUCCESS) {
19632 goto failure;
19633 }
19634 result = tickle_apex_rrset(dns_rdatatype_cdnskey, zone, db, ver, now,
19635 diff, zonediff, zone_keys, nkeys, inception,
19636 keyexpire, check_ksk, keyset_kskonly);
19637 if (result != ISC_R_SUCCESS) {
19638 goto failure;
19639 }
19640
19641 result = dns__zone_updatesigs(diff, db, ver, zone_keys, nkeys, zone,
19642 inception, soaexpire, keyexpire, now,
19643 check_ksk, keyset_kskonly, zonediff);
19644
19645 if (result != ISC_R_SUCCESS) {
19646 dnssec_log(zone, ISC_LOG_ERROR,
19647 "sign_apex:dns__zone_updatesigs -> %s",
19648 dns_result_totext(result));
19649 goto failure;
19650 }
19651
19652 failure:
19653 for (i = 0; i < nkeys; i++) {
19654 dst_key_free(&zone_keys[i]);
19655 }
19656 return (result);
19657 }
19658
19659 /*
19660 * Prevent the zone entering a inconsistent state where
19661 * NSEC only DNSKEYs are present with NSEC3 chains.
19662 * See update.c:check_dnssec()
19663 */
19664 static bool
19665 dnskey_sane(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
19666 dns_diff_t *diff) {
19667 isc_result_t result;
19668 dns_difftuple_t *tuple;
19669 bool nseconly = false, nsec3 = false;
19670 dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
19671
19672 /* Scan the tuples for an NSEC-only DNSKEY */
19673 for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL;
19674 tuple = ISC_LIST_NEXT(tuple, link))
19675 {
19676 uint8_t alg;
19677 if (tuple->rdata.type != dns_rdatatype_dnskey ||
19678 tuple->op != DNS_DIFFOP_ADD) {
19679 continue;
19680 }
19681
19682 alg = tuple->rdata.data[3];
19683 if (alg == DST_ALG_RSASHA1) {
19684 nseconly = true;
19685 break;
19686 }
19687 }
19688
19689 /* Check existing DB for NSEC-only DNSKEY */
19690 if (!nseconly) {
19691 result = dns_nsec_nseconly(db, ver, &nseconly);
19692 if (result == ISC_R_NOTFOUND) {
19693 result = ISC_R_SUCCESS;
19694 }
19695 CHECK(result);
19696 }
19697
19698 /* Check existing DB for NSEC3 */
19699 if (!nsec3) {
19700 CHECK(dns_nsec3_activex(db, ver, false, privatetype, &nsec3));
19701 }
19702
19703 /* Refuse to allow NSEC3 with NSEC-only keys */
19704 if (nseconly && nsec3) {
19705 dnssec_log(zone, ISC_LOG_ERROR,
19706 "NSEC only DNSKEYs and NSEC3 chains not allowed");
19707 goto failure;
19708 }
19709
19710 return (true);
19711
19712 failure:
19713 return (false);
19714 }
19715
19716 static isc_result_t
19717 clean_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
19718 dns_diff_t *diff) {
19719 isc_result_t result;
19720 dns_dbnode_t *node = NULL;
19721 dns_rdataset_t rdataset;
19722
19723 dns_rdataset_init(&rdataset);
19724 CHECK(dns_db_getoriginnode(db, &node));
19725
19726 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
19727 dns_rdatatype_none, 0, &rdataset, NULL);
19728 if (dns_rdataset_isassociated(&rdataset)) {
19729 dns_rdataset_disassociate(&rdataset);
19730 }
19731 if (result != ISC_R_NOTFOUND) {
19732 goto failure;
19733 }
19734
19735 result = dns_nsec3param_deletechains(db, ver, zone, true, diff);
19736
19737 failure:
19738 if (node != NULL) {
19739 dns_db_detachnode(db, &node);
19740 }
19741 return (result);
19742 }
19743
19744 /*
19745 * Given an RRSIG rdataset and an algorithm, determine whether there
19746 * are any signatures using that algorithm.
19747 */
19748 static bool
19749 signed_with_alg(dns_rdataset_t *rdataset, dns_secalg_t alg) {
19750 dns_rdata_t rdata = DNS_RDATA_INIT;
19751 dns_rdata_rrsig_t rrsig;
19752 isc_result_t result;
19753
19754 REQUIRE(rdataset == NULL || rdataset->type == dns_rdatatype_rrsig);
19755 if (rdataset == NULL || !dns_rdataset_isassociated(rdataset)) {
19756 return (false);
19757 }
19758
19759 for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
19760 result = dns_rdataset_next(rdataset))
19761 {
19762 dns_rdataset_current(rdataset, &rdata);
19763 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
19764 RUNTIME_CHECK(result == ISC_R_SUCCESS);
19765 dns_rdata_reset(&rdata);
19766 if (rrsig.algorithm == alg) {
19767 return (true);
19768 }
19769 }
19770
19771 return (false);
19772 }
19773
19774 static isc_result_t
19775 add_chains(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
19776 dns_diff_t *diff) {
19777 dns_name_t *origin;
19778 bool build_nsec3;
19779 isc_result_t result;
19780
19781 origin = dns_db_origin(db);
19782 CHECK(dns_private_chains(db, ver, zone->privatetype, NULL,
19783 &build_nsec3));
19784 if (build_nsec3) {
19785 CHECK(dns_nsec3_addnsec3sx(db, ver, origin, zone->minimum,
19786 false, zone->privatetype, diff));
19787 }
19788 CHECK(updatesecure(db, ver, origin, zone->minimum, true, diff));
19789
19790 failure:
19791 return (result);
19792 }
19793
19794 static void
19795 dnssec_report(const char *format, ...) {
19796 va_list args;
19797 va_start(args, format);
19798 isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_ZONE,
19799 ISC_LOG_INFO, format, args);
19800 va_end(args);
19801 }
19802
19803 static void
19804 zone_rekey(dns_zone_t *zone) {
19805 isc_result_t result;
19806 dns_db_t *db = NULL;
19807 dns_dbnode_t *node = NULL;
19808 dns_dbversion_t *ver = NULL;
19809 dns_rdataset_t cdsset, soaset, soasigs, keyset, keysigs, cdnskeyset;
19810 dns_dnsseckeylist_t dnskeys, keys, rmkeys;
19811 dns_dnsseckey_t *key = NULL;
19812 dns_diff_t diff, _sig_diff;
19813 dns_kasp_t *kasp;
19814 dns__zonediff_t zonediff;
19815 bool commit = false, newactive = false;
19816 bool newalg = false;
19817 bool fullsign, use_kasp;
19818 dns_ttl_t ttl = 3600;
19819 const char *dir = NULL;
19820 isc_mem_t *mctx = NULL;
19821 isc_stdtime_t now, nexttime = 0;
19822 isc_time_t timenow;
19823 isc_interval_t ival;
19824 char timebuf[80];
19825
19826 REQUIRE(DNS_ZONE_VALID(zone));
19827
19828 ISC_LIST_INIT(dnskeys);
19829 ISC_LIST_INIT(keys);
19830 ISC_LIST_INIT(rmkeys);
19831 dns_rdataset_init(&soaset);
19832 dns_rdataset_init(&soasigs);
19833 dns_rdataset_init(&keyset);
19834 dns_rdataset_init(&keysigs);
19835 dns_rdataset_init(&cdsset);
19836 dns_rdataset_init(&cdnskeyset);
19837 dir = dns_zone_getkeydirectory(zone);
19838 mctx = zone->mctx;
19839 dns_diff_init(mctx, &diff);
19840 dns_diff_init(mctx, &_sig_diff);
19841 zonediff_init(&zonediff, &_sig_diff);
19842
19843 CHECK(dns_zone_getdb(zone, &db));
19844 CHECK(dns_db_newversion(db, &ver));
19845 CHECK(dns_db_getoriginnode(db, &node));
19846
19847 TIME_NOW(&timenow);
19848 now = isc_time_seconds(&timenow);
19849
19850 dnssec_log(zone, ISC_LOG_INFO, "reconfiguring zone keys");
19851
19852 /* Get the SOA record's TTL */
19853 CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_soa,
19854 dns_rdatatype_none, 0, &soaset, &soasigs));
19855 ttl = soaset.ttl;
19856 dns_rdataset_disassociate(&soaset);
19857
19858 /* Get the DNSKEY rdataset */
19859 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
19860 dns_rdatatype_none, 0, &keyset, &keysigs);
19861 if (result == ISC_R_SUCCESS) {
19862 ttl = keyset.ttl;
19863 CHECK(dns_dnssec_keylistfromrdataset(
19864 &zone->origin, dir, mctx, &keyset, &keysigs, &soasigs,
19865 false, false, &dnskeys));
19866 } else if (result != ISC_R_NOTFOUND) {
19867 goto failure;
19868 }
19869
19870 /* Get the CDS rdataset */
19871 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_cds,
19872 dns_rdatatype_none, 0, &cdsset, NULL);
19873 if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdsset)) {
19874 dns_rdataset_disassociate(&cdsset);
19875 }
19876
19877 /* Get the CDNSKEY rdataset */
19878 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_cdnskey,
19879 dns_rdatatype_none, 0, &cdnskeyset, NULL);
19880 if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdnskeyset)) {
19881 dns_rdataset_disassociate(&cdnskeyset);
19882 }
19883
19884 /*
19885 * True when called from "rndc sign". Indicates the zone should be
19886 * fully signed now.
19887 */
19888 fullsign = DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_FULLSIGN);
19889
19890 kasp = dns_zone_getkasp(zone);
19891 use_kasp = dns_zone_use_kasp(zone);
19892 if (kasp != NULL) {
19893 LOCK(&kasp->lock);
19894 }
19895
19896 result = dns_dnssec_findmatchingkeys(&zone->origin, dir, now, mctx,
19897 &keys);
19898 if (result != ISC_R_SUCCESS) {
19899 dnssec_log(zone, ISC_LOG_DEBUG(1),
19900 "zone_rekey:dns_dnssec_findmatchingkeys failed: %s",
19901 isc_result_totext(result));
19902 }
19903
19904 if (use_kasp && (result == ISC_R_SUCCESS || result == ISC_R_NOTFOUND)) {
19905 result = dns_keymgr_run(&zone->origin, zone->rdclass, dir, mctx,
19906 &keys, kasp, now, &nexttime);
19907 if (result != ISC_R_SUCCESS) {
19908 dnssec_log(zone, ISC_LOG_ERROR,
19909 "zone_rekey:dns_dnssec_keymgr failed: %s",
19910 isc_result_totext(result));
19911 goto failure;
19912 }
19913 }
19914
19915 if (kasp != NULL) {
19916 UNLOCK(&kasp->lock);
19917 }
19918
19919 if (result == ISC_R_SUCCESS) {
19920 bool insecure = dns_zone_secure_to_insecure(zone, false);
19921
19922 /*
19923 * Only update DNSKEY TTL if we have a policy.
19924 */
19925 if (kasp != NULL && strcmp(dns_kasp_getname(kasp), "none") != 0)
19926 {
19927 ttl = dns_kasp_dnskeyttl(kasp);
19928 }
19929
19930 result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys,
19931 &zone->origin, ttl, &diff, mctx,
19932 dnssec_report);
19933 /*
19934 * Keys couldn't be updated for some reason;
19935 * try again later.
19936 */
19937 if (result != ISC_R_SUCCESS) {
19938 dnssec_log(zone, ISC_LOG_ERROR,
19939 "zone_rekey:couldn't update zone keys: %s",
19940 isc_result_totext(result));
19941 goto failure;
19942 }
19943
19944 /*
19945 * Update CDS / CDNSKEY records.
19946 */
19947 result = dns_dnssec_syncupdate(&dnskeys, &rmkeys, &cdsset,
19948 &cdnskeyset, now, ttl, &diff,
19949 mctx);
19950 if (result != ISC_R_SUCCESS) {
19951 dnssec_log(zone, ISC_LOG_ERROR,
19952 "zone_rekey:couldn't update CDS/CDNSKEY: %s",
19953 isc_result_totext(result));
19954 goto failure;
19955 }
19956
19957 result = dns_dnssec_syncdelete(&cdsset, &cdnskeyset,
19958 &zone->origin, zone->rdclass,
19959 ttl, &diff, mctx, insecure);
19960 if (result != ISC_R_SUCCESS) {
19961 dnssec_log(zone, ISC_LOG_ERROR,
19962 "zone_rekey:couldn't update CDS/CDNSKEY "
19963 "DELETE records: %s",
19964 isc_result_totext(result));
19965 goto failure;
19966 }
19967
19968 /*
19969 * See if any pre-existing keys have newly become active;
19970 * also, see if any new key is for a new algorithm, as in that
19971 * event, we need to sign the zone fully. (If there's a new
19972 * key, but it's for an already-existing algorithm, then
19973 * the zone signing can be handled incrementally.)
19974 */
19975 for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
19976 key = ISC_LIST_NEXT(key, link)) {
19977 if (!key->first_sign) {
19978 continue;
19979 }
19980
19981 newactive = true;
19982
19983 if (!dns_rdataset_isassociated(&keysigs)) {
19984 newalg = true;
19985 break;
19986 }
19987
19988 if (signed_with_alg(&keysigs, dst_key_alg(key->key))) {
19989 /*
19990 * This isn't a new algorithm; clear
19991 * first_sign so we won't sign the
19992 * whole zone with this key later.
19993 */
19994 key->first_sign = false;
19995 } else {
19996 newalg = true;
19997 break;
19998 }
19999 }
20000
20001 if ((newactive || fullsign || !ISC_LIST_EMPTY(diff.tuples)) &&
20002 dnskey_sane(zone, db, ver, &diff))
20003 {
20004 CHECK(dns_diff_apply(&diff, db, ver));
20005 CHECK(clean_nsec3param(zone, db, ver, &diff));
20006 CHECK(add_signing_records(db, zone->privatetype, ver,
20007 &diff, (newalg || fullsign)));
20008 CHECK(update_soa_serial(zone, db, ver, &diff, mctx,
20009 zone->updatemethod));
20010 CHECK(add_chains(zone, db, ver, &diff));
20011 CHECK(sign_apex(zone, db, ver, now, &diff, &zonediff));
20012 CHECK(zone_journal(zone, zonediff.diff, NULL,
20013 "zone_rekey"));
20014 commit = true;
20015 }
20016 }
20017
20018 dns_db_closeversion(db, &ver, true);
20019
20020 LOCK_ZONE(zone);
20021
20022 if (commit) {
20023 dns_difftuple_t *tuple;
20024
20025 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
20026
20027 zone_needdump(zone, DNS_DUMP_DELAY);
20028
20029 zone_settimer(zone, &timenow);
20030
20031 /* Remove any signatures from removed keys. */
20032 if (!ISC_LIST_EMPTY(rmkeys)) {
20033 for (key = ISC_LIST_HEAD(rmkeys); key != NULL;
20034 key = ISC_LIST_NEXT(key, link)) {
20035 result = zone_signwithkey(
20036 zone, dst_key_alg(key->key),
20037 dst_key_id(key->key), true);
20038 if (result != ISC_R_SUCCESS) {
20039 dnssec_log(zone, ISC_LOG_ERROR,
20040 "zone_signwithkey failed: "
20041 "%s",
20042 dns_result_totext(result));
20043 }
20044 }
20045 }
20046
20047 if (fullsign) {
20048 /*
20049 * "rndc sign" was called, so we now sign the zone
20050 * with all active keys, whether they're new or not.
20051 */
20052 for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
20053 key = ISC_LIST_NEXT(key, link)) {
20054 if (!key->force_sign && !key->hint_sign) {
20055 continue;
20056 }
20057
20058 result = zone_signwithkey(
20059 zone, dst_key_alg(key->key),
20060 dst_key_id(key->key), false);
20061 if (result != ISC_R_SUCCESS) {
20062 dnssec_log(zone, ISC_LOG_ERROR,
20063 "zone_signwithkey failed: "
20064 "%s",
20065 dns_result_totext(result));
20066 }
20067 }
20068 } else if (newalg) {
20069 /*
20070 * We haven't been told to sign fully, but a new
20071 * algorithm was added to the DNSKEY. We sign
20072 * the full zone, but only with newly active
20073 * keys.
20074 */
20075 for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
20076 key = ISC_LIST_NEXT(key, link)) {
20077 if (!key->first_sign) {
20078 continue;
20079 }
20080
20081 result = zone_signwithkey(
20082 zone, dst_key_alg(key->key),
20083 dst_key_id(key->key), false);
20084 if (result != ISC_R_SUCCESS) {
20085 dnssec_log(zone, ISC_LOG_ERROR,
20086 "zone_signwithkey failed: "
20087 "%s",
20088 dns_result_totext(result));
20089 }
20090 }
20091 }
20092
20093 /*
20094 * Clear fullsign flag, if it was set, so we don't do
20095 * another full signing next time.
20096 */
20097 DNS_ZONEKEY_CLROPTION(zone, DNS_ZONEKEY_FULLSIGN);
20098
20099 /*
20100 * Cause the zone to add/delete NSEC3 chains for the
20101 * deferred NSEC3PARAM changes.
20102 */
20103 for (tuple = ISC_LIST_HEAD(zonediff.diff->tuples);
20104 tuple != NULL; tuple = ISC_LIST_NEXT(tuple, link))
20105 {
20106 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
20107 dns_rdata_t rdata = DNS_RDATA_INIT;
20108 dns_rdata_nsec3param_t nsec3param;
20109
20110 if (tuple->rdata.type != zone->privatetype ||
20111 tuple->op != DNS_DIFFOP_ADD) {
20112 continue;
20113 }
20114
20115 if (!dns_nsec3param_fromprivate(&tuple->rdata, &rdata,
20116 buf, sizeof(buf))) {
20117 continue;
20118 }
20119
20120 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
20121 RUNTIME_CHECK(result == ISC_R_SUCCESS);
20122 if (nsec3param.flags == 0) {
20123 continue;
20124 }
20125
20126 result = zone_addnsec3chain(zone, &nsec3param);
20127 if (result != ISC_R_SUCCESS) {
20128 dnssec_log(zone, ISC_LOG_ERROR,
20129 "zone_addnsec3chain failed: %s",
20130 dns_result_totext(result));
20131 }
20132 }
20133
20134 /*
20135 * Activate any NSEC3 chain updates that may have
20136 * been scheduled before this rekey.
20137 */
20138 if (fullsign || newalg) {
20139 resume_addnsec3chain(zone);
20140 }
20141
20142 /*
20143 * Schedule the next resigning event
20144 */
20145 set_resigntime(zone);
20146 }
20147
20148 isc_time_settoepoch(&zone->refreshkeytime);
20149
20150 /*
20151 * If keymgr provided a next time, use the calculated next rekey time.
20152 */
20153 if (use_kasp) {
20154 isc_time_t timenext;
20155 uint32_t nexttime_seconds;
20156
20157 /*
20158 * Set the key refresh timer to the next scheduled key event
20159 * or to 'dnssec-loadkeys-interval' seconds in the future
20160 * if no next key event is scheduled (nexttime == 0).
20161 */
20162 if (nexttime > 0) {
20163 nexttime_seconds = nexttime - now;
20164 } else {
20165 nexttime_seconds = zone->refreshkeyinterval;
20166 }
20167
20168 DNS_ZONE_TIME_ADD(&timenow, nexttime_seconds, &timenext);
20169 zone->refreshkeytime = timenext;
20170 zone_settimer(zone, &timenow);
20171 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
20172
20173 dnssec_log(zone, ISC_LOG_DEBUG(3),
20174 "next key event in %u seconds", nexttime_seconds);
20175 dnssec_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
20176 }
20177 /*
20178 * If we're doing key maintenance, set the key refresh timer to
20179 * the next scheduled key event or to 'dnssec-loadkeys-interval'
20180 * seconds in the future, whichever is sooner.
20181 */
20182 else if (DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
20183 {
20184 isc_time_t timethen;
20185 isc_stdtime_t then;
20186
20187 DNS_ZONE_TIME_ADD(&timenow, zone->refreshkeyinterval,
20188 &timethen);
20189 zone->refreshkeytime = timethen;
20190
20191 for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
20192 key = ISC_LIST_NEXT(key, link)) {
20193 then = now;
20194 result = next_keyevent(key->key, &then);
20195 if (result != ISC_R_SUCCESS) {
20196 continue;
20197 }
20198
20199 DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
20200 if (isc_time_compare(&timethen, &zone->refreshkeytime) <
20201 0) {
20202 zone->refreshkeytime = timethen;
20203 }
20204 }
20205
20206 zone_settimer(zone, &timenow);
20207
20208 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
20209 dnssec_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
20210 }
20211 UNLOCK_ZONE(zone);
20212
20213 if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
20214 for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
20215 key = ISC_LIST_NEXT(key, link)) {
20216 /* This debug log is used in the kasp system test */
20217 char algbuf[DNS_SECALG_FORMATSIZE];
20218 dns_secalg_format(dst_key_alg(key->key), algbuf,
20219 sizeof(algbuf));
20220 dnssec_log(zone, ISC_LOG_DEBUG(3),
20221 "zone_rekey done: key %d/%s",
20222 dst_key_id(key->key), algbuf);
20223 }
20224 }
20225
20226 result = ISC_R_SUCCESS;
20227
20228 failure:
20229 LOCK_ZONE(zone);
20230 if (result != ISC_R_SUCCESS) {
20231 /*
20232 * Something went wrong; try again in ten minutes or
20233 * after a key refresh interval, whichever is shorter.
20234 */
20235 isc_interval_set(&ival, ISC_MIN(zone->refreshkeyinterval, 600),
20236 0);
20237 isc_time_nowplusinterval(&zone->refreshkeytime, &ival);
20238 }
20239 UNLOCK_ZONE(zone);
20240
20241 dns_diff_clear(&diff);
20242 dns_diff_clear(&_sig_diff);
20243
20244 clear_keylist(&dnskeys, mctx);
20245 clear_keylist(&keys, mctx);
20246 clear_keylist(&rmkeys, mctx);
20247
20248 if (ver != NULL) {
20249 dns_db_closeversion(db, &ver, false);
20250 }
20251 if (dns_rdataset_isassociated(&cdsset)) {
20252 dns_rdataset_disassociate(&cdsset);
20253 }
20254 if (dns_rdataset_isassociated(&keyset)) {
20255 dns_rdataset_disassociate(&keyset);
20256 }
20257 if (dns_rdataset_isassociated(&keysigs)) {
20258 dns_rdataset_disassociate(&keysigs);
20259 }
20260 if (dns_rdataset_isassociated(&soasigs)) {
20261 dns_rdataset_disassociate(&soasigs);
20262 }
20263 if (dns_rdataset_isassociated(&cdnskeyset)) {
20264 dns_rdataset_disassociate(&cdnskeyset);
20265 }
20266 if (node != NULL) {
20267 dns_db_detachnode(db, &node);
20268 }
20269 if (db != NULL) {
20270 dns_db_detach(&db);
20271 }
20272
20273 INSIST(ver == NULL);
20274 }
20275
20276 void
20277 dns_zone_rekey(dns_zone_t *zone, bool fullsign) {
20278 isc_time_t now;
20279
20280 if (zone->type == dns_zone_master && zone->task != NULL) {
20281 LOCK_ZONE(zone);
20282
20283 if (fullsign) {
20284 DNS_ZONEKEY_SETOPTION(zone, DNS_ZONEKEY_FULLSIGN);
20285 }
20286
20287 TIME_NOW(&now);
20288 zone->refreshkeytime = now;
20289 zone_settimer(zone, &now);
20290
20291 UNLOCK_ZONE(zone);
20292 }
20293 }
20294
20295 isc_result_t
20296 dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
20297 unsigned int *errors) {
20298 isc_result_t result;
20299 dns_dbnode_t *node = NULL;
20300
20301 REQUIRE(DNS_ZONE_VALID(zone));
20302 REQUIRE(errors != NULL);
20303
20304 result = dns_db_getoriginnode(db, &node);
20305 if (result != ISC_R_SUCCESS) {
20306 return (result);
20307 }
20308 result = zone_count_ns_rr(zone, db, node, version, NULL, errors, false);
20309 dns_db_detachnode(db, &node);
20310 return (result);
20311 }
20312
20313 isc_result_t
20314 dns_zone_cdscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version) {
20315 isc_result_t result;
20316 dns_dbnode_t *node = NULL;
20317 dns_rdataset_t dnskey, cds, cdnskey;
20318 unsigned char buffer[DNS_DS_BUFFERSIZE];
20319 unsigned char algorithms[256];
20320 unsigned int i;
20321
20322 enum { notexpected = 0, expected = 1, found = 2 };
20323
20324 REQUIRE(DNS_ZONE_VALID(zone));
20325
20326 result = dns_db_getoriginnode(db, &node);
20327 if (result != ISC_R_SUCCESS) {
20328 return (result);
20329 }
20330
20331 dns_rdataset_init(&cds);
20332 dns_rdataset_init(&dnskey);
20333 dns_rdataset_init(&cdnskey);
20334
20335 result = dns_db_findrdataset(db, node, version, dns_rdatatype_cds,
20336 dns_rdatatype_none, 0, &cds, NULL);
20337 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
20338 goto failure;
20339 }
20340
20341 result = dns_db_findrdataset(db, node, version, dns_rdatatype_cdnskey,
20342 dns_rdatatype_none, 0, &cdnskey, NULL);
20343 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
20344 goto failure;
20345 }
20346
20347 if (!dns_rdataset_isassociated(&cds) &&
20348 !dns_rdataset_isassociated(&cdnskey)) {
20349 result = ISC_R_SUCCESS;
20350 goto failure;
20351 }
20352
20353 result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
20354 dns_rdatatype_none, 0, &dnskey, NULL);
20355 if (result == ISC_R_NOTFOUND) {
20356 if (dns_rdataset_isassociated(&cds)) {
20357 result = DNS_R_BADCDS;
20358 } else {
20359 result = DNS_R_BADCDNSKEY;
20360 }
20361 goto failure;
20362 }
20363 if (result != ISC_R_SUCCESS) {
20364 goto failure;
20365 }
20366
20367 /*
20368 * For each DNSSEC algorithm in the CDS RRset there must be
20369 * a matching DNSKEY record with the exception of a CDS deletion
20370 * record which must be by itself.
20371 */
20372 if (dns_rdataset_isassociated(&cds)) {
20373 bool delete = false;
20374 memset(algorithms, notexpected, sizeof(algorithms));
20375 for (result = dns_rdataset_first(&cds); result == ISC_R_SUCCESS;
20376 result = dns_rdataset_next(&cds))
20377 {
20378 dns_rdata_t crdata = DNS_RDATA_INIT;
20379 dns_rdata_cds_t structcds;
20380
20381 dns_rdataset_current(&cds, &crdata);
20382 /*
20383 * CDS deletion record has this form "0 0 0 00" which
20384 * is 5 zero octets.
20385 */
20386 if (crdata.length == 5U &&
20387 memcmp(crdata.data,
20388 (unsigned char[5]){ 0, 0, 0, 0, 0 }, 5) == 0)
20389 {
20390 delete = true;
20391 continue;
20392 }
20393 CHECK(dns_rdata_tostruct(&crdata, &structcds, NULL));
20394 if (algorithms[structcds.algorithm] == 0) {
20395 algorithms[structcds.algorithm] = expected;
20396 }
20397 for (result = dns_rdataset_first(&dnskey);
20398 result == ISC_R_SUCCESS;
20399 result = dns_rdataset_next(&dnskey))
20400 {
20401 dns_rdata_t rdata = DNS_RDATA_INIT;
20402 dns_rdata_t dsrdata = DNS_RDATA_INIT;
20403
20404 dns_rdataset_current(&dnskey, &rdata);
20405 CHECK(dns_ds_buildrdata(&zone->origin, &rdata,
20406 structcds.digest_type,
20407 buffer, &dsrdata));
20408 if (crdata.length == dsrdata.length &&
20409 memcmp(crdata.data, dsrdata.data,
20410 dsrdata.length) == 0)
20411 {
20412 algorithms[structcds.algorithm] = found;
20413 }
20414 }
20415 if (result != ISC_R_NOMORE) {
20416 goto failure;
20417 }
20418 }
20419 for (i = 0; i < sizeof(algorithms); i++) {
20420 if (delete) {
20421 if (algorithms[i] != notexpected) {
20422 result = DNS_R_BADCDS;
20423 goto failure;
20424 }
20425 } else if (algorithms[i] == expected) {
20426 result = DNS_R_BADCDS;
20427 goto failure;
20428 }
20429 }
20430 }
20431
20432 /*
20433 * For each DNSSEC algorithm in the CDNSKEY RRset there must be
20434 * a matching DNSKEY record with the exception of a CDNSKEY deletion
20435 * record which must be by itself.
20436 */
20437 if (dns_rdataset_isassociated(&cdnskey)) {
20438 bool delete = false;
20439 memset(algorithms, notexpected, sizeof(algorithms));
20440 for (result = dns_rdataset_first(&cdnskey);
20441 result == ISC_R_SUCCESS;
20442 result = dns_rdataset_next(&cdnskey))
20443 {
20444 dns_rdata_t crdata = DNS_RDATA_INIT;
20445 dns_rdata_cdnskey_t structcdnskey;
20446
20447 dns_rdataset_current(&cdnskey, &crdata);
20448 /*
20449 * CDNSKEY deletion record has this form
20450 * "0 3 0 AA==" which is 2 zero octets, a 3,
20451 * and 2 zero octets.
20452 */
20453 if (crdata.length == 5U &&
20454 memcmp(crdata.data,
20455 (unsigned char[5]){ 0, 0, 3, 0, 0 }, 5) == 0)
20456 {
20457 delete = true;
20458 continue;
20459 }
20460 CHECK(dns_rdata_tostruct(&crdata, &structcdnskey,
20461 NULL));
20462 if (algorithms[structcdnskey.algorithm] == 0) {
20463 algorithms[structcdnskey.algorithm] = expected;
20464 }
20465 for (result = dns_rdataset_first(&dnskey);
20466 result == ISC_R_SUCCESS;
20467 result = dns_rdataset_next(&dnskey))
20468 {
20469 dns_rdata_t rdata = DNS_RDATA_INIT;
20470
20471 dns_rdataset_current(&dnskey, &rdata);
20472 if (crdata.length == rdata.length &&
20473 memcmp(crdata.data, rdata.data,
20474 rdata.length) == 0)
20475 {
20476 algorithms[structcdnskey.algorithm] =
20477 found;
20478 }
20479 }
20480 if (result != ISC_R_NOMORE) {
20481 goto failure;
20482 }
20483 }
20484 for (i = 0; i < sizeof(algorithms); i++) {
20485 if (delete) {
20486 if (algorithms[i] != notexpected) {
20487 result = DNS_R_BADCDNSKEY;
20488 goto failure;
20489 }
20490 } else if (algorithms[i] == expected) {
20491 result = DNS_R_BADCDNSKEY;
20492 goto failure;
20493 }
20494 }
20495 }
20496 result = ISC_R_SUCCESS;
20497
20498 failure:
20499 if (dns_rdataset_isassociated(&cds)) {
20500 dns_rdataset_disassociate(&cds);
20501 }
20502 if (dns_rdataset_isassociated(&dnskey)) {
20503 dns_rdataset_disassociate(&dnskey);
20504 }
20505 if (dns_rdataset_isassociated(&cdnskey)) {
20506 dns_rdataset_disassociate(&cdnskey);
20507 }
20508 dns_db_detachnode(db, &node);
20509 return (result);
20510 }
20511
20512 void
20513 dns_zone_setautomatic(dns_zone_t *zone, bool automatic) {
20514 REQUIRE(DNS_ZONE_VALID(zone));
20515
20516 LOCK_ZONE(zone);
20517 zone->automatic = automatic;
20518 UNLOCK_ZONE(zone);
20519 }
20520
20521 bool
20522 dns_zone_getautomatic(dns_zone_t *zone) {
20523 REQUIRE(DNS_ZONE_VALID(zone));
20524 return (zone->automatic);
20525 }
20526
20527 void
20528 dns_zone_setadded(dns_zone_t *zone, bool added) {
20529 REQUIRE(DNS_ZONE_VALID(zone));
20530
20531 LOCK_ZONE(zone);
20532 zone->added = added;
20533 UNLOCK_ZONE(zone);
20534 }
20535
20536 bool
20537 dns_zone_getadded(dns_zone_t *zone) {
20538 REQUIRE(DNS_ZONE_VALID(zone));
20539 return (zone->added);
20540 }
20541
20542 isc_result_t
20543 dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db) {
20544 isc_time_t loadtime;
20545 isc_result_t result;
20546 dns_zone_t *secure = NULL;
20547
20548 TIME_NOW(&loadtime);
20549
20550 /*
20551 * Lock hierarchy: zmgr, zone, raw.
20552 */
20553 again:
20554 LOCK_ZONE(zone);
20555 INSIST(zone != zone->raw);
20556 if (inline_secure(zone)) {
20557 LOCK_ZONE(zone->raw);
20558 } else if (inline_raw(zone)) {
20559 secure = zone->secure;
20560 TRYLOCK_ZONE(result, secure);
20561 if (result != ISC_R_SUCCESS) {
20562 UNLOCK_ZONE(zone);
20563 secure = NULL;
20564 isc_thread_yield();
20565 goto again;
20566 }
20567 }
20568 result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
20569 if (inline_secure(zone)) {
20570 UNLOCK_ZONE(zone->raw);
20571 } else if (secure != NULL) {
20572 UNLOCK_ZONE(secure);
20573 }
20574 UNLOCK_ZONE(zone);
20575 return (result);
20576 }
20577
20578 isc_result_t
20579 dns_zone_setrefreshkeyinterval(dns_zone_t *zone, uint32_t interval) {
20580 REQUIRE(DNS_ZONE_VALID(zone));
20581 if (interval == 0) {
20582 return (ISC_R_RANGE);
20583 }
20584 /* Maximum value: 24 hours (3600 minutes) */
20585 if (interval > (24 * 60)) {
20586 interval = (24 * 60);
20587 }
20588 /* Multiply by 60 for seconds */
20589 zone->refreshkeyinterval = interval * 60;
20590 return (ISC_R_SUCCESS);
20591 }
20592
20593 void
20594 dns_zone_setrequestixfr(dns_zone_t *zone, bool flag) {
20595 REQUIRE(DNS_ZONE_VALID(zone));
20596 zone->requestixfr = flag;
20597 }
20598
20599 bool
20600 dns_zone_getrequestixfr(dns_zone_t *zone) {
20601 REQUIRE(DNS_ZONE_VALID(zone));
20602 return (zone->requestixfr);
20603 }
20604
20605 void
20606 dns_zone_setixfrratio(dns_zone_t *zone, uint32_t ratio) {
20607 REQUIRE(DNS_ZONE_VALID(zone));
20608 zone->ixfr_ratio = ratio;
20609 }
20610
20611 uint32_t
20612 dns_zone_getixfrratio(dns_zone_t *zone) {
20613 REQUIRE(DNS_ZONE_VALID(zone));
20614 return (zone->ixfr_ratio);
20615 }
20616
20617 void
20618 dns_zone_setrequestexpire(dns_zone_t *zone, bool flag) {
20619 REQUIRE(DNS_ZONE_VALID(zone));
20620 zone->requestexpire = flag;
20621 }
20622
20623 bool
20624 dns_zone_getrequestexpire(dns_zone_t *zone) {
20625 REQUIRE(DNS_ZONE_VALID(zone));
20626 return (zone->requestexpire);
20627 }
20628
20629 void
20630 dns_zone_setserialupdatemethod(dns_zone_t *zone, dns_updatemethod_t method) {
20631 REQUIRE(DNS_ZONE_VALID(zone));
20632 zone->updatemethod = method;
20633 }
20634
20635 dns_updatemethod_t
20636 dns_zone_getserialupdatemethod(dns_zone_t *zone) {
20637 REQUIRE(DNS_ZONE_VALID(zone));
20638 return (zone->updatemethod);
20639 }
20640
20641 /*
20642 * Lock hierarchy: zmgr, zone, raw.
20643 */
20644 isc_result_t
20645 dns_zone_link(dns_zone_t *zone, dns_zone_t *raw) {
20646 isc_result_t result;
20647 dns_zonemgr_t *zmgr;
20648
20649 REQUIRE(DNS_ZONE_VALID(zone));
20650 REQUIRE(zone->zmgr != NULL);
20651 REQUIRE(zone->task != NULL);
20652 REQUIRE(zone->loadtask != NULL);
20653 REQUIRE(zone->raw == NULL);
20654
20655 REQUIRE(DNS_ZONE_VALID(raw));
20656 REQUIRE(raw->zmgr == NULL);
20657 REQUIRE(raw->task == NULL);
20658 REQUIRE(raw->loadtask == NULL);
20659 REQUIRE(raw->secure == NULL);
20660
20661 REQUIRE(zone != raw);
20662
20663 /*
20664 * Lock hierarchy: zmgr, zone, raw.
20665 */
20666 zmgr = zone->zmgr;
20667 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
20668 LOCK_ZONE(zone);
20669 LOCK_ZONE(raw);
20670
20671 result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive, NULL,
20672 NULL, zone->task, zone_timer, raw,
20673 &raw->timer);
20674 if (result != ISC_R_SUCCESS) {
20675 goto unlock;
20676 }
20677
20678 /*
20679 * The timer "holds" a iref.
20680 */
20681 isc_refcount_increment0(&raw->irefs);
20682
20683 /* dns_zone_attach(raw, &zone->raw); */
20684 isc_refcount_increment(&raw->erefs);
20685 zone->raw = raw;
20686
20687 /* dns_zone_iattach(zone, &raw->secure); */
20688 zone_iattach(zone, &raw->secure);
20689
20690 isc_task_attach(zone->task, &raw->task);
20691 isc_task_attach(zone->loadtask, &raw->loadtask);
20692
20693 ISC_LIST_APPEND(zmgr->zones, raw, link);
20694 raw->zmgr = zmgr;
20695 isc_refcount_increment(&zmgr->refs);
20696
20697 unlock:
20698 UNLOCK_ZONE(raw);
20699 UNLOCK_ZONE(zone);
20700 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
20701 return (result);
20702 }
20703
20704 void
20705 dns_zone_getraw(dns_zone_t *zone, dns_zone_t **raw) {
20706 REQUIRE(DNS_ZONE_VALID(zone));
20707 REQUIRE(raw != NULL && *raw == NULL);
20708
20709 LOCK(&zone->lock);
20710 INSIST(zone != zone->raw);
20711 if (zone->raw != NULL) {
20712 dns_zone_attach(zone->raw, raw);
20713 }
20714 UNLOCK(&zone->lock);
20715 }
20716
20717 struct keydone {
20718 isc_event_t event;
20719 bool all;
20720 unsigned char data[5];
20721 };
20722
20723 #define PENDINGFLAGS (DNS_NSEC3FLAG_CREATE | DNS_NSEC3FLAG_INITIAL)
20724
20725 static void
20726 keydone(isc_task_t *task, isc_event_t *event) {
20727 const char *me = "keydone";
20728 bool commit = false;
20729 isc_result_t result;
20730 dns_rdata_t rdata = DNS_RDATA_INIT;
20731 dns_dbversion_t *oldver = NULL, *newver = NULL;
20732 dns_zone_t *zone;
20733 dns_db_t *db = NULL;
20734 dns_dbnode_t *node = NULL;
20735 dns_rdataset_t rdataset;
20736 dns_diff_t diff;
20737 struct keydone *kd = (struct keydone *)event;
20738 dns_update_log_t log = { update_log_cb, NULL };
20739 bool clear_pending = false;
20740
20741 UNUSED(task);
20742
20743 zone = event->ev_arg;
20744 INSIST(DNS_ZONE_VALID(zone));
20745
20746 ENTER;
20747
20748 dns_rdataset_init(&rdataset);
20749 dns_diff_init(zone->mctx, &diff);
20750
20751 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
20752 if (zone->db != NULL) {
20753 dns_db_attach(zone->db, &db);
20754 }
20755 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
20756 if (db == NULL) {
20757 goto failure;
20758 }
20759
20760 dns_db_currentversion(db, &oldver);
20761 result = dns_db_newversion(db, &newver);
20762 if (result != ISC_R_SUCCESS) {
20763 dnssec_log(zone, ISC_LOG_ERROR,
20764 "keydone:dns_db_newversion -> %s",
20765 dns_result_totext(result));
20766 goto failure;
20767 }
20768
20769 result = dns_db_getoriginnode(db, &node);
20770 if (result != ISC_R_SUCCESS) {
20771 goto failure;
20772 }
20773
20774 result = dns_db_findrdataset(db, node, newver, zone->privatetype,
20775 dns_rdatatype_none, 0, &rdataset, NULL);
20776 if (result == ISC_R_NOTFOUND) {
20777 INSIST(!dns_rdataset_isassociated(&rdataset));
20778 goto failure;
20779 }
20780 if (result != ISC_R_SUCCESS) {
20781 INSIST(!dns_rdataset_isassociated(&rdataset));
20782 goto failure;
20783 }
20784
20785 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
20786 result = dns_rdataset_next(&rdataset))
20787 {
20788 bool found = false;
20789
20790 dns_rdataset_current(&rdataset, &rdata);
20791
20792 if (kd->all) {
20793 if (rdata.length == 5 && rdata.data[0] != 0 &&
20794 rdata.data[3] == 0 && rdata.data[4] == 1)
20795 {
20796 found = true;
20797 } else if (rdata.data[0] == 0 &&
20798 (rdata.data[2] & PENDINGFLAGS) != 0) {
20799 found = true;
20800 clear_pending = true;
20801 }
20802 } else if (rdata.length == 5 &&
20803 memcmp(rdata.data, kd->data, 5) == 0) {
20804 found = true;
20805 }
20806
20807 if (found) {
20808 CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_DEL,
20809 &zone->origin, rdataset.ttl,
20810 &rdata));
20811 }
20812 dns_rdata_reset(&rdata);
20813 }
20814
20815 if (!ISC_LIST_EMPTY(diff.tuples)) {
20816 /* Write changes to journal file. */
20817 CHECK(update_soa_serial(zone, db, newver, &diff, zone->mctx,
20818 zone->updatemethod));
20819
20820 result = dns_update_signatures(&log, zone, db, oldver, newver,
20821 &diff,
20822 zone->sigvalidityinterval);
20823 if (!clear_pending) {
20824 CHECK(result);
20825 }
20826
20827 CHECK(zone_journal(zone, &diff, NULL, "keydone"));
20828 commit = true;
20829
20830 LOCK_ZONE(zone);
20831 DNS_ZONE_SETFLAG(zone,
20832 DNS_ZONEFLG_LOADED | DNS_ZONEFLG_NEEDNOTIFY);
20833 zone_needdump(zone, 30);
20834 UNLOCK_ZONE(zone);
20835 }
20836
20837 failure:
20838 if (dns_rdataset_isassociated(&rdataset)) {
20839 dns_rdataset_disassociate(&rdataset);
20840 }
20841 if (db != NULL) {
20842 if (node != NULL) {
20843 dns_db_detachnode(db, &node);
20844 }
20845 if (oldver != NULL) {
20846 dns_db_closeversion(db, &oldver, false);
20847 }
20848 if (newver != NULL) {
20849 dns_db_closeversion(db, &newver, commit);
20850 }
20851 dns_db_detach(&db);
20852 }
20853 dns_diff_clear(&diff);
20854 isc_event_free(&event);
20855 dns_zone_idetach(&zone);
20856
20857 INSIST(oldver == NULL);
20858 INSIST(newver == NULL);
20859 }
20860
20861 isc_result_t
20862 dns_zone_keydone(dns_zone_t *zone, const char *keystr) {
20863 isc_result_t result = ISC_R_SUCCESS;
20864 isc_event_t *e;
20865 isc_buffer_t b;
20866 dns_zone_t *dummy = NULL;
20867 struct keydone *kd;
20868
20869 REQUIRE(DNS_ZONE_VALID(zone));
20870
20871 LOCK_ZONE(zone);
20872
20873 e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_KEYDONE, keydone,
20874 zone, sizeof(struct keydone));
20875
20876 kd = (struct keydone *)e;
20877 if (strcasecmp(keystr, "all") == 0) {
20878 kd->all = true;
20879 } else {
20880 isc_textregion_t r;
20881 const char *algstr;
20882 dns_keytag_t keyid;
20883 dns_secalg_t alg;
20884 size_t n;
20885
20886 kd->all = false;
20887
20888 n = sscanf(keystr, "%hu/", &keyid);
20889 if (n == 0U) {
20890 CHECK(ISC_R_FAILURE);
20891 }
20892
20893 algstr = strchr(keystr, '/');
20894 if (algstr != NULL) {
20895 algstr++;
20896 } else {
20897 CHECK(ISC_R_FAILURE);
20898 }
20899
20900 n = sscanf(algstr, "%hhu", &alg);
20901 if (n == 0U) {
20902 DE_CONST(algstr, r.base);
20903 r.length = strlen(algstr);
20904 CHECK(dns_secalg_fromtext(&alg, &r));
20905 }
20906
20907 /* construct a private-type rdata */
20908 isc_buffer_init(&b, kd->data, sizeof(kd->data));
20909 isc_buffer_putuint8(&b, alg);
20910 isc_buffer_putuint8(&b, (keyid & 0xff00) >> 8);
20911 isc_buffer_putuint8(&b, (keyid & 0xff));
20912 isc_buffer_putuint8(&b, 0);
20913 isc_buffer_putuint8(&b, 1);
20914 }
20915
20916 zone_iattach(zone, &dummy);
20917 isc_task_send(zone->task, &e);
20918
20919 failure:
20920 if (e != NULL) {
20921 isc_event_free(&e);
20922 }
20923 UNLOCK_ZONE(zone);
20924 return (result);
20925 }
20926
20927 /*
20928 * Called from the zone task's queue after the relevant event is posted by
20929 * dns_zone_setnsec3param().
20930 */
20931 static void
20932 setnsec3param(isc_task_t *task, isc_event_t *event) {
20933 const char *me = "setnsec3param";
20934 dns_zone_t *zone = event->ev_arg;
20935
20936 INSIST(DNS_ZONE_VALID(zone));
20937
20938 UNUSED(task);
20939
20940 ENTER;
20941
20942 /*
20943 * If receive_secure_serial is still processing or we have a
20944 * queued event append rss_post queue.
20945 */
20946 if (zone->rss_newver != NULL || ISC_LIST_HEAD(zone->rss_post) != NULL) {
20947 /*
20948 * Wait for receive_secure_serial() to finish processing.
20949 */
20950 ISC_LIST_APPEND(zone->rss_post, event, ev_link);
20951 } else {
20952 rss_post(zone, event);
20953 }
20954 dns_zone_idetach(&zone);
20955 }
20956
20957 /*
20958 * Check whether NSEC3 chain addition or removal specified by the private-type
20959 * record passed with the event was already queued (or even fully performed).
20960 * If not, modify the relevant private-type records at the zone apex and call
20961 * resume_addnsec3chain().
20962 */
20963 static void
20964 rss_post(dns_zone_t *zone, isc_event_t *event) {
20965 const char *me = "rss_post";
20966 bool commit = false;
20967 isc_result_t result;
20968 dns_dbversion_t *oldver = NULL, *newver = NULL;
20969 dns_db_t *db = NULL;
20970 dns_dbnode_t *node = NULL;
20971 dns_rdataset_t prdataset, nrdataset;
20972 dns_diff_t diff;
20973 struct np3event *npe = (struct np3event *)event;
20974 nsec3param_t *np;
20975 dns_update_log_t log = { update_log_cb, NULL };
20976 dns_rdata_t rdata;
20977 bool nseconly;
20978 bool exists = false;
20979
20980 ENTER;
20981
20982 np = &npe->params;
20983
20984 dns_rdataset_init(&prdataset);
20985 dns_rdataset_init(&nrdataset);
20986 dns_diff_init(zone->mctx, &diff);
20987
20988 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
20989 if (zone->db != NULL) {
20990 dns_db_attach(zone->db, &db);
20991 }
20992 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
20993 if (db == NULL) {
20994 goto failure;
20995 }
20996
20997 dns_db_currentversion(db, &oldver);
20998 result = dns_db_newversion(db, &newver);
20999 if (result != ISC_R_SUCCESS) {
21000 dnssec_log(zone, ISC_LOG_ERROR,
21001 "setnsec3param:dns_db_newversion -> %s",
21002 dns_result_totext(result));
21003 goto failure;
21004 }
21005
21006 CHECK(dns_db_getoriginnode(db, &node));
21007
21008 /*
21009 * Does a private-type record already exist for this chain?
21010 */
21011 result = dns_db_findrdataset(db, node, newver, zone->privatetype,
21012 dns_rdatatype_none, 0, &prdataset, NULL);
21013 if (result == ISC_R_SUCCESS) {
21014 for (result = dns_rdataset_first(&prdataset);
21015 result == ISC_R_SUCCESS;
21016 result = dns_rdataset_next(&prdataset))
21017 {
21018 dns_rdata_init(&rdata);
21019 dns_rdataset_current(&prdataset, &rdata);
21020
21021 if (np->length == rdata.length &&
21022 memcmp(rdata.data, np->data, np->length) == 0) {
21023 exists = true;
21024 break;
21025 }
21026 }
21027 } else if (result != ISC_R_NOTFOUND) {
21028 INSIST(!dns_rdataset_isassociated(&prdataset));
21029 goto failure;
21030 }
21031
21032 /*
21033 * Does the chain already exist?
21034 */
21035 result = dns_db_findrdataset(db, node, newver, dns_rdatatype_nsec3param,
21036 dns_rdatatype_none, 0, &nrdataset, NULL);
21037 if (result == ISC_R_SUCCESS) {
21038 for (result = dns_rdataset_first(&nrdataset);
21039 result == ISC_R_SUCCESS;
21040 result = dns_rdataset_next(&nrdataset))
21041 {
21042 dns_rdata_init(&rdata);
21043 dns_rdataset_current(&nrdataset, &rdata);
21044
21045 if (np->length == (rdata.length + 1) &&
21046 memcmp(rdata.data, np->data + 1, np->length - 1) ==
21047 0)
21048 {
21049 exists = true;
21050 break;
21051 }
21052 }
21053 } else if (result != ISC_R_NOTFOUND) {
21054 INSIST(!dns_rdataset_isassociated(&nrdataset));
21055 goto failure;
21056 }
21057
21058 /*
21059 * We need to remove any existing NSEC3 chains if the supplied NSEC3
21060 * parameters are supposed to replace the current ones or if we are
21061 * switching to NSEC.
21062 */
21063 if (!exists && np->replace && (np->length != 0 || np->nsec)) {
21064 CHECK(dns_nsec3param_deletechains(db, newver, zone, !np->nsec,
21065 &diff));
21066 }
21067
21068 if (!exists && np->length != 0) {
21069 /*
21070 * We're creating an NSEC3 chain. Add the private-type record
21071 * passed in the event handler's argument to the zone apex.
21072 *
21073 * If the zone is not currently capable of supporting an NSEC3
21074 * chain (due to the DNSKEY RRset at the zone apex not existing
21075 * or containing at least one key using an NSEC-only
21076 * algorithm), add the INITIAL flag, so these parameters can be
21077 * used later when NSEC3 becomes available.
21078 */
21079 dns_rdata_init(&rdata);
21080
21081 np->data[2] |= DNS_NSEC3FLAG_CREATE;
21082 result = dns_nsec_nseconly(db, newver, &nseconly);
21083 if (result == ISC_R_NOTFOUND || nseconly) {
21084 np->data[2] |= DNS_NSEC3FLAG_INITIAL;
21085 }
21086
21087 rdata.length = np->length;
21088 rdata.data = np->data;
21089 rdata.type = zone->privatetype;
21090 rdata.rdclass = zone->rdclass;
21091 CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_ADD,
21092 &zone->origin, 0, &rdata));
21093 }
21094
21095 /*
21096 * If we changed anything in the zone, write changes to journal file
21097 * and set commit to true so that resume_addnsec3chain() will be
21098 * called below in order to kick off adding/removing relevant NSEC3
21099 * records.
21100 */
21101 if (!ISC_LIST_EMPTY(diff.tuples)) {
21102 CHECK(update_soa_serial(zone, db, newver, &diff, zone->mctx,
21103 zone->updatemethod));
21104 result = dns_update_signatures(&log, zone, db, oldver, newver,
21105 &diff,
21106 zone->sigvalidityinterval);
21107 if (result != ISC_R_NOTFOUND) {
21108 CHECK(result);
21109 }
21110 CHECK(zone_journal(zone, &diff, NULL, "setnsec3param"));
21111 commit = true;
21112
21113 LOCK_ZONE(zone);
21114 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
21115 zone_needdump(zone, 30);
21116 UNLOCK_ZONE(zone);
21117 }
21118
21119 failure:
21120 if (dns_rdataset_isassociated(&prdataset)) {
21121 dns_rdataset_disassociate(&prdataset);
21122 }
21123 if (dns_rdataset_isassociated(&nrdataset)) {
21124 dns_rdataset_disassociate(&nrdataset);
21125 }
21126 if (node != NULL) {
21127 dns_db_detachnode(db, &node);
21128 }
21129 if (oldver != NULL) {
21130 dns_db_closeversion(db, &oldver, false);
21131 }
21132 if (newver != NULL) {
21133 dns_db_closeversion(db, &newver, commit);
21134 }
21135 if (db != NULL) {
21136 dns_db_detach(&db);
21137 }
21138 if (commit) {
21139 LOCK_ZONE(zone);
21140 resume_addnsec3chain(zone);
21141 UNLOCK_ZONE(zone);
21142 }
21143 dns_diff_clear(&diff);
21144 isc_event_free(&event);
21145
21146 INSIST(oldver == NULL);
21147 INSIST(newver == NULL);
21148 }
21149
21150 static void
21151 salt2text(unsigned char *salt, uint8_t saltlen, unsigned char *text,
21152 unsigned int textlen) {
21153 isc_region_t r;
21154 isc_buffer_t buf;
21155 isc_result_t result;
21156
21157 r.base = salt;
21158 r.length = (unsigned int)saltlen;
21159
21160 isc_buffer_init(&buf, text, textlen);
21161 result = isc_hex_totext(&r, 2, "", &buf);
21162 if (result == ISC_R_SUCCESS) {
21163 text[saltlen * 2] = 0;
21164 } else {
21165 text[0] = 0;
21166 }
21167 }
21168
21169 /*
21170 * Check if zone has NSEC3PARAM (and thus a chain) with the right parameters.
21171 *
21172 * If 'salt' is NULL, a match is found if the salt has the requested length,
21173 * otherwise the NSEC3 salt must match the requested salt value too.
21174 *
21175 * Returns ISC_R_SUCCESS, if a match is found, or an error if no match is
21176 * found, or if the db lookup failed.
21177 */
21178 isc_result_t
21179 dns__zone_lookup_nsec3param(dns_zone_t *zone, dns_rdata_nsec3param_t *lookup,
21180 dns_rdata_nsec3param_t *param,
21181 unsigned char saltbuf[255], bool resalt) {
21182 isc_result_t result = ISC_R_UNEXPECTED;
21183 dns_dbnode_t *node = NULL;
21184 dns_db_t *db = NULL;
21185 dns_dbversion_t *version = NULL;
21186 dns_rdataset_t rdataset;
21187 dns_rdata_nsec3param_t nsec3param;
21188 dns_rdata_t rdata = DNS_RDATA_INIT;
21189
21190 REQUIRE(DNS_ZONE_VALID(zone));
21191
21192 dns_rdataset_init(&rdataset);
21193
21194 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
21195 if (zone->db != NULL) {
21196 dns_db_attach(zone->db, &db);
21197 }
21198 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
21199 if (db == NULL) {
21200 goto setparam;
21201 }
21202
21203 result = dns_db_findnode(db, &zone->origin, false, &node);
21204 if (result != ISC_R_SUCCESS) {
21205 dns_zone_log(zone, ISC_LOG_ERROR,
21206 "nsec3param lookup failure: %s",
21207 dns_result_totext(result));
21208 goto setparam;
21209 }
21210 dns_db_currentversion(db, &version);
21211
21212 result = dns_db_findrdataset(db, node, version,
21213 dns_rdatatype_nsec3param,
21214 dns_rdatatype_none, 0, &rdataset, NULL);
21215 if (result != ISC_R_SUCCESS) {
21216 INSIST(!dns_rdataset_isassociated(&rdataset));
21217 if (result != ISC_R_NOTFOUND) {
21218 dns_zone_log(zone, ISC_LOG_ERROR,
21219 "nsec3param lookup failure: %s",
21220 dns_result_totext(result));
21221 }
21222 goto setparam;
21223 }
21224
21225 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
21226 result = dns_rdataset_next(&rdataset))
21227 {
21228 dns_rdataset_current(&rdataset, &rdata);
21229 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
21230 INSIST(result == ISC_R_SUCCESS);
21231 dns_rdata_reset(&rdata);
21232
21233 /* Check parameters. */
21234 if (nsec3param.hash != lookup->hash) {
21235 continue;
21236 }
21237 if (nsec3param.iterations != lookup->iterations) {
21238 continue;
21239 }
21240 if (nsec3param.salt_length != lookup->salt_length) {
21241 continue;
21242 }
21243 if (lookup->salt != NULL) {
21244 if (memcmp(nsec3param.salt, lookup->salt,
21245 lookup->salt_length) != 0) {
21246 continue;
21247 }
21248 }
21249 /* Found a match. */
21250 result = ISC_R_SUCCESS;
21251 param->hash = nsec3param.hash;
21252 param->flags = nsec3param.flags;
21253 param->iterations = nsec3param.iterations;
21254 param->salt_length = nsec3param.salt_length;
21255 param->salt = nsec3param.salt;
21256 break;
21257 }
21258
21259 setparam:
21260 if (result != ISC_R_SUCCESS) {
21261 /* Found no match. */
21262 result = ISC_R_NOTFOUND;
21263 param->hash = lookup->hash;
21264 param->flags = lookup->flags;
21265 param->iterations = lookup->iterations;
21266 param->salt_length = lookup->salt_length;
21267 param->salt = lookup->salt;
21268 }
21269
21270 if (param->salt_length == 0) {
21271 DE_CONST("-", param->salt);
21272 } else if (resalt || param->salt == NULL) {
21273 unsigned char *newsalt;
21274 unsigned char salttext[255 * 2 + 1];
21275 do {
21276 /* Generate a new salt. */
21277 result = dns_nsec3_generate_salt(saltbuf,
21278 param->salt_length);
21279 if (result != ISC_R_SUCCESS) {
21280 break;
21281 }
21282 newsalt = saltbuf;
21283 salt2text(newsalt, param->salt_length, salttext,
21284 sizeof(salttext));
21285 dnssec_log(zone, ISC_LOG_INFO, "generated salt: %s",
21286 salttext);
21287 /* Check for salt conflict. */
21288 if (param->salt != NULL &&
21289 memcmp(newsalt, param->salt, param->salt_length) ==
21290 0)
21291 {
21292 result = ISC_R_SUCCESS;
21293 } else {
21294 param->salt = newsalt;
21295 result = DNS_R_NSEC3RESALT;
21296 }
21297 } while (result == ISC_R_SUCCESS);
21298
21299 INSIST(result != ISC_R_SUCCESS);
21300 }
21301
21302 if (dns_rdataset_isassociated(&rdataset)) {
21303 dns_rdataset_disassociate(&rdataset);
21304 }
21305 if (node != NULL) {
21306 dns_db_detachnode(db, &node);
21307 }
21308 if (version != NULL) {
21309 dns_db_closeversion(db, &version, false);
21310 }
21311 if (db != NULL) {
21312 dns_db_detach(&db);
21313 }
21314
21315 return (result);
21316 }
21317
21318 /*
21319 * Called when an "rndc signing -nsec3param ..." command is received, or the
21320 * 'dnssec-policy' has changed.
21321 *
21322 * Allocate and prepare an nsec3param_t structure which holds information about
21323 * the NSEC3 changes requested for the zone:
21324 *
21325 * - if NSEC3 is to be disabled ("-nsec3param none"), only set the "nsec"
21326 * field of the structure to true and the "replace" field to the value
21327 * of the "replace" argument, leaving other fields initialized to zeros, to
21328 * signal that the zone should be signed using NSEC instead of NSEC3,
21329 *
21330 * - otherwise, prepare NSEC3PARAM RDATA that will eventually be inserted at
21331 * the zone apex, convert it to a private-type record and store the latter
21332 * in the "data" field of the nsec3param_t structure.
21333 *
21334 * Once the nsec3param_t structure is prepared, post an event to the zone's
21335 * task which will cause setnsec3param() to be called with the prepared
21336 * structure passed as an argument.
21337 */
21338 isc_result_t
21339 dns_zone_setnsec3param(dns_zone_t *zone, uint8_t hash, uint8_t flags,
21340 uint16_t iter, uint8_t saltlen, unsigned char *salt,
21341 bool replace, bool resalt) {
21342 isc_result_t result = ISC_R_SUCCESS;
21343 dns_rdata_nsec3param_t param, lookup;
21344 dns_rdata_t nrdata = DNS_RDATA_INIT;
21345 dns_rdata_t prdata = DNS_RDATA_INIT;
21346 unsigned char nbuf[DNS_NSEC3PARAM_BUFFERSIZE];
21347 unsigned char saltbuf[255];
21348 struct np3event *npe;
21349 nsec3param_t *np;
21350 dns_zone_t *dummy = NULL;
21351 isc_buffer_t b;
21352 isc_event_t *e = NULL;
21353
21354 REQUIRE(DNS_ZONE_VALID(zone));
21355
21356 LOCK_ZONE(zone);
21357
21358 /*
21359 * First check if the requested NSEC3 parameters are already set,
21360 * if so, no need to set again.
21361 */
21362 if (hash != 0) {
21363 lookup.hash = hash;
21364 lookup.flags = flags;
21365 lookup.iterations = iter;
21366 lookup.salt_length = saltlen;
21367 lookup.salt = salt;
21368 param.salt = NULL;
21369 result = dns__zone_lookup_nsec3param(zone, &lookup, ¶m,
21370 saltbuf, resalt);
21371 if (result == ISC_R_SUCCESS) {
21372 UNLOCK_ZONE(zone);
21373 return (ISC_R_SUCCESS);
21374 }
21375 INSIST(param.salt != NULL);
21376 }
21377
21378 e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETNSEC3PARAM,
21379 setnsec3param, zone, sizeof(struct np3event));
21380
21381 npe = (struct np3event *)e;
21382 np = &npe->params;
21383
21384 np->replace = replace;
21385 if (hash == 0) {
21386 np->length = 0;
21387 np->nsec = true;
21388 dnssec_log(zone, ISC_LOG_DEBUG(3), "setnsec3param:nsec");
21389 } else {
21390 param.common.rdclass = zone->rdclass;
21391 param.common.rdtype = dns_rdatatype_nsec3param;
21392 ISC_LINK_INIT(¶m.common, link);
21393 param.mctx = NULL;
21394 /* nsec3 specific param set in dns__zone_lookup_nsec3param() */
21395 isc_buffer_init(&b, nbuf, sizeof(nbuf));
21396 CHECK(dns_rdata_fromstruct(&nrdata, zone->rdclass,
21397 dns_rdatatype_nsec3param, ¶m,
21398 &b));
21399 dns_nsec3param_toprivate(&nrdata, &prdata, zone->privatetype,
21400 np->data, sizeof(np->data));
21401 np->length = prdata.length;
21402 np->nsec = false;
21403
21404 if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
21405 unsigned char salttext[255 * 2 + 1];
21406 salt2text(param.salt, param.salt_length, salttext,
21407 sizeof(salttext));
21408 dnssec_log(zone, ISC_LOG_DEBUG(3),
21409 "setnsec3param:nsec3 %u %u %u %s",
21410 param.hash, param.flags, param.iterations,
21411 salttext);
21412 }
21413 }
21414
21415 /*
21416 * setnsec3param() will silently return early if the zone does not yet
21417 * have a database. Prevent that by queueing the event up if zone->db
21418 * is NULL. All events queued here are subsequently processed by
21419 * receive_secure_db() if it ever gets called or simply freed by
21420 * zone_free() otherwise.
21421 */
21422
21423 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
21424 if (zone->db != NULL) {
21425 zone_iattach(zone, &dummy);
21426 isc_task_send(zone->task, &e);
21427 } else {
21428 ISC_LIST_APPEND(zone->setnsec3param_queue, e, ev_link);
21429 e = NULL;
21430 }
21431 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
21432
21433 result = ISC_R_SUCCESS;
21434
21435 failure:
21436 if (e != NULL) {
21437 isc_event_free(&e);
21438 }
21439 UNLOCK_ZONE(zone);
21440 return (result);
21441 }
21442
21443 isc_result_t
21444 dns_zone_getloadtime(dns_zone_t *zone, isc_time_t *loadtime) {
21445 REQUIRE(DNS_ZONE_VALID(zone));
21446 REQUIRE(loadtime != NULL);
21447
21448 LOCK_ZONE(zone);
21449 *loadtime = zone->loadtime;
21450 UNLOCK_ZONE(zone);
21451 return (ISC_R_SUCCESS);
21452 }
21453
21454 isc_result_t
21455 dns_zone_getexpiretime(dns_zone_t *zone, isc_time_t *expiretime) {
21456 REQUIRE(DNS_ZONE_VALID(zone));
21457 REQUIRE(expiretime != NULL);
21458
21459 LOCK_ZONE(zone);
21460 *expiretime = zone->expiretime;
21461 UNLOCK_ZONE(zone);
21462 return (ISC_R_SUCCESS);
21463 }
21464
21465 isc_result_t
21466 dns_zone_getrefreshtime(dns_zone_t *zone, isc_time_t *refreshtime) {
21467 REQUIRE(DNS_ZONE_VALID(zone));
21468 REQUIRE(refreshtime != NULL);
21469
21470 LOCK_ZONE(zone);
21471 *refreshtime = zone->refreshtime;
21472 UNLOCK_ZONE(zone);
21473 return (ISC_R_SUCCESS);
21474 }
21475
21476 isc_result_t
21477 dns_zone_getrefreshkeytime(dns_zone_t *zone, isc_time_t *refreshkeytime) {
21478 REQUIRE(DNS_ZONE_VALID(zone));
21479 REQUIRE(refreshkeytime != NULL);
21480
21481 LOCK_ZONE(zone);
21482 *refreshkeytime = zone->refreshkeytime;
21483 UNLOCK_ZONE(zone);
21484 return (ISC_R_SUCCESS);
21485 }
21486
21487 unsigned int
21488 dns_zone_getincludes(dns_zone_t *zone, char ***includesp) {
21489 dns_include_t *include;
21490 char **array = NULL;
21491 unsigned int n = 0;
21492
21493 REQUIRE(DNS_ZONE_VALID(zone));
21494 REQUIRE(includesp != NULL && *includesp == NULL);
21495
21496 LOCK_ZONE(zone);
21497 if (zone->nincludes == 0) {
21498 goto done;
21499 }
21500
21501 array = isc_mem_allocate(zone->mctx, sizeof(char *) * zone->nincludes);
21502 for (include = ISC_LIST_HEAD(zone->includes); include != NULL;
21503 include = ISC_LIST_NEXT(include, link))
21504 {
21505 INSIST(n < zone->nincludes);
21506 array[n++] = isc_mem_strdup(zone->mctx, include->name);
21507 }
21508 INSIST(n == zone->nincludes);
21509 *includesp = array;
21510
21511 done:
21512 UNLOCK_ZONE(zone);
21513 return (n);
21514 }
21515
21516 void
21517 dns_zone_setstatlevel(dns_zone_t *zone, dns_zonestat_level_t level) {
21518 REQUIRE(DNS_ZONE_VALID(zone));
21519
21520 zone->statlevel = level;
21521 }
21522
21523 dns_zonestat_level_t
21524 dns_zone_getstatlevel(dns_zone_t *zone) {
21525 REQUIRE(DNS_ZONE_VALID(zone));
21526
21527 return (zone->statlevel);
21528 }
21529
21530 static void
21531 setserial(isc_task_t *task, isc_event_t *event) {
21532 uint32_t oldserial, desired;
21533 const char *me = "setserial";
21534 bool commit = false;
21535 isc_result_t result;
21536 dns_dbversion_t *oldver = NULL, *newver = NULL;
21537 dns_zone_t *zone;
21538 dns_db_t *db = NULL;
21539 dns_diff_t diff;
21540 struct ssevent *sse = (struct ssevent *)event;
21541 dns_update_log_t log = { update_log_cb, NULL };
21542 dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
21543
21544 UNUSED(task);
21545
21546 zone = event->ev_arg;
21547 INSIST(DNS_ZONE_VALID(zone));
21548
21549 ENTER;
21550
21551 if (zone->update_disabled) {
21552 goto failure;
21553 }
21554
21555 desired = sse->serial;
21556
21557 dns_diff_init(zone->mctx, &diff);
21558
21559 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
21560 if (zone->db != NULL) {
21561 dns_db_attach(zone->db, &db);
21562 }
21563 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
21564 if (db == NULL) {
21565 goto failure;
21566 }
21567
21568 dns_db_currentversion(db, &oldver);
21569 result = dns_db_newversion(db, &newver);
21570 if (result != ISC_R_SUCCESS) {
21571 dns_zone_log(zone, ISC_LOG_ERROR,
21572 "setserial:dns_db_newversion -> %s",
21573 dns_result_totext(result));
21574 goto failure;
21575 }
21576
21577 CHECK(dns_db_createsoatuple(db, oldver, diff.mctx, DNS_DIFFOP_DEL,
21578 &oldtuple));
21579 CHECK(dns_difftuple_copy(oldtuple, &newtuple));
21580 newtuple->op = DNS_DIFFOP_ADD;
21581
21582 oldserial = dns_soa_getserial(&oldtuple->rdata);
21583 if (desired == 0U) {
21584 desired = 1;
21585 }
21586 if (!isc_serial_gt(desired, oldserial)) {
21587 if (desired != oldserial) {
21588 dns_zone_log(zone, ISC_LOG_INFO,
21589 "setserial: desired serial (%u) "
21590 "out of range (%u-%u)",
21591 desired, oldserial + 1,
21592 (oldserial + 0x7fffffff));
21593 }
21594 goto failure;
21595 }
21596
21597 dns_soa_setserial(desired, &newtuple->rdata);
21598 CHECK(do_one_tuple(&oldtuple, db, newver, &diff));
21599 CHECK(do_one_tuple(&newtuple, db, newver, &diff));
21600 result = dns_update_signatures(&log, zone, db, oldver, newver, &diff,
21601 zone->sigvalidityinterval);
21602 if (result != ISC_R_NOTFOUND) {
21603 CHECK(result);
21604 }
21605
21606 /* Write changes to journal file. */
21607 CHECK(zone_journal(zone, &diff, NULL, "setserial"));
21608 commit = true;
21609
21610 LOCK_ZONE(zone);
21611 zone_needdump(zone, 30);
21612 UNLOCK_ZONE(zone);
21613
21614 failure:
21615 if (oldtuple != NULL) {
21616 dns_difftuple_free(&oldtuple);
21617 }
21618 if (newtuple != NULL) {
21619 dns_difftuple_free(&newtuple);
21620 }
21621 if (oldver != NULL) {
21622 dns_db_closeversion(db, &oldver, false);
21623 }
21624 if (newver != NULL) {
21625 dns_db_closeversion(db, &newver, commit);
21626 }
21627 if (db != NULL) {
21628 dns_db_detach(&db);
21629 }
21630 dns_diff_clear(&diff);
21631 isc_event_free(&event);
21632 dns_zone_idetach(&zone);
21633
21634 INSIST(oldver == NULL);
21635 INSIST(newver == NULL);
21636 }
21637
21638 isc_result_t
21639 dns_zone_setserial(dns_zone_t *zone, uint32_t serial) {
21640 isc_result_t result = ISC_R_SUCCESS;
21641 dns_zone_t *dummy = NULL;
21642 isc_event_t *e = NULL;
21643 struct ssevent *sse;
21644
21645 REQUIRE(DNS_ZONE_VALID(zone));
21646
21647 LOCK_ZONE(zone);
21648
21649 if (!inline_secure(zone)) {
21650 if (!dns_zone_isdynamic(zone, true)) {
21651 result = DNS_R_NOTDYNAMIC;
21652 goto failure;
21653 }
21654 }
21655
21656 if (zone->update_disabled) {
21657 result = DNS_R_FROZEN;
21658 goto failure;
21659 }
21660
21661 e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETSERIAL, setserial,
21662 zone, sizeof(struct ssevent));
21663
21664 sse = (struct ssevent *)e;
21665 sse->serial = serial;
21666
21667 zone_iattach(zone, &dummy);
21668 isc_task_send(zone->task, &e);
21669
21670 failure:
21671 if (e != NULL) {
21672 isc_event_free(&e);
21673 }
21674 UNLOCK_ZONE(zone);
21675 return (result);
21676 }
21677
21678 isc_stats_t *
21679 dns_zone_getgluecachestats(dns_zone_t *zone) {
21680 REQUIRE(DNS_ZONE_VALID(zone));
21681
21682 return (zone->gluecachestats);
21683 }
21684
21685 bool
21686 dns_zone_isloaded(dns_zone_t *zone) {
21687 REQUIRE(DNS_ZONE_VALID(zone));
21688
21689 return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED));
21690 }
21691
21692 isc_result_t
21693 dns_zone_verifydb(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver) {
21694 dns_dbversion_t *version = NULL;
21695 dns_keytable_t *secroots = NULL;
21696 isc_result_t result;
21697 dns_name_t *origin;
21698
21699 const char me[] = "dns_zone_verifydb";
21700
21701 REQUIRE(DNS_ZONE_VALID(zone));
21702 REQUIRE(db != NULL);
21703
21704 ENTER;
21705
21706 if (dns_zone_gettype(zone) != dns_zone_mirror) {
21707 return (ISC_R_SUCCESS);
21708 }
21709
21710 if (ver == NULL) {
21711 dns_db_currentversion(db, &version);
21712 } else {
21713 version = ver;
21714 }
21715
21716 if (zone->view != NULL) {
21717 result = dns_view_getsecroots(zone->view, &secroots);
21718 if (result != ISC_R_SUCCESS) {
21719 goto done;
21720 }
21721 }
21722
21723 origin = dns_db_origin(db);
21724 result = dns_zoneverify_dnssec(zone, db, version, origin, secroots,
21725 zone->mctx, true, false, dnssec_report);
21726
21727 done:
21728 if (secroots != NULL) {
21729 dns_keytable_detach(&secroots);
21730 }
21731
21732 if (ver == NULL) {
21733 dns_db_closeversion(db, &version, false);
21734 }
21735
21736 if (result != ISC_R_SUCCESS) {
21737 dnssec_log(zone, ISC_LOG_ERROR, "zone verification failed: %s",
21738 isc_result_totext(result));
21739 result = DNS_R_VERIFYFAILURE;
21740 }
21741
21742 return (result);
21743 }
21744