Coverage Report

Created: 2023-11-19 06:22

/src/bind9/lib/dns/zone.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3
 *
4
 * SPDX-License-Identifier: MPL-2.0
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/async.h>
21
#include <isc/atomic.h>
22
#include <isc/file.h>
23
#include <isc/hash.h>
24
#include <isc/hashmap.h>
25
#include <isc/hex.h>
26
#include <isc/loop.h>
27
#include <isc/md.h>
28
#include <isc/mutex.h>
29
#include <isc/overflow.h>
30
#include <isc/random.h>
31
#include <isc/ratelimiter.h>
32
#include <isc/refcount.h>
33
#include <isc/result.h>
34
#include <isc/rwlock.h>
35
#include <isc/serial.h>
36
#include <isc/stats.h>
37
#include <isc/stdtime.h>
38
#include <isc/strerr.h>
39
#include <isc/string.h>
40
#include <isc/thread.h>
41
#include <isc/tid.h>
42
#include <isc/timer.h>
43
#include <isc/tls.h>
44
#include <isc/util.h>
45
46
#include <dns/acl.h>
47
#include <dns/adb.h>
48
#include <dns/callbacks.h>
49
#include <dns/catz.h>
50
#include <dns/db.h>
51
#include <dns/dbiterator.h>
52
#include <dns/dlz.h>
53
#include <dns/dnssec.h>
54
#include <dns/journal.h>
55
#include <dns/kasp.h>
56
#include <dns/keydata.h>
57
#include <dns/keymgr.h>
58
#include <dns/keytable.h>
59
#include <dns/keyvalues.h>
60
#include <dns/log.h>
61
#include <dns/master.h>
62
#include <dns/masterdump.h>
63
#include <dns/message.h>
64
#include <dns/name.h>
65
#include <dns/nsec.h>
66
#include <dns/nsec3.h>
67
#include <dns/opcode.h>
68
#include <dns/peer.h>
69
#include <dns/private.h>
70
#include <dns/rcode.h>
71
#include <dns/rdata.h>
72
#include <dns/rdataclass.h>
73
#include <dns/rdatalist.h>
74
#include <dns/rdataset.h>
75
#include <dns/rdatasetiter.h>
76
#include <dns/rdatastruct.h>
77
#include <dns/rdatatype.h>
78
#include <dns/remote.h>
79
#include <dns/request.h>
80
#include <dns/resolver.h>
81
#include <dns/rriterator.h>
82
#include <dns/soa.h>
83
#include <dns/ssu.h>
84
#include <dns/stats.h>
85
#include <dns/time.h>
86
#include <dns/tsig.h>
87
#include <dns/update.h>
88
#include <dns/xfrin.h>
89
#include <dns/zone.h>
90
#include <dns/zoneverify.h>
91
#include <dns/zt.h>
92
93
#include <dst/dst.h>
94
95
#include "zone_p.h"
96
97
2
#define ZONE_MAGIC       ISC_MAGIC('Z', 'O', 'N', 'E')
98
#define DNS_ZONE_VALID(zone) ISC_MAGIC_VALID(zone, ZONE_MAGIC)
99
100
0
#define NOTIFY_MAGIC     ISC_MAGIC('N', 't', 'f', 'y')
101
#define DNS_NOTIFY_VALID(notify) ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)
102
103
0
#define CHECKDS_MAGIC      ISC_MAGIC('C', 'h', 'D', 'S')
104
#define DNS_CHECKDS_VALID(checkds) ISC_MAGIC_VALID(checkds, CHECKDS_MAGIC)
105
106
0
#define STUB_MAGIC       ISC_MAGIC('S', 't', 'u', 'b')
107
#define DNS_STUB_VALID(stub) ISC_MAGIC_VALID(stub, STUB_MAGIC)
108
109
0
#define ZONEMGR_MAGIC   ISC_MAGIC('Z', 'm', 'g', 'r')
110
#define DNS_ZONEMGR_VALID(stub) ISC_MAGIC_VALID(stub, ZONEMGR_MAGIC)
111
112
0
#define FORWARD_MAGIC   ISC_MAGIC('F', 'o', 'r', 'w')
113
#define DNS_FORWARD_VALID(load) ISC_MAGIC_VALID(load, FORWARD_MAGIC)
114
115
#define IO_MAGIC     ISC_MAGIC('Z', 'm', 'I', 'O')
116
#define DNS_IO_VALID(load) ISC_MAGIC_VALID(load, IO_MAGIC)
117
118
0
#define KEYMGMT_MAGIC   ISC_MAGIC('M', 'g', 'm', 't')
119
#define DNS_KEYMGMT_VALID(load) ISC_MAGIC_VALID(load, KEYMGMT_MAGIC)
120
121
0
#define KEYFILEIO_MAGIC     ISC_MAGIC('K', 'y', 'I', 'O')
122
#define DNS_KEYFILEIO_VALID(kfio) ISC_MAGIC_VALID(kfio, KEYFILEIO_MAGIC)
123
124
/*%
125
 * Ensure 'a' is at least 'min' but not more than 'max'.
126
 */
127
6
#define RANGE(a, min, max) (((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max)))
128
129
0
#define NSEC3REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
130
131
/*%
132
 * Key flags
133
 */
134
0
#define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
135
0
#define KSK(x)    ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
136
0
#define ID(x)   dst_key_id(x)
137
0
#define ALG(x)    dst_key_alg(x)
138
139
/*%
140
 * KASP flags
141
 */
142
#define KASP_LOCK(k)                  \
143
0
  if ((k) != NULL) {            \
144
0
    LOCK((&((k)->lock))); \
145
0
  }
146
147
#define KASP_UNLOCK(k)                  \
148
0
  if ((k) != NULL) {              \
149
0
    UNLOCK((&((k)->lock))); \
150
0
  }
151
152
/*
153
 * Default values.
154
 */
155
2
#define DNS_DEFAULT_IDLEIN  3600       /*%< 1 hour */
156
2
#define DNS_DEFAULT_IDLEOUT 3600       /*%< 1 hour */
157
4
#define MAX_XFER_TIME     (2 * 3600) /*%< Documented default is 2 hours */
158
#define RESIGN_DELAY      3600       /*%< 1 hour */
159
160
#ifndef DNS_MAX_EXPIRE
161
#define DNS_MAX_EXPIRE 14515200 /*%< 24 weeks */
162
#endif        /* ifndef DNS_MAX_EXPIRE */
163
164
#ifndef DNS_DUMP_DELAY
165
0
#define DNS_DUMP_DELAY 900 /*%< 15 minutes */
166
#endif         /* ifndef DNS_DUMP_DELAY */
167
168
typedef struct dns_notify dns_notify_t;
169
typedef struct dns_checkds dns_checkds_t;
170
typedef struct dns_stub dns_stub_t;
171
typedef struct dns_load dns_load_t;
172
typedef struct dns_forward dns_forward_t;
173
typedef ISC_LIST(dns_forward_t) dns_forwardlist_t;
174
typedef struct dns_keymgmt dns_keymgmt_t;
175
typedef struct dns_signing dns_signing_t;
176
typedef ISC_LIST(dns_signing_t) dns_signinglist_t;
177
typedef struct dns_nsec3chain dns_nsec3chain_t;
178
typedef ISC_LIST(dns_nsec3chain_t) dns_nsec3chainlist_t;
179
typedef struct dns_nsfetch dns_nsfetch_t;
180
typedef struct dns_keyfetch dns_keyfetch_t;
181
typedef struct dns_asyncload dns_asyncload_t;
182
typedef struct dns_include dns_include_t;
183
184
#define DNS_ZONE_CHECKLOCK
185
#ifdef DNS_ZONE_CHECKLOCK
186
#define LOCK_ZONE(z)                  \
187
16
  do {                          \
188
16
    LOCK(&(z)->lock);     \
189
16
    INSIST(!(z)->locked); \
190
16
    (z)->locked = true;   \
191
16
  } while (0)
192
#define UNLOCK_ZONE(z)               \
193
16
  do {                         \
194
16
    (z)->locked = false; \
195
16
    UNLOCK(&(z)->lock);  \
196
16
  } while (0)
197
#define LOCKED_ZONE(z) ((z)->locked)
198
#define TRYLOCK_ZONE(result, z)                         \
199
0
  do {                                            \
200
0
    result = isc_mutex_trylock(&(z)->lock); \
201
0
    if (result == ISC_R_SUCCESS) {          \
202
0
      INSIST(!(z)->locked);           \
203
0
      (z)->locked = true;             \
204
0
    }                                       \
205
0
  } while (0)
206
#else /* ifdef DNS_ZONE_CHECKLOCK */
207
#define LOCK_ZONE(z)   LOCK(&(z)->lock)
208
#define UNLOCK_ZONE(z) UNLOCK(&(z)->lock)
209
#define LOCKED_ZONE(z) true
210
#define TRYLOCK_ZONE(result, z)                         \
211
  do {                                            \
212
    result = isc_mutex_trylock(&(z)->lock); \
213
  } while (0)
214
#endif /* ifdef DNS_ZONE_CHECKLOCK */
215
216
2
#define ZONEDB_INITLOCK(l)    isc_rwlock_init((l))
217
0
#define ZONEDB_DESTROYLOCK(l) isc_rwlock_destroy(l)
218
188
#define ZONEDB_LOCK(l, t)     RWLOCK((l), (t))
219
188
#define ZONEDB_UNLOCK(l, t)   RWUNLOCK((l), (t))
220
221
#ifdef ENABLE_AFL
222
extern bool dns_fuzzing_resolver;
223
#endif /* ifdef ENABLE_AFL */
224
225
/*%
226
 *  Hold key file IO locks.
227
 */
228
typedef struct dns_keyfileio {
229
  unsigned int magic;
230
  isc_mutex_t lock;
231
  isc_refcount_t references;
232
  dns_name_t *name;
233
  dns_fixedname_t fname;
234
} dns_keyfileio_t;
235
236
struct dns_keymgmt {
237
  unsigned int magic;
238
  isc_rwlock_t lock;
239
  isc_mem_t *mctx;
240
  isc_hashmap_t *table;
241
};
242
243
/*
244
 * Initial size of the keymgmt hash table.
245
 */
246
0
#define DNS_KEYMGMT_HASH_BITS 12
247
248
struct dns_zone {
249
  /* Unlocked */
250
  unsigned int magic;
251
  isc_mutex_t lock;
252
#ifdef DNS_ZONE_CHECKLOCK
253
  bool locked;
254
#endif /* ifdef DNS_ZONE_CHECKLOCK */
255
  isc_mem_t *mctx;
256
  isc_refcount_t references;
257
258
  isc_rwlock_t dblock;
259
  dns_db_t *db; /* Locked by dblock */
260
261
  unsigned int tid;
262
263
  /* Locked */
264
  dns_zonemgr_t *zmgr;
265
  ISC_LINK(dns_zone_t) link; /* Used by zmgr. */
266
  isc_loop_t *loop;
267
  isc_timer_t *timer;
268
  isc_refcount_t irefs;
269
  dns_name_t origin;
270
  char *masterfile;
271
  const FILE *stream;        /* loading from a stream? */
272
  ISC_LIST(dns_include_t) includes;    /* Include files */
273
  ISC_LIST(dns_include_t) newincludes; /* Loading */
274
  unsigned int nincludes;
275
  dns_masterformat_t masterformat;
276
  const dns_master_style_t *masterstyle;
277
  char *journal;
278
  int32_t journalsize;
279
  dns_rdataclass_t rdclass;
280
  dns_zonetype_t type;
281
  atomic_uint_fast64_t flags;
282
  atomic_uint_fast64_t options;
283
  unsigned int db_argc;
284
  char **db_argv;
285
  isc_time_t expiretime;
286
  isc_time_t refreshtime;
287
  isc_time_t dumptime;
288
  isc_time_t loadtime;
289
  isc_time_t notifytime;
290
  isc_time_t resigntime;
291
  isc_time_t keywarntime;
292
  isc_time_t signingtime;
293
  isc_time_t nsec3chaintime;
294
  isc_time_t refreshkeytime;
295
  isc_time_t xfrintime;
296
  uint32_t refreshkeyinterval;
297
  uint32_t refreshkeycount;
298
  uint32_t refresh;
299
  uint32_t retry;
300
  uint32_t expire;
301
  uint32_t minimum;
302
  isc_stdtime_t key_expiry;
303
  isc_stdtime_t log_key_expired_timer;
304
  char *keydirectory;
305
  dns_keyfileio_t *kfio;
306
307
  uint32_t maxrefresh;
308
  uint32_t minrefresh;
309
  uint32_t maxretry;
310
  uint32_t minretry;
311
312
  uint32_t maxrecords;
313
314
  dns_remote_t primaries;
315
316
  dns_remote_t parentals;
317
  dns_dnsseckeylist_t checkds_ok;
318
  dns_checkdstype_t checkdstype;
319
  uint32_t nsfetchcount;
320
  uint32_t parent_nscount;
321
322
  dns_remote_t notify;
323
  dns_notifytype_t notifytype;
324
  isc_sockaddr_t notifyfrom;
325
  isc_sockaddr_t notifysrc4;
326
  isc_sockaddr_t notifysrc6;
327
  isc_sockaddr_t parentalsrc4;
328
  isc_sockaddr_t parentalsrc6;
329
  isc_sockaddr_t xfrsource4;
330
  isc_sockaddr_t xfrsource6;
331
  isc_sockaddr_t sourceaddr;
332
  dns_xfrin_t *xfr;     /* loop locked */
333
  dns_tsigkey_t *tsigkey;     /* key used for xfr */
334
  dns_transport_t *transport; /* transport used for xfr */
335
  /* Access Control Lists */
336
  dns_acl_t *update_acl;
337
  dns_acl_t *forward_acl;
338
  dns_acl_t *notify_acl;
339
  dns_acl_t *query_acl;
340
  dns_acl_t *queryon_acl;
341
  dns_acl_t *xfr_acl;
342
  bool update_disabled;
343
  bool zero_no_soa_ttl;
344
  dns_severity_t check_names;
345
  ISC_LIST(dns_notify_t) notifies;
346
  ISC_LIST(dns_checkds_t) checkds_requests;
347
  dns_request_t *request;
348
  dns_loadctx_t *loadctx;
349
  dns_dumpctx_t *dumpctx;
350
  uint32_t maxxfrin;
351
  uint32_t maxxfrout;
352
  uint32_t idlein;
353
  uint32_t idleout;
354
  dns_ssutable_t *ssutable;
355
  uint32_t sigvalidityinterval;
356
  uint32_t keyvalidityinterval;
357
  uint32_t sigresigninginterval;
358
  dns_view_t *view;
359
  dns_view_t *prev_view;
360
  dns_kasp_t *kasp;
361
  dns_kasp_t *defaultkasp;
362
  dns_checkmxfunc_t checkmx;
363
  dns_checksrvfunc_t checksrv;
364
  dns_checknsfunc_t checkns;
365
  /*%
366
   * Zones in certain states such as "waiting for zone transfer"
367
   * or "zone transfer in progress" are kept on per-state linked lists
368
   * in the zone manager using the 'statelink' field.  The 'statelist'
369
   * field points at the list the zone is currently on.  It the zone
370
   * is not on any such list, statelist is NULL.
371
   */
372
  ISC_LINK(dns_zone_t) statelink;
373
  dns_zonelist_t *statelist;
374
  /*%
375
   * Statistics counters about zone management.
376
   */
377
  isc_stats_t *stats;
378
  /*%
379
   * Optional per-zone statistics counters.  Counted outside of this
380
   * module.
381
   */
382
  dns_zonestat_level_t statlevel;
383
  bool requeststats_on;
384
  isc_stats_t *requeststats;
385
  dns_stats_t *rcvquerystats;
386
  dns_stats_t *dnssecsignstats;
387
  uint32_t notifydelay;
388
  dns_isselffunc_t isself;
389
  void *isselfarg;
390
391
  char *strnamerd;
392
  char *strname;
393
  char *strrdclass;
394
  char *strviewname;
395
396
  /*%
397
   * Serial number for deferred journal compaction.
398
   */
399
  uint32_t compact_serial;
400
  /*%
401
   * Keys that are signing the zone for the first time.
402
   */
403
  dns_signinglist_t signing;
404
  dns_nsec3chainlist_t nsec3chain;
405
  /*%
406
   * List of outstanding NSEC3PARAM change requests.
407
   */
408
  ISC_LIST(struct np3) setnsec3param_queue;
409
  /*%
410
   * Signing / re-signing quantum stopping parameters.
411
   */
412
  uint32_t signatures;
413
  uint32_t nodes;
414
  dns_rdatatype_t privatetype;
415
416
  /*%
417
   * Autosigning/key-maintenance options
418
   */
419
  atomic_uint_fast64_t keyopts;
420
421
  /*%
422
   * True if added by "rndc addzone"
423
   */
424
  bool added;
425
426
  /*%
427
   * True if added by automatically by named.
428
   */
429
  bool automatic;
430
431
  /*%
432
   * response policy data to be relayed to the database
433
   */
434
  dns_rpz_zones_t *rpzs;
435
  dns_rpz_num_t rpz_num;
436
437
  /*%
438
   * catalog zone data
439
   */
440
  dns_catz_zones_t *catzs;
441
442
  /*%
443
   * parent catalog zone
444
   */
445
  dns_catz_zone_t *parentcatz;
446
447
  /*%
448
   * Serial number update method.
449
   */
450
  dns_updatemethod_t updatemethod;
451
452
  /*%
453
   * whether ixfr is requested
454
   */
455
  bool requestixfr;
456
  uint32_t ixfr_ratio;
457
458
  /*%
459
   * whether EDNS EXPIRE is requested
460
   */
461
  bool requestexpire;
462
463
  /*%
464
   * Outstanding forwarded UPDATE requests.
465
   */
466
  dns_forwardlist_t forwards;
467
468
  dns_zone_t *raw;
469
  dns_zone_t *secure;
470
471
  bool sourceserialset;
472
  uint32_t sourceserial;
473
474
  /*%
475
   * soa and maximum zone ttl
476
   */
477
  dns_ttl_t soattl;
478
  dns_ttl_t maxttl;
479
480
  /*
481
   * Inline zone signing state.
482
   */
483
  dns_diff_t rss_diff;
484
  dns_dbversion_t *rss_newver;
485
  dns_dbversion_t *rss_oldver;
486
  dns_db_t *rss_db;
487
  dns_zone_t *rss_raw;
488
  struct rss *rss;
489
  dns_update_state_t *rss_state;
490
491
  isc_stats_t *gluecachestats;
492
};
493
494
#define zonediff_init(z, d)                \
495
0
  do {                               \
496
0
    dns__zonediff_t *_z = (z); \
497
0
    (_z)->diff = (d);          \
498
0
    (_z)->offline = false;     \
499
0
  } while (0)
500
501
14
#define DNS_ZONE_FLAG(z, f)    ((atomic_load_relaxed(&(z)->flags) & (f)) != 0)
502
4
#define DNS_ZONE_SETFLAG(z, f) atomic_fetch_or(&(z)->flags, (f))
503
4
#define DNS_ZONE_CLRFLAG(z, f) atomic_fetch_and(&(z)->flags, ~(f))
504
typedef enum {
505
  DNS_ZONEFLG_REFRESH = 0x00000001U,     /*%< refresh check in progress */
506
  DNS_ZONEFLG_NEEDDUMP = 0x00000002U,    /*%< zone need consolidation */
507
  DNS_ZONEFLG_USEVC = 0x00000004U,       /*%< use tcp for refresh query */
508
  DNS_ZONEFLG_DUMPING = 0x00000008U,     /*%< a dump is in progress */
509
  DNS_ZONEFLG_HASINCLUDE = 0x00000010U,  /*%< $INCLUDE in zone file */
510
  DNS_ZONEFLG_LOADED = 0x00000020U,      /*%< database has loaded */
511
  DNS_ZONEFLG_EXITING = 0x00000040U,     /*%< zone is being destroyed */
512
  DNS_ZONEFLG_EXPIRED = 0x00000080U,     /*%< zone has expired */
513
  DNS_ZONEFLG_NEEDREFRESH = 0x00000100U, /*%< refresh check needed */
514
  DNS_ZONEFLG_UPTODATE = 0x00000200U,    /*%< zone contents are
515
            * up-to-date */
516
  DNS_ZONEFLG_NEEDNOTIFY = 0x00000400U,  /*%< need to send out notify
517
            * messages */
518
  DNS_ZONEFLG_FIXJOURNAL = 0x00000800U,  /*%< journal file had
519
            * recoverable error,
520
            * needs rewriting */
521
  DNS_ZONEFLG_NOPRIMARIES = 0x00001000U, /*%< an attempt to refresh a
522
            * zone with no primaries
523
            * occurred */
524
  DNS_ZONEFLG_LOADING = 0x00002000U,     /*%< load from disk in progress*/
525
  DNS_ZONEFLG_HAVETIMERS = 0x00004000U,  /*%< timer values have been set
526
            * from SOA (if not set, we
527
            * are still using
528
            * default timer values) */
529
  DNS_ZONEFLG_FORCEXFER = 0x00008000U,   /*%< Force a zone xfer */
530
  DNS_ZONEFLG_NOREFRESH = 0x00010000U,
531
  DNS_ZONEFLG_DIALNOTIFY = 0x00020000U,
532
  DNS_ZONEFLG_DIALREFRESH = 0x00040000U,
533
  DNS_ZONEFLG_SHUTDOWN = 0x00080000U,
534
  DNS_ZONEFLG_NOIXFR = 0x00100000U, /*%< IXFR failed, force AXFR */
535
  DNS_ZONEFLG_FLUSH = 0x00200000U,
536
  DNS_ZONEFLG_NOEDNS = 0x00400000U,
537
  DNS_ZONEFLG_USEALTXFRSRC = 0x00800000U, /*%< Obsoleted. */
538
  DNS_ZONEFLG_SOABEFOREAXFR = 0x01000000U,
539
  DNS_ZONEFLG_NEEDCOMPACT = 0x02000000U,
540
  DNS_ZONEFLG_REFRESHING = 0x04000000U, /*%< Refreshing keydata */
541
  DNS_ZONEFLG_THAW = 0x08000000U,
542
  DNS_ZONEFLG_LOADPENDING = 0x10000000U, /*%< Loading scheduled */
543
  DNS_ZONEFLG_NODELAY = 0x20000000U,
544
  DNS_ZONEFLG_SENDSECURE = 0x40000000U,
545
  DNS_ZONEFLG_NEEDSTARTUPNOTIFY = 0x80000000U, /*%< need to send out
546
                  * notify due to the zone
547
                  * just being loaded for
548
                  * the first time. */
549
  DNS_ZONEFLG___MAX = UINT64_MAX, /* trick to make the ENUM 64-bit wide */
550
} dns_zoneflg_t;
551
552
32
#define DNS_ZONE_OPTION(z, o)  ((atomic_load_relaxed(&(z)->options) & (o)) != 0)
553
0
#define DNS_ZONE_SETOPTION(z, o) atomic_fetch_or(&(z)->options, (o))
554
0
#define DNS_ZONE_CLROPTION(z, o) atomic_fetch_and(&(z)->options, ~(o))
555
556
#define DNS_ZONEKEY_OPTION(z, o) \
557
2
  ((atomic_load_relaxed(&(z)->keyopts) & (o)) != 0)
558
0
#define DNS_ZONEKEY_SETOPTION(z, o) atomic_fetch_or(&(z)->keyopts, (o))
559
0
#define DNS_ZONEKEY_CLROPTION(z, o) atomic_fetch_and(&(z)->keyopts, ~(o))
560
561
/* Flags for zone_load() */
562
typedef enum {
563
  DNS_ZONELOADFLAG_NOSTAT = 0x00000001U, /* Do not stat() master files */
564
  DNS_ZONELOADFLAG_THAW = 0x00000002U,   /* Thaw the zone on successful
565
            * load. */
566
} dns_zoneloadflag_t;
567
568
0
#define UNREACH_CACHE_SIZE 10U
569
#define UNREACH_HOLD_TIME  600 /* 10 minutes */
570
571
#define CHECK(op)                            \
572
0
  do {                                 \
573
0
    result = (op);               \
574
0
    if (result != ISC_R_SUCCESS) \
575
0
      goto failure;        \
576
0
  } while (0)
577
578
struct dns_unreachable {
579
  isc_sockaddr_t remote;
580
  isc_sockaddr_t local;
581
  atomic_uint_fast32_t expire;
582
  atomic_uint_fast32_t last;
583
  uint32_t count;
584
};
585
586
struct dns_zonemgr {
587
  unsigned int magic;
588
  isc_mem_t *mctx;
589
  isc_refcount_t refs;
590
  isc_loopmgr_t *loopmgr;
591
  isc_nm_t *netmgr;
592
  uint32_t workers;
593
  isc_mem_t **mctxpool;
594
  isc_ratelimiter_t *checkdsrl;
595
  isc_ratelimiter_t *notifyrl;
596
  isc_ratelimiter_t *refreshrl;
597
  isc_ratelimiter_t *startupnotifyrl;
598
  isc_ratelimiter_t *startuprefreshrl;
599
  isc_rwlock_t rwlock;
600
  isc_rwlock_t urlock;
601
602
  /* Locked by rwlock. */
603
  dns_zonelist_t zones;
604
  dns_zonelist_t waiting_for_xfrin;
605
  dns_zonelist_t xfrin_in_progress;
606
607
  /* Configuration data. */
608
  uint32_t transfersin;
609
  uint32_t transfersperns;
610
  unsigned int checkdsrate;
611
  unsigned int notifyrate;
612
  unsigned int startupnotifyrate;
613
  unsigned int serialqueryrate;
614
  unsigned int startupserialqueryrate;
615
616
  /* Locked by urlock. */
617
  /* LRU cache */
618
  struct dns_unreachable unreachable[UNREACH_CACHE_SIZE];
619
620
  dns_keymgmt_t *keymgmt;
621
622
  isc_tlsctx_cache_t *tlsctx_cache;
623
  isc_rwlock_t tlsctx_cache_rwlock;
624
};
625
626
/*%
627
 * Hold notify state.
628
 */
629
struct dns_notify {
630
  unsigned int magic;
631
  unsigned int flags;
632
  isc_mem_t *mctx;
633
  dns_zone_t *zone;
634
  dns_adbfind_t *find;
635
  dns_request_t *request;
636
  dns_name_t ns;
637
  isc_sockaddr_t src;
638
  isc_sockaddr_t dst;
639
  dns_tsigkey_t *key;
640
  dns_transport_t *transport;
641
  ISC_LINK(dns_notify_t) link;
642
  isc_rlevent_t *rlevent;
643
};
644
645
typedef enum dns_notify_flags {
646
  DNS_NOTIFY_NOSOA = 1 << 0,
647
  DNS_NOTIFY_STARTUP = 1 << 1,
648
  DNS_NOTIFY_TCP = 1 << 2,
649
} dns_notify_flags_t;
650
651
/*%
652
 * Hold checkds state.
653
 */
654
struct dns_checkds {
655
  unsigned int magic;
656
  dns_notify_flags_t flags;
657
  isc_mem_t *mctx;
658
  dns_zone_t *zone;
659
  dns_adbfind_t *find;
660
  dns_request_t *request;
661
  dns_name_t ns;
662
  isc_sockaddr_t src;
663
  isc_sockaddr_t dst;
664
  dns_tsigkey_t *key;
665
  dns_transport_t *transport;
666
  ISC_LINK(dns_checkds_t) link;
667
  isc_rlevent_t *rlevent;
668
};
669
670
/*%
671
 *  dns_stub holds state while performing a 'stub' transfer.
672
 *  'db' is the zone's 'db' or a new one if this is the initial
673
 *  transfer.
674
 */
675
676
struct dns_stub {
677
  unsigned int magic;
678
  isc_mem_t *mctx;
679
  dns_zone_t *zone;
680
  dns_db_t *db;
681
  dns_dbversion_t *version;
682
  atomic_uint_fast32_t pending_requests;
683
};
684
685
/*%
686
 *  Hold load state.
687
 */
688
struct dns_load {
689
  dns_zone_t *zone;
690
  dns_db_t *db;
691
  isc_time_t loadtime;
692
  dns_rdatacallbacks_t callbacks;
693
};
694
695
/*%
696
 *  Hold forward state.
697
 */
698
struct dns_forward {
699
  unsigned int magic;
700
  isc_mem_t *mctx;
701
  dns_zone_t *zone;
702
  isc_buffer_t *msgbuf;
703
  dns_request_t *request;
704
  uint32_t which;
705
  isc_sockaddr_t addr;
706
  dns_transport_t *transport;
707
  dns_updatecallback_t callback;
708
  void *callback_arg;
709
  unsigned int options;
710
  ISC_LINK(dns_forward_t) link;
711
};
712
713
/*%
714
 *  Hold state for when we are signing a zone with a new
715
 *  DNSKEY as result of an update.
716
 */
717
struct dns_signing {
718
  unsigned int magic;
719
  dns_db_t *db;
720
  dns_dbiterator_t *dbiterator;
721
  dns_secalg_t algorithm;
722
  uint16_t keyid;
723
  bool deleteit;
724
  bool done;
725
  ISC_LINK(dns_signing_t) link;
726
};
727
728
struct dns_nsec3chain {
729
  unsigned int magic;
730
  dns_db_t *db;
731
  dns_dbiterator_t *dbiterator;
732
  dns_rdata_nsec3param_t nsec3param;
733
  unsigned char salt[255];
734
  bool done;
735
  bool seen_nsec;
736
  bool delete_nsec;
737
  bool save_delete_nsec;
738
  ISC_LINK(dns_nsec3chain_t) link;
739
};
740
741
/*%<
742
 * 'dbiterator' contains a iterator for the database.  If we are creating
743
 * a NSEC3 chain only the non-NSEC3 nodes will be iterated.  If we are
744
 * removing a NSEC3 chain then both NSEC3 and non-NSEC3 nodes will be
745
 * iterated.
746
 *
747
 * 'nsec3param' contains the parameters of the NSEC3 chain being created
748
 * or removed.
749
 *
750
 * 'salt' is buffer space and is referenced via 'nsec3param.salt'.
751
 *
752
 * 'seen_nsec' will be set to true if, while iterating the zone to create a
753
 * NSEC3 chain, a NSEC record is seen.
754
 *
755
 * 'delete_nsec' will be set to true if, at the completion of the creation
756
 * of a NSEC3 chain, 'seen_nsec' is true.  If 'delete_nsec' is true then we
757
 * are in the process of deleting the NSEC chain.
758
 *
759
 * 'save_delete_nsec' is used to store the initial state of 'delete_nsec'
760
 * so it can be recovered in the event of a error.
761
 */
762
763
struct dns_keyfetch {
764
  isc_mem_t *mctx;
765
  dns_fixedname_t name;
766
  dns_rdataset_t keydataset;
767
  dns_rdataset_t dnskeyset;
768
  dns_rdataset_t dnskeysigset;
769
  dns_zone_t *zone;
770
  dns_db_t *db;
771
  dns_fetch_t *fetch;
772
};
773
774
struct dns_nsfetch {
775
  isc_mem_t *mctx;
776
  dns_fixedname_t name;
777
  dns_name_t pname;
778
  dns_rdataset_t nsrrset;
779
  dns_rdataset_t nssigset;
780
  dns_zone_t *zone;
781
  dns_fetch_t *fetch;
782
};
783
784
/*%
785
 * Hold state for an asynchronous load
786
 */
787
struct dns_asyncload {
788
  dns_zone_t *zone;
789
  unsigned int flags;
790
  dns_zt_callback_t *loaded;
791
  void *loaded_arg;
792
};
793
794
/*%
795
 * Reference to an include file encountered during loading
796
 */
797
struct dns_include {
798
  char *name;
799
  isc_time_t filetime;
800
  ISC_LINK(dns_include_t) link;
801
};
802
803
/*
804
 * These can be overridden by the -T mkeytimers option on the command
805
 * line, so that we can test with shorter periods than specified in
806
 * RFC 5011.
807
 */
808
#define HOUR  3600
809
#define DAY   (24 * HOUR)
810
#define MONTH (30 * DAY)
811
unsigned int dns_zone_mkey_hour = HOUR;
812
unsigned int dns_zone_mkey_day = DAY;
813
unsigned int dns_zone_mkey_month = MONTH;
814
815
0
#define SEND_BUFFER_SIZE 2048
816
817
static void
818
zone_timer_set(dns_zone_t *zone, isc_time_t *next, isc_time_t *now);
819
820
typedef struct zone_settimer {
821
  dns_zone_t *zone;
822
  isc_time_t now;
823
} zone_settimer_t;
824
825
static void
826
zone_settimer(dns_zone_t *, isc_time_t *);
827
static void
828
cancel_refresh(dns_zone_t *);
829
static void
830
zone_debuglog(dns_zone_t *zone, const char *, int debuglevel, const char *msg,
831
        ...) ISC_FORMAT_PRINTF(4, 5);
832
static void
833
notify_log(dns_zone_t *zone, int level, const char *fmt, ...)
834
  ISC_FORMAT_PRINTF(3, 4);
835
static void
836
dnssec_log(dns_zone_t *zone, int level, const char *fmt, ...)
837
  ISC_FORMAT_PRINTF(3, 4);
838
static void
839
queue_xfrin(dns_zone_t *zone);
840
static isc_result_t
841
update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
842
        dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
843
        dns_rdata_t *rdata);
844
static void
845
zone_unload(dns_zone_t *zone);
846
static void
847
zone_expire(dns_zone_t *zone);
848
static void
849
zone_refresh(dns_zone_t *zone);
850
static void
851
zone_iattach(dns_zone_t *source, dns_zone_t **target);
852
static void
853
zone_idetach(dns_zone_t **zonep);
854
static isc_result_t
855
zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump);
856
static void
857
zone_attachdb(dns_zone_t *zone, dns_db_t *db);
858
static void
859
zone_detachdb(dns_zone_t *zone);
860
static void
861
zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs);
862
static void
863
zone_catz_disable(dns_zone_t *zone);
864
static isc_result_t
865
default_journal(dns_zone_t *zone);
866
static void
867
zone_xfrdone(dns_zone_t *zone, uint32_t *expireopt, isc_result_t result);
868
static isc_result_t
869
zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
870
        isc_result_t result);
871
static void
872
zone_needdump(dns_zone_t *zone, unsigned int delay);
873
static void
874
zone_shutdown(void *arg);
875
static void
876
zone_loaddone(void *arg, isc_result_t result);
877
static isc_result_t
878
zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime);
879
static void
880
zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length);
881
static void
882
zone_name_tostr(dns_zone_t *zone, char *buf, size_t length);
883
static void
884
zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length);
885
static void
886
zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length);
887
static isc_result_t
888
zone_send_secureserial(dns_zone_t *zone, uint32_t serial);
889
static void
890
refresh_callback(void *arg);
891
static void
892
stub_callback(void *arg);
893
static void
894
queue_soa_query(dns_zone_t *zone);
895
static void
896
soa_query(void *arg);
897
static void
898
ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub);
899
static int
900
message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type);
901
static void
902
checkds_cancel(dns_zone_t *zone);
903
static void
904
checkds_find_address(dns_checkds_t *checkds);
905
static void
906
checkds_send(dns_zone_t *zone);
907
static void
908
checkds_createmessage(dns_zone_t *zone, dns_message_t **messagep);
909
static void
910
checkds_done(void *arg);
911
static void
912
checkds_send_tons(dns_checkds_t *checkds);
913
static void
914
checkds_send_toaddr(void *arg);
915
static void
916
nsfetch_levelup(dns_nsfetch_t *nsfetch);
917
static void
918
notify_cancel(dns_zone_t *zone);
919
static void
920
notify_find_address(dns_notify_t *notify);
921
static void
922
notify_send(dns_notify_t *notify);
923
static isc_result_t
924
notify_createmessage(dns_zone_t *zone, unsigned int flags,
925
         dns_message_t **messagep);
926
static void
927
notify_done(void *arg);
928
static void
929
notify_send_toaddr(void *arg);
930
static isc_result_t
931
zone_dump(dns_zone_t *, bool);
932
static void
933
got_transfer_quota(void *arg);
934
static isc_result_t
935
zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone);
936
static void
937
zmgr_resume_xfrs(dns_zonemgr_t *zmgr, bool multi);
938
static void
939
zonemgr_free(dns_zonemgr_t *zmgr);
940
static void
941
rss_post(void *arg);
942
943
static isc_result_t
944
zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
945
     unsigned int *soacount, uint32_t *soattl, uint32_t *serial,
946
     uint32_t *refresh, uint32_t *retry, uint32_t *expire,
947
     uint32_t *minimum, unsigned int *errors);
948
949
static void
950
zone_freedbargs(dns_zone_t *zone);
951
static void
952
forward_callback(void *arg);
953
static void
954
zone_saveunique(dns_zone_t *zone, const char *path, const char *templat);
955
static void
956
zone_maintenance(dns_zone_t *zone);
957
static void
958
zone_notify(dns_zone_t *zone, isc_time_t *now);
959
static void
960
dump_done(void *arg, isc_result_t result);
961
static isc_result_t
962
zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid,
963
     bool deleteit);
964
static isc_result_t
965
delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
966
      dns_name_t *name, dns_diff_t *diff);
967
static void
968
zone_rekey(dns_zone_t *zone);
969
static isc_result_t
970
zone_send_securedb(dns_zone_t *zone, dns_db_t *db);
971
static dns_ttl_t
972
zone_nsecttl(dns_zone_t *zone);
973
static void
974
setrl(isc_ratelimiter_t *rl, unsigned int *rate, unsigned int value);
975
static void
976
zone_journal_compact(dns_zone_t *zone, dns_db_t *db, uint32_t serial);
977
static isc_result_t
978
zone_journal_rollforward(dns_zone_t *zone, dns_db_t *db, bool *needdump,
979
       bool *fixjournal);
980
static void
981
setnsec3param(void *arg);
982
983
static void
984
zmgr_tlsctx_attach(dns_zonemgr_t *zmgr, isc_tlsctx_cache_t **ptlsctx_cache);
985
/*%<
986
 *  Attach to TLS client context cache used for zone transfers via
987
 *  encrypted transports (e.g. XoT).
988
 *
989
 * The obtained reference needs to be detached by a call to
990
 * 'isc_tlsctx_cache_detach()' when not needed anymore.
991
 *
992
 * Requires:
993
 *\li 'zmgr' is a valid zone manager.
994
 *\li 'ptlsctx_cache' is not 'NULL' and points to 'NULL'.
995
 */
996
997
4
#define ENTER zone_debuglog(zone, __func__, 1, "enter")
998
999
static const unsigned int dbargc_default = 1;
1000
static const char *dbargv_default[] = { "rbt" };
1001
1002
#define DNS_ZONE_JITTER_ADD(a, b, c)                                         \
1003
0
  do {                                                                 \
1004
0
    isc_interval_t _i;                                           \
1005
0
    uint32_t _j;                                                 \
1006
0
    _j = (b)-isc_random_uniform((b) / 4);                        \
1007
0
    isc_interval_set(&_i, _j, 0);                                \
1008
0
    if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) {          \
1009
0
      dns_zone_log(zone, ISC_LOG_WARNING,                  \
1010
0
             "epoch approaching: upgrade required: " \
1011
0
             "now + %s failed",                      \
1012
0
             #b);                                    \
1013
0
      isc_interval_set(&_i, _j / 2, 0);                    \
1014
0
      (void)isc_time_add((a), &_i, (c));                   \
1015
0
    }                                                            \
1016
0
  } while (0)
1017
1018
#define DNS_ZONE_TIME_ADD(a, b, c)                                           \
1019
0
  do {                                                                 \
1020
0
    isc_interval_t _i;                                           \
1021
0
    isc_interval_set(&_i, (b), 0);                               \
1022
0
    if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) {          \
1023
0
      dns_zone_log(zone, ISC_LOG_WARNING,                  \
1024
0
             "epoch approaching: upgrade required: " \
1025
0
             "now + %s failed",                      \
1026
0
             #b);                                    \
1027
0
      isc_interval_set(&_i, (b) / 2, 0);                   \
1028
0
      (void)isc_time_add((a), &_i, (c));                   \
1029
0
    }                                                            \
1030
0
  } while (0)
1031
1032
typedef struct nsec3param nsec3param_t;
1033
struct nsec3param {
1034
  dns_rdata_nsec3param_t rdata;
1035
  unsigned char data[DNS_NSEC3PARAM_BUFFERSIZE + 1];
1036
  unsigned int length;
1037
  bool nsec;
1038
  bool replace;
1039
  bool resalt;
1040
  bool lookup;
1041
  ISC_LINK(nsec3param_t) link;
1042
};
1043
typedef ISC_LIST(nsec3param_t) nsec3paramlist_t;
1044
1045
struct np3 {
1046
  dns_zone_t *zone;
1047
  nsec3param_t params;
1048
  ISC_LINK(struct np3) link;
1049
};
1050
1051
struct setserial {
1052
  dns_zone_t *zone;
1053
  uint32_t serial;
1054
};
1055
1056
struct stub_cb_args {
1057
  dns_stub_t *stub;
1058
  dns_tsigkey_t *tsig_key;
1059
  uint16_t udpsize;
1060
  int timeout;
1061
  bool reqnsid;
1062
};
1063
1064
struct stub_glue_request {
1065
  dns_request_t *request;
1066
  dns_name_t name;
1067
  struct stub_cb_args *args;
1068
  bool ipv4;
1069
};
1070
1071
/*%
1072
 * Increment resolver-related statistics counters.  Zone must be locked.
1073
 */
1074
static void
1075
0
inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
1076
0
  if (zone->stats != NULL) {
1077
0
    isc_stats_increment(zone->stats, counter);
1078
0
  }
1079
0
}
1080
1081
/***
1082
 ***  Public functions.
1083
 ***/
1084
1085
void
1086
2
dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx, unsigned int tid) {
1087
2
  isc_time_t now;
1088
2
  dns_zone_t *zone = NULL;
1089
1090
2
  REQUIRE(zonep != NULL && *zonep == NULL);
1091
2
  REQUIRE(mctx != NULL);
1092
1093
2
  now = isc_time_now();
1094
2
  zone = isc_mem_get(mctx, sizeof(*zone));
1095
2
  *zone = (dns_zone_t){
1096
2
    .masterformat = dns_masterformat_none,
1097
2
    .journalsize = -1,
1098
2
    .rdclass = dns_rdataclass_none,
1099
2
    .type = dns_zone_none,
1100
2
    .refresh = DNS_ZONE_DEFAULTREFRESH,
1101
2
    .retry = DNS_ZONE_DEFAULTRETRY,
1102
2
    .maxrefresh = DNS_ZONE_MAXREFRESH,
1103
2
    .minrefresh = DNS_ZONE_MINREFRESH,
1104
2
    .maxretry = DNS_ZONE_MAXRETRY,
1105
2
    .minretry = DNS_ZONE_MINRETRY,
1106
2
    .checkdstype = dns_checkdstype_yes,
1107
2
    .notifytype = dns_notifytype_yes,
1108
2
    .zero_no_soa_ttl = true,
1109
2
    .check_names = dns_severity_ignore,
1110
2
    .idlein = DNS_DEFAULT_IDLEIN,
1111
2
    .idleout = DNS_DEFAULT_IDLEOUT,
1112
2
    .maxxfrin = MAX_XFER_TIME,
1113
2
    .maxxfrout = MAX_XFER_TIME,
1114
2
    .sigvalidityinterval = 30 * 24 * 3600,
1115
2
    .sigresigninginterval = 7 * 24 * 3600,
1116
2
    .statlevel = dns_zonestat_none,
1117
2
    .notifydelay = 5,
1118
2
    .signatures = 10,
1119
2
    .nodes = 100,
1120
2
    .privatetype = (dns_rdatatype_t)0xffffU,
1121
2
    .rpz_num = DNS_RPZ_INVALID_NUM,
1122
2
    .requestixfr = true,
1123
2
    .ixfr_ratio = 100,
1124
2
    .requestexpire = true,
1125
2
    .updatemethod = dns_updatemethod_increment,
1126
2
    .tid = tid,
1127
2
    .notifytime = now,
1128
2
    .newincludes = ISC_LIST_INITIALIZER,
1129
2
    .notifies = ISC_LIST_INITIALIZER,
1130
2
    .checkds_requests = ISC_LIST_INITIALIZER,
1131
2
    .signing = ISC_LIST_INITIALIZER,
1132
2
    .nsec3chain = ISC_LIST_INITIALIZER,
1133
2
    .setnsec3param_queue = ISC_LIST_INITIALIZER,
1134
2
    .forwards = ISC_LIST_INITIALIZER,
1135
2
    .link = ISC_LINK_INITIALIZER,
1136
2
    .statelink = ISC_LINK_INITIALIZER,
1137
2
  };
1138
2
  dns_remote_t r = {
1139
2
    .magic = DNS_REMOTE_MAGIC,
1140
2
  };
1141
1142
2
  isc_mem_attach(mctx, &zone->mctx);
1143
2
  isc_mutex_init(&zone->lock);
1144
2
  ZONEDB_INITLOCK(&zone->dblock);
1145
1146
2
  isc_refcount_init(&zone->references, 1);
1147
2
  isc_refcount_init(&zone->irefs, 0);
1148
2
  dns_name_init(&zone->origin, NULL);
1149
2
  isc_sockaddr_any(&zone->notifysrc4);
1150
2
  isc_sockaddr_any6(&zone->notifysrc6);
1151
2
  isc_sockaddr_any(&zone->parentalsrc4);
1152
2
  isc_sockaddr_any6(&zone->parentalsrc6);
1153
2
  isc_sockaddr_any(&zone->xfrsource4);
1154
2
  isc_sockaddr_any6(&zone->xfrsource6);
1155
1156
2
  zone->primaries = r;
1157
2
  zone->parentals = r;
1158
2
  zone->notify = r;
1159
2
  zone->defaultkasp = NULL;
1160
1161
2
  isc_stats_create(mctx, &zone->gluecachestats,
1162
2
       dns_gluecachestatscounter_max);
1163
1164
2
  zone->magic = ZONE_MAGIC;
1165
1166
  /* Must be after magic is set. */
1167
2
  dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
1168
1169
2
  *zonep = zone;
1170
2
}
1171
1172
static void
1173
0
clear_keylist(dns_dnsseckeylist_t *list, isc_mem_t *mctx) {
1174
0
  dns_dnsseckey_t *key;
1175
0
  while (!ISC_LIST_EMPTY(*list)) {
1176
0
    key = ISC_LIST_HEAD(*list);
1177
0
    ISC_LIST_UNLINK(*list, key, link);
1178
0
    dns_dnsseckey_destroy(mctx, &key);
1179
0
  }
1180
0
}
1181
1182
/*
1183
 * Free a zone.  Because we require that there be no more
1184
 * outstanding events or references, no locking is necessary.
1185
 */
1186
static void
1187
0
zone_free(dns_zone_t *zone) {
1188
0
  dns_signing_t *signing = NULL;
1189
0
  dns_nsec3chain_t *nsec3chain = NULL;
1190
0
  dns_include_t *include = NULL;
1191
1192
0
  REQUIRE(DNS_ZONE_VALID(zone));
1193
0
  REQUIRE(!LOCKED_ZONE(zone));
1194
0
  REQUIRE(zone->timer == NULL);
1195
0
  REQUIRE(zone->zmgr == NULL);
1196
1197
0
  isc_refcount_destroy(&zone->references);
1198
0
  isc_refcount_destroy(&zone->irefs);
1199
1200
  /*
1201
   * Managed objects.  Order is important.
1202
   */
1203
0
  if (zone->request != NULL) {
1204
0
    dns_request_destroy(&zone->request); /* XXXMPA */
1205
0
  }
1206
0
  INSIST(zone->statelist == NULL);
1207
0
  INSIST(zone->view == NULL);
1208
0
  INSIST(zone->prev_view == NULL);
1209
1210
  /* Unmanaged objects */
1211
0
  for (struct np3 *npe = ISC_LIST_HEAD(zone->setnsec3param_queue);
1212
0
       npe != NULL; npe = ISC_LIST_HEAD(zone->setnsec3param_queue))
1213
0
  {
1214
0
    ISC_LIST_UNLINK(zone->setnsec3param_queue, npe, link);
1215
0
    isc_mem_put(zone->mctx, npe, sizeof(*npe));
1216
0
  }
1217
1218
0
  for (signing = ISC_LIST_HEAD(zone->signing); signing != NULL;
1219
0
       signing = ISC_LIST_HEAD(zone->signing))
1220
0
  {
1221
0
    ISC_LIST_UNLINK(zone->signing, signing, link);
1222
0
    dns_db_detach(&signing->db);
1223
0
    dns_dbiterator_destroy(&signing->dbiterator);
1224
0
    isc_mem_put(zone->mctx, signing, sizeof *signing);
1225
0
  }
1226
0
  for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain); nsec3chain != NULL;
1227
0
       nsec3chain = ISC_LIST_HEAD(zone->nsec3chain))
1228
0
  {
1229
0
    ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
1230
0
    dns_db_detach(&nsec3chain->db);
1231
0
    dns_dbiterator_destroy(&nsec3chain->dbiterator);
1232
0
    isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
1233
0
  }
1234
0
  for (include = ISC_LIST_HEAD(zone->includes); include != NULL;
1235
0
       include = ISC_LIST_HEAD(zone->includes))
1236
0
  {
1237
0
    ISC_LIST_UNLINK(zone->includes, include, link);
1238
0
    isc_mem_free(zone->mctx, include->name);
1239
0
    isc_mem_put(zone->mctx, include, sizeof *include);
1240
0
  }
1241
0
  for (include = ISC_LIST_HEAD(zone->newincludes); include != NULL;
1242
0
       include = ISC_LIST_HEAD(zone->newincludes))
1243
0
  {
1244
0
    ISC_LIST_UNLINK(zone->newincludes, include, link);
1245
0
    isc_mem_free(zone->mctx, include->name);
1246
0
    isc_mem_put(zone->mctx, include, sizeof *include);
1247
0
  }
1248
0
  if (zone->masterfile != NULL) {
1249
0
    isc_mem_free(zone->mctx, zone->masterfile);
1250
0
  }
1251
0
  zone->masterfile = NULL;
1252
0
  if (zone->keydirectory != NULL) {
1253
0
    isc_mem_free(zone->mctx, zone->keydirectory);
1254
0
  }
1255
0
  zone->keydirectory = NULL;
1256
0
  if (zone->kasp != NULL) {
1257
0
    dns_kasp_detach(&zone->kasp);
1258
0
  }
1259
0
  if (zone->defaultkasp != NULL) {
1260
0
    dns_kasp_detach(&zone->defaultkasp);
1261
0
  }
1262
0
  if (!ISC_LIST_EMPTY(zone->checkds_ok)) {
1263
0
    clear_keylist(&zone->checkds_ok, zone->mctx);
1264
0
  }
1265
1266
0
  zone->journalsize = -1;
1267
0
  if (zone->journal != NULL) {
1268
0
    isc_mem_free(zone->mctx, zone->journal);
1269
0
  }
1270
0
  zone->journal = NULL;
1271
0
  if (zone->stats != NULL) {
1272
0
    isc_stats_detach(&zone->stats);
1273
0
  }
1274
0
  if (zone->requeststats != NULL) {
1275
0
    isc_stats_detach(&zone->requeststats);
1276
0
  }
1277
0
  if (zone->rcvquerystats != NULL) {
1278
0
    dns_stats_detach(&zone->rcvquerystats);
1279
0
  }
1280
0
  if (zone->dnssecsignstats != NULL) {
1281
0
    dns_stats_detach(&zone->dnssecsignstats);
1282
0
  }
1283
0
  if (zone->db != NULL) {
1284
0
    zone_detachdb(zone);
1285
0
  }
1286
0
  if (zone->rpzs != NULL) {
1287
0
    REQUIRE(zone->rpz_num < zone->rpzs->p.num_zones);
1288
0
    dns_rpz_zones_detach(&zone->rpzs);
1289
0
    zone->rpz_num = DNS_RPZ_INVALID_NUM;
1290
0
  }
1291
0
  if (zone->catzs != NULL) {
1292
0
    dns_catz_zones_detach(&zone->catzs);
1293
0
  }
1294
0
  zone_freedbargs(zone);
1295
1296
0
  dns_zone_setparentals(zone, NULL, NULL, NULL, NULL, 0);
1297
0
  dns_zone_setprimaries(zone, NULL, NULL, NULL, NULL, 0);
1298
0
  dns_zone_setalsonotify(zone, NULL, NULL, NULL, NULL, 0);
1299
1300
0
  zone->check_names = dns_severity_ignore;
1301
0
  if (zone->update_acl != NULL) {
1302
0
    dns_acl_detach(&zone->update_acl);
1303
0
  }
1304
0
  if (zone->forward_acl != NULL) {
1305
0
    dns_acl_detach(&zone->forward_acl);
1306
0
  }
1307
0
  if (zone->notify_acl != NULL) {
1308
0
    dns_acl_detach(&zone->notify_acl);
1309
0
  }
1310
0
  if (zone->query_acl != NULL) {
1311
0
    dns_acl_detach(&zone->query_acl);
1312
0
  }
1313
0
  if (zone->queryon_acl != NULL) {
1314
0
    dns_acl_detach(&zone->queryon_acl);
1315
0
  }
1316
0
  if (zone->xfr_acl != NULL) {
1317
0
    dns_acl_detach(&zone->xfr_acl);
1318
0
  }
1319
0
  if (dns_name_dynamic(&zone->origin)) {
1320
0
    dns_name_free(&zone->origin, zone->mctx);
1321
0
  }
1322
0
  if (zone->strnamerd != NULL) {
1323
0
    isc_mem_free(zone->mctx, zone->strnamerd);
1324
0
  }
1325
0
  if (zone->strname != NULL) {
1326
0
    isc_mem_free(zone->mctx, zone->strname);
1327
0
  }
1328
0
  if (zone->strrdclass != NULL) {
1329
0
    isc_mem_free(zone->mctx, zone->strrdclass);
1330
0
  }
1331
0
  if (zone->strviewname != NULL) {
1332
0
    isc_mem_free(zone->mctx, zone->strviewname);
1333
0
  }
1334
0
  if (zone->ssutable != NULL) {
1335
0
    dns_ssutable_detach(&zone->ssutable);
1336
0
  }
1337
0
  if (zone->gluecachestats != NULL) {
1338
0
    isc_stats_detach(&zone->gluecachestats);
1339
0
  }
1340
1341
  /* last stuff */
1342
0
  ZONEDB_DESTROYLOCK(&zone->dblock);
1343
0
  isc_mutex_destroy(&zone->lock);
1344
0
  zone->magic = 0;
1345
0
  isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
1346
0
}
1347
1348
/*
1349
 * Returns true iff this the signed side of an inline-signing zone.
1350
 * Caller should hold zone lock.
1351
 */
1352
static bool
1353
20
inline_secure(dns_zone_t *zone) {
1354
20
  REQUIRE(DNS_ZONE_VALID(zone));
1355
20
  if (zone->raw != NULL) {
1356
0
    return (true);
1357
0
  }
1358
20
  return (false);
1359
20
}
1360
1361
/*
1362
 * Returns true iff this the unsigned side of an inline-signing zone
1363
 * Caller should hold zone lock.
1364
 */
1365
static bool
1366
12
inline_raw(dns_zone_t *zone) {
1367
12
  REQUIRE(DNS_ZONE_VALID(zone));
1368
12
  if (zone->secure != NULL) {
1369
0
    return (true);
1370
0
  }
1371
12
  return (false);
1372
12
}
1373
1374
/*
1375
 *  Single shot.
1376
 */
1377
void
1378
2
dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
1379
2
  char namebuf[1024];
1380
1381
2
  REQUIRE(DNS_ZONE_VALID(zone));
1382
2
  REQUIRE(rdclass != dns_rdataclass_none);
1383
1384
  /*
1385
   * Test and set.
1386
   */
1387
2
  LOCK_ZONE(zone);
1388
2
  INSIST(zone != zone->raw);
1389
2
  REQUIRE(zone->rdclass == dns_rdataclass_none ||
1390
2
    zone->rdclass == rdclass);
1391
2
  zone->rdclass = rdclass;
1392
1393
2
  if (zone->strnamerd != NULL) {
1394
2
    isc_mem_free(zone->mctx, zone->strnamerd);
1395
2
  }
1396
2
  if (zone->strrdclass != NULL) {
1397
0
    isc_mem_free(zone->mctx, zone->strrdclass);
1398
0
  }
1399
1400
2
  zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1401
2
  zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1402
2
  zone_rdclass_tostr(zone, namebuf, sizeof namebuf);
1403
2
  zone->strrdclass = isc_mem_strdup(zone->mctx, namebuf);
1404
1405
2
  if (inline_secure(zone)) {
1406
0
    dns_zone_setclass(zone->raw, rdclass);
1407
0
  }
1408
2
  UNLOCK_ZONE(zone);
1409
2
}
1410
1411
dns_rdataclass_t
1412
0
dns_zone_getclass(dns_zone_t *zone) {
1413
0
  REQUIRE(DNS_ZONE_VALID(zone));
1414
1415
0
  return (zone->rdclass);
1416
0
}
1417
1418
void
1419
0
dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
1420
0
  REQUIRE(DNS_ZONE_VALID(zone));
1421
1422
0
  LOCK_ZONE(zone);
1423
0
  zone->notifytype = notifytype;
1424
0
  UNLOCK_ZONE(zone);
1425
0
}
1426
1427
void
1428
0
dns_zone_setcheckdstype(dns_zone_t *zone, dns_checkdstype_t checkdstype) {
1429
0
  REQUIRE(DNS_ZONE_VALID(zone));
1430
1431
0
  LOCK_ZONE(zone);
1432
0
  zone->checkdstype = checkdstype;
1433
0
  UNLOCK_ZONE(zone);
1434
0
}
1435
1436
isc_result_t
1437
0
dns_zone_getserial(dns_zone_t *zone, uint32_t *serialp) {
1438
0
  isc_result_t result;
1439
0
  unsigned int soacount;
1440
1441
0
  REQUIRE(DNS_ZONE_VALID(zone));
1442
0
  REQUIRE(serialp != NULL);
1443
1444
0
  LOCK_ZONE(zone);
1445
0
  ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1446
0
  if (zone->db != NULL) {
1447
0
    result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL,
1448
0
            serialp, NULL, NULL, NULL, NULL,
1449
0
            NULL);
1450
0
    if (result == ISC_R_SUCCESS && soacount == 0) {
1451
0
      result = ISC_R_FAILURE;
1452
0
    }
1453
0
  } else {
1454
0
    result = DNS_R_NOTLOADED;
1455
0
  }
1456
0
  ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1457
0
  UNLOCK_ZONE(zone);
1458
1459
0
  return (result);
1460
0
}
1461
1462
/*
1463
 *  Single shot.
1464
 */
1465
void
1466
2
dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) {
1467
2
  char namebuf[1024];
1468
1469
2
  REQUIRE(DNS_ZONE_VALID(zone));
1470
2
  REQUIRE(type != dns_zone_none);
1471
1472
  /*
1473
   * Test and set.
1474
   */
1475
2
  LOCK_ZONE(zone);
1476
2
  REQUIRE(zone->type == dns_zone_none || zone->type == type);
1477
2
  zone->type = type;
1478
1479
2
  if (zone->strnamerd != NULL) {
1480
2
    isc_mem_free(zone->mctx, zone->strnamerd);
1481
2
  }
1482
1483
2
  zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1484
2
  zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1485
2
  UNLOCK_ZONE(zone);
1486
2
}
1487
1488
static void
1489
2
zone_freedbargs(dns_zone_t *zone) {
1490
2
  unsigned int i;
1491
1492
  /* Free the old database argument list. */
1493
2
  if (zone->db_argv != NULL) {
1494
0
    for (i = 0; i < zone->db_argc; i++) {
1495
0
      isc_mem_free(zone->mctx, zone->db_argv[i]);
1496
0
    }
1497
0
    isc_mem_cput(zone->mctx, zone->db_argv, zone->db_argc,
1498
0
           sizeof(*zone->db_argv));
1499
0
  }
1500
2
  zone->db_argc = 0;
1501
2
  zone->db_argv = NULL;
1502
2
}
1503
1504
isc_result_t
1505
0
dns_zone_getdbtype(dns_zone_t *zone, char ***argv, isc_mem_t *mctx) {
1506
0
  size_t size = 0;
1507
0
  unsigned int i;
1508
0
  isc_result_t result = ISC_R_SUCCESS;
1509
0
  void *mem;
1510
0
  char **tmp, *tmp2, *base;
1511
1512
0
  REQUIRE(DNS_ZONE_VALID(zone));
1513
0
  REQUIRE(argv != NULL && *argv == NULL);
1514
1515
0
  LOCK_ZONE(zone);
1516
0
  size = ISC_CHECKED_MUL((zone->db_argc + 1), sizeof(char *));
1517
0
  for (i = 0; i < zone->db_argc; i++) {
1518
0
    size += strlen(zone->db_argv[i]) + 1;
1519
0
  }
1520
0
  mem = isc_mem_allocate(mctx, size);
1521
0
  {
1522
0
    tmp = mem;
1523
0
    tmp2 = mem;
1524
0
    base = mem;
1525
0
    tmp2 += ISC_CHECKED_MUL((zone->db_argc + 1), sizeof(char *));
1526
0
    for (i = 0; i < zone->db_argc; i++) {
1527
0
      *tmp++ = tmp2;
1528
0
      strlcpy(tmp2, zone->db_argv[i], size - (tmp2 - base));
1529
0
      tmp2 += strlen(tmp2) + 1;
1530
0
    }
1531
0
    *tmp = NULL;
1532
0
  }
1533
0
  UNLOCK_ZONE(zone);
1534
0
  *argv = mem;
1535
0
  return (result);
1536
0
}
1537
1538
void
1539
dns_zone_setdbtype(dns_zone_t *zone, unsigned int dbargc,
1540
2
       const char *const *dbargv) {
1541
2
  char **argv = NULL;
1542
2
  unsigned int i;
1543
1544
2
  REQUIRE(DNS_ZONE_VALID(zone));
1545
2
  REQUIRE(dbargc >= 1);
1546
2
  REQUIRE(dbargv != NULL);
1547
1548
2
  LOCK_ZONE(zone);
1549
1550
  /* Set up a new database argument list. */
1551
2
  argv = isc_mem_cget(zone->mctx, dbargc, sizeof(*argv));
1552
4
  for (i = 0; i < dbargc; i++) {
1553
2
    argv[i] = NULL;
1554
2
  }
1555
4
  for (i = 0; i < dbargc; i++) {
1556
2
    argv[i] = isc_mem_strdup(zone->mctx, dbargv[i]);
1557
2
  }
1558
1559
  /* Free the old list. */
1560
2
  zone_freedbargs(zone);
1561
1562
2
  zone->db_argc = dbargc;
1563
2
  zone->db_argv = argv;
1564
1565
2
  UNLOCK_ZONE(zone);
1566
2
}
1567
1568
static void
1569
2
dns_zone_setview_helper(dns_zone_t *zone, dns_view_t *view) {
1570
2
  char namebuf[1024];
1571
1572
2
  if (zone->prev_view == NULL && zone->view != NULL) {
1573
0
    dns_view_weakattach(zone->view, &zone->prev_view);
1574
0
  }
1575
1576
2
  INSIST(zone != zone->raw);
1577
2
  if (zone->view != NULL) {
1578
0
    dns_view_sfd_del(zone->view, &zone->origin);
1579
0
    dns_view_weakdetach(&zone->view);
1580
0
  }
1581
2
  dns_view_weakattach(view, &zone->view);
1582
2
  dns_view_sfd_add(view, &zone->origin);
1583
1584
2
  if (zone->strviewname != NULL) {
1585
0
    isc_mem_free(zone->mctx, zone->strviewname);
1586
0
  }
1587
2
  if (zone->strnamerd != NULL) {
1588
2
    isc_mem_free(zone->mctx, zone->strnamerd);
1589
2
  }
1590
1591
2
  zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1592
2
  zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1593
2
  zone_viewname_tostr(zone, namebuf, sizeof namebuf);
1594
2
  zone->strviewname = isc_mem_strdup(zone->mctx, namebuf);
1595
1596
2
  if (inline_secure(zone)) {
1597
0
    dns_zone_setview(zone->raw, view);
1598
0
  }
1599
2
}
1600
1601
void
1602
2
dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
1603
2
  REQUIRE(DNS_ZONE_VALID(zone));
1604
1605
2
  LOCK_ZONE(zone);
1606
2
  dns_zone_setview_helper(zone, view);
1607
2
  UNLOCK_ZONE(zone);
1608
2
}
1609
1610
dns_view_t *
1611
0
dns_zone_getview(dns_zone_t *zone) {
1612
0
  REQUIRE(DNS_ZONE_VALID(zone));
1613
1614
0
  return (zone->view);
1615
0
}
1616
1617
void
1618
0
dns_zone_setviewcommit(dns_zone_t *zone) {
1619
0
  REQUIRE(DNS_ZONE_VALID(zone));
1620
1621
0
  LOCK_ZONE(zone);
1622
0
  if (zone->prev_view != NULL) {
1623
0
    dns_view_weakdetach(&zone->prev_view);
1624
0
  }
1625
0
  if (inline_secure(zone)) {
1626
0
    dns_zone_setviewcommit(zone->raw);
1627
0
  }
1628
0
  UNLOCK_ZONE(zone);
1629
0
}
1630
1631
void
1632
0
dns_zone_setviewrevert(dns_zone_t *zone) {
1633
0
  REQUIRE(DNS_ZONE_VALID(zone));
1634
1635
0
  LOCK_ZONE(zone);
1636
0
  if (zone->prev_view != NULL) {
1637
0
    dns_zone_setview_helper(zone, zone->prev_view);
1638
0
    dns_view_weakdetach(&zone->prev_view);
1639
0
  }
1640
0
  if (zone->catzs != NULL) {
1641
0
    zone_catz_enable(zone, zone->catzs);
1642
0
  }
1643
0
  if (inline_secure(zone)) {
1644
0
    dns_zone_setviewrevert(zone->raw);
1645
0
  }
1646
0
  UNLOCK_ZONE(zone);
1647
0
}
1648
1649
isc_result_t
1650
2
dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
1651
2
  isc_result_t result = ISC_R_SUCCESS;
1652
2
  char namebuf[1024];
1653
1654
2
  REQUIRE(DNS_ZONE_VALID(zone));
1655
2
  REQUIRE(origin != NULL);
1656
1657
2
  LOCK_ZONE(zone);
1658
2
  INSIST(zone != zone->raw);
1659
2
  if (dns_name_dynamic(&zone->origin)) {
1660
0
    dns_name_free(&zone->origin, zone->mctx);
1661
0
    dns_name_init(&zone->origin, NULL);
1662
0
  }
1663
2
  dns_name_dup(origin, zone->mctx, &zone->origin);
1664
1665
2
  if (zone->strnamerd != NULL) {
1666
0
    isc_mem_free(zone->mctx, zone->strnamerd);
1667
0
  }
1668
2
  if (zone->strname != NULL) {
1669
0
    isc_mem_free(zone->mctx, zone->strname);
1670
0
  }
1671
1672
2
  zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1673
2
  zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1674
2
  zone_name_tostr(zone, namebuf, sizeof namebuf);
1675
2
  zone->strname = isc_mem_strdup(zone->mctx, namebuf);
1676
1677
2
  if (inline_secure(zone)) {
1678
0
    result = dns_zone_setorigin(zone->raw, origin);
1679
0
  }
1680
2
  UNLOCK_ZONE(zone);
1681
2
  return (result);
1682
2
}
1683
1684
static isc_result_t
1685
6
dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
1686
6
  char *copy;
1687
1688
6
  if (value != NULL) {
1689
6
    copy = isc_mem_strdup(zone->mctx, value);
1690
6
  } else {
1691
0
    copy = NULL;
1692
0
  }
1693
1694
6
  if (*field != NULL) {
1695
0
    isc_mem_free(zone->mctx, *field);
1696
0
  }
1697
1698
6
  *field = copy;
1699
6
  return (ISC_R_SUCCESS);
1700
6
}
1701
1702
isc_result_t
1703
dns_zone_setfile(dns_zone_t *zone, const char *file, dns_masterformat_t format,
1704
2
     const dns_master_style_t *style) {
1705
2
  isc_result_t result = ISC_R_SUCCESS;
1706
1707
2
  REQUIRE(DNS_ZONE_VALID(zone));
1708
2
  REQUIRE(zone->stream == NULL);
1709
1710
2
  LOCK_ZONE(zone);
1711
2
  result = dns_zone_setstring(zone, &zone->masterfile, file);
1712
2
  if (result == ISC_R_SUCCESS) {
1713
2
    zone->masterformat = format;
1714
2
    if (format == dns_masterformat_text) {
1715
2
      zone->masterstyle = style;
1716
2
    }
1717
2
    result = default_journal(zone);
1718
2
  }
1719
2
  UNLOCK_ZONE(zone);
1720
1721
2
  return (result);
1722
2
}
1723
1724
const char *
1725
0
dns_zone_getfile(dns_zone_t *zone) {
1726
0
  REQUIRE(DNS_ZONE_VALID(zone));
1727
1728
0
  return (zone->masterfile);
1729
0
}
1730
1731
isc_result_t
1732
dns_zone_setstream(dns_zone_t *zone, const FILE *stream,
1733
0
       dns_masterformat_t format, const dns_master_style_t *style) {
1734
0
  isc_result_t result = ISC_R_SUCCESS;
1735
1736
0
  REQUIRE(DNS_ZONE_VALID(zone));
1737
0
  REQUIRE(stream != NULL);
1738
0
  REQUIRE(zone->masterfile == NULL);
1739
1740
0
  LOCK_ZONE(zone);
1741
0
  zone->stream = stream;
1742
0
  zone->masterformat = format;
1743
0
  if (format == dns_masterformat_text) {
1744
0
    zone->masterstyle = style;
1745
0
  }
1746
0
  result = default_journal(zone);
1747
0
  UNLOCK_ZONE(zone);
1748
1749
0
  return (result);
1750
0
}
1751
1752
dns_ttl_t
1753
0
dns_zone_getmaxttl(dns_zone_t *zone) {
1754
0
  REQUIRE(DNS_ZONE_VALID(zone));
1755
1756
0
  return (zone->maxttl);
1757
0
}
1758
1759
void
1760
0
dns_zone_setmaxttl(dns_zone_t *zone, dns_ttl_t maxttl) {
1761
0
  REQUIRE(DNS_ZONE_VALID(zone));
1762
1763
0
  LOCK_ZONE(zone);
1764
0
  if (maxttl != 0) {
1765
0
    DNS_ZONE_SETOPTION(zone, DNS_ZONEOPT_CHECKTTL);
1766
0
  } else {
1767
0
    DNS_ZONE_CLROPTION(zone, DNS_ZONEOPT_CHECKTTL);
1768
0
  }
1769
0
  zone->maxttl = maxttl;
1770
0
  UNLOCK_ZONE(zone);
1771
1772
0
  return;
1773
0
}
1774
1775
static isc_result_t
1776
2
default_journal(dns_zone_t *zone) {
1777
2
  isc_result_t result;
1778
2
  char *journal;
1779
1780
2
  REQUIRE(DNS_ZONE_VALID(zone));
1781
2
  REQUIRE(LOCKED_ZONE(zone));
1782
1783
2
  if (zone->masterfile != NULL) {
1784
    /* Calculate string length including '\0'. */
1785
2
    int len = strlen(zone->masterfile) + sizeof(".jnl");
1786
2
    journal = isc_mem_allocate(zone->mctx, len);
1787
2
    strlcpy(journal, zone->masterfile, len);
1788
2
    strlcat(journal, ".jnl", len);
1789
2
  } else {
1790
0
    journal = NULL;
1791
0
  }
1792
2
  result = dns_zone_setstring(zone, &zone->journal, journal);
1793
2
  if (journal != NULL) {
1794
2
    isc_mem_free(zone->mctx, journal);
1795
2
  }
1796
2
  return (result);
1797
2
}
1798
1799
isc_result_t
1800
0
dns_zone_setjournal(dns_zone_t *zone, const char *myjournal) {
1801
0
  isc_result_t result = ISC_R_SUCCESS;
1802
1803
0
  REQUIRE(DNS_ZONE_VALID(zone));
1804
1805
0
  LOCK_ZONE(zone);
1806
0
  result = dns_zone_setstring(zone, &zone->journal, myjournal);
1807
0
  UNLOCK_ZONE(zone);
1808
1809
0
  return (result);
1810
0
}
1811
1812
char *
1813
0
dns_zone_getjournal(dns_zone_t *zone) {
1814
0
  REQUIRE(DNS_ZONE_VALID(zone));
1815
1816
0
  return (zone->journal);
1817
0
}
1818
1819
/*
1820
 * Return true iff the zone is "dynamic", in the sense that the zone's
1821
 * master file (if any) is written by the server, rather than being
1822
 * updated manually and read by the server.
1823
 *
1824
 * This is true for secondary zones, mirror zones, stub zones, key zones,
1825
 * and zones that allow dynamic updates either by having an update
1826
 * policy ("ssutable") or an "allow-update" ACL with a value other than
1827
 * exactly "{ none; }".
1828
 */
1829
bool
1830
6
dns_zone_isdynamic(dns_zone_t *zone, bool ignore_freeze) {
1831
6
  REQUIRE(DNS_ZONE_VALID(zone));
1832
1833
6
  if (zone->type == dns_zone_secondary || zone->type == dns_zone_mirror ||
1834
6
      zone->type == dns_zone_stub || zone->type == dns_zone_key ||
1835
6
      (zone->type == dns_zone_redirect &&
1836
6
       dns_remote_addresses(&zone->primaries) != NULL))
1837
0
  {
1838
0
    return (true);
1839
0
  }
1840
1841
  /* Inline zones are always dynamic. */
1842
6
  if (zone->type == dns_zone_primary && zone->raw != NULL) {
1843
0
    return (true);
1844
0
  }
1845
1846
  /* If !ignore_freeze, we need check whether updates are disabled.  */
1847
6
  if (zone->type == dns_zone_primary &&
1848
6
      (!zone->update_disabled || ignore_freeze) &&
1849
6
      ((zone->ssutable != NULL) ||
1850
6
       (zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl))))
1851
0
  {
1852
0
    return (true);
1853
0
  }
1854
1855
6
  return (false);
1856
6
}
1857
1858
/*
1859
 * Set the response policy index and information for a zone.
1860
 */
1861
isc_result_t
1862
dns_zone_rpz_enable(dns_zone_t *zone, dns_rpz_zones_t *rpzs,
1863
0
        dns_rpz_num_t rpz_num) {
1864
  /*
1865
   * Only RBTDB zones can be used for response policy zones,
1866
   * because only they have the code to create the summary data.
1867
   * Only zones that are loaded instead of mmap()ed create the
1868
   * summary data and so can be policy zones.
1869
   */
1870
0
  if (strcmp(zone->db_argv[0], "rbt") != 0) {
1871
0
    return (ISC_R_NOTIMPLEMENTED);
1872
0
  }
1873
1874
  /*
1875
   * This must happen only once or be redundant.
1876
   */
1877
0
  LOCK_ZONE(zone);
1878
0
  if (zone->rpzs != NULL) {
1879
0
    REQUIRE(zone->rpzs == rpzs && zone->rpz_num == rpz_num);
1880
0
  } else {
1881
0
    REQUIRE(zone->rpz_num == DNS_RPZ_INVALID_NUM);
1882
0
    dns_rpz_zones_attach(rpzs, &zone->rpzs);
1883
0
    zone->rpz_num = rpz_num;
1884
0
  }
1885
0
  rpzs->defined |= DNS_RPZ_ZBIT(rpz_num);
1886
0
  UNLOCK_ZONE(zone);
1887
1888
0
  return (ISC_R_SUCCESS);
1889
0
}
1890
1891
dns_rpz_num_t
1892
0
dns_zone_get_rpz_num(dns_zone_t *zone) {
1893
0
  return (zone->rpz_num);
1894
0
}
1895
1896
/*
1897
 * If a zone is a response policy zone, mark its new database.
1898
 */
1899
void
1900
2
dns_zone_rpz_enable_db(dns_zone_t *zone, dns_db_t *db) {
1901
2
  if (zone->rpz_num == DNS_RPZ_INVALID_NUM) {
1902
2
    return;
1903
2
  }
1904
0
  REQUIRE(zone->rpzs != NULL);
1905
0
  dns_rpz_dbupdate_register(db, zone->rpzs->zones[zone->rpz_num]);
1906
0
}
1907
1908
static void
1909
0
dns_zone_rpz_disable_db(dns_zone_t *zone, dns_db_t *db) {
1910
0
  if (zone->rpz_num == DNS_RPZ_INVALID_NUM) {
1911
0
    return;
1912
0
  }
1913
0
  REQUIRE(zone->rpzs != NULL);
1914
0
  dns_rpz_dbupdate_unregister(db, zone->rpzs->zones[zone->rpz_num]);
1915
0
}
1916
1917
/*
1918
 * If a zone is a catalog zone, attach it to update notification in database.
1919
 */
1920
void
1921
2
dns_zone_catz_enable_db(dns_zone_t *zone, dns_db_t *db) {
1922
2
  REQUIRE(DNS_ZONE_VALID(zone));
1923
2
  REQUIRE(db != NULL);
1924
1925
2
  if (zone->catzs != NULL) {
1926
0
    dns_catz_dbupdate_register(db, zone->catzs);
1927
0
  }
1928
2
}
1929
1930
static void
1931
0
dns_zone_catz_disable_db(dns_zone_t *zone, dns_db_t *db) {
1932
0
  REQUIRE(DNS_ZONE_VALID(zone));
1933
0
  REQUIRE(db != NULL);
1934
1935
0
  if (zone->catzs != NULL) {
1936
0
    dns_catz_dbupdate_unregister(db, zone->catzs);
1937
0
  }
1938
0
}
1939
1940
static void
1941
0
zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs) {
1942
0
  REQUIRE(DNS_ZONE_VALID(zone));
1943
0
  REQUIRE(catzs != NULL);
1944
1945
0
  INSIST(zone->catzs == NULL || zone->catzs == catzs);
1946
0
  dns_catz_catzs_set_view(catzs, zone->view);
1947
0
  if (zone->catzs == NULL) {
1948
0
    dns_catz_zones_attach(catzs, &zone->catzs);
1949
0
  }
1950
0
}
1951
1952
void
1953
0
dns_zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs) {
1954
0
  REQUIRE(DNS_ZONE_VALID(zone));
1955
1956
0
  LOCK_ZONE(zone);
1957
0
  zone_catz_enable(zone, catzs);
1958
0
  UNLOCK_ZONE(zone);
1959
0
}
1960
1961
static void
1962
0
zone_catz_disable(dns_zone_t *zone) {
1963
0
  REQUIRE(DNS_ZONE_VALID(zone));
1964
1965
0
  if (zone->catzs != NULL) {
1966
0
    if (zone->db != NULL) {
1967
0
      dns_zone_catz_disable_db(zone, zone->db);
1968
0
    }
1969
0
    dns_catz_zones_detach(&zone->catzs);
1970
0
  }
1971
0
}
1972
1973
void
1974
0
dns_zone_catz_disable(dns_zone_t *zone) {
1975
0
  REQUIRE(DNS_ZONE_VALID(zone));
1976
1977
0
  LOCK_ZONE(zone);
1978
0
  zone_catz_disable(zone);
1979
0
  UNLOCK_ZONE(zone);
1980
0
}
1981
1982
bool
1983
0
dns_zone_catz_is_enabled(dns_zone_t *zone) {
1984
0
  REQUIRE(DNS_ZONE_VALID(zone));
1985
1986
0
  return (zone->catzs != NULL);
1987
0
}
1988
1989
/*
1990
 * Set catalog zone ownership of the zone
1991
 */
1992
void
1993
0
dns_zone_set_parentcatz(dns_zone_t *zone, dns_catz_zone_t *catz) {
1994
0
  REQUIRE(DNS_ZONE_VALID(zone));
1995
0
  REQUIRE(catz != NULL);
1996
0
  LOCK_ZONE(zone);
1997
0
  INSIST(zone->parentcatz == NULL || zone->parentcatz == catz);
1998
0
  zone->parentcatz = catz;
1999
0
  UNLOCK_ZONE(zone);
2000
0
}
2001
2002
dns_catz_zone_t *
2003
0
dns_zone_get_parentcatz(dns_zone_t *zone) {
2004
0
  REQUIRE(DNS_ZONE_VALID(zone));
2005
2006
0
  dns_catz_zone_t *parentcatz = NULL;
2007
2008
0
  LOCK_ZONE(zone);
2009
0
  parentcatz = zone->parentcatz;
2010
0
  UNLOCK_ZONE(zone);
2011
2012
0
  return (parentcatz);
2013
0
}
2014
2015
static bool
2016
0
zone_touched(dns_zone_t *zone) {
2017
0
  isc_result_t result;
2018
0
  isc_time_t modtime;
2019
0
  dns_include_t *include;
2020
2021
0
  REQUIRE(DNS_ZONE_VALID(zone));
2022
2023
0
  result = isc_file_getmodtime(zone->masterfile, &modtime);
2024
0
  if (result != ISC_R_SUCCESS ||
2025
0
      isc_time_compare(&modtime, &zone->loadtime) > 0)
2026
0
  {
2027
0
    return (true);
2028
0
  }
2029
2030
0
  for (include = ISC_LIST_HEAD(zone->includes); include != NULL;
2031
0
       include = ISC_LIST_NEXT(include, link))
2032
0
  {
2033
0
    result = isc_file_getmodtime(include->name, &modtime);
2034
0
    if (result != ISC_R_SUCCESS ||
2035
0
        isc_time_compare(&modtime, &include->filetime) > 0)
2036
0
    {
2037
0
      return (true);
2038
0
    }
2039
0
  }
2040
2041
0
  return (false);
2042
0
}
2043
2044
/*
2045
 * Note: when dealing with inline-signed zones, external callers will always
2046
 * call zone_load() for the secure zone; zone_load() calls itself recursively
2047
 * in order to load the raw zone.
2048
 */
2049
static isc_result_t
2050
2
zone_load(dns_zone_t *zone, unsigned int flags, bool locked) {
2051
2
  isc_result_t result;
2052
2
  isc_time_t now;
2053
2
  isc_time_t loadtime;
2054
2
  dns_db_t *db = NULL;
2055
2
  bool rbt, hasraw, is_dynamic;
2056
2057
2
  REQUIRE(DNS_ZONE_VALID(zone));
2058
2059
2
  if (!locked) {
2060
2
    LOCK_ZONE(zone);
2061
2
  }
2062
2063
2
  INSIST(zone != zone->raw);
2064
2
  hasraw = inline_secure(zone);
2065
2
  if (hasraw) {
2066
    /*
2067
     * We are trying to load an inline-signed zone.  First call
2068
     * self recursively to try loading the raw version of the zone.
2069
     * Assuming the raw zone file is readable, there are two
2070
     * possibilities:
2071
     *
2072
     *  a) the raw zone was not yet loaded and thus it will be
2073
     *     loaded now, synchronously; if this succeeds, a
2074
     *     subsequent attempt to load the signed zone file will
2075
     *     take place and thus zone_postload() will be called
2076
     *     twice: first for the raw zone and then for the secure
2077
     *     zone; the latter call will take care of syncing the raw
2078
     *     version with the secure version,
2079
     *
2080
     *  b) the raw zone was already loaded and we are trying to
2081
     *     reload it, which will happen asynchronously; this means
2082
     *     zone_postload() will only be called for the raw zone
2083
     *     because "result" returned by the zone_load() call below
2084
     *     will not be ISC_R_SUCCESS but rather DNS_R_CONTINUE;
2085
     *     zone_postload() called for the raw zone will take care
2086
     *     of syncing the raw version with the secure version.
2087
     */
2088
0
    result = zone_load(zone->raw, flags, false);
2089
0
    if (result != ISC_R_SUCCESS) {
2090
0
      if (!locked) {
2091
0
        UNLOCK_ZONE(zone);
2092
0
      }
2093
0
      return (result);
2094
0
    }
2095
0
    LOCK_ZONE(zone->raw);
2096
0
  }
2097
2098
2
  now = isc_time_now();
2099
2100
2
  INSIST(zone->type != dns_zone_none);
2101
2102
2
  if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
2103
0
    if ((flags & DNS_ZONELOADFLAG_THAW) != 0) {
2104
0
      DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
2105
0
    }
2106
0
    result = DNS_R_CONTINUE;
2107
0
    goto cleanup;
2108
0
  }
2109
2110
2
  INSIST(zone->db_argc >= 1);
2111
2112
2
  rbt = strcmp(zone->db_argv[0], "rbt") == 0;
2113
2114
2
  if (zone->db != NULL && zone->masterfile == NULL && rbt) {
2115
    /*
2116
     * The zone has no master file configured.
2117
     */
2118
0
    result = ISC_R_SUCCESS;
2119
0
    goto cleanup;
2120
0
  }
2121
2122
2
  is_dynamic = dns_zone_isdynamic(zone, false);
2123
2
  if (zone->db != NULL && is_dynamic) {
2124
    /*
2125
     * This is a secondary, stub, or dynamically updated zone
2126
     * being reloaded.  Do nothing - the database we already
2127
     * have is guaranteed to be up-to-date.
2128
     */
2129
0
    if (zone->type == dns_zone_primary && !hasraw) {
2130
0
      result = DNS_R_DYNAMIC;
2131
0
    } else {
2132
0
      result = ISC_R_SUCCESS;
2133
0
    }
2134
0
    goto cleanup;
2135
0
  }
2136
2137
  /*
2138
   * Store the current time before the zone is loaded, so that if the
2139
   * file changes between the time of the load and the time that
2140
   * zone->loadtime is set, then the file will still be reloaded
2141
   * the next time dns_zone_load is called.
2142
   */
2143
2
  loadtime = isc_time_now();
2144
2145
  /*
2146
   * Don't do the load if the file that stores the zone is older
2147
   * than the last time the zone was loaded.  If the zone has not
2148
   * been loaded yet, zone->loadtime will be the epoch.
2149
   */
2150
2
  if (zone->masterfile != NULL) {
2151
2
    isc_time_t filetime;
2152
2153
    /*
2154
     * The file is already loaded.  If we are just doing a
2155
     * "rndc reconfig", we are done.
2156
     */
2157
2
    if (!isc_time_isepoch(&zone->loadtime) &&
2158
2
        (flags & DNS_ZONELOADFLAG_NOSTAT) != 0)
2159
0
    {
2160
0
      result = ISC_R_SUCCESS;
2161
0
      goto cleanup;
2162
0
    }
2163
2164
2
    if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
2165
2
        !zone_touched(zone))
2166
0
    {
2167
0
      dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2168
0
              ISC_LOG_DEBUG(1),
2169
0
              "skipping load: master file "
2170
0
              "older than last load");
2171
0
      result = DNS_R_UPTODATE;
2172
0
      goto cleanup;
2173
0
    }
2174
2175
    /*
2176
     * If the file modification time is in the past
2177
     * set loadtime to that value.
2178
     */
2179
2
    result = isc_file_getmodtime(zone->masterfile, &filetime);
2180
2
    if (result == ISC_R_SUCCESS &&
2181
2
        isc_time_compare(&loadtime, &filetime) > 0)
2182
1
    {
2183
1
      loadtime = filetime;
2184
1
    }
2185
2
  }
2186
2187
  /*
2188
   * Built in zones (with the exception of empty zones) don't need
2189
   * to be reloaded.
2190
   */
2191
2
  if (zone->type == dns_zone_primary &&
2192
2
      strcmp(zone->db_argv[0], "_builtin") == 0 &&
2193
2
      (zone->db_argc < 2 || strcmp(zone->db_argv[1], "empty") != 0) &&
2194
2
      DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
2195
0
  {
2196
0
    result = ISC_R_SUCCESS;
2197
0
    goto cleanup;
2198
0
  }
2199
2200
  /*
2201
   * Zones associated with a DLZ don't need to be loaded either,
2202
   * but we need to associate the database with the zone object.
2203
   */
2204
2
  if (strcmp(zone->db_argv[0], "dlz") == 0) {
2205
0
    dns_dlzdb_t *dlzdb;
2206
0
    dns_dlzfindzone_t findzone;
2207
2208
0
    for (dlzdb = ISC_LIST_HEAD(zone->view->dlz_unsearched);
2209
0
         dlzdb != NULL; dlzdb = ISC_LIST_NEXT(dlzdb, link))
2210
0
    {
2211
0
      INSIST(DNS_DLZ_VALID(dlzdb));
2212
0
      if (strcmp(zone->db_argv[1], dlzdb->dlzname) == 0) {
2213
0
        break;
2214
0
      }
2215
0
    }
2216
2217
0
    if (dlzdb == NULL) {
2218
0
      dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2219
0
              ISC_LOG_ERROR,
2220
0
              "DLZ %s does not exist or is set "
2221
0
              "to 'search yes;'",
2222
0
              zone->db_argv[1]);
2223
0
      result = ISC_R_NOTFOUND;
2224
0
      goto cleanup;
2225
0
    }
2226
2227
0
    ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
2228
    /* ask SDLZ driver if the zone is supported */
2229
0
    findzone = dlzdb->implementation->methods->findzone;
2230
0
    result = (*findzone)(dlzdb->implementation->driverarg,
2231
0
             dlzdb->dbdata, dlzdb->mctx,
2232
0
             zone->view->rdclass, &zone->origin, NULL,
2233
0
             NULL, &db);
2234
0
    if (result != ISC_R_NOTFOUND) {
2235
0
      if (zone->db != NULL) {
2236
0
        zone_detachdb(zone);
2237
0
      }
2238
0
      zone_attachdb(zone, db);
2239
0
      dns_db_detach(&db);
2240
0
      result = ISC_R_SUCCESS;
2241
0
    }
2242
0
    ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
2243
2244
0
    if (result == ISC_R_SUCCESS) {
2245
0
      if (dlzdb->configure_callback == NULL) {
2246
0
        goto cleanup;
2247
0
      }
2248
2249
0
      result = (*dlzdb->configure_callback)(zone->view, dlzdb,
2250
0
                    zone);
2251
0
      if (result != ISC_R_SUCCESS) {
2252
0
        dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2253
0
                ISC_LOG_ERROR,
2254
0
                "DLZ configuration callback: %s",
2255
0
                isc_result_totext(result));
2256
0
      }
2257
0
    }
2258
0
    goto cleanup;
2259
0
  }
2260
2261
2
  if ((zone->type == dns_zone_secondary ||
2262
2
       zone->type == dns_zone_mirror || zone->type == dns_zone_stub ||
2263
2
       (zone->type == dns_zone_redirect &&
2264
2
        dns_remote_addresses(&zone->primaries) != NULL)) &&
2265
2
      rbt)
2266
0
  {
2267
0
    if (zone->stream == NULL &&
2268
0
        (zone->masterfile == NULL ||
2269
0
         !isc_file_exists(zone->masterfile)))
2270
0
    {
2271
0
      if (zone->masterfile != NULL) {
2272
0
        dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2273
0
                ISC_LOG_DEBUG(1),
2274
0
                "no master file");
2275
0
      }
2276
0
      zone->refreshtime = now;
2277
0
      if (zone->loop != NULL) {
2278
0
        zone_settimer(zone, &now);
2279
0
      }
2280
0
      result = ISC_R_SUCCESS;
2281
0
      goto cleanup;
2282
0
    }
2283
0
  }
2284
2285
2
  dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
2286
2
          "starting load");
2287
2288
2
  result = dns_db_create(zone->mctx, zone->db_argv[0], &zone->origin,
2289
2
             (zone->type == dns_zone_stub) ? dns_dbtype_stub
2290
2
                   : dns_dbtype_zone,
2291
2
             zone->rdclass, zone->db_argc - 1,
2292
2
             zone->db_argv + 1, &db);
2293
2294
2
  if (result != ISC_R_SUCCESS) {
2295
0
    dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
2296
0
            "loading zone: creating database: %s",
2297
0
            isc_result_totext(result));
2298
0
    goto cleanup;
2299
0
  }
2300
2
  dns_db_setloop(db, zone->loop);
2301
2302
2
  if (zone->type == dns_zone_primary ||
2303
2
      zone->type == dns_zone_secondary || zone->type == dns_zone_mirror)
2304
2
  {
2305
2
    result = dns_db_setgluecachestats(db, zone->gluecachestats);
2306
2
    if (result == ISC_R_NOTIMPLEMENTED) {
2307
0
      result = ISC_R_SUCCESS;
2308
0
    }
2309
2
    if (result != ISC_R_SUCCESS) {
2310
0
      goto cleanup;
2311
0
    }
2312
2
  }
2313
2314
2
  if (!dns_db_ispersistent(db)) {
2315
2
    if (zone->masterfile != NULL || zone->stream != NULL) {
2316
2
      result = zone_startload(db, zone, loadtime);
2317
2
    } else {
2318
0
      result = DNS_R_NOMASTERFILE;
2319
0
      if (zone->type == dns_zone_primary ||
2320
0
          (zone->type == dns_zone_redirect &&
2321
0
           dns_remote_addresses(&zone->primaries) == NULL))
2322
0
      {
2323
0
        dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2324
0
                ISC_LOG_ERROR,
2325
0
                "loading zone: "
2326
0
                "no master file configured");
2327
0
        goto cleanup;
2328
0
      }
2329
0
      dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2330
0
              ISC_LOG_INFO,
2331
0
              "loading zone: "
2332
0
              "no master file configured: continuing");
2333
0
    }
2334
2
  }
2335
2336
2
  if (result == DNS_R_CONTINUE) {
2337
0
    DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING);
2338
0
    if ((flags & DNS_ZONELOADFLAG_THAW) != 0) {
2339
0
      DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
2340
0
    }
2341
0
    goto cleanup;
2342
0
  }
2343
2344
2
  result = zone_postload(zone, db, loadtime, result);
2345
2346
2
cleanup:
2347
2
  if (hasraw) {
2348
0
    UNLOCK_ZONE(zone->raw);
2349
0
  }
2350
2
  if (!locked) {
2351
2
    UNLOCK_ZONE(zone);
2352
2
  }
2353
2
  if (db != NULL) {
2354
2
    dns_db_detach(&db);
2355
2
  }
2356
2
  return (result);
2357
2
}
2358
2359
isc_result_t
2360
2
dns_zone_load(dns_zone_t *zone, bool newonly) {
2361
2
  return (zone_load(zone, newonly ? DNS_ZONELOADFLAG_NOSTAT : 0, false));
2362
2
}
2363
2364
static void
2365
0
zone_asyncload(void *arg) {
2366
0
  dns_asyncload_t *asl = arg;
2367
0
  dns_zone_t *zone = asl->zone;
2368
0
  isc_result_t result;
2369
2370
0
  REQUIRE(DNS_ZONE_VALID(zone));
2371
2372
0
  LOCK_ZONE(zone);
2373
0
  result = zone_load(zone, asl->flags, true);
2374
0
  if (result != DNS_R_CONTINUE) {
2375
0
    DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
2376
0
  }
2377
0
  UNLOCK_ZONE(zone);
2378
2379
  /* Inform the zone table we've finished loading */
2380
0
  if (asl->loaded != NULL) {
2381
0
    asl->loaded(asl->loaded_arg);
2382
0
  }
2383
2384
0
  isc_mem_put(zone->mctx, asl, sizeof(*asl));
2385
0
  dns_zone_idetach(&zone);
2386
0
}
2387
2388
isc_result_t
2389
dns_zone_asyncload(dns_zone_t *zone, bool newonly, dns_zt_callback_t *done,
2390
0
       void *arg) {
2391
0
  dns_asyncload_t *asl = NULL;
2392
2393
0
  REQUIRE(DNS_ZONE_VALID(zone));
2394
2395
0
  if (zone->zmgr == NULL) {
2396
0
    return (ISC_R_FAILURE);
2397
0
  }
2398
2399
  /* If we already have a load pending, stop now */
2400
0
  LOCK_ZONE(zone);
2401
0
  if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING)) {
2402
0
    UNLOCK_ZONE(zone);
2403
0
    return (ISC_R_ALREADYRUNNING);
2404
0
  }
2405
2406
0
  asl = isc_mem_get(zone->mctx, sizeof(*asl));
2407
2408
0
  asl->zone = NULL;
2409
0
  asl->flags = newonly ? DNS_ZONELOADFLAG_NOSTAT : 0;
2410
0
  asl->loaded = done;
2411
0
  asl->loaded_arg = arg;
2412
2413
0
  zone_iattach(zone, &asl->zone);
2414
0
  DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADPENDING);
2415
0
  isc_async_run(zone->loop, zone_asyncload, asl);
2416
0
  UNLOCK_ZONE(zone);
2417
2418
0
  return (ISC_R_SUCCESS);
2419
0
}
2420
2421
bool
2422
0
dns__zone_loadpending(dns_zone_t *zone) {
2423
0
  REQUIRE(DNS_ZONE_VALID(zone));
2424
2425
0
  return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING));
2426
0
}
2427
2428
isc_result_t
2429
0
dns_zone_loadandthaw(dns_zone_t *zone) {
2430
0
  isc_result_t result;
2431
2432
0
  if (inline_raw(zone)) {
2433
0
    result = zone_load(zone->secure, DNS_ZONELOADFLAG_THAW, false);
2434
0
  } else {
2435
    /*
2436
     * When thawing a zone, we don't know what changes
2437
     * have been made. If we do DNSSEC maintenance on this
2438
     * zone, schedule a full sign for this zone.
2439
     */
2440
0
    if (zone->type == dns_zone_primary &&
2441
0
        DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
2442
0
    {
2443
0
      DNS_ZONEKEY_SETOPTION(zone, DNS_ZONEKEY_FULLSIGN);
2444
0
    }
2445
0
    result = zone_load(zone, DNS_ZONELOADFLAG_THAW, false);
2446
0
  }
2447
2448
0
  switch (result) {
2449
0
  case DNS_R_CONTINUE:
2450
    /* Deferred thaw. */
2451
0
    break;
2452
0
  case DNS_R_UPTODATE:
2453
0
  case ISC_R_SUCCESS:
2454
0
  case DNS_R_SEENINCLUDE:
2455
0
    zone->update_disabled = false;
2456
0
    break;
2457
0
  case DNS_R_NOMASTERFILE:
2458
0
    zone->update_disabled = false;
2459
0
    break;
2460
0
  default:
2461
    /* Error, remain in disabled state. */
2462
0
    break;
2463
0
  }
2464
0
  return (result);
2465
0
}
2466
2467
static unsigned int
2468
2
get_primary_options(dns_zone_t *zone) {
2469
2
  unsigned int options;
2470
2471
2
  options = DNS_MASTER_ZONE | DNS_MASTER_RESIGN;
2472
2
  if (zone->type == dns_zone_secondary || zone->type == dns_zone_mirror ||
2473
2
      (zone->type == dns_zone_redirect &&
2474
2
       dns_remote_addresses(&zone->primaries) == NULL))
2475
0
  {
2476
0
    options |= DNS_MASTER_SECONDARY;
2477
0
  }
2478
2
  if (zone->type == dns_zone_key) {
2479
0
    options |= DNS_MASTER_KEY;
2480
0
  }
2481
2
  if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS)) {
2482
0
    options |= DNS_MASTER_CHECKNS;
2483
0
  }
2484
2
  if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS)) {
2485
0
    options |= DNS_MASTER_FATALNS;
2486
0
  }
2487
2
  if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES)) {
2488
0
    options |= DNS_MASTER_CHECKNAMES;
2489
0
  }
2490
2
  if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) {
2491
0
    options |= DNS_MASTER_CHECKNAMESFAIL;
2492
0
  }
2493
2
  if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMX)) {
2494
0
    options |= DNS_MASTER_CHECKMX;
2495
0
  }
2496
2
  if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL)) {
2497
0
    options |= DNS_MASTER_CHECKMXFAIL;
2498
0
  }
2499
2
  if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKWILDCARD)) {
2500
0
    options |= DNS_MASTER_CHECKWILDCARD;
2501
0
  }
2502
2
  if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKTTL)) {
2503
0
    options |= DNS_MASTER_CHECKTTL;
2504
0
  }
2505
2
  if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSVCB)) {
2506
0
    options |= DNS_MASTER_CHECKSVCB;
2507
0
  }
2508
2509
2
  return (options);
2510
2
}
2511
2512
static void
2513
0
zone_registerinclude(const char *filename, void *arg) {
2514
0
  isc_result_t result;
2515
0
  dns_zone_t *zone = (dns_zone_t *)arg;
2516
0
  dns_include_t *inc = NULL;
2517
2518
0
  REQUIRE(DNS_ZONE_VALID(zone));
2519
2520
0
  if (filename == NULL) {
2521
0
    return;
2522
0
  }
2523
2524
  /*
2525
   * Suppress duplicates.
2526
   */
2527
0
  for (inc = ISC_LIST_HEAD(zone->newincludes); inc != NULL;
2528
0
       inc = ISC_LIST_NEXT(inc, link))
2529
0
  {
2530
0
    if (strcmp(filename, inc->name) == 0) {
2531
0
      return;
2532
0
    }
2533
0
  }
2534
2535
0
  inc = isc_mem_get(zone->mctx, sizeof(dns_include_t));
2536
0
  inc->name = isc_mem_strdup(zone->mctx, filename);
2537
0
  ISC_LINK_INIT(inc, link);
2538
2539
0
  result = isc_file_getmodtime(filename, &inc->filetime);
2540
0
  if (result != ISC_R_SUCCESS) {
2541
0
    isc_time_settoepoch(&inc->filetime);
2542
0
  }
2543
2544
0
  ISC_LIST_APPEND(zone->newincludes, inc, link);
2545
0
}
2546
2547
static void
2548
0
get_raw_serial(dns_zone_t *raw, dns_masterrawheader_t *rawdata) {
2549
0
  isc_result_t result;
2550
0
  unsigned int soacount;
2551
2552
0
  LOCK(&raw->lock);
2553
0
  if (raw->db != NULL) {
2554
0
    result = zone_get_from_db(raw, raw->db, NULL, &soacount, NULL,
2555
0
            &rawdata->sourceserial, NULL, NULL,
2556
0
            NULL, NULL, NULL);
2557
0
    if (result == ISC_R_SUCCESS && soacount > 0U) {
2558
0
      rawdata->flags |= DNS_MASTERRAW_SOURCESERIALSET;
2559
0
    }
2560
0
  }
2561
0
  UNLOCK(&raw->lock);
2562
0
}
2563
2564
/*
2565
 * Save the raw serial number for inline-signing zones.
2566
 * (XXX: Other information from the header will be used
2567
 * for other purposes in the future, but for now this is
2568
 * all we're interested in.)
2569
 */
2570
static void
2571
0
zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
2572
0
  if ((header->flags & DNS_MASTERRAW_SOURCESERIALSET) == 0) {
2573
0
    return;
2574
0
  }
2575
2576
0
  zone->sourceserial = header->sourceserial;
2577
0
  zone->sourceserialset = true;
2578
0
}
2579
2580
void
2581
0
dns_zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
2582
0
  if (zone == NULL) {
2583
0
    return;
2584
0
  }
2585
2586
0
  LOCK_ZONE(zone);
2587
0
  zone_setrawdata(zone, header);
2588
0
  UNLOCK_ZONE(zone);
2589
0
}
2590
2591
static isc_result_t
2592
2
zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
2593
2
  isc_result_t result;
2594
2
  isc_result_t tresult;
2595
2
  unsigned int options;
2596
2
  dns_load_t *load = isc_mem_get(zone->mctx, sizeof(*load));
2597
2598
2
  ENTER;
2599
2600
2
  *load = (dns_load_t){
2601
2
    .loadtime = loadtime,
2602
2
  };
2603
2604
2
  dns_zone_rpz_enable_db(zone, db);
2605
2
  dns_zone_catz_enable_db(zone, db);
2606
2607
2
  options = get_primary_options(zone);
2608
2
  if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS)) {
2609
0
    options |= DNS_MASTER_MANYERRORS;
2610
0
  }
2611
2612
2
  zone_iattach(zone, &load->zone);
2613
2
  dns_db_attach(db, &load->db);
2614
2615
2
  dns_rdatacallbacks_init(&load->callbacks);
2616
2
  load->callbacks.rawdata = zone_setrawdata;
2617
2
  zone_iattach(zone, &load->callbacks.zone);
2618
2619
2
  result = dns_db_beginload(db, &load->callbacks);
2620
2
  if (result != ISC_R_SUCCESS) {
2621
0
    goto cleanup;
2622
0
  }
2623
2624
2
  if (zone->zmgr != NULL && zone->db != NULL) {
2625
0
    result = dns_master_loadfileasync(
2626
0
      zone->masterfile, dns_db_origin(db), dns_db_origin(db),
2627
0
      zone->rdclass, options, 0, &load->callbacks, zone->loop,
2628
0
      zone_loaddone, load, &zone->loadctx,
2629
0
      zone_registerinclude, zone, zone->mctx,
2630
0
      zone->masterformat, zone->maxttl);
2631
0
    if (result != ISC_R_SUCCESS) {
2632
0
      goto cleanup;
2633
0
    }
2634
2635
0
    return (DNS_R_CONTINUE);
2636
2
  } else if (zone->stream != NULL) {
2637
0
    FILE *stream = UNCONST(zone->stream);
2638
0
    result = dns_master_loadstream(
2639
0
      stream, &zone->origin, &zone->origin, zone->rdclass,
2640
0
      options, &load->callbacks, zone->mctx);
2641
2
  } else {
2642
2
    result = dns_master_loadfile(
2643
2
      zone->masterfile, &zone->origin, &zone->origin,
2644
2
      zone->rdclass, options, 0, &load->callbacks,
2645
2
      zone_registerinclude, zone, zone->mctx,
2646
2
      zone->masterformat, zone->maxttl);
2647
2
  }
2648
2649
2
cleanup:
2650
2
  if (result != ISC_R_SUCCESS) {
2651
0
    dns_zone_rpz_disable_db(zone, load->db);
2652
0
    dns_zone_catz_disable_db(zone, load->db);
2653
0
  }
2654
2655
2
  tresult = dns_db_endload(db, &load->callbacks);
2656
2
  if (result == ISC_R_SUCCESS) {
2657
2
    result = tresult;
2658
2
  }
2659
2660
2
  zone_idetach(&load->callbacks.zone);
2661
2
  dns_db_detach(&load->db);
2662
2
  zone_idetach(&load->zone);
2663
2664
2
  isc_mem_put(zone->mctx, load, sizeof(*load));
2665
2
  return (result);
2666
2
}
2667
2668
static bool
2669
zone_check_mx(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2670
0
        dns_name_t *owner) {
2671
0
  isc_result_t result;
2672
0
  char ownerbuf[DNS_NAME_FORMATSIZE];
2673
0
  char namebuf[DNS_NAME_FORMATSIZE];
2674
0
  char altbuf[DNS_NAME_FORMATSIZE];
2675
0
  dns_fixedname_t fixed;
2676
0
  dns_name_t *foundname;
2677
0
  int level;
2678
2679
  /*
2680
   * "." means the services does not exist.
2681
   */
2682
0
  if (dns_name_equal(name, dns_rootname)) {
2683
0
    return (true);
2684
0
  }
2685
2686
  /*
2687
   * Outside of zone.
2688
   */
2689
0
  if (!dns_name_issubdomain(name, &zone->origin)) {
2690
0
    if (zone->checkmx != NULL) {
2691
0
      return ((zone->checkmx)(zone, name, owner));
2692
0
    }
2693
0
    return (true);
2694
0
  }
2695
2696
0
  if (zone->type == dns_zone_primary) {
2697
0
    level = ISC_LOG_ERROR;
2698
0
  } else {
2699
0
    level = ISC_LOG_WARNING;
2700
0
  }
2701
2702
0
  foundname = dns_fixedname_initname(&fixed);
2703
2704
0
  result = dns_db_find(db, name, NULL, dns_rdatatype_a, 0, 0, NULL,
2705
0
           foundname, NULL, NULL);
2706
0
  if (result == ISC_R_SUCCESS) {
2707
0
    return (true);
2708
0
  }
2709
2710
0
  if (result == DNS_R_NXRRSET) {
2711
0
    result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa, 0, 0,
2712
0
             NULL, foundname, NULL, NULL);
2713
0
    if (result == ISC_R_SUCCESS) {
2714
0
      return (true);
2715
0
    }
2716
0
  }
2717
2718
0
  dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2719
0
  dns_name_format(name, namebuf, sizeof namebuf);
2720
0
  if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2721
0
      result == DNS_R_EMPTYNAME)
2722
0
  {
2723
0
    if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL)) {
2724
0
      level = ISC_LOG_WARNING;
2725
0
    }
2726
0
    dns_zone_log(zone, level,
2727
0
           "%s/MX '%s' has no address records (A or AAAA)",
2728
0
           ownerbuf, namebuf);
2729
0
    return ((level == ISC_LOG_WARNING) ? true : false);
2730
0
  }
2731
2732
0
  if (result == DNS_R_CNAME) {
2733
0
    if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
2734
0
        DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2735
0
    {
2736
0
      level = ISC_LOG_WARNING;
2737
0
    }
2738
0
    if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
2739
0
      dns_zone_log(zone, level,
2740
0
             "%s/MX '%s' is a CNAME (illegal)",
2741
0
             ownerbuf, namebuf);
2742
0
    }
2743
0
    return ((level == ISC_LOG_WARNING) ? true : false);
2744
0
  }
2745
2746
0
  if (result == DNS_R_DNAME) {
2747
0
    if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
2748
0
        DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2749
0
    {
2750
0
      level = ISC_LOG_WARNING;
2751
0
    }
2752
0
    if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
2753
0
      dns_name_format(foundname, altbuf, sizeof altbuf);
2754
0
      dns_zone_log(zone, level,
2755
0
             "%s/MX '%s' is below a DNAME"
2756
0
             " '%s' (illegal)",
2757
0
             ownerbuf, namebuf, altbuf);
2758
0
    }
2759
0
    return ((level == ISC_LOG_WARNING) ? true : false);
2760
0
  }
2761
2762
0
  if (zone->checkmx != NULL && result == DNS_R_DELEGATION) {
2763
0
    return ((zone->checkmx)(zone, name, owner));
2764
0
  }
2765
2766
0
  return (true);
2767
0
}
2768
2769
static bool
2770
zone_check_srv(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2771
0
         dns_name_t *owner) {
2772
0
  isc_result_t result;
2773
0
  char ownerbuf[DNS_NAME_FORMATSIZE];
2774
0
  char namebuf[DNS_NAME_FORMATSIZE];
2775
0
  char altbuf[DNS_NAME_FORMATSIZE];
2776
0
  dns_fixedname_t fixed;
2777
0
  dns_name_t *foundname;
2778
0
  int level;
2779
2780
  /*
2781
   * "." means the services does not exist.
2782
   */
2783
0
  if (dns_name_equal(name, dns_rootname)) {
2784
0
    return (true);
2785
0
  }
2786
2787
  /*
2788
   * Outside of zone.
2789
   */
2790
0
  if (!dns_name_issubdomain(name, &zone->origin)) {
2791
0
    if (zone->checksrv != NULL) {
2792
0
      return ((zone->checksrv)(zone, name, owner));
2793
0
    }
2794
0
    return (true);
2795
0
  }
2796
2797
0
  if (zone->type == dns_zone_primary) {
2798
0
    level = ISC_LOG_ERROR;
2799
0
  } else {
2800
0
    level = ISC_LOG_WARNING;
2801
0
  }
2802
2803
0
  foundname = dns_fixedname_initname(&fixed);
2804
2805
0
  result = dns_db_find(db, name, NULL, dns_rdatatype_a, 0, 0, NULL,
2806
0
           foundname, NULL, NULL);
2807
0
  if (result == ISC_R_SUCCESS) {
2808
0
    return (true);
2809
0
  }
2810
2811
0
  if (result == DNS_R_NXRRSET) {
2812
0
    result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa, 0, 0,
2813
0
             NULL, foundname, NULL, NULL);
2814
0
    if (result == ISC_R_SUCCESS) {
2815
0
      return (true);
2816
0
    }
2817
0
  }
2818
2819
0
  dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2820
0
  dns_name_format(name, namebuf, sizeof namebuf);
2821
0
  if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2822
0
      result == DNS_R_EMPTYNAME)
2823
0
  {
2824
0
    dns_zone_log(zone, level,
2825
0
           "%s/SRV '%s' has no address records (A or AAAA)",
2826
0
           ownerbuf, namebuf);
2827
    /* XXX950 make fatal for 9.5.0. */
2828
0
    return (true);
2829
0
  }
2830
2831
0
  if (result == DNS_R_CNAME) {
2832
0
    if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
2833
0
        DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2834
0
    {
2835
0
      level = ISC_LOG_WARNING;
2836
0
    }
2837
0
    if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
2838
0
      dns_zone_log(zone, level,
2839
0
             "%s/SRV '%s' is a CNAME (illegal)",
2840
0
             ownerbuf, namebuf);
2841
0
    }
2842
0
    return ((level == ISC_LOG_WARNING) ? true : false);
2843
0
  }
2844
2845
0
  if (result == DNS_R_DNAME) {
2846
0
    if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
2847
0
        DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2848
0
    {
2849
0
      level = ISC_LOG_WARNING;
2850
0
    }
2851
0
    if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
2852
0
      dns_name_format(foundname, altbuf, sizeof altbuf);
2853
0
      dns_zone_log(zone, level,
2854
0
             "%s/SRV '%s' is below a "
2855
0
             "DNAME '%s' (illegal)",
2856
0
             ownerbuf, namebuf, altbuf);
2857
0
    }
2858
0
    return ((level == ISC_LOG_WARNING) ? true : false);
2859
0
  }
2860
2861
0
  if (zone->checksrv != NULL && result == DNS_R_DELEGATION) {
2862
0
    return ((zone->checksrv)(zone, name, owner));
2863
0
  }
2864
2865
0
  return (true);
2866
0
}
2867
2868
static bool
2869
zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2870
0
    dns_name_t *owner) {
2871
0
  bool answer = true;
2872
0
  isc_result_t result, tresult;
2873
0
  char ownerbuf[DNS_NAME_FORMATSIZE];
2874
0
  char namebuf[DNS_NAME_FORMATSIZE];
2875
0
  char altbuf[DNS_NAME_FORMATSIZE];
2876
0
  dns_fixedname_t fixed;
2877
0
  dns_name_t *foundname;
2878
0
  dns_rdataset_t a;
2879
0
  dns_rdataset_t aaaa;
2880
0
  int level;
2881
2882
  /*
2883
   * Outside of zone.
2884
   */
2885
0
  if (!dns_name_issubdomain(name, &zone->origin)) {
2886
0
    if (zone->checkns != NULL) {
2887
0
      return ((zone->checkns)(zone, name, owner, NULL, NULL));
2888
0
    }
2889
0
    return (true);
2890
0
  }
2891
2892
0
  if (zone->type == dns_zone_primary) {
2893
0
    level = ISC_LOG_ERROR;
2894
0
  } else {
2895
0
    level = ISC_LOG_WARNING;
2896
0
  }
2897
2898
0
  foundname = dns_fixedname_initname(&fixed);
2899
0
  dns_rdataset_init(&a);
2900
0
  dns_rdataset_init(&aaaa);
2901
2902
  /*
2903
   * Perform a regular lookup to catch DNAME records then look
2904
   * for glue.
2905
   */
2906
0
  result = dns_db_find(db, name, NULL, dns_rdatatype_a, 0, 0, NULL,
2907
0
           foundname, &a, NULL);
2908
0
  switch (result) {
2909
0
  case ISC_R_SUCCESS:
2910
0
  case DNS_R_DNAME:
2911
0
  case DNS_R_CNAME:
2912
0
    break;
2913
0
  default:
2914
0
    if (dns_rdataset_isassociated(&a)) {
2915
0
      dns_rdataset_disassociate(&a);
2916
0
    }
2917
0
    result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2918
0
             DNS_DBFIND_GLUEOK, 0, NULL, foundname, &a,
2919
0
             NULL);
2920
0
  }
2921
0
  if (result == ISC_R_SUCCESS) {
2922
0
    dns_rdataset_disassociate(&a);
2923
0
    return (true);
2924
0
  } else if (result == DNS_R_DELEGATION) {
2925
0
    dns_rdataset_disassociate(&a);
2926
0
  }
2927
2928
0
  if (result == DNS_R_NXRRSET || result == DNS_R_DELEGATION ||
2929
0
      result == DNS_R_GLUE)
2930
0
  {
2931
0
    tresult = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2932
0
              DNS_DBFIND_GLUEOK, 0, NULL, foundname,
2933
0
              &aaaa, NULL);
2934
0
    if (tresult == ISC_R_SUCCESS) {
2935
0
      if (dns_rdataset_isassociated(&a)) {
2936
0
        dns_rdataset_disassociate(&a);
2937
0
      }
2938
0
      dns_rdataset_disassociate(&aaaa);
2939
0
      return (true);
2940
0
    }
2941
0
    if (tresult == DNS_R_DELEGATION || tresult == DNS_R_DNAME) {
2942
0
      dns_rdataset_disassociate(&aaaa);
2943
0
    }
2944
0
    if (result == DNS_R_GLUE || tresult == DNS_R_GLUE) {
2945
      /*
2946
       * Check glue against child zone.
2947
       */
2948
0
      if (zone->checkns != NULL) {
2949
0
        answer = (zone->checkns)(zone, name, owner, &a,
2950
0
               &aaaa);
2951
0
      }
2952
0
      if (dns_rdataset_isassociated(&a)) {
2953
0
        dns_rdataset_disassociate(&a);
2954
0
      }
2955
0
      if (dns_rdataset_isassociated(&aaaa)) {
2956
0
        dns_rdataset_disassociate(&aaaa);
2957
0
      }
2958
0
      return (answer);
2959
0
    }
2960
0
  }
2961
2962
0
  dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2963
0
  dns_name_format(name, namebuf, sizeof namebuf);
2964
0
  if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2965
0
      result == DNS_R_EMPTYNAME || result == DNS_R_DELEGATION)
2966
0
  {
2967
0
    const char *what;
2968
0
    bool required = false;
2969
0
    if (dns_name_issubdomain(name, owner)) {
2970
0
      what = "REQUIRED GLUE ";
2971
0
      required = true;
2972
0
    } else if (result == DNS_R_DELEGATION) {
2973
0
      what = "SIBLING GLUE ";
2974
0
    } else {
2975
0
      what = "";
2976
0
    }
2977
2978
0
    if (result != DNS_R_DELEGATION || required ||
2979
0
        DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSIBLING))
2980
0
    {
2981
0
      dns_zone_log(zone, level,
2982
0
             "%s/NS '%s' has no %s"
2983
0
             "address records (A or AAAA)",
2984
0
             ownerbuf, namebuf, what);
2985
      /*
2986
       * Log missing address record.
2987
       */
2988
0
      if (result == DNS_R_DELEGATION && zone->checkns != NULL)
2989
0
      {
2990
0
        (void)(zone->checkns)(zone, name, owner, &a,
2991
0
                  &aaaa);
2992
0
      }
2993
      /* XXX950 make fatal for 9.5.0. */
2994
      /* answer = false; */
2995
0
    }
2996
0
  } else if (result == DNS_R_CNAME) {
2997
0
    dns_zone_log(zone, level, "%s/NS '%s' is a CNAME (illegal)",
2998
0
           ownerbuf, namebuf);
2999
    /* XXX950 make fatal for 9.5.0. */
3000
    /* answer = false; */
3001
0
  } else if (result == DNS_R_DNAME) {
3002
0
    dns_name_format(foundname, altbuf, sizeof altbuf);
3003
0
    dns_zone_log(zone, level,
3004
0
           "%s/NS '%s' is below a DNAME '%s' (illegal)",
3005
0
           ownerbuf, namebuf, altbuf);
3006
    /* XXX950 make fatal for 9.5.0. */
3007
    /* answer = false; */
3008
0
  }
3009
3010
0
  if (dns_rdataset_isassociated(&a)) {
3011
0
    dns_rdataset_disassociate(&a);
3012
0
  }
3013
0
  if (dns_rdataset_isassociated(&aaaa)) {
3014
0
    dns_rdataset_disassociate(&aaaa);
3015
0
  }
3016
0
  return (answer);
3017
0
}
3018
3019
static bool
3020
zone_rrset_check_dup(dns_zone_t *zone, dns_name_t *owner,
3021
0
         dns_rdataset_t *rdataset) {
3022
0
  dns_rdataset_t tmprdataset;
3023
0
  isc_result_t result;
3024
0
  bool answer = true;
3025
0
  bool format = true;
3026
0
  int level = ISC_LOG_WARNING;
3027
0
  char ownerbuf[DNS_NAME_FORMATSIZE];
3028
0
  char typebuf[DNS_RDATATYPE_FORMATSIZE];
3029
0
  unsigned int count1 = 0;
3030
3031
0
  if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRRFAIL)) {
3032
0
    level = ISC_LOG_ERROR;
3033
0
  }
3034
3035
0
  dns_rdataset_init(&tmprdataset);
3036
0
  for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
3037
0
       result = dns_rdataset_next(rdataset))
3038
0
  {
3039
0
    dns_rdata_t rdata1 = DNS_RDATA_INIT;
3040
0
    unsigned int count2 = 0;
3041
3042
0
    count1++;
3043
0
    dns_rdataset_current(rdataset, &rdata1);
3044
0
    dns_rdataset_clone(rdataset, &tmprdataset);
3045
0
    for (result = dns_rdataset_first(&tmprdataset);
3046
0
         result == ISC_R_SUCCESS;
3047
0
         result = dns_rdataset_next(&tmprdataset))
3048
0
    {
3049
0
      dns_rdata_t rdata2 = DNS_RDATA_INIT;
3050
0
      count2++;
3051
0
      if (count1 >= count2) {
3052
0
        continue;
3053
0
      }
3054
0
      dns_rdataset_current(&tmprdataset, &rdata2);
3055
0
      if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) {
3056
0
        if (format) {
3057
0
          dns_name_format(owner, ownerbuf,
3058
0
              sizeof ownerbuf);
3059
0
          dns_rdatatype_format(rdata1.type,
3060
0
                   typebuf,
3061
0
                   sizeof(typebuf));
3062
0
          format = false;
3063
0
        }
3064
0
        dns_zone_log(zone, level,
3065
0
               "%s/%s has "
3066
0
               "semantically identical records",
3067
0
               ownerbuf, typebuf);
3068
0
        if (level == ISC_LOG_ERROR) {
3069
0
          answer = false;
3070
0
        }
3071
0
        break;
3072
0
      }
3073
0
    }
3074
0
    dns_rdataset_disassociate(&tmprdataset);
3075
0
    if (!format) {
3076
0
      break;
3077
0
    }
3078
0
  }
3079
0
  return (answer);
3080
0
}
3081
3082
static bool
3083
0
zone_check_dup(dns_zone_t *zone, dns_db_t *db) {
3084
0
  dns_dbiterator_t *dbiterator = NULL;
3085
0
  dns_dbnode_t *node = NULL;
3086
0
  dns_fixedname_t fixed;
3087
0
  dns_name_t *name;
3088
0
  dns_rdataset_t rdataset;
3089
0
  dns_rdatasetiter_t *rdsit = NULL;
3090
0
  bool ok = true;
3091
0
  isc_result_t result;
3092
3093
0
  name = dns_fixedname_initname(&fixed);
3094
0
  dns_rdataset_init(&rdataset);
3095
3096
0
  result = dns_db_createiterator(db, 0, &dbiterator);
3097
0
  if (result != ISC_R_SUCCESS) {
3098
0
    return (true);
3099
0
  }
3100
3101
0
  for (result = dns_dbiterator_first(dbiterator); result == ISC_R_SUCCESS;
3102
0
       result = dns_dbiterator_next(dbiterator))
3103
0
  {
3104
0
    result = dns_dbiterator_current(dbiterator, &node, name);
3105
0
    if (result != ISC_R_SUCCESS) {
3106
0
      continue;
3107
0
    }
3108
3109
0
    result = dns_db_allrdatasets(db, node, NULL, 0, 0, &rdsit);
3110
0
    if (result != ISC_R_SUCCESS) {
3111
0
      continue;
3112
0
    }
3113
3114
0
    for (result = dns_rdatasetiter_first(rdsit);
3115
0
         result == ISC_R_SUCCESS;
3116
0
         result = dns_rdatasetiter_next(rdsit))
3117
0
    {
3118
0
      dns_rdatasetiter_current(rdsit, &rdataset);
3119
0
      if (!zone_rrset_check_dup(zone, name, &rdataset)) {
3120
0
        ok = false;
3121
0
      }
3122
0
      dns_rdataset_disassociate(&rdataset);
3123
0
    }
3124
0
    dns_rdatasetiter_destroy(&rdsit);
3125
0
    dns_db_detachnode(db, &node);
3126
0
  }
3127
3128
0
  if (node != NULL) {
3129
0
    dns_db_detachnode(db, &node);
3130
0
  }
3131
0
  dns_dbiterator_destroy(&dbiterator);
3132
3133
0
  return (ok);
3134
0
}
3135
3136
static bool
3137
0
isspf(const dns_rdata_t *rdata) {
3138
0
  char buf[1024];
3139
0
  const unsigned char *data = rdata->data;
3140
0
  unsigned int rdl = rdata->length, i = 0, tl, len;
3141
3142
0
  while (rdl > 0U) {
3143
0
    len = tl = *data;
3144
0
    ++data;
3145
0
    --rdl;
3146
0
    INSIST(tl <= rdl);
3147
0
    if (len > sizeof(buf) - i - 1) {
3148
0
      len = sizeof(buf) - i - 1;
3149
0
    }
3150
0
    memmove(buf + i, data, len);
3151
0
    i += len;
3152
0
    data += tl;
3153
0
    rdl -= tl;
3154
0
  }
3155
3156
0
  if (i < 6U) {
3157
0
    return (false);
3158
0
  }
3159
3160
0
  buf[i] = 0;
3161
0
  if (strncmp(buf, "v=spf1", 6) == 0 && (buf[6] == 0 || buf[6] == ' ')) {
3162
0
    return (true);
3163
0
  }
3164
0
  return (false);
3165
0
}
3166
3167
static bool
3168
0
integrity_checks(dns_zone_t *zone, dns_db_t *db) {
3169
0
  dns_dbiterator_t *dbiterator = NULL;
3170
0
  dns_dbnode_t *node = NULL;
3171
0
  dns_rdataset_t rdataset;
3172
0
  dns_fixedname_t fixed;
3173
0
  dns_fixedname_t fixedbottom;
3174
0
  dns_rdata_mx_t mx;
3175
0
  dns_rdata_ns_t ns;
3176
0
  dns_rdata_in_srv_t srv;
3177
0
  dns_rdata_t rdata;
3178
0
  dns_name_t *name;
3179
0
  dns_name_t *bottom;
3180
0
  isc_result_t result;
3181
0
  bool ok = true, have_spf, have_txt;
3182
0
  int level;
3183
0
  char namebuf[DNS_NAME_FORMATSIZE];
3184
3185
0
  name = dns_fixedname_initname(&fixed);
3186
0
  bottom = dns_fixedname_initname(&fixedbottom);
3187
0
  dns_rdataset_init(&rdataset);
3188
0
  dns_rdata_init(&rdata);
3189
3190
0
  result = dns_db_createiterator(db, 0, &dbiterator);
3191
0
  if (result != ISC_R_SUCCESS) {
3192
0
    return (true);
3193
0
  }
3194
3195
0
  result = dns_dbiterator_first(dbiterator);
3196
0
  while (result == ISC_R_SUCCESS) {
3197
0
    result = dns_dbiterator_current(dbiterator, &node, name);
3198
0
    if (result != ISC_R_SUCCESS) {
3199
0
      goto cleanup;
3200
0
    }
3201
3202
    /*
3203
     * Is this name visible in the zone?
3204
     */
3205
0
    if (!dns_name_issubdomain(name, &zone->origin) ||
3206
0
        (dns_name_countlabels(bottom) > 0 &&
3207
0
         dns_name_issubdomain(name, bottom)))
3208
0
    {
3209
0
      goto next;
3210
0
    }
3211
3212
0
    dns_dbiterator_pause(dbiterator);
3213
3214
    /*
3215
     * Don't check the NS records at the origin.
3216
     */
3217
0
    if (dns_name_equal(name, &zone->origin)) {
3218
0
      goto checkfords;
3219
0
    }
3220
3221
0
    result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ns,
3222
0
               0, 0, &rdataset, NULL);
3223
0
    if (result != ISC_R_SUCCESS) {
3224
0
      goto checkfords;
3225
0
    }
3226
    /*
3227
     * Remember bottom of zone due to NS.
3228
     */
3229
0
    dns_name_copy(name, bottom);
3230
3231
0
    result = dns_rdataset_first(&rdataset);
3232
0
    while (result == ISC_R_SUCCESS) {
3233
0
      dns_rdataset_current(&rdataset, &rdata);
3234
0
      result = dns_rdata_tostruct(&rdata, &ns, NULL);
3235
0
      RUNTIME_CHECK(result == ISC_R_SUCCESS);
3236
0
      if (!zone_check_glue(zone, db, &ns.name, name)) {
3237
0
        ok = false;
3238
0
      }
3239
0
      dns_rdata_reset(&rdata);
3240
0
      result = dns_rdataset_next(&rdataset);
3241
0
    }
3242
0
    dns_rdataset_disassociate(&rdataset);
3243
0
    goto next;
3244
3245
0
  checkfords:
3246
0
    result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ds,
3247
0
               0, 0, &rdataset, NULL);
3248
0
    if (result != ISC_R_SUCCESS) {
3249
0
      goto checkfordname;
3250
0
    }
3251
0
    dns_rdataset_disassociate(&rdataset);
3252
3253
0
    if (zone->type == dns_zone_primary) {
3254
0
      level = ISC_LOG_ERROR;
3255
0
      ok = false;
3256
0
    } else {
3257
0
      level = ISC_LOG_WARNING;
3258
0
    }
3259
0
    dns_name_format(name, namebuf, sizeof(namebuf));
3260
0
    dns_zone_log(zone, level, "DS not at delegation point (%s)",
3261
0
           namebuf);
3262
3263
0
  checkfordname:
3264
0
    result = dns_db_findrdataset(db, node, NULL,
3265
0
               dns_rdatatype_dname, 0, 0,
3266
0
               &rdataset, NULL);
3267
0
    if (result == ISC_R_SUCCESS) {
3268
      /*
3269
       * Remember bottom of zone due to DNAME.
3270
       */
3271
0
      dns_name_copy(name, bottom);
3272
0
      dns_rdataset_disassociate(&rdataset);
3273
0
    }
3274
3275
0
    result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_mx,
3276
0
               0, 0, &rdataset, NULL);
3277
0
    if (result != ISC_R_SUCCESS) {
3278
0
      goto checksrv;
3279
0
    }
3280
0
    result = dns_rdataset_first(&rdataset);
3281
0
    while (result == ISC_R_SUCCESS) {
3282
0
      dns_rdataset_current(&rdataset, &rdata);
3283
0
      result = dns_rdata_tostruct(&rdata, &mx, NULL);
3284
0
      RUNTIME_CHECK(result == ISC_R_SUCCESS);
3285
0
      if (!zone_check_mx(zone, db, &mx.mx, name)) {
3286
0
        ok = false;
3287
0
      }
3288
0
      dns_rdata_reset(&rdata);
3289
0
      result = dns_rdataset_next(&rdataset);
3290
0
    }
3291
0
    dns_rdataset_disassociate(&rdataset);
3292
3293
0
  checksrv:
3294
0
    if (zone->rdclass != dns_rdataclass_in) {
3295
0
      goto next;
3296
0
    }
3297
0
    result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_srv,
3298
0
               0, 0, &rdataset, NULL);
3299
0
    if (result != ISC_R_SUCCESS) {
3300
0
      goto checkspf;
3301
0
    }
3302
0
    result = dns_rdataset_first(&rdataset);
3303
0
    while (result == ISC_R_SUCCESS) {
3304
0
      dns_rdataset_current(&rdataset, &rdata);
3305
0
      result = dns_rdata_tostruct(&rdata, &srv, NULL);
3306
0
      RUNTIME_CHECK(result == ISC_R_SUCCESS);
3307
0
      if (!zone_check_srv(zone, db, &srv.target, name)) {
3308
0
        ok = false;
3309
0
      }
3310
0
      dns_rdata_reset(&rdata);
3311
0
      result = dns_rdataset_next(&rdataset);
3312
0
    }
3313
0
    dns_rdataset_disassociate(&rdataset);
3314
3315
0
  checkspf:
3316
    /*
3317
     * Check if there is a type SPF record without an
3318
     * SPF-formatted type TXT record also being present.
3319
     */
3320
0
    if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSPF)) {
3321
0
      goto next;
3322
0
    }
3323
0
    if (zone->rdclass != dns_rdataclass_in) {
3324
0
      goto next;
3325
0
    }
3326
0
    have_spf = have_txt = false;
3327
0
    result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_spf,
3328
0
               0, 0, &rdataset, NULL);
3329
0
    if (result == ISC_R_SUCCESS) {
3330
0
      dns_rdataset_disassociate(&rdataset);
3331
0
      have_spf = true;
3332
0
    }
3333
0
    result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_txt,
3334
0
               0, 0, &rdataset, NULL);
3335
0
    if (result != ISC_R_SUCCESS) {
3336
0
      goto notxt;
3337
0
    }
3338
0
    result = dns_rdataset_first(&rdataset);
3339
0
    while (result == ISC_R_SUCCESS) {
3340
0
      dns_rdataset_current(&rdataset, &rdata);
3341
0
      have_txt = isspf(&rdata);
3342
0
      dns_rdata_reset(&rdata);
3343
0
      if (have_txt) {
3344
0
        break;
3345
0
      }
3346
0
      result = dns_rdataset_next(&rdataset);
3347
0
    }
3348
0
    dns_rdataset_disassociate(&rdataset);
3349
3350
0
  notxt:
3351
0
    if (have_spf && !have_txt) {
3352
0
      dns_name_format(name, namebuf, sizeof(namebuf));
3353
0
      dns_zone_log(zone, ISC_LOG_WARNING,
3354
0
             "'%s' found type "
3355
0
             "SPF record but no SPF TXT record found, "
3356
0
             "add matching type TXT record",
3357
0
             namebuf);
3358
0
    }
3359
3360
0
  next:
3361
0
    dns_db_detachnode(db, &node);
3362
0
    result = dns_dbiterator_next(dbiterator);
3363
0
  }
3364
3365
0
cleanup:
3366
0
  if (node != NULL) {
3367
0
    dns_db_detachnode(db, &node);
3368
0
  }
3369
0
  dns_dbiterator_destroy(&dbiterator);
3370
3371
0
  return (ok);
3372
0
}
3373
3374
/*
3375
 * OpenSSL verification of RSA keys with exponent 3 is known to be
3376
 * broken prior OpenSSL 0.9.8c/0.9.7k.  Look for such keys and warn
3377
 * if they are in use.
3378
 */
3379
static void
3380
2
zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
3381
2
  dns_dbnode_t *node = NULL;
3382
2
  dns_dbversion_t *version = NULL;
3383
2
  dns_rdata_dnskey_t dnskey;
3384
2
  dns_rdata_t rdata = DNS_RDATA_INIT;
3385
2
  dns_rdataset_t rdataset;
3386
2
  isc_result_t result;
3387
3388
2
  result = dns_db_findnode(db, &zone->origin, false, &node);
3389
2
  if (result != ISC_R_SUCCESS) {
3390
0
    goto cleanup;
3391
0
  }
3392
3393
2
  dns_db_currentversion(db, &version);
3394
2
  dns_rdataset_init(&rdataset);
3395
2
  result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
3396
2
             dns_rdatatype_none, 0, &rdataset, NULL);
3397
2
  if (result != ISC_R_SUCCESS) {
3398
2
    goto cleanup;
3399
2
  }
3400
3401
0
  for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
3402
0
       result = dns_rdataset_next(&rdataset))
3403
0
  {
3404
0
    dns_rdataset_current(&rdataset, &rdata);
3405
0
    result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
3406
0
    INSIST(result == ISC_R_SUCCESS);
3407
3408
    /*
3409
     * RFC 3110, section 4: Performance Considerations:
3410
     *
3411
     * A public exponent of 3 minimizes the effort needed to verify
3412
     * a signature.  Use of 3 as the public exponent is weak for
3413
     * confidentiality uses since, if the same data can be collected
3414
     * encrypted under three different keys with an exponent of 3
3415
     * then, using the Chinese Remainder Theorem [NETSEC], the
3416
     * original plain text can be easily recovered.  If a key is
3417
     * known to be used only for authentication, as is the case with
3418
     * DNSSEC, then an exponent of 3 is acceptable.  However other
3419
     * applications in the future may wish to leverage DNS
3420
     * distributed keys for applications that do require
3421
     * confidentiality.  For keys which might have such other uses,
3422
     * a more conservative choice would be 65537 (F4, the fourth
3423
     * fermat number).
3424
     */
3425
0
    if (dnskey.datalen > 1 && dnskey.data[0] == 1 &&
3426
0
        dnskey.data[1] == 3 &&
3427
0
        (dnskey.algorithm == DNS_KEYALG_RSAMD5 ||
3428
0
         dnskey.algorithm == DNS_KEYALG_RSASHA1 ||
3429
0
         dnskey.algorithm == DNS_KEYALG_NSEC3RSASHA1 ||
3430
0
         dnskey.algorithm == DNS_KEYALG_RSASHA256 ||
3431
0
         dnskey.algorithm == DNS_KEYALG_RSASHA512))
3432
0
    {
3433
0
      char algorithm[DNS_SECALG_FORMATSIZE];
3434
0
      isc_region_t r;
3435
3436
0
      dns_rdata_toregion(&rdata, &r);
3437
0
      dns_secalg_format(dnskey.algorithm, algorithm,
3438
0
            sizeof(algorithm));
3439
3440
0
      dnssec_log(zone, ISC_LOG_WARNING,
3441
0
           "weak %s (%u) key found (exponent=3, id=%u)",
3442
0
           algorithm, dnskey.algorithm,
3443
0
           dst_region_computeid(&r));
3444
0
    }
3445
0
    dns_rdata_reset(&rdata);
3446
0
  }
3447
0
  dns_rdataset_disassociate(&rdataset);
3448
3449
2
cleanup:
3450
2
  if (node != NULL) {
3451
2
    dns_db_detachnode(db, &node);
3452
2
  }
3453
2
  if (version != NULL) {
3454
2
    dns_db_closeversion(db, &version, false);
3455
2
  }
3456
2
}
3457
3458
static void
3459
0
resume_signingwithkey(dns_zone_t *zone) {
3460
0
  dns_dbnode_t *node = NULL;
3461
0
  dns_dbversion_t *version = NULL;
3462
0
  dns_rdata_t rdata = DNS_RDATA_INIT;
3463
0
  dns_rdataset_t rdataset;
3464
0
  isc_result_t result;
3465
0
  dns_db_t *db = NULL;
3466
3467
0
  ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3468
0
  if (zone->db != NULL) {
3469
0
    dns_db_attach(zone->db, &db);
3470
0
  }
3471
0
  ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3472
0
  if (db == NULL) {
3473
0
    goto cleanup;
3474
0
  }
3475
3476
0
  result = dns_db_findnode(db, &zone->origin, false, &node);
3477
0
  if (result != ISC_R_SUCCESS) {
3478
0
    goto cleanup;
3479
0
  }
3480
3481
0
  dns_db_currentversion(db, &version);
3482
0
  dns_rdataset_init(&rdataset);
3483
0
  result = dns_db_findrdataset(db, node, version, zone->privatetype,
3484
0
             dns_rdatatype_none, 0, &rdataset, NULL);
3485
0
  if (result != ISC_R_SUCCESS) {
3486
0
    INSIST(!dns_rdataset_isassociated(&rdataset));
3487
0
    goto cleanup;
3488
0
  }
3489
3490
0
  for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
3491
0
       result = dns_rdataset_next(&rdataset))
3492
0
  {
3493
0
    dns_rdataset_current(&rdataset, &rdata);
3494
0
    if (rdata.length != 5 || rdata.data[0] == 0 ||
3495
0
        rdata.data[4] != 0)
3496
0
    {
3497
0
      dns_rdata_reset(&rdata);
3498
0
      continue;
3499
0
    }
3500
3501
0
    result = zone_signwithkey(zone, rdata.data[0],
3502
0
            (rdata.data[1] << 8) | rdata.data[2],
3503
0
            rdata.data[3]);
3504
0
    if (result != ISC_R_SUCCESS) {
3505
0
      dnssec_log(zone, ISC_LOG_ERROR,
3506
0
           "zone_signwithkey failed: %s",
3507
0
           isc_result_totext(result));
3508
0
    }
3509
0
    dns_rdata_reset(&rdata);
3510
0
  }
3511
0
  dns_rdataset_disassociate(&rdataset);
3512
3513
0
cleanup:
3514
0
  if (db != NULL) {
3515
0
    if (node != NULL) {
3516
0
      dns_db_detachnode(db, &node);
3517
0
    }
3518
0
    if (version != NULL) {
3519
0
      dns_db_closeversion(db, &version, false);
3520
0
    }
3521
0
    dns_db_detach(&db);
3522
0
  }
3523
0
}
3524
3525
/*
3526
 * Initiate adding/removing NSEC3 records belonging to the chain defined by the
3527
 * supplied NSEC3PARAM RDATA.
3528
 *
3529
 * Zone must be locked by caller.
3530
 */
3531
static isc_result_t
3532
0
zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
3533
0
  dns_nsec3chain_t *nsec3chain, *current;
3534
0
  dns_dbversion_t *version = NULL;
3535
0
  bool nseconly = false, nsec3ok = false;
3536
0
  isc_result_t result;
3537
0
  isc_time_t now;
3538
0
  unsigned int options = 0;
3539
0
  char saltbuf[255 * 2 + 1];
3540
0
  char flags[sizeof("INITIAL|REMOVE|CREATE|NONSEC|OPTOUT")];
3541
0
  dns_db_t *db = NULL;
3542
3543
0
  ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3544
0
  if (zone->db != NULL) {
3545
0
    dns_db_attach(zone->db, &db);
3546
0
  }
3547
0
  ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3548
3549
0
  if (db == NULL) {
3550
0
    result = ISC_R_SUCCESS;
3551
0
    goto cleanup;
3552
0
  }
3553
3554
  /*
3555
   * If this zone is not NSEC3-capable, attempting to remove any NSEC3
3556
   * chain from it is pointless as it would not be possible for the
3557
   * latter to exist in the first place.
3558
   */
3559
0
  dns_db_currentversion(db, &version);
3560
0
  result = dns_nsec_nseconly(db, version, NULL, &nseconly);
3561
0
  nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
3562
0
  dns_db_closeversion(db, &version, false);
3563
0
  if (!nsec3ok && (nsec3param->flags & DNS_NSEC3FLAG_REMOVE) == 0) {
3564
0
    result = ISC_R_SUCCESS;
3565
0
    goto cleanup;
3566
0
  }
3567
3568
  /*
3569
   * Allocate and initialize structure preserving state of
3570
   * adding/removing records belonging to this NSEC3 chain between
3571
   * separate zone_nsec3chain() calls.
3572
   */
3573
0
  nsec3chain = isc_mem_get(zone->mctx, sizeof *nsec3chain);
3574
3575
0
  nsec3chain->magic = 0;
3576
0
  nsec3chain->done = false;
3577
0
  nsec3chain->db = NULL;
3578
0
  nsec3chain->dbiterator = NULL;
3579
0
  nsec3chain->nsec3param.common.rdclass = nsec3param->common.rdclass;
3580
0
  nsec3chain->nsec3param.common.rdtype = nsec3param->common.rdtype;
3581
0
  nsec3chain->nsec3param.hash = nsec3param->hash;
3582
0
  nsec3chain->nsec3param.iterations = nsec3param->iterations;
3583
0
  nsec3chain->nsec3param.flags = nsec3param->flags;
3584
0
  nsec3chain->nsec3param.salt_length = nsec3param->salt_length;
3585
0
  memmove(nsec3chain->salt, nsec3param->salt, nsec3param->salt_length);
3586
0
  nsec3chain->nsec3param.salt = nsec3chain->salt;
3587
0
  nsec3chain->seen_nsec = false;
3588
0
  nsec3chain->delete_nsec = false;
3589
0
  nsec3chain->save_delete_nsec = false;
3590
3591
  /*
3592
   * Log NSEC3 parameters defined by supplied NSEC3PARAM RDATA.
3593
   */
3594
0
  if (nsec3param->flags == 0) {
3595
0
    strlcpy(flags, "NONE", sizeof(flags));
3596
0
  } else {
3597
0
    flags[0] = '\0';
3598
0
    if ((nsec3param->flags & DNS_NSEC3FLAG_REMOVE) != 0) {
3599
0
      strlcat(flags, "REMOVE", sizeof(flags));
3600
0
    }
3601
0
    if ((nsec3param->flags & DNS_NSEC3FLAG_INITIAL) != 0) {
3602
0
      if (flags[0] == '\0') {
3603
0
        strlcpy(flags, "INITIAL", sizeof(flags));
3604
0
      } else {
3605
0
        strlcat(flags, "|INITIAL", sizeof(flags));
3606
0
      }
3607
0
    }
3608
0
    if ((nsec3param->flags & DNS_NSEC3FLAG_CREATE) != 0) {
3609
0
      if (flags[0] == '\0') {
3610
0
        strlcpy(flags, "CREATE", sizeof(flags));
3611
0
      } else {
3612
0
        strlcat(flags, "|CREATE", sizeof(flags));
3613
0
      }
3614
0
    }
3615
0
    if ((nsec3param->flags & DNS_NSEC3FLAG_NONSEC) != 0) {
3616
0
      if (flags[0] == '\0') {
3617
0
        strlcpy(flags, "NONSEC", sizeof(flags));
3618
0
      } else {
3619
0
        strlcat(flags, "|NONSEC", sizeof(flags));
3620
0
      }
3621
0
    }
3622
0
    if ((nsec3param->flags & DNS_NSEC3FLAG_OPTOUT) != 0) {
3623
0
      if (flags[0] == '\0') {
3624
0
        strlcpy(flags, "OPTOUT", sizeof(flags));
3625
0
      } else {
3626
0
        strlcat(flags, "|OPTOUT", sizeof(flags));
3627
0
      }
3628
0
    }
3629
0
  }
3630
0
  result = dns_nsec3param_salttotext(nsec3param, saltbuf,
3631
0
             sizeof(saltbuf));
3632
0
  RUNTIME_CHECK(result == ISC_R_SUCCESS);
3633
0
  dnssec_log(zone, ISC_LOG_INFO, "zone_addnsec3chain(%u,%s,%u,%s)",
3634
0
       nsec3param->hash, flags, nsec3param->iterations, saltbuf);
3635
3636
  /*
3637
   * If the NSEC3 chain defined by the supplied NSEC3PARAM RDATA is
3638
   * currently being processed, interrupt its processing to avoid
3639
   * simultaneously adding and removing records for the same NSEC3 chain.
3640
   */
3641
0
  for (current = ISC_LIST_HEAD(zone->nsec3chain); current != NULL;
3642
0
       current = ISC_LIST_NEXT(current, link))
3643
0
  {
3644
0
    if ((current->db == db) &&
3645
0
        (current->nsec3param.hash == nsec3param->hash) &&
3646
0
        (current->nsec3param.iterations ==
3647
0
         nsec3param->iterations) &&
3648
0
        (current->nsec3param.salt_length ==
3649
0
         nsec3param->salt_length) &&
3650
0
        memcmp(current->nsec3param.salt, nsec3param->salt,
3651
0
         nsec3param->salt_length) == 0)
3652
0
    {
3653
0
      current->done = true;
3654
0
    }
3655
0
  }
3656
3657
  /*
3658
   * Attach zone database to the structure initialized above and create
3659
   * an iterator for it with appropriate options in order to avoid
3660
   * creating NSEC3 records for NSEC3 records.
3661
   */
3662
0
  dns_db_attach(db, &nsec3chain->db);
3663
0
  if ((nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0) {
3664
0
    options = DNS_DB_NONSEC3;
3665
0
  }
3666
0
  result = dns_db_createiterator(nsec3chain->db, options,
3667
0
               &nsec3chain->dbiterator);
3668
0
  if (result == ISC_R_SUCCESS) {
3669
0
    result = dns_dbiterator_first(nsec3chain->dbiterator);
3670
0
  }
3671
0
  if (result == ISC_R_SUCCESS) {
3672
    /*
3673
     * Database iterator initialization succeeded.  We are now
3674
     * ready to kick off adding/removing records belonging to this
3675
     * NSEC3 chain.  Append the structure initialized above to the
3676
     * "nsec3chain" list for the zone and set the appropriate zone
3677
     * timer so that zone_nsec3chain() is called as soon as
3678
     * possible.
3679
     */
3680
0
    dns_dbiterator_pause(nsec3chain->dbiterator);
3681
0
    ISC_LIST_INITANDAPPEND(zone->nsec3chain, nsec3chain, link);
3682
0
    nsec3chain = NULL;
3683
0
    if (isc_time_isepoch(&zone->nsec3chaintime)) {
3684
0
      now = isc_time_now();
3685
0
      zone->nsec3chaintime = now;
3686
0
      if (zone->loop != NULL) {
3687
0
        zone_settimer(zone, &now);
3688
0
      }
3689
0
    }
3690
0
  }
3691
3692
0
  if (nsec3chain != NULL) {
3693
0
    if (nsec3chain->db != NULL) {
3694
0
      dns_db_detach(&nsec3chain->db);
3695
0
    }
3696
0
    if (nsec3chain->dbiterator != NULL) {
3697
0
      dns_dbiterator_destroy(&nsec3chain->dbiterator);
3698
0
    }
3699
0
    isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
3700
0
  }
3701
3702
0
cleanup:
3703
0
  if (db != NULL) {
3704
0
    dns_db_detach(&db);
3705
0
  }
3706
0
  return (result);
3707
0
}
3708
3709
/*
3710
 * Find private-type records at the zone apex which signal that an NSEC3 chain
3711
 * should be added or removed.  For each such record, extract NSEC3PARAM RDATA
3712
 * and pass it to zone_addnsec3chain().
3713
 *
3714
 * Zone must be locked by caller.
3715
 */
3716
static void
3717
0
resume_addnsec3chain(dns_zone_t *zone) {
3718
0
  dns_dbnode_t *node = NULL;
3719
0
  dns_dbversion_t *version = NULL;
3720
0
  dns_rdataset_t rdataset;
3721
0
  isc_result_t result;
3722
0
  dns_rdata_nsec3param_t nsec3param;
3723
0
  bool nseconly = false, nsec3ok = false;
3724
0
  dns_db_t *db = NULL;
3725
3726
0
  INSIST(LOCKED_ZONE(zone));
3727
3728
0
  if (zone->privatetype == 0) {
3729
0
    return;
3730
0
  }
3731
3732
0
  ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3733
0
  if (zone->db != NULL) {
3734
0
    dns_db_attach(zone->db, &db);
3735
0
  }
3736
0
  ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3737
0
  if (db == NULL) {
3738
0
    goto cleanup;
3739
0
  }
3740
3741
0
  result = dns_db_findnode(db, &zone->origin, false, &node);
3742
0
  if (result != ISC_R_SUCCESS) {
3743
0
    goto cleanup;
3744
0
  }
3745
3746
0
  dns_db_currentversion(db, &version);
3747
3748
  /*
3749
   * In order to create NSEC3 chains we need the DNSKEY RRset at zone
3750
   * apex to exist and contain no keys using NSEC-only algorithms.
3751
   */
3752
0
  result = dns_nsec_nseconly(db, version, NULL, &nseconly);
3753
0
  nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
3754
3755
  /*
3756
   * Get the RRset containing all private-type records at the zone apex.
3757
   */
3758
0
  dns_rdataset_init(&rdataset);
3759
0
  result = dns_db_findrdataset(db, node, version, zone->privatetype,
3760
0
             dns_rdatatype_none, 0, &rdataset, NULL);
3761
0
  if (result != ISC_R_SUCCESS) {
3762
0
    INSIST(!dns_rdataset_isassociated(&rdataset));
3763
0
    goto cleanup;
3764
0
  }
3765
3766
0
  for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
3767
0
       result = dns_rdataset_next(&rdataset))
3768
0
  {
3769
0
    unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
3770
0
    dns_rdata_t rdata = DNS_RDATA_INIT;
3771
0
    dns_rdata_t private = DNS_RDATA_INIT;
3772
3773
0
    dns_rdataset_current(&rdataset, &private);
3774
    /*
3775
     * Try extracting NSEC3PARAM RDATA from this private-type
3776
     * record.  Failure means this private-type record does not
3777
     * represent an NSEC3PARAM record, so skip it.
3778
     */
3779
0
    if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
3780
0
            sizeof(buf)))
3781
0
    {
3782
0
      continue;
3783
0
    }
3784
0
    result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
3785
0
    RUNTIME_CHECK(result == ISC_R_SUCCESS);
3786
0
    if (((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) ||
3787
0
        ((nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0 && nsec3ok))
3788
0
    {
3789
      /*
3790
       * Pass the NSEC3PARAM RDATA contained in this
3791
       * private-type record to zone_addnsec3chain() so that
3792
       * it can kick off adding or removing NSEC3 records.
3793
       */
3794
0
      result = zone_addnsec3chain(zone, &nsec3param);
3795
0
      if (result != ISC_R_SUCCESS) {
3796
0
        dnssec_log(zone, ISC_LOG_ERROR,
3797
0
             "zone_addnsec3chain failed: %s",
3798
0
             isc_result_totext(result));
3799
0
      }
3800
0
    }
3801
0
  }
3802
0
  dns_rdataset_disassociate(&rdataset);
3803
3804
0
cleanup:
3805
0
  if (db != NULL) {
3806
0
    if (node != NULL) {
3807
0
      dns_db_detachnode(db, &node);
3808
0
    }
3809
0
    if (version != NULL) {
3810
0
      dns_db_closeversion(db, &version, false);
3811
0
    }
3812
0
    dns_db_detach(&db);
3813
0
  }
3814
0
}
3815
3816
static void
3817
0
set_resigntime(dns_zone_t *zone) {
3818
0
  dns_rdataset_t rdataset;
3819
0
  dns_fixedname_t fixed;
3820
0
  unsigned int resign;
3821
0
  isc_result_t result;
3822
0
  uint32_t nanosecs;
3823
0
  dns_db_t *db = NULL;
3824
3825
0
  INSIST(LOCKED_ZONE(zone));
3826
3827
  /* We only re-sign zones that can be dynamically updated */
3828
0
  if (!dns_zone_isdynamic(zone, false)) {
3829
0
    return;
3830
0
  }
3831
3832
0
  if (inline_raw(zone)) {
3833
0
    return;
3834
0
  }
3835
3836
0
  dns_rdataset_init(&rdataset);
3837
0
  dns_fixedname_init(&fixed);
3838
3839
0
  ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3840
0
  if (zone->db != NULL) {
3841
0
    dns_db_attach(zone->db, &db);
3842
0
  }
3843
0
  ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3844
0
  if (db == NULL) {
3845
0
    isc_time_settoepoch(&zone->resigntime);
3846
0
    return;
3847
0
  }
3848
3849
0
  result = dns_db_getsigningtime(db, &rdataset,
3850
0
               dns_fixedname_name(&fixed));
3851
0
  if (result != ISC_R_SUCCESS) {
3852
0
    isc_time_settoepoch(&zone->resigntime);
3853
0
    goto cleanup;
3854
0
  }
3855
3856
0
  resign = rdataset.resign - dns_zone_getsigresigninginterval(zone);
3857
0
  dns_rdataset_disassociate(&rdataset);
3858
0
  nanosecs = isc_random_uniform(1000000000);
3859
0
  isc_time_set(&zone->resigntime, resign, nanosecs);
3860
3861
0
cleanup:
3862
0
  dns_db_detach(&db);
3863
0
  return;
3864
0
}
3865
3866
static isc_result_t
3867
2
check_nsec3param(dns_zone_t *zone, dns_db_t *db) {
3868
2
  bool ok = false;
3869
2
  dns_dbnode_t *node = NULL;
3870
2
  dns_dbversion_t *version = NULL;
3871
2
  dns_rdata_nsec3param_t nsec3param;
3872
2
  dns_rdataset_t rdataset;
3873
2
  isc_result_t result;
3874
2
  bool dynamic = (zone->type == dns_zone_primary)
3875
2
             ? dns_zone_isdynamic(zone, false)
3876
2
             : false;
3877
3878
2
  dns_rdataset_init(&rdataset);
3879
2
  result = dns_db_findnode(db, &zone->origin, false, &node);
3880
2
  if (result != ISC_R_SUCCESS) {
3881
0
    dns_zone_log(zone, ISC_LOG_ERROR,
3882
0
           "nsec3param lookup failure: %s",
3883
0
           isc_result_totext(result));
3884
0
    return (result);
3885
0
  }
3886
2
  dns_db_currentversion(db, &version);
3887
3888
2
  result = dns_db_findrdataset(db, node, version,
3889
2
             dns_rdatatype_nsec3param,
3890
2
             dns_rdatatype_none, 0, &rdataset, NULL);
3891
2
  if (result == ISC_R_NOTFOUND) {
3892
2
    INSIST(!dns_rdataset_isassociated(&rdataset));
3893
2
    result = ISC_R_SUCCESS;
3894
2
    goto cleanup;
3895
2
  }
3896
0
  if (result != ISC_R_SUCCESS) {
3897
0
    INSIST(!dns_rdataset_isassociated(&rdataset));
3898
0
    dns_zone_log(zone, ISC_LOG_ERROR,
3899
0
           "nsec3param lookup failure: %s",
3900
0
           isc_result_totext(result));
3901
0
    goto cleanup;
3902
0
  }
3903
3904
0
  for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
3905
0
       result = dns_rdataset_next(&rdataset))
3906
0
  {
3907
0
    dns_rdata_t rdata = DNS_RDATA_INIT;
3908
3909
0
    dns_rdataset_current(&rdataset, &rdata);
3910
0
    result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
3911
0
    RUNTIME_CHECK(result == ISC_R_SUCCESS);
3912
3913
    /*
3914
     * For dynamic zones we must support every algorithm so we
3915
     * can regenerate all the NSEC3 chains.
3916
     * For non-dynamic zones we only need to find a supported
3917
     * algorithm.
3918
     */
3919
0
    if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NSEC3TESTZONE) &&
3920
0
        nsec3param.hash == DNS_NSEC3_UNKNOWNALG && !dynamic)
3921
0
    {
3922
0
      dns_zone_log(zone, ISC_LOG_WARNING,
3923
0
             "nsec3 test \"unknown\" hash algorithm "
3924
0
             "found: %u",
3925
0
             nsec3param.hash);
3926
0
      ok = true;
3927
0
    } else if (!dns_nsec3_supportedhash(nsec3param.hash)) {
3928
0
      if (dynamic) {
3929
0
        dns_zone_log(zone, ISC_LOG_ERROR,
3930
0
               "unsupported nsec3 hash algorithm"
3931
0
               " in dynamic zone: %u",
3932
0
               nsec3param.hash);
3933
0
        result = DNS_R_BADZONE;
3934
        /* Stop second error message. */
3935
0
        ok = true;
3936
0
        break;
3937
0
      } else {
3938
0
        dns_zone_log(zone, ISC_LOG_WARNING,
3939
0
               "unsupported nsec3 hash "
3940
0
               "algorithm: %u",
3941
0
               nsec3param.hash);
3942
0
      }
3943
0
    } else {
3944
0
      ok = true;
3945
0
    }
3946
3947
    /*
3948
     * Warn if the zone has excessive NSEC3 iterations.
3949
     */
3950
0
    if (nsec3param.iterations > dns_nsec3_maxiterations()) {
3951
0
      dnssec_log(zone, ISC_LOG_WARNING,
3952
0
           "excessive NSEC3PARAM iterations %u > %u",
3953
0
           nsec3param.iterations,
3954
0
           dns_nsec3_maxiterations());
3955
0
    }
3956
0
  }
3957
0
  if (result == ISC_R_NOMORE) {
3958
0
    result = ISC_R_SUCCESS;
3959
0
  }
3960
3961
0
  if (!ok) {
3962
0
    result = DNS_R_BADZONE;
3963
0
    dns_zone_log(zone, ISC_LOG_ERROR,
3964
0
           "no supported nsec3 hash algorithm");
3965
0
  }
3966
3967
2
cleanup:
3968
2
  if (dns_rdataset_isassociated(&rdataset)) {
3969
0
    dns_rdataset_disassociate(&rdataset);
3970
0
  }
3971
2
  dns_db_closeversion(db, &version, false);
3972
2
  dns_db_detachnode(db, &node);
3973
2
  return (result);
3974
0
}
3975
3976
/*
3977
 * Set the timer for refreshing the key zone to the soonest future time
3978
 * of the set (current timer, keydata->refresh, keydata->addhd,
3979
 * keydata->removehd).
3980
 */
3981
static void
3982
set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key,
3983
0
        isc_stdtime_t now, bool force) {
3984
0
  isc_stdtime_t then;
3985
0
  isc_time_t timenow, timethen;
3986
0
  char timebuf[80];
3987
3988
0
  ENTER;
3989
0
  then = key->refresh;
3990
0
  if (force) {
3991
0
    then = now;
3992
0
  }
3993
0
  if (key->addhd > now && key->addhd < then) {
3994
0
    then = key->addhd;
3995
0
  }
3996
0
  if (key->removehd > now && key->removehd < then) {
3997
0
    then = key->removehd;
3998
0
  }
3999
4000
0
  timenow = isc_time_now();
4001
0
  if (then > now) {
4002
0
    DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
4003
0
  } else {
4004
0
    timethen = timenow;
4005
0
  }
4006
0
  if (isc_time_compare(&zone->refreshkeytime, &timenow) < 0 ||
4007
0
      isc_time_compare(&timethen, &zone->refreshkeytime) < 0)
4008
0
  {
4009
0
    zone->refreshkeytime = timethen;
4010
0
  }
4011
4012
0
  isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
4013
0
  dns_zone_log(zone, ISC_LOG_DEBUG(1), "next key refresh: %s", timebuf);
4014
0
  zone_settimer(zone, &timenow);
4015
0
}
4016
4017
/*
4018
 * If keynode references a key or a DS rdataset, and if the key
4019
 * zone does not contain a KEYDATA record for the corresponding name,
4020
 * then create an empty KEYDATA and push it into the zone as a placeholder,
4021
 * then schedule a key refresh immediately. This new KEYDATA record will be
4022
 * updated during the refresh.
4023
 *
4024
 * If the key zone is changed, set '*changed' to true.
4025
 */
4026
static isc_result_t
4027
create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
4028
         dns_diff_t *diff, dns_keynode_t *keynode, dns_name_t *keyname,
4029
0
         bool *changed) {
4030
0
  isc_result_t result = ISC_R_SUCCESS;
4031
0
  dns_rdata_t rdata = DNS_RDATA_INIT;
4032
0
  dns_rdata_keydata_t kd;
4033
0
  unsigned char rrdata[4096];
4034
0
  isc_buffer_t rrdatabuf;
4035
0
  isc_stdtime_t now = isc_stdtime_now();
4036
4037
0
  REQUIRE(keynode != NULL);
4038
4039
0
  ENTER;
4040
4041
  /*
4042
   * If the keynode has no trust anchor set, we shouldn't be here.
4043
   */
4044
0
  if (!dns_keynode_dsset(keynode, NULL)) {
4045
0
    return (ISC_R_FAILURE);
4046
0
  }
4047
4048
0
  memset(&kd, 0, sizeof(kd));
4049
0
  kd.common.rdclass = zone->rdclass;
4050
0
  kd.common.rdtype = dns_rdatatype_keydata;
4051
0
  ISC_LINK_INIT(&kd.common, link);
4052
4053
0
  isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
4054
4055
0
  CHECK(dns_rdata_fromstruct(&rdata, zone->rdclass, dns_rdatatype_keydata,
4056
0
           &kd, &rrdatabuf));
4057
  /* Add rdata to zone. */
4058
0
  CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, keyname, 0, &rdata));
4059
0
  *changed = true;
4060
4061
  /* Refresh new keys from the zone apex as soon as possible. */
4062
0
  set_refreshkeytimer(zone, &kd, now, true);
4063
0
  return (ISC_R_SUCCESS);
4064
4065
0
failure:
4066
0
  return (result);
4067
0
}
4068
4069
/*
4070
 * Remove from the key zone all the KEYDATA records found in rdataset.
4071
 */
4072
static isc_result_t
4073
delete_keydata(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
4074
0
         dns_name_t *name, dns_rdataset_t *rdataset) {
4075
0
  dns_rdata_t rdata = DNS_RDATA_INIT;
4076
0
  isc_result_t result, uresult;
4077
4078
0
  for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
4079
0
       result = dns_rdataset_next(rdataset))
4080
0
  {
4081
0
    dns_rdata_reset(&rdata);
4082
0
    dns_rdataset_current(rdataset, &rdata);
4083
0
    uresult = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name, 0,
4084
0
          &rdata);
4085
0
    if (uresult != ISC_R_SUCCESS) {
4086
0
      return (uresult);
4087
0
    }
4088
0
  }
4089
0
  if (result == ISC_R_NOMORE) {
4090
0
    result = ISC_R_SUCCESS;
4091
0
  }
4092
0
  return (result);
4093
0
}
4094
4095
/*
4096
 * Compute the DNSSEC key ID for a DNSKEY record.
4097
 */
4098
static isc_result_t
4099
compute_tag(dns_name_t *name, dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx,
4100
0
      dns_keytag_t *tag) {
4101
0
  isc_result_t result;
4102
0
  dns_rdata_t rdata = DNS_RDATA_INIT;
4103
0
  unsigned char data[4096];
4104
0
  isc_buffer_t buffer;
4105
0
  dst_key_t *dstkey = NULL;
4106
4107
0
  isc_buffer_init(&buffer, data, sizeof(data));
4108
0
  dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
4109
0
           dns_rdatatype_dnskey, dnskey, &buffer);
4110
4111
0
  result = dns_dnssec_keyfromrdata(name, &rdata, mctx, &dstkey);
4112
0
  if (result == ISC_R_SUCCESS) {
4113
0
    *tag = dst_key_id(dstkey);
4114
0
    dst_key_free(&dstkey);
4115
0
  }
4116
4117
0
  return (result);
4118
0
}
4119
4120
/*
4121
 * Synth-from-dnssec callbacks to add/delete names from namespace tree.
4122
 */
4123
static void
4124
0
sfd_add(const dns_name_t *name, void *arg) {
4125
0
  if (arg != NULL) {
4126
0
    dns_view_sfd_add(arg, name);
4127
0
  }
4128
0
}
4129
4130
static void
4131
0
sfd_del(const dns_name_t *name, void *arg) {
4132
0
  if (arg != NULL) {
4133
0
    dns_view_sfd_del(arg, name);
4134
0
  }
4135
0
}
4136
4137
/*
4138
 * Add key to the security roots.
4139
 */
4140
static void
4141
trust_key(dns_zone_t *zone, dns_name_t *keyname, dns_rdata_dnskey_t *dnskey,
4142
0
    bool initial) {
4143
0
  isc_result_t result;
4144
0
  dns_rdata_t rdata = DNS_RDATA_INIT;
4145
0
  unsigned char data[4096], digest[ISC_MAX_MD_SIZE];
4146
0
  isc_buffer_t buffer;
4147
0
  dns_keytable_t *sr = NULL;
4148
0
  dns_rdata_ds_t ds;
4149
4150
0
  result = dns_view_getsecroots(zone->view, &sr);
4151
0
  if (result != ISC_R_SUCCESS) {
4152
0
    return;
4153
0
  }
4154
4155
  /* Build DS record for key. */
4156
0
  isc_buffer_init(&buffer, data, sizeof(data));
4157
0
  dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
4158
0
           dns_rdatatype_dnskey, dnskey, &buffer);
4159
0
  CHECK(dns_ds_fromkeyrdata(keyname, &rdata, DNS_DSDIGEST_SHA256, digest,
4160
0
          &ds));
4161
0
  CHECK(dns_keytable_add(sr, true, initial, keyname, &ds, sfd_add,
4162
0
             zone->view));
4163
4164
0
  dns_keytable_detach(&sr);
4165
4166
0
failure:
4167
0
  if (sr != NULL) {
4168
0
    dns_keytable_detach(&sr);
4169
0
  }
4170
0
  return;
4171
0
}
4172
4173
/*
4174
 * Add a null key to the security roots for so that all queries
4175
 * to the zone will fail.
4176
 */
4177
static void
4178
0
fail_secure(dns_zone_t *zone, dns_name_t *keyname) {
4179
0
  isc_result_t result;
4180
0
  dns_keytable_t *sr = NULL;
4181
4182
0
  result = dns_view_getsecroots(zone->view, &sr);
4183
0
  if (result == ISC_R_SUCCESS) {
4184
0
    dns_keytable_marksecure(sr, keyname);
4185
0
    dns_keytable_detach(&sr);
4186
0
  }
4187
0
}
4188
4189
/*
4190
 * Scan a set of KEYDATA records from the key zone.  The ones that are
4191
 * valid (i.e., the add holddown timer has expired) become trusted keys.
4192
 */
4193
static void
4194
0
load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
4195
0
  isc_result_t result;
4196
0
  dns_rdata_t rdata = DNS_RDATA_INIT;
4197
0
  dns_rdata_keydata_t keydata;
4198
0
  dns_rdata_dnskey_t dnskey;
4199
0
  int trusted = 0, revoked = 0, pending = 0;
4200
0
  isc_stdtime_t now = isc_stdtime_now();
4201
0
  dns_keytable_t *sr = NULL;
4202
4203
0
  result = dns_view_getsecroots(zone->view, &sr);
4204
0
  if (result == ISC_R_SUCCESS) {
4205
0
    dns_keytable_delete(sr, name, sfd_del, zone->view);
4206
0
    dns_keytable_detach(&sr);
4207
0
  }
4208
4209
  /* Now insert all the accepted trust anchors from this keydata set. */
4210
0
  for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
4211
0
       result = dns_rdataset_next(rdataset))
4212
0
  {
4213
0
    dns_rdata_reset(&rdata);
4214
0
    dns_rdataset_current(rdataset, &rdata);
4215
4216
    /* Convert rdata to keydata. */
4217
0
    result = dns_rdata_tostruct(&rdata, &keydata, NULL);
4218
0
    if (result == ISC_R_NOTIMPLEMENTED) {
4219
0
      continue;
4220
0
    }
4221
0
    RUNTIME_CHECK(result == ISC_R_SUCCESS);
4222
4223
    /* Set the key refresh timer to force a fast refresh. */
4224
0
    set_refreshkeytimer(zone, &keydata, now, true);
4225
4226
    /* If the removal timer is nonzero, this key was revoked. */
4227
0
    if (keydata.removehd != 0) {
4228
0
      revoked++;
4229
0
      continue;
4230
0
    }
4231
4232
    /*
4233
     * If the add timer is still pending, this key is not
4234
     * trusted yet.
4235
     */
4236
0
    if (now < keydata.addhd) {
4237
0
      pending++;
4238
0
      continue;
4239
0
    }
4240
4241
    /* Convert keydata to dnskey. */
4242
0
    dns_keydata_todnskey(&keydata, &dnskey, NULL);
4243
4244
    /* Add to keytables. */
4245
0
    trusted++;
4246
0
    trust_key(zone, name, &dnskey, (keydata.addhd == 0));
4247
0
  }
4248
4249
0
  if (trusted == 0 && pending != 0) {
4250
0
    char namebuf[DNS_NAME_FORMATSIZE];
4251
0
    dns_name_format(name, namebuf, sizeof namebuf);
4252
0
    dnssec_log(zone, ISC_LOG_ERROR,
4253
0
         "No valid trust anchors for '%s'!", namebuf);
4254
0
    dnssec_log(zone, ISC_LOG_ERROR,
4255
0
         "%d key(s) revoked, %d still pending", revoked,
4256
0
         pending);
4257
0
    dnssec_log(zone, ISC_LOG_ERROR, "All queries to '%s' will fail",
4258
0
         namebuf);
4259
0
    fail_secure(zone, name);
4260
0
  }
4261
0
}
4262
4263
static isc_result_t
4264
do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
4265
0
       dns_diff_t *diff) {
4266
0
  dns_diff_t temp_diff;
4267
0
  isc_result_t result;
4268
4269
  /*
4270
   * Create a singleton diff.
4271
   */
4272
0
  dns_diff_init(diff->mctx, &temp_diff);
4273
0
  ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
4274
4275
  /*
4276
   * Apply it to the database.
4277
   */
4278
0
  result = dns_diff_apply(&temp_diff, db, ver);
4279
0
  ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
4280
0
  if (result != ISC_R_SUCCESS) {
4281
0
    dns_difftuple_free(tuple);
4282
0
    return (result);
4283
0
  }
4284
4285
  /*
4286
   * Merge it into the current pending journal entry.
4287
   */
4288
0
  dns_diff_appendminimal(diff, tuple);
4289
4290
  /*
4291
   * Do not clear temp_diff.
4292
   */
4293
0
  return (ISC_R_SUCCESS);
4294
0
}
4295
4296
static isc_result_t
4297
update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
4298
        dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
4299
0
        dns_rdata_t *rdata) {
4300
0
  dns_difftuple_t *tuple = NULL;
4301
0
  isc_result_t result;
4302
0
  result = dns_difftuple_create(diff->mctx, op, name, ttl, rdata, &tuple);
4303
0
  if (result != ISC_R_SUCCESS) {
4304
0
    return (result);
4305
0
  }
4306
0
  return (do_one_tuple(&tuple, db, ver, diff));
4307
0
}
4308
4309
static isc_result_t
4310
update_soa_serial(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
4311
      dns_diff_t *diff, isc_mem_t *mctx,
4312
0
      dns_updatemethod_t method) {
4313
0
  dns_difftuple_t *deltuple = NULL;
4314
0
  dns_difftuple_t *addtuple = NULL;
4315
0
  uint32_t serial;
4316
0
  isc_result_t result;
4317
0
  dns_updatemethod_t used = dns_updatemethod_none;
4318
4319
0
  INSIST(method != dns_updatemethod_none);
4320
4321
0
  CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple));
4322
0
  CHECK(dns_difftuple_copy(deltuple, &addtuple));
4323
0
  addtuple->op = DNS_DIFFOP_ADD;
4324
4325
0
  serial = dns_soa_getserial(&addtuple->rdata);
4326
0
  serial = dns_update_soaserial(serial, method, &used);
4327
0
  if (method != used) {
4328
0
    dns_zone_log(zone, ISC_LOG_WARNING,
4329
0
           "update_soa_serial:new serial would be lower than "
4330
0
           "old serial, using increment method instead");
4331
0
  }
4332
0
  dns_soa_setserial(serial, &addtuple->rdata);
4333
0
  CHECK(do_one_tuple(&deltuple, db, ver, diff));
4334
0
  CHECK(do_one_tuple(&addtuple, db, ver, diff));
4335
0
  result = ISC_R_SUCCESS;
4336
4337
0
failure:
4338
0
  if (addtuple != NULL) {
4339
0
    dns_difftuple_free(&addtuple);
4340
0
  }
4341
0
  if (deltuple != NULL) {
4342
0
    dns_difftuple_free(&deltuple);
4343
0
  }
4344
0
  return (result);
4345
0
}
4346
4347
/*
4348
 * Write all transactions in 'diff' to the zone journal file.
4349
 */
4350
static isc_result_t
4351
zone_journal(dns_zone_t *zone, dns_diff_t *diff, uint32_t *sourceserial,
4352
0
       const char *caller) {
4353
0
  const char *journalfile;
4354
0
  isc_result_t result = ISC_R_SUCCESS;
4355
0
  dns_journal_t *journal = NULL;
4356
0
  unsigned int mode = DNS_JOURNAL_CREATE | DNS_JOURNAL_WRITE;
4357
4358
0
  ENTER;
4359
0
  journalfile = dns_zone_getjournal(zone);
4360
0
  if (journalfile != NULL) {
4361
0
    result = dns_journal_open(zone->mctx, journalfile, mode,
4362
0
            &journal);
4363
0
    if (result != ISC_R_SUCCESS) {
4364
0
      dns_zone_log(zone, ISC_LOG_ERROR,
4365
0
             "%s:dns_journal_open -> %s", caller,
4366
0
             isc_result_totext(result));
4367
0
      return (result);
4368
0
    }
4369
4370
0
    if (sourceserial != NULL) {
4371
0
      dns_journal_set_sourceserial(journal, *sourceserial);
4372
0
    }
4373
4374
0
    result = dns_journal_write_transaction(journal, diff);
4375
0
    if (result != ISC_R_SUCCESS) {
4376
0
      dns_zone_log(zone, ISC_LOG_ERROR,
4377
0
             "%s:dns_journal_write_transaction -> %s",
4378
0
             caller, isc_result_totext(result));
4379
0
    }
4380
0
    dns_journal_destroy(&journal);
4381
0
  }
4382
4383
0
  return (result);
4384
0
}
4385
4386
/*
4387
 * Create an SOA record for a newly-created zone
4388
 */
4389
static isc_result_t
4390
0
add_soa(dns_zone_t *zone, dns_db_t *db) {
4391
0
  isc_result_t result;
4392
0
  dns_rdata_t rdata = DNS_RDATA_INIT;
4393
0
  unsigned char buf[DNS_SOA_BUFFERSIZE];
4394
0
  dns_dbversion_t *ver = NULL;
4395
0
  dns_diff_t diff;
4396
4397
0
  dns_zone_log(zone, ISC_LOG_DEBUG(1), "creating SOA");
4398
4399
0
  dns_diff_init(zone->mctx, &diff);
4400
0
  result = dns_db_newversion(db, &ver);
4401
0
  if (result != ISC_R_SUCCESS) {
4402
0
    dns_zone_log(zone, ISC_LOG_ERROR,
4403
0
           "add_soa:dns_db_newversion -> %s",
4404
0
           isc_result_totext(result));
4405
0
    goto failure;
4406
0
  }
4407
4408
  /* Build SOA record */
4409
0
  result = dns_soa_buildrdata(&zone->origin, dns_rootname, zone->rdclass,
4410
0
            0, 0, 0, 0, 0, buf, &rdata);
4411
0
  if (result != ISC_R_SUCCESS) {
4412
0
    dns_zone_log(zone, ISC_LOG_ERROR,
4413
0
           "add_soa:dns_soa_buildrdata -> %s",
4414
0
           isc_result_totext(result));
4415
0
    goto failure;
4416
0
  }
4417
4418
0
  result = update_one_rr(db, ver, &diff, DNS_DIFFOP_ADD, &zone->origin, 0,
4419
0
             &rdata);
4420
4421
0
failure:
4422
0
  dns_diff_clear(&diff);
4423
0
  if (ver != NULL) {
4424
0
    dns_db_closeversion(db, &ver, (result == ISC_R_SUCCESS));
4425
0
  }
4426
4427
0
  INSIST(ver == NULL);
4428
4429
0
  return (result);
4430
0
}
4431
4432
struct addifmissing_arg {
4433
  dns_db_t *db;
4434
  dns_dbversion_t *ver;
4435
  dns_diff_t *diff;
4436
  dns_zone_t *zone;
4437
  bool *changed;
4438
  isc_result_t result;
4439
};
4440
4441
static void
4442
addifmissing(dns_keytable_t *keytable, dns_keynode_t *keynode,
4443
0
       dns_name_t *keyname, void *arg) {
4444
0
  dns_db_t *db = ((struct addifmissing_arg *)arg)->db;
4445
0
  dns_dbversion_t *ver = ((struct addifmissing_arg *)arg)->ver;
4446
0
  dns_diff_t *diff = ((struct addifmissing_arg *)arg)->diff;
4447
0
  dns_zone_t *zone = ((struct addifmissing_arg *)arg)->zone;
4448
0
  bool *changed = ((struct addifmissing_arg *)arg)->changed;
4449
0
  isc_result_t result;
4450
0
  dns_fixedname_t fname;
4451
4452
0
  UNUSED(keytable);
4453
4454
0
  if (((struct addifmissing_arg *)arg)->result != ISC_R_SUCCESS) {
4455
0
    return;
4456
0
  }
4457
4458
0
  if (!dns_keynode_managed(keynode)) {
4459
0
    return;
4460
0
  }
4461
4462
  /*
4463
   * If the keynode has no trust anchor set, return.
4464
   */
4465
0
  if (!dns_keynode_dsset(keynode, NULL)) {
4466
0
    return;
4467
0
  }
4468
4469
  /*
4470
   * Check whether there's already a KEYDATA entry for this name;
4471
   * if so, we don't need to add another.
4472
   */
4473
0
  dns_fixedname_init(&fname);
4474
0
  result = dns_db_find(db, keyname, ver, dns_rdatatype_keydata,
4475
0
           DNS_DBFIND_NOWILD, 0, NULL,
4476
0
           dns_fixedname_name(&fname), NULL, NULL);
4477
0
  if (result == ISC_R_SUCCESS) {
4478
0
    return;
4479
0
  }
4480
4481
  /*
4482
   * Create the keydata.
4483
   */
4484
0
  result = create_keydata(zone, db, ver, diff, keynode, keyname, changed);
4485
0
  if (result != ISC_R_SUCCESS && result != ISC_R_NOMORE) {
4486
0
    ((struct addifmissing_arg *)arg)->result = result;
4487
0
  }
4488
0
}
4489
4490
/*
4491
 * Synchronize the set of initializing keys found in managed-keys {}
4492
 * statements with the set of trust anchors found in the managed-keys.bind
4493
 * zone.  If a domain is no longer named in managed-keys, delete all keys
4494
 * from that domain from the key zone.  If a domain is configured as an
4495
 * initial-key in trust-anchors, but there are no references to it in the
4496
 * key zone, load the key zone with the initializing key(s) for that
4497
 * domain and schedule a key refresh. If a domain is configured as
4498
 * an initial-ds in trust-anchors, fetch the DNSKEY RRset, load the key
4499
 * zone with the matching key, and schedule a key refresh.
4500
 */
4501
static isc_result_t
4502
0
sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
4503
0
  isc_result_t result = ISC_R_SUCCESS;
4504
0
  bool changed = false;
4505
0
  bool commit = false;
4506
0
  dns_keynode_t *keynode = NULL;
4507
0
  dns_view_t *view = zone->view;
4508
0
  dns_keytable_t *sr = NULL;
4509
0
  dns_dbversion_t *ver = NULL;
4510
0
  dns_diff_t diff;
4511
0
  dns_rriterator_t rrit;
4512
0
  struct addifmissing_arg arg;
4513
4514
0
  dns_zone_log(zone, ISC_LOG_DEBUG(1), "synchronizing trusted keys");
4515
4516
0
  dns_diff_init(zone->mctx, &diff);
4517
4518
0
  CHECK(dns_view_getsecroots(view, &sr));
4519
4520
0
  result = dns_db_newversion(db, &ver);
4521
0
  if (result != ISC_R_SUCCESS) {
4522
0
    dnssec_log(zone, ISC_LOG_ERROR,
4523
0
         "sync_keyzone:dns_db_newversion -> %s",
4524
0
         isc_result_totext(result));
4525
0
    goto failure;
4526
0
  }
4527
4528
  /*
4529
   * Walk the zone DB.  If we find any keys whose names are no longer
4530
   * in trust-anchors, or which have been changed from initial to static,
4531
   * (meaning they are permanent and not RFC5011-maintained), delete
4532
   * them from the zone.  Otherwise call load_secroots(), which
4533
   * loads keys into secroots as appropriate.
4534
   */
4535
0
  dns_rriterator_init(&rrit, db, ver, 0);
4536
0
  for (result = dns_rriterator_first(&rrit); result == ISC_R_SUCCESS;
4537
0
       result = dns_rriterator_nextrrset(&rrit))
4538
0
  {
4539
0
    dns_rdataset_t *rdataset = NULL;
4540
0
    dns_rdata_t rdata = DNS_RDATA_INIT;
4541
0
    dns_rdata_keydata_t keydata;
4542
0
    isc_stdtime_t now = isc_stdtime_now();
4543
0
    bool load = true;
4544
0
    dns_name_t *rrname = NULL;
4545
0
    uint32_t ttl;
4546
4547
0
    dns_rriterator_current(&rrit, &rrname, &ttl, &rdataset, NULL);
4548
0
    if (!dns_rdataset_isassociated(rdataset)) {
4549
0
      dns_rriterator_destroy(&rrit);
4550
0
      goto failure;
4551
0
    }
4552
4553
0
    if (rdataset->type != dns_rdatatype_keydata) {
4554
0
      continue;
4555
0
    }
4556
4557
    /*
4558
     * The managed-keys zone can contain a placeholder instead of
4559
     * legitimate data, in which case we will not use it, and we
4560
     * will try to refresh it.
4561
     */
4562
0
    for (result = dns_rdataset_first(rdataset);
4563
0
         result == ISC_R_SUCCESS;
4564
0
         result = dns_rdataset_next(rdataset))
4565
0
    {
4566
0
      isc_result_t iresult;
4567
4568
0
      dns_rdata_reset(&rdata);
4569
0
      dns_rdataset_current(rdataset, &rdata);
4570
4571
0
      iresult = dns_rdata_tostruct(&rdata, &keydata, NULL);
4572
      /* Do we have a valid placeholder KEYDATA record? */
4573
0
      if (iresult == ISC_R_SUCCESS && keydata.flags == 0 &&
4574
0
          keydata.protocol == 0 && keydata.algorithm == 0)
4575
0
      {
4576
0
        set_refreshkeytimer(zone, &keydata, now, true);
4577
0
        load = false;
4578
0
      }
4579
0
    }
4580
4581
    /*
4582
     * Release db wrlock to prevent LOR reports against
4583
     * dns_keytable_forall() call below.
4584
     */
4585
0
    dns_rriterator_pause(&rrit);
4586
0
    result = dns_keytable_find(sr, rrname, &keynode);
4587
0
    if (result != ISC_R_SUCCESS || !dns_keynode_managed(keynode)) {
4588
0
      CHECK(delete_keydata(db, ver, &diff, rrname, rdataset));
4589
0
      changed = true;
4590
0
    } else if (load) {
4591
0
      load_secroots(zone, rrname, rdataset);
4592
0
    }
4593
4594
0
    if (keynode != NULL) {
4595
0
      dns_keynode_detach(&keynode);
4596
0
    }
4597
0
  }
4598
0
  dns_rriterator_destroy(&rrit);
4599
4600
  /*
4601
   * Walk secroots to find any initial keys that aren't in
4602
   * the zone.  If we find any, add them to the zone directly.
4603
   * If any DS-style initial keys are found, refresh the key
4604
   * zone so that they'll be looked up.
4605
   */
4606
0
  arg.db = db;
4607
0
  arg.ver = ver;
4608
0
  arg.result = ISC_R_SUCCESS;
4609
0
  arg.diff = &diff;
4610
0
  arg.zone = zone;
4611
0
  arg.changed = &changed;
4612
0
  dns_keytable_forall(sr, addifmissing, &arg);
4613
0
  result = arg.result;
4614
0
  if (changed) {
4615
    /* Write changes to journal file. */
4616
0
    CHECK(update_soa_serial(zone, db, ver, &diff, zone->mctx,
4617
0
          zone->updatemethod));
4618
0
    CHECK(zone_journal(zone, &diff, NULL, "sync_keyzone"));
4619
4620
0
    DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
4621
0
    zone_needdump(zone, 30);
4622
0
    commit = true;
4623
0
  }
4624
4625
0
failure:
4626
0
  if (result != ISC_R_SUCCESS) {
4627
0
    dnssec_log(zone, ISC_LOG_ERROR,
4628
0
         "unable to synchronize managed keys: %s",
4629
0
         isc_result_totext(result));
4630
0
    isc_time_settoepoch(&zone->refreshkeytime);
4631
0
  }
4632
0
  if (keynode != NULL) {
4633
0
    dns_keynode_detach(&keynode);
4634
0
  }
4635
0
  if (sr != NULL) {
4636
0
    dns_keytable_detach(&sr);
4637
0
  }
4638
0
  if (ver != NULL) {
4639
0
    dns_db_closeversion(db, &ver, commit);
4640
0
  }
4641
0
  dns_diff_clear(&diff);
4642
4643
0
  INSIST(ver == NULL);
4644
4645
0
  return (result);
4646
0
}
4647
4648
isc_result_t
4649
0
dns_zone_synckeyzone(dns_zone_t *zone) {
4650
0
  isc_result_t result;
4651
0
  dns_db_t *db = NULL;
4652
4653
0
  if (zone->type != dns_zone_key) {
4654
0
    return (DNS_R_BADZONE);
4655
0
  }
4656
4657
0
  CHECK(dns_zone_getdb(zone, &db));
4658
4659
0
  LOCK_ZONE(zone);
4660
0
  result = sync_keyzone(zone, db);
4661
0
  UNLOCK_ZONE(zone);
4662
4663
0
failure:
4664
0
  if (db != NULL) {
4665
0
    dns_db_detach(&db);
4666
0
  }
4667
0
  return (result);
4668
0
}
4669
4670
static void
4671
0
maybe_send_secure(dns_zone_t *zone) {
4672
0
  isc_result_t result;
4673
4674
  /*
4675
   * We've finished loading, or else failed to load, an inline-signing
4676
   * 'secure' zone.  We now need information about the status of the
4677
   * 'raw' zone.  If we failed to load, then we need it to send a
4678
   * copy of its database; if we succeeded, we need it to send its
4679
   * serial number so that we can sync with it.  If it has not yet
4680
   * loaded, we set a flag so that it will send the necessary
4681
   * information when it has finished loading.
4682
   */
4683
0
  if (zone->raw->db != NULL) {
4684
0
    if (zone->db != NULL) {
4685
0
      uint32_t serial;
4686
0
      unsigned int soacount;
4687
4688
0
      result = zone_get_from_db(
4689
0
        zone->raw, zone->raw->db, NULL, &soacount, NULL,
4690
0
        &serial, NULL, NULL, NULL, NULL, NULL);
4691
0
      if (result == ISC_R_SUCCESS && soacount > 0U) {
4692
0
        zone_send_secureserial(zone->raw, serial);
4693
0
      }
4694
0
    } else {
4695
0
      zone_send_securedb(zone->raw, zone->raw->db);
4696
0
    }
4697
0
  } else {
4698
0
    DNS_ZONE_SETFLAG(zone->raw, DNS_ZONEFLG_SENDSECURE);
4699
0
  }
4700
0
}
4701
4702
static bool
4703
0
zone_unchanged(dns_db_t *db1, dns_db_t *db2, isc_mem_t *mctx) {
4704
0
  isc_result_t result;
4705
0
  bool answer = false;
4706
0
  dns_diff_t diff;
4707
4708
0
  dns_diff_init(mctx, &diff);
4709
0
  result = dns_db_diffx(&diff, db1, NULL, db2, NULL, NULL);
4710
0
  if (result == ISC_R_SUCCESS && ISC_LIST_EMPTY(diff.tuples)) {
4711
0
    answer = true;
4712
0
  }
4713
0
  dns_diff_clear(&diff);
4714
0
  return (answer);
4715
0
}
4716
4717
static void
4718
0
process_zone_setnsec3param(dns_zone_t *zone) {
4719
0
  struct np3 *npe = NULL;
4720
0
  while ((npe = ISC_LIST_HEAD(zone->setnsec3param_queue)) != NULL) {
4721
0
    ISC_LIST_UNLINK(zone->setnsec3param_queue, npe, link);
4722
0
    zone_iattach(zone, &npe->zone);
4723
0
    isc_async_run(zone->loop, setnsec3param, npe);
4724
0
  }
4725
0
}
4726
4727
/*
4728
 * The zone is presumed to be locked.
4729
 * If this is a inline_raw zone the secure version is also locked.
4730
 */
4731
static isc_result_t
4732
zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
4733
2
        isc_result_t result) {
4734
2
  unsigned int soacount = 0;
4735
2
  unsigned int nscount = 0;
4736
2
  unsigned int errors = 0;
4737
2
  uint32_t serial, oldserial, refresh, retry, expire, minimum, soattl;
4738
2
  isc_time_t now;
4739
2
  bool needdump = false;
4740
2
  bool fixjournal = false;
4741
2
  bool hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE);
4742
2
  bool noprimary = false;
4743
2
  bool had_db = false;
4744
2
  dns_include_t *inc;
4745
2
  bool is_dynamic = false;
4746
4747
2
  INSIST(LOCKED_ZONE(zone));
4748
2
  if (inline_raw(zone)) {
4749
0
    INSIST(LOCKED_ZONE(zone->secure));
4750
0
  }
4751
4752
2
  now = isc_time_now();
4753
4754
  /*
4755
   * Initiate zone transfer?  We may need a error code that
4756
   * indicates that the "permanent" form does not exist.
4757
   * XXX better error feedback to log.
4758
   */
4759
2
  if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
4760
0
    if (zone->type == dns_zone_secondary ||
4761
0
        zone->type == dns_zone_mirror ||
4762
0
        zone->type == dns_zone_stub ||
4763
0
        (zone->type == dns_zone_redirect &&
4764
0
         dns_remote_addresses(&zone->primaries) == NULL))
4765
0
    {
4766
0
      if (result == ISC_R_FILENOTFOUND) {
4767
0
        dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4768
0
                ISC_LOG_DEBUG(1),
4769
0
                "no master file");
4770
0
      } else if (result != DNS_R_NOMASTERFILE) {
4771
0
        dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4772
0
                ISC_LOG_ERROR,
4773
0
                "loading from master file %s "
4774
0
                "failed: %s",
4775
0
                zone->masterfile,
4776
0
                isc_result_totext(result));
4777
0
      }
4778
0
    } else if (zone->type == dns_zone_primary &&
4779
0
         inline_secure(zone) && result == ISC_R_FILENOTFOUND)
4780
0
    {
4781
0
      dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4782
0
              ISC_LOG_DEBUG(1),
4783
0
              "no master file, requesting db");
4784
0
      maybe_send_secure(zone);
4785
0
    } else {
4786
0
      int level = ISC_LOG_ERROR;
4787
0
      if (zone->type == dns_zone_key &&
4788
0
          result == ISC_R_FILENOTFOUND)
4789
0
      {
4790
0
        level = ISC_LOG_DEBUG(1);
4791
0
      }
4792
0
      dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, level,
4793
0
              "loading from master file %s failed: %s",
4794
0
              zone->masterfile,
4795
0
              isc_result_totext(result));
4796
0
      noprimary = true;
4797
0
    }
4798
4799
0
    if (zone->type != dns_zone_key) {
4800
0
      goto cleanup;
4801
0
    }
4802
0
  }
4803
4804
2
  dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(2),
4805
2
          "number of nodes in database: %u",
4806
2
          dns_db_nodecount(db, dns_dbtree_main));
4807
4808
2
  if (result == DNS_R_SEENINCLUDE) {
4809
0
    DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
4810
2
  } else {
4811
2
    DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
4812
2
  }
4813
4814
  /*
4815
   * If there's no master file for a key zone, then the zone is new:
4816
   * create an SOA record.  (We do this now, instead of later, so that
4817
   * if there happens to be a journal file, we can roll forward from
4818
   * a sane starting point.)
4819
   */
4820
2
  if (noprimary && zone->type == dns_zone_key) {
4821
0
    result = add_soa(zone, db);
4822
0
    if (result != ISC_R_SUCCESS) {
4823
0
      goto cleanup;
4824
0
    }
4825
0
  }
4826
4827
  /*
4828
   * Apply update log, if any, on initial load.
4829
   */
4830
2
  if (zone->journal != NULL &&
4831
2
      !DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE) &&
4832
2
      !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
4833
2
  {
4834
2
    result = zone_journal_rollforward(zone, db, &needdump,
4835
2
              &fixjournal);
4836
2
    if (result != ISC_R_SUCCESS) {
4837
0
      goto cleanup;
4838
0
    }
4839
2
  }
4840
4841
  /*
4842
   * Obtain ns, soa and cname counts for top of zone.
4843
   */
4844
2
  INSIST(db != NULL);
4845
2
  result = zone_get_from_db(zone, db, &nscount, &soacount, &soattl,
4846
2
          &serial, &refresh, &retry, &expire, &minimum,
4847
2
          &errors);
4848
2
  if (result != ISC_R_SUCCESS && zone->type != dns_zone_key) {
4849
0
    dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
4850
0
            "could not find NS and/or SOA records");
4851
0
  }
4852
4853
  /*
4854
   * Process any queued NSEC3PARAM change requests. Only for dynamic
4855
   * zones, an inline-signing zone will perform this action when
4856
   * receiving the secure db (receive_secure_db).
4857
   */
4858
2
  is_dynamic = dns_zone_isdynamic(zone, true);
4859
2
  if (is_dynamic) {
4860
0
    process_zone_setnsec3param(zone);
4861
0
  }
4862
4863
  /*
4864
   * Check to make sure the journal is up to date, and remove the
4865
   * journal file if it isn't, as we wouldn't be able to apply
4866
   * updates otherwise.
4867
   */
4868
2
  if (zone->journal != NULL && is_dynamic &&
4869
2
      !DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS))
4870
0
  {
4871
0
    uint32_t jserial;
4872
0
    dns_journal_t *journal = NULL;
4873
0
    bool empty = false;
4874
4875
0
    result = dns_journal_open(zone->mctx, zone->journal,
4876
0
            DNS_JOURNAL_READ, &journal);
4877
0
    if (result == ISC_R_SUCCESS) {
4878
0
      jserial = dns_journal_last_serial(journal);
4879
0
      empty = dns_journal_empty(journal);
4880
0
      dns_journal_destroy(&journal);
4881
0
    } else {
4882
0
      jserial = serial;
4883
0
      result = ISC_R_SUCCESS;
4884
0
    }
4885
4886
0
    if (jserial != serial) {
4887
0
      if (!empty) {
4888
0
        dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4889
0
                ISC_LOG_INFO,
4890
0
                "journal file is out of date: "
4891
0
                "removing journal file");
4892
0
      }
4893
0
      if (remove(zone->journal) < 0 && errno != ENOENT) {
4894
0
        char strbuf[ISC_STRERRORSIZE];
4895
0
        strerror_r(errno, strbuf, sizeof(strbuf));
4896
0
        isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
4897
0
                DNS_LOGMODULE_ZONE,
4898
0
                ISC_LOG_WARNING,
4899
0
                "unable to remove journal "
4900
0
                "'%s': '%s'",
4901
0
                zone->journal, strbuf);
4902
0
      }
4903
0
    }
4904
0
  }
4905
4906
2
  dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
4907
2
          "loaded; checking validity");
4908
4909
  /*
4910
   * Primary / Secondary / Mirror / Stub zones require both NS and SOA
4911
   * records at the top of the zone.
4912
   */
4913
4914
2
  switch (zone->type) {
4915
0
  case dns_zone_dlz:
4916
2
  case dns_zone_primary:
4917
2
  case dns_zone_secondary:
4918
2
  case dns_zone_mirror:
4919
2
  case dns_zone_stub:
4920
2
  case dns_zone_redirect:
4921
2
    if (soacount != 1) {
4922
0
      dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4923
0
              ISC_LOG_ERROR, "has %d SOA records",
4924
0
              soacount);
4925
0
      result = DNS_R_BADZONE;
4926
0
    }
4927
2
    if (nscount == 0) {
4928
0
      dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4929
0
              ISC_LOG_ERROR, "has no NS records");
4930
0
      result = DNS_R_BADZONE;
4931
0
    }
4932
2
    if (result != ISC_R_SUCCESS) {
4933
0
      goto cleanup;
4934
0
    }
4935
2
    if (zone->type == dns_zone_primary && errors != 0) {
4936
0
      result = DNS_R_BADZONE;
4937
0
      goto cleanup;
4938
0
    }
4939
2
    if (zone->type != dns_zone_stub &&
4940
2
        zone->type != dns_zone_redirect)
4941
2
    {
4942
2
      result = check_nsec3param(zone, db);
4943
2
      if (result != ISC_R_SUCCESS) {
4944
0
        goto cleanup;
4945
0
      }
4946
2
    }
4947
2
    if (zone->type == dns_zone_primary &&
4948
2
        DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKINTEGRITY) &&
4949
2
        !integrity_checks(zone, db))
4950
0
    {
4951
0
      result = DNS_R_BADZONE;
4952
0
      goto cleanup;
4953
0
    }
4954
2
    if (zone->type == dns_zone_primary &&