Coverage Report

Created: 2024-06-21 06:39

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