]> CyberLeo.Net >> Repos - FreeBSD/releng/9.3.git/blob - contrib/bind9/lib/dns/update.c
Fix BIND remote Denial of Service vulnerability. [SA-16:34]
[FreeBSD/releng/9.3.git] / contrib / bind9 / lib / dns / update.c
1 /*
2  * Copyright (C) 2011-2013  Internet Systems Consortium, Inc. ("ISC")
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14  * PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 /* $Id$ */
18
19 #include <config.h>
20
21 #include <isc/log.h>
22 #include <isc/netaddr.h>
23 #include <isc/print.h>
24 #include <isc/serial.h>
25 #include <isc/stats.h>
26 #include <isc/stdtime.h>
27 #include <isc/string.h>
28 #include <isc/taskpool.h>
29 #include <isc/util.h>
30
31 #include <dns/db.h>
32 #include <dns/dbiterator.h>
33 #include <dns/diff.h>
34 #include <dns/dnssec.h>
35 #include <dns/events.h>
36 #include <dns/fixedname.h>
37 #include <dns/journal.h>
38 #include <dns/keyvalues.h>
39 #include <dns/log.h>
40 #include <dns/message.h>
41 #include <dns/nsec.h>
42 #include <dns/nsec3.h>
43 #include <dns/private.h>
44 #include <dns/rdataclass.h>
45 #include <dns/rdataset.h>
46 #include <dns/rdatasetiter.h>
47 #include <dns/rdatastruct.h>
48 #include <dns/rdatatype.h>
49 #include <dns/result.h>
50 #include <dns/soa.h>
51 #include <dns/ssu.h>
52 #include <dns/tsig.h>
53 #include <dns/update.h>
54 #include <dns/view.h>
55 #include <dns/zone.h>
56 #include <dns/zt.h>
57
58
59 /**************************************************************************/
60
61 /*%
62  * Log level for tracing dynamic update protocol requests.
63  */
64 #define LOGLEVEL_PROTOCOL       ISC_LOG_INFO
65
66 /*%
67  * Log level for low-level debug tracing.
68  */
69 #define LOGLEVEL_DEBUG          ISC_LOG_DEBUG(8)
70
71 /*%
72  * Check an operation for failure.  These macros all assume that
73  * the function using them has a 'result' variable and a 'failure'
74  * label.
75  */
76 #define CHECK(op) \
77         do { result = (op); \
78                 if (result != ISC_R_SUCCESS) goto failure; \
79         } while (0)
80
81 /*%
82  * Fail unconditionally with result 'code', which must not
83  * be ISC_R_SUCCESS.  The reason for failure presumably has
84  * been logged already.
85  *
86  * The test against ISC_R_SUCCESS is there to keep the Solaris compiler
87  * from complaining about "end-of-loop code not reached".
88  */
89
90 #define FAIL(code) \
91         do {                                                    \
92                 result = (code);                                \
93                 if (result != ISC_R_SUCCESS) goto failure;      \
94         } while (0)
95
96 /*%
97  * Fail unconditionally and log as a client error.
98  * The test against ISC_R_SUCCESS is there to keep the Solaris compiler
99  * from complaining about "end-of-loop code not reached".
100  */
101 #define FAILC(code, msg) \
102         do {                                                    \
103                 const char *_what = "failed";                   \
104                 result = (code);                                \
105                 switch (result) {                               \
106                 case DNS_R_NXDOMAIN:                            \
107                 case DNS_R_YXDOMAIN:                            \
108                 case DNS_R_YXRRSET:                             \
109                 case DNS_R_NXRRSET:                             \
110                         _what = "unsuccessful";                 \
111                 }                                               \
112                 update_log(log, zone, LOGLEVEL_PROTOCOL,        \
113                            "update %s: %s (%s)", _what,         \
114                            msg, isc_result_totext(result));     \
115                 if (result != ISC_R_SUCCESS) goto failure;      \
116         } while (0)
117
118 #define FAILN(code, name, msg) \
119         do {                                                            \
120                 const char *_what = "failed";                           \
121                 result = (code);                                        \
122                 switch (result) {                                       \
123                 case DNS_R_NXDOMAIN:                                    \
124                 case DNS_R_YXDOMAIN:                                    \
125                 case DNS_R_YXRRSET:                                     \
126                 case DNS_R_NXRRSET:                                     \
127                         _what = "unsuccessful";                         \
128                 }                                                       \
129                 if (isc_log_wouldlog(dns_lctx, LOGLEVEL_PROTOCOL)) {    \
130                         char _nbuf[DNS_NAME_FORMATSIZE];                \
131                         dns_name_format(name, _nbuf, sizeof(_nbuf));    \
132                         update_log(log, zone, LOGLEVEL_PROTOCOL,        \
133                                    "update %s: %s: %s (%s)", _what, _nbuf, \
134                                    msg, isc_result_totext(result));     \
135                 }                                                       \
136                 if (result != ISC_R_SUCCESS) goto failure;              \
137         } while (0)
138
139 #define FAILNT(code, name, type, msg) \
140         do {                                                            \
141                 const char *_what = "failed";                           \
142                 result = (code);                                        \
143                 switch (result) {                                       \
144                 case DNS_R_NXDOMAIN:                                    \
145                 case DNS_R_YXDOMAIN:                                    \
146                 case DNS_R_YXRRSET:                                     \
147                 case DNS_R_NXRRSET:                                     \
148                         _what = "unsuccessful";                         \
149                 }                                                       \
150                 if (isc_log_wouldlog(dns_lctx, LOGLEVEL_PROTOCOL)) {    \
151                         char _nbuf[DNS_NAME_FORMATSIZE];                \
152                         char _tbuf[DNS_RDATATYPE_FORMATSIZE];           \
153                         dns_name_format(name, _nbuf, sizeof(_nbuf));    \
154                         dns_rdatatype_format(type, _tbuf, sizeof(_tbuf)); \
155                         update_log(log, zone, LOGLEVEL_PROTOCOL,        \
156                                    "update %s: %s/%s: %s (%s)",         \
157                                    _what, _nbuf, _tbuf, msg,            \
158                                    isc_result_totext(result));          \
159                 }                                                       \
160                 if (result != ISC_R_SUCCESS) goto failure;              \
161         } while (0)
162
163 /*%
164  * Fail unconditionally and log as a server error.
165  * The test against ISC_R_SUCCESS is there to keep the Solaris compiler
166  * from complaining about "end-of-loop code not reached".
167  */
168 #define FAILS(code, msg) \
169         do {                                                    \
170                 result = (code);                                \
171                 update_log(log, zone, LOGLEVEL_PROTOCOL,        \
172                            "error: %s: %s",                     \
173                            msg, isc_result_totext(result));     \
174                 if (result != ISC_R_SUCCESS) goto failure;      \
175         } while (0)
176
177 /**************************************************************************/
178
179 typedef struct rr rr_t;
180
181 struct rr {
182         /* dns_name_t name; */
183         isc_uint32_t            ttl;
184         dns_rdata_t             rdata;
185 };
186
187 typedef struct update_event update_event_t;
188
189 /**************************************************************************/
190
191 static void
192 update_log(dns_update_log_t *callback, dns_zone_t *zone,
193            int level, const char *fmt, ...) ISC_FORMAT_PRINTF(4, 5);
194
195 static void
196 update_log(dns_update_log_t *callback, dns_zone_t *zone,
197            int level, const char *fmt, ...)
198 {
199         va_list ap;
200         char message[4096];
201
202         if (callback == NULL)
203                 return;
204
205         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
206                 return;
207
208
209         va_start(ap, fmt);
210         vsnprintf(message, sizeof(message), fmt, ap);
211         va_end(ap);
212
213         (callback->func)(callback->arg, zone, level, message);
214 }
215
216 /*%
217  * Update a single RR in version 'ver' of 'db' and log the
218  * update in 'diff'.
219  *
220  * Ensures:
221  * \li  '*tuple' == NULL.  Either the tuple is freed, or its
222  *      ownership has been transferred to the diff.
223  */
224 static isc_result_t
225 do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
226              dns_diff_t *diff)
227 {
228         dns_diff_t temp_diff;
229         isc_result_t result;
230
231         /*
232          * Create a singleton diff.
233          */
234         dns_diff_init(diff->mctx, &temp_diff);
235         ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
236
237         /*
238          * Apply it to the database.
239          */
240         result = dns_diff_apply(&temp_diff, db, ver);
241         ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
242         if (result != ISC_R_SUCCESS) {
243                 dns_difftuple_free(tuple);
244                 return (result);
245         }
246
247         /*
248          * Merge it into the current pending journal entry.
249          */
250         dns_diff_appendminimal(diff, tuple);
251
252         /*
253          * Do not clear temp_diff.
254          */
255         return (ISC_R_SUCCESS);
256 }
257
258 static isc_result_t
259 update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
260               dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
261               dns_rdata_t *rdata)
262 {
263         dns_difftuple_t *tuple = NULL;
264         isc_result_t result;
265         result = dns_difftuple_create(diff->mctx, op,
266                                       name, ttl, rdata, &tuple);
267         if (result != ISC_R_SUCCESS)
268                 return (result);
269         return (do_one_tuple(&tuple, db, ver, diff));
270 }
271
272 /**************************************************************************/
273 /*
274  * Callback-style iteration over rdatasets and rdatas.
275  *
276  * foreach_rrset() can be used to iterate over the RRsets
277  * of a name and call a callback function with each
278  * one.  Similarly, foreach_rr() can be used to iterate
279  * over the individual RRs at name, optionally restricted
280  * to RRs of a given type.
281  *
282  * The callback functions are called "actions" and take
283  * two arguments: a void pointer for passing arbitrary
284  * context information, and a pointer to the current RRset
285  * or RR.  By convention, their names end in "_action".
286  */
287
288 /*
289  * XXXRTH  We might want to make this public somewhere in libdns.
290  */
291
292 /*%
293  * Function type for foreach_rrset() iterator actions.
294  */
295 typedef isc_result_t rrset_func(void *data, dns_rdataset_t *rrset);
296
297 /*%
298  * Function type for foreach_rr() iterator actions.
299  */
300 typedef isc_result_t rr_func(void *data, rr_t *rr);
301
302 /*%
303  * Internal context struct for foreach_node_rr().
304  */
305 typedef struct {
306         rr_func *       rr_action;
307         void *          rr_action_data;
308 } foreach_node_rr_ctx_t;
309
310 /*%
311  * Internal helper function for foreach_node_rr().
312  */
313 static isc_result_t
314 foreach_node_rr_action(void *data, dns_rdataset_t *rdataset) {
315         isc_result_t result;
316         foreach_node_rr_ctx_t *ctx = data;
317         for (result = dns_rdataset_first(rdataset);
318              result == ISC_R_SUCCESS;
319              result = dns_rdataset_next(rdataset))
320         {
321                 rr_t rr = { 0, DNS_RDATA_INIT };
322
323                 dns_rdataset_current(rdataset, &rr.rdata);
324                 rr.ttl = rdataset->ttl;
325                 result = (*ctx->rr_action)(ctx->rr_action_data, &rr);
326                 if (result != ISC_R_SUCCESS)
327                         return (result);
328         }
329         if (result != ISC_R_NOMORE)
330                 return (result);
331         return (ISC_R_SUCCESS);
332 }
333
334 /*%
335  * For each rdataset of 'name' in 'ver' of 'db', call 'action'
336  * with the rdataset and 'action_data' as arguments.  If the name
337  * does not exist, do nothing.
338  *
339  * If 'action' returns an error, abort iteration and return the error.
340  */
341 static isc_result_t
342 foreach_rrset(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
343               rrset_func *action, void *action_data)
344 {
345         isc_result_t result;
346         dns_dbnode_t *node;
347         dns_rdatasetiter_t *iter;
348
349         node = NULL;
350         result = dns_db_findnode(db, name, ISC_FALSE, &node);
351         if (result == ISC_R_NOTFOUND)
352                 return (ISC_R_SUCCESS);
353         if (result != ISC_R_SUCCESS)
354                 return (result);
355
356         iter = NULL;
357         result = dns_db_allrdatasets(db, node, ver,
358                                      (isc_stdtime_t) 0, &iter);
359         if (result != ISC_R_SUCCESS)
360                 goto cleanup_node;
361
362         for (result = dns_rdatasetiter_first(iter);
363              result == ISC_R_SUCCESS;
364              result = dns_rdatasetiter_next(iter))
365         {
366                 dns_rdataset_t rdataset;
367
368                 dns_rdataset_init(&rdataset);
369                 dns_rdatasetiter_current(iter, &rdataset);
370
371                 result = (*action)(action_data, &rdataset);
372
373                 dns_rdataset_disassociate(&rdataset);
374                 if (result != ISC_R_SUCCESS)
375                         goto cleanup_iterator;
376         }
377         if (result == ISC_R_NOMORE)
378                 result = ISC_R_SUCCESS;
379
380  cleanup_iterator:
381         dns_rdatasetiter_destroy(&iter);
382
383  cleanup_node:
384         dns_db_detachnode(db, &node);
385
386         return (result);
387 }
388
389 /*%
390  * For each RR of 'name' in 'ver' of 'db', call 'action'
391  * with the RR and 'action_data' as arguments.  If the name
392  * does not exist, do nothing.
393  *
394  * If 'action' returns an error, abort iteration
395  * and return the error.
396  */
397 static isc_result_t
398 foreach_node_rr(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
399                 rr_func *rr_action, void *rr_action_data)
400 {
401         foreach_node_rr_ctx_t ctx;
402         ctx.rr_action = rr_action;
403         ctx.rr_action_data = rr_action_data;
404         return (foreach_rrset(db, ver, name,
405                               foreach_node_rr_action, &ctx));
406 }
407
408
409 /*%
410  * For each of the RRs specified by 'db', 'ver', 'name', 'type',
411  * (which can be dns_rdatatype_any to match any type), and 'covers', call
412  * 'action' with the RR and 'action_data' as arguments. If the name
413  * does not exist, or if no RRset of the given type exists at the name,
414  * do nothing.
415  *
416  * If 'action' returns an error, abort iteration and return the error.
417  */
418 static isc_result_t
419 foreach_rr(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
420            dns_rdatatype_t type, dns_rdatatype_t covers, rr_func *rr_action,
421            void *rr_action_data)
422 {
423
424         isc_result_t result;
425         dns_dbnode_t *node;
426         dns_rdataset_t rdataset;
427
428         if (type == dns_rdatatype_any)
429                 return (foreach_node_rr(db, ver, name,
430                                         rr_action, rr_action_data));
431
432         node = NULL;
433         if (type == dns_rdatatype_nsec3 ||
434             (type == dns_rdatatype_rrsig && covers == dns_rdatatype_nsec3))
435                 result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
436         else
437                 result = dns_db_findnode(db, name, ISC_FALSE, &node);
438         if (result == ISC_R_NOTFOUND)
439                 return (ISC_R_SUCCESS);
440         if (result != ISC_R_SUCCESS)
441                 return (result);
442
443         dns_rdataset_init(&rdataset);
444         result = dns_db_findrdataset(db, node, ver, type, covers,
445                                      (isc_stdtime_t) 0, &rdataset, NULL);
446         if (result == ISC_R_NOTFOUND) {
447                 result = ISC_R_SUCCESS;
448                 goto cleanup_node;
449         }
450         if (result != ISC_R_SUCCESS)
451                 goto cleanup_node;
452
453         for (result = dns_rdataset_first(&rdataset);
454              result == ISC_R_SUCCESS;
455              result = dns_rdataset_next(&rdataset))
456         {
457                 rr_t rr = { 0, DNS_RDATA_INIT };
458                 dns_rdataset_current(&rdataset, &rr.rdata);
459                 rr.ttl = rdataset.ttl;
460                 result = (*rr_action)(rr_action_data, &rr);
461                 if (result != ISC_R_SUCCESS)
462                         goto cleanup_rdataset;
463         }
464         if (result != ISC_R_NOMORE)
465                 goto cleanup_rdataset;
466         result = ISC_R_SUCCESS;
467
468  cleanup_rdataset:
469         dns_rdataset_disassociate(&rdataset);
470  cleanup_node:
471         dns_db_detachnode(db, &node);
472
473         return (result);
474 }
475
476 /**************************************************************************/
477 /*
478  * Various tests on the database contents (for prerequisites, etc).
479  */
480
481 /*%
482  * Function type for predicate functions that compare a database RR 'db_rr'
483  * against an update RR 'update_rr'.
484  */
485 typedef isc_boolean_t rr_predicate(dns_rdata_t *update_rr, dns_rdata_t *db_rr);
486
487 /*%
488  * Helper function for rrset_exists().
489  */
490 static isc_result_t
491 rrset_exists_action(void *data, rr_t *rr) {
492         UNUSED(data);
493         UNUSED(rr);
494         return (ISC_R_EXISTS);
495 }
496
497 /*%
498  * Utility macro for RR existence checking functions.
499  *
500  * If the variable 'result' has the value ISC_R_EXISTS or
501  * ISC_R_SUCCESS, set *exists to ISC_TRUE or ISC_FALSE,
502  * respectively, and return success.
503  *
504  * If 'result' has any other value, there was a failure.
505  * Return the failure result code and do not set *exists.
506  *
507  * This would be more readable as "do { if ... } while(0)",
508  * but that form generates tons of warnings on Solaris 2.6.
509  */
510 #define RETURN_EXISTENCE_FLAG                           \
511         return ((result == ISC_R_EXISTS) ?              \
512                 (*exists = ISC_TRUE, ISC_R_SUCCESS) :   \
513                 ((result == ISC_R_SUCCESS) ?            \
514                  (*exists = ISC_FALSE, ISC_R_SUCCESS) : \
515                  result))
516
517 /*%
518  * Set '*exists' to true iff an rrset of the given type exists,
519  * to false otherwise.
520  */
521 static isc_result_t
522 rrset_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
523              dns_rdatatype_t type, dns_rdatatype_t covers,
524              isc_boolean_t *exists)
525 {
526         isc_result_t result;
527         result = foreach_rr(db, ver, name, type, covers,
528                             rrset_exists_action, NULL);
529         RETURN_EXISTENCE_FLAG;
530 }
531
532 /*%
533  * Set '*visible' to true if the RRset exists and is part of the
534  * visible zone.  Otherwise '*visible' is set to false unless a
535  * error occurs.
536  */
537 static isc_result_t
538 rrset_visible(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
539               dns_rdatatype_t type, isc_boolean_t *visible)
540 {
541         isc_result_t result;
542         dns_fixedname_t fixed;
543
544         dns_fixedname_init(&fixed);
545         result = dns_db_find(db, name, ver, type, DNS_DBFIND_NOWILD,
546                              (isc_stdtime_t) 0, NULL,
547                              dns_fixedname_name(&fixed), NULL, NULL);
548         switch (result) {
549         case ISC_R_SUCCESS:
550                 *visible = ISC_TRUE;
551                 break;
552         /*
553          * Glue, obscured, deleted or replaced records.
554          */
555         case DNS_R_DELEGATION:
556         case DNS_R_DNAME:
557         case DNS_R_CNAME:
558         case DNS_R_NXDOMAIN:
559         case DNS_R_NXRRSET:
560         case DNS_R_EMPTYNAME:
561         case DNS_R_COVERINGNSEC:
562                 *visible = ISC_FALSE;
563                 result = ISC_R_SUCCESS;
564                 break;
565         default:
566                 break;
567         }
568         return (result);
569 }
570
571 /*%
572  * Context struct and helper function for name_exists().
573  */
574
575 static isc_result_t
576 name_exists_action(void *data, dns_rdataset_t *rrset) {
577         UNUSED(data);
578         UNUSED(rrset);
579         return (ISC_R_EXISTS);
580 }
581
582 /*%
583  * Set '*exists' to true iff the given name exists, to false otherwise.
584  */
585 static isc_result_t
586 name_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
587             isc_boolean_t *exists)
588 {
589         isc_result_t result;
590         result = foreach_rrset(db, ver, name,
591                                name_exists_action, NULL);
592         RETURN_EXISTENCE_FLAG;
593 }
594
595 /**************************************************************************/
596 /*
597  * Checking of "RRset exists (value dependent)" prerequisites.
598  *
599  * In the RFC2136 section 3.2.5, this is the pseudocode involving
600  * a variable called "temp", a mapping of <name, type> tuples to rrsets.
601  *
602  * Here, we represent the "temp" data structure as (non-minimal) "dns_diff_t"
603  * where each tuple has op==DNS_DIFFOP_EXISTS.
604  */
605
606 /*%
607  * A comparison function defining the sorting order for the entries
608  * in the "temp" data structure.  The major sort key is the owner name,
609  * followed by the type and rdata.
610  */
611 static int
612 temp_order(const void *av, const void *bv) {
613         dns_difftuple_t const * const *ap = av;
614         dns_difftuple_t const * const *bp = bv;
615         dns_difftuple_t const *a = *ap;
616         dns_difftuple_t const *b = *bp;
617         int r;
618         r = dns_name_compare(&a->name, &b->name);
619         if (r != 0)
620                 return (r);
621         r = (b->rdata.type - a->rdata.type);
622         if (r != 0)
623                 return (r);
624         r = dns_rdata_casecompare(&a->rdata, &b->rdata);
625         return (r);
626 }
627
628 /**************************************************************************/
629 /*
630  * Conditional deletion of RRs.
631  */
632
633 /*%
634  * Context structure for delete_if().
635  */
636
637 typedef struct {
638         rr_predicate *predicate;
639         dns_db_t *db;
640         dns_dbversion_t *ver;
641         dns_diff_t *diff;
642         dns_name_t *name;
643         dns_rdata_t *update_rr;
644 } conditional_delete_ctx_t;
645
646 /*%
647  * Predicate functions for delete_if().
648  */
649
650 /*%
651  * Return true always.
652  */
653 static isc_boolean_t
654 true_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) {
655         UNUSED(update_rr);
656         UNUSED(db_rr);
657         return (ISC_TRUE);
658 }
659
660 /*%
661  * Return true if the record is a RRSIG.
662  */
663 static isc_boolean_t
664 rrsig_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) {
665         UNUSED(update_rr);
666         return ((db_rr->type == dns_rdatatype_rrsig) ?
667                 ISC_TRUE : ISC_FALSE);
668 }
669
670 /*%
671  * Internal helper function for delete_if().
672  */
673 static isc_result_t
674 delete_if_action(void *data, rr_t *rr) {
675         conditional_delete_ctx_t *ctx = data;
676         if ((*ctx->predicate)(ctx->update_rr, &rr->rdata)) {
677                 isc_result_t result;
678                 result = update_one_rr(ctx->db, ctx->ver, ctx->diff,
679                                        DNS_DIFFOP_DEL, ctx->name,
680                                        rr->ttl, &rr->rdata);
681                 return (result);
682         } else {
683                 return (ISC_R_SUCCESS);
684         }
685 }
686
687 /*%
688  * Conditionally delete RRs.  Apply 'predicate' to the RRs
689  * specified by 'db', 'ver', 'name', and 'type' (which can
690  * be dns_rdatatype_any to match any type).  Delete those
691  * RRs for which the predicate returns true, and log the
692  * deletions in 'diff'.
693  */
694 static isc_result_t
695 delete_if(rr_predicate *predicate, dns_db_t *db, dns_dbversion_t *ver,
696           dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers,
697           dns_rdata_t *update_rr, dns_diff_t *diff)
698 {
699         conditional_delete_ctx_t ctx;
700         ctx.predicate = predicate;
701         ctx.db = db;
702         ctx.ver = ver;
703         ctx.diff = diff;
704         ctx.name = name;
705         ctx.update_rr = update_rr;
706         return (foreach_rr(db, ver, name, type, covers,
707                            delete_if_action, &ctx));
708 }
709
710 /**************************************************************************/
711 /*
712  * Incremental updating of NSECs and RRSIGs.
713  */
714
715 /*%
716  * We abuse the dns_diff_t type to represent a set of domain names
717  * affected by the update.
718  */
719 static isc_result_t
720 namelist_append_name(dns_diff_t *list, dns_name_t *name) {
721         isc_result_t result;
722         dns_difftuple_t *tuple = NULL;
723         static dns_rdata_t dummy_rdata = DNS_RDATA_INIT;
724
725         CHECK(dns_difftuple_create(list->mctx, DNS_DIFFOP_EXISTS, name, 0,
726                                    &dummy_rdata, &tuple));
727         dns_diff_append(list, &tuple);
728  failure:
729         return (result);
730 }
731
732 static isc_result_t
733 namelist_append_subdomain(dns_db_t *db, dns_name_t *name, dns_diff_t *affected)
734 {
735         isc_result_t result;
736         dns_fixedname_t fixedname;
737         dns_name_t *child;
738         dns_dbiterator_t *dbit = NULL;
739
740         dns_fixedname_init(&fixedname);
741         child = dns_fixedname_name(&fixedname);
742
743         CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit));
744
745         for (result = dns_dbiterator_seek(dbit, name);
746              result == ISC_R_SUCCESS;
747              result = dns_dbiterator_next(dbit))
748         {
749                 dns_dbnode_t *node = NULL;
750                 CHECK(dns_dbiterator_current(dbit, &node, child));
751                 dns_db_detachnode(db, &node);
752                 if (! dns_name_issubdomain(child, name))
753                         break;
754                 CHECK(namelist_append_name(affected, child));
755         }
756         if (result == ISC_R_NOMORE)
757                 result = ISC_R_SUCCESS;
758  failure:
759         if (dbit != NULL)
760                 dns_dbiterator_destroy(&dbit);
761         return (result);
762 }
763
764
765
766 /*%
767  * Helper function for non_nsec_rrset_exists().
768  */
769 static isc_result_t
770 is_non_nsec_action(void *data, dns_rdataset_t *rrset) {
771         UNUSED(data);
772         if (!(rrset->type == dns_rdatatype_nsec ||
773               rrset->type == dns_rdatatype_nsec3 ||
774               (rrset->type == dns_rdatatype_rrsig &&
775                (rrset->covers == dns_rdatatype_nsec ||
776                 rrset->covers == dns_rdatatype_nsec3))))
777                 return (ISC_R_EXISTS);
778         return (ISC_R_SUCCESS);
779 }
780
781 /*%
782  * Check whether there is an rrset other than a NSEC or RRSIG NSEC,
783  * i.e., anything that justifies the continued existence of a name
784  * after a secure update.
785  *
786  * If such an rrset exists, set '*exists' to ISC_TRUE.
787  * Otherwise, set it to ISC_FALSE.
788  */
789 static isc_result_t
790 non_nsec_rrset_exists(dns_db_t *db, dns_dbversion_t *ver,
791                      dns_name_t *name, isc_boolean_t *exists)
792 {
793         isc_result_t result;
794         result = foreach_rrset(db, ver, name, is_non_nsec_action, NULL);
795         RETURN_EXISTENCE_FLAG;
796 }
797
798 /*%
799  * A comparison function for sorting dns_diff_t:s by name.
800  */
801 static int
802 name_order(const void *av, const void *bv) {
803         dns_difftuple_t const * const *ap = av;
804         dns_difftuple_t const * const *bp = bv;
805         dns_difftuple_t const *a = *ap;
806         dns_difftuple_t const *b = *bp;
807         return (dns_name_compare(&a->name, &b->name));
808 }
809
810 static isc_result_t
811 uniqify_name_list(dns_diff_t *list) {
812         isc_result_t result;
813         dns_difftuple_t *p, *q;
814
815         CHECK(dns_diff_sort(list, name_order));
816
817         p = ISC_LIST_HEAD(list->tuples);
818         while (p != NULL) {
819                 do {
820                         q = ISC_LIST_NEXT(p, link);
821                         if (q == NULL || ! dns_name_equal(&p->name, &q->name))
822                                 break;
823                         ISC_LIST_UNLINK(list->tuples, q, link);
824                         dns_difftuple_free(&q);
825                 } while (1);
826                 p = ISC_LIST_NEXT(p, link);
827         }
828  failure:
829         return (result);
830 }
831
832 static isc_result_t
833 is_active(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
834           isc_boolean_t *flag, isc_boolean_t *cut, isc_boolean_t *unsecure)
835 {
836         isc_result_t result;
837         dns_fixedname_t foundname;
838         dns_fixedname_init(&foundname);
839         result = dns_db_find(db, name, ver, dns_rdatatype_any,
840                              DNS_DBFIND_GLUEOK | DNS_DBFIND_NOWILD,
841                              (isc_stdtime_t) 0, NULL,
842                              dns_fixedname_name(&foundname),
843                              NULL, NULL);
844         if (result == ISC_R_SUCCESS || result == DNS_R_EMPTYNAME) {
845                 *flag = ISC_TRUE;
846                 *cut = ISC_FALSE;
847                 if (unsecure != NULL)
848                         *unsecure = ISC_FALSE;
849                 return (ISC_R_SUCCESS);
850         } else if (result == DNS_R_ZONECUT) {
851                 *flag = ISC_TRUE;
852                 *cut = ISC_TRUE;
853                 if (unsecure != NULL) {
854                         /*
855                          * We are at the zonecut.  Check to see if there
856                          * is a DS RRset.
857                          */
858                         if (dns_db_find(db, name, ver, dns_rdatatype_ds, 0,
859                                         (isc_stdtime_t) 0, NULL,
860                                         dns_fixedname_name(&foundname),
861                                         NULL, NULL) == DNS_R_NXRRSET)
862                                 *unsecure = ISC_TRUE;
863                         else
864                                 *unsecure = ISC_FALSE;
865                 }
866                 return (ISC_R_SUCCESS);
867         } else if (result == DNS_R_GLUE || result == DNS_R_DNAME ||
868                    result == DNS_R_DELEGATION || result == DNS_R_NXDOMAIN) {
869                 *flag = ISC_FALSE;
870                 *cut = ISC_FALSE;
871                 if (unsecure != NULL)
872                         *unsecure = ISC_FALSE;
873                 return (ISC_R_SUCCESS);
874         } else {
875                 /*
876                  * Silence compiler.
877                  */
878                 *flag = ISC_FALSE;
879                 *cut = ISC_FALSE;
880                 if (unsecure != NULL)
881                         *unsecure = ISC_FALSE;
882                 return (result);
883         }
884 }
885
886 /*%
887  * Find the next/previous name that has a NSEC record.
888  * In other words, skip empty database nodes and names that
889  * have had their NSECs removed because they are obscured by
890  * a zone cut.
891  */
892 static isc_result_t
893 next_active(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
894             dns_dbversion_t *ver, dns_name_t *oldname, dns_name_t *newname,
895             isc_boolean_t forward)
896 {
897         isc_result_t result;
898         dns_dbiterator_t *dbit = NULL;
899         isc_boolean_t has_nsec = ISC_FALSE;
900         unsigned int wraps = 0;
901         isc_boolean_t secure = dns_db_issecure(db);
902
903         CHECK(dns_db_createiterator(db, 0, &dbit));
904
905         CHECK(dns_dbiterator_seek(dbit, oldname));
906         do {
907                 dns_dbnode_t *node = NULL;
908
909                 if (forward)
910                         result = dns_dbiterator_next(dbit);
911                 else
912                         result = dns_dbiterator_prev(dbit);
913                 if (result == ISC_R_NOMORE) {
914                         /*
915                          * Wrap around.
916                          */
917                         if (forward)
918                                 CHECK(dns_dbiterator_first(dbit));
919                         else
920                                 CHECK(dns_dbiterator_last(dbit));
921                         wraps++;
922                         if (wraps == 2) {
923                                 update_log(log, zone, ISC_LOG_ERROR,
924                                            "secure zone with no NSECs");
925                                 result = DNS_R_BADZONE;
926                                 goto failure;
927                         }
928                 }
929                 CHECK(dns_dbiterator_current(dbit, &node, newname));
930                 dns_db_detachnode(db, &node);
931
932                 /*
933                  * The iterator may hold the tree lock, and
934                  * rrset_exists() calls dns_db_findnode() which
935                  * may try to reacquire it.  To avoid deadlock
936                  * we must pause the iterator first.
937                  */
938                 CHECK(dns_dbiterator_pause(dbit));
939                 if (secure) {
940                         CHECK(rrset_exists(db, ver, newname,
941                                            dns_rdatatype_nsec, 0, &has_nsec));
942                 } else {
943                         dns_fixedname_t ffound;
944                         dns_name_t *found;
945                         dns_fixedname_init(&ffound);
946                         found = dns_fixedname_name(&ffound);
947                         result = dns_db_find(db, newname, ver,
948                                              dns_rdatatype_soa,
949                                              DNS_DBFIND_NOWILD, 0, NULL, found,
950                                              NULL, NULL);
951                         if (result == ISC_R_SUCCESS ||
952                             result == DNS_R_EMPTYNAME ||
953                             result == DNS_R_NXRRSET ||
954                             result == DNS_R_CNAME ||
955                             (result == DNS_R_DELEGATION &&
956                              dns_name_equal(newname, found))) {
957                                 has_nsec = ISC_TRUE;
958                                 result = ISC_R_SUCCESS;
959                         } else if (result != DNS_R_NXDOMAIN)
960                                 break;
961                 }
962         } while (! has_nsec);
963  failure:
964         if (dbit != NULL)
965                 dns_dbiterator_destroy(&dbit);
966
967         return (result);
968 }
969
970 /*%
971  * Add a NSEC record for "name", recording the change in "diff".
972  * The existing NSEC is removed.
973  */
974 static isc_result_t
975 add_nsec(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
976          dns_dbversion_t *ver, dns_name_t *name, dns_ttl_t nsecttl,
977          dns_diff_t *diff)
978 {
979         isc_result_t result;
980         dns_dbnode_t *node = NULL;
981         unsigned char buffer[DNS_NSEC_BUFFERSIZE];
982         dns_rdata_t rdata = DNS_RDATA_INIT;
983         dns_difftuple_t *tuple = NULL;
984         dns_fixedname_t fixedname;
985         dns_name_t *target;
986
987         dns_fixedname_init(&fixedname);
988         target = dns_fixedname_name(&fixedname);
989
990         /*
991          * Find the successor name, aka NSEC target.
992          */
993         CHECK(next_active(log, zone, db, ver, name, target, ISC_TRUE));
994
995         /*
996          * Create the NSEC RDATA.
997          */
998         CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
999         dns_rdata_init(&rdata);
1000         CHECK(dns_nsec_buildrdata(db, ver, node, target, buffer, &rdata));
1001         dns_db_detachnode(db, &node);
1002
1003         /*
1004          * Delete the old NSEC and record the change.
1005          */
1006         CHECK(delete_if(true_p, db, ver, name, dns_rdatatype_nsec, 0,
1007                         NULL, diff));
1008         /*
1009          * Add the new NSEC and record the change.
1010          */
1011         CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, name,
1012                                    nsecttl, &rdata, &tuple));
1013         CHECK(do_one_tuple(&tuple, db, ver, diff));
1014         INSIST(tuple == NULL);
1015
1016  failure:
1017         if (node != NULL)
1018                 dns_db_detachnode(db, &node);
1019         return (result);
1020 }
1021
1022 /*%
1023  * Add a placeholder NSEC record for "name", recording the change in "diff".
1024  */
1025 static isc_result_t
1026 add_placeholder_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
1027                      dns_diff_t *diff)
1028 {
1029         isc_result_t result;
1030         dns_difftuple_t *tuple = NULL;
1031         isc_region_t r;
1032         unsigned char data[1] = { 0 }; /* The root domain, no bits. */
1033         dns_rdata_t rdata = DNS_RDATA_INIT;
1034
1035         r.base = data;
1036         r.length = sizeof(data);
1037         dns_rdata_fromregion(&rdata, dns_db_class(db), dns_rdatatype_nsec, &r);
1038         CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, name, 0,
1039                                    &rdata, &tuple));
1040         CHECK(do_one_tuple(&tuple, db, ver, diff));
1041  failure:
1042         return (result);
1043 }
1044
1045 static isc_result_t
1046 find_zone_keys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
1047                isc_mem_t *mctx, unsigned int maxkeys,
1048                dst_key_t **keys, unsigned int *nkeys)
1049 {
1050         isc_result_t result;
1051         dns_dbnode_t *node = NULL;
1052         const char *directory = dns_zone_getkeydirectory(zone);
1053         CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node));
1054         CHECK(dns_dnssec_findzonekeys2(db, ver, node, dns_db_origin(db),
1055                                        directory, mctx, maxkeys, keys, nkeys));
1056  failure:
1057         if (node != NULL)
1058                 dns_db_detachnode(db, &node);
1059         return (result);
1060 }
1061
1062 /*%
1063  * Add RRSIG records for an RRset, recording the change in "diff".
1064  */
1065 static isc_result_t
1066 add_sigs(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
1067          dns_dbversion_t *ver, dns_name_t *name, dns_rdatatype_t type,
1068          dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys,
1069          isc_stdtime_t inception, isc_stdtime_t expire,
1070          isc_boolean_t check_ksk, isc_boolean_t keyset_kskonly)
1071 {
1072         isc_result_t result;
1073         dns_dbnode_t *node = NULL;
1074         dns_rdataset_t rdataset;
1075         dns_rdata_t sig_rdata = DNS_RDATA_INIT;
1076         isc_buffer_t buffer;
1077         unsigned char data[1024]; /* XXX */
1078         unsigned int i, j;
1079         isc_boolean_t added_sig = ISC_FALSE;
1080         isc_mem_t *mctx = diff->mctx;
1081
1082         dns_rdataset_init(&rdataset);
1083         isc_buffer_init(&buffer, data, sizeof(data));
1084
1085         /* Get the rdataset to sign. */
1086         if (type == dns_rdatatype_nsec3)
1087                 CHECK(dns_db_findnsec3node(db, name, ISC_FALSE, &node));
1088         else
1089                 CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
1090         CHECK(dns_db_findrdataset(db, node, ver, type, 0,
1091                                   (isc_stdtime_t) 0, &rdataset, NULL));
1092         dns_db_detachnode(db, &node);
1093
1094 #define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
1095 #define KSK(x) ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
1096 #define ALG(x) dst_key_alg(x)
1097
1098         /*
1099          * If we are honoring KSK flags then we need to check that we
1100          * have both KSK and non-KSK keys that are not revoked per
1101          * algorithm.
1102          */
1103         for (i = 0; i < nkeys; i++) {
1104                 isc_boolean_t both = ISC_FALSE;
1105
1106                 if (!dst_key_isprivate(keys[i]))
1107                         continue;
1108
1109                 if (check_ksk && !REVOKE(keys[i])) {
1110                         isc_boolean_t have_ksk, have_nonksk;
1111                         if (KSK(keys[i])) {
1112                                 have_ksk = ISC_TRUE;
1113                                 have_nonksk = ISC_FALSE;
1114                         } else {
1115                                 have_ksk = ISC_FALSE;
1116                                 have_nonksk = ISC_TRUE;
1117                         }
1118                         for (j = 0; j < nkeys; j++) {
1119                                 if (j == i || ALG(keys[i]) != ALG(keys[j]))
1120                                         continue;
1121                                 if (REVOKE(keys[j]))
1122                                         continue;
1123                                 if (KSK(keys[j]))
1124                                         have_ksk = ISC_TRUE;
1125                                 else
1126                                         have_nonksk = ISC_TRUE;
1127                                 both = have_ksk && have_nonksk;
1128                                 if (both)
1129                                         break;
1130                         }
1131                 }
1132
1133                 if (both) {
1134                         if (type == dns_rdatatype_dnskey) {
1135                                 if (!KSK(keys[i]) && keyset_kskonly)
1136                                         continue;
1137                         } else if (KSK(keys[i]))
1138                                 continue;
1139                 } else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey)
1140                         continue;
1141
1142                 /* Calculate the signature, creating a RRSIG RDATA. */
1143                 CHECK(dns_dnssec_sign(name, &rdataset, keys[i],
1144                                       &inception, &expire,
1145                                       mctx, &buffer, &sig_rdata));
1146
1147                 /* Update the database and journal with the RRSIG. */
1148                 /* XXX inefficient - will cause dataset merging */
1149                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN, name,
1150                                     rdataset.ttl, &sig_rdata));
1151                 dns_rdata_reset(&sig_rdata);
1152                 isc_buffer_init(&buffer, data, sizeof(data));
1153                 added_sig = ISC_TRUE;
1154         }
1155         if (!added_sig) {
1156                 update_log(log, zone, ISC_LOG_ERROR,
1157                            "found no active private keys, "
1158                            "unable to generate any signatures");
1159                 result = ISC_R_NOTFOUND;
1160         }
1161
1162  failure:
1163         if (dns_rdataset_isassociated(&rdataset))
1164                 dns_rdataset_disassociate(&rdataset);
1165         if (node != NULL)
1166                 dns_db_detachnode(db, &node);
1167         return (result);
1168 }
1169
1170 /*
1171  * Delete expired RRsigs and any RRsigs we are about to re-sign.
1172  * See also zone.c:del_sigs().
1173  */
1174 static isc_result_t
1175 del_keysigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
1176             dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys)
1177 {
1178         isc_result_t result;
1179         dns_dbnode_t *node = NULL;
1180         dns_rdataset_t rdataset;
1181         dns_rdata_t rdata = DNS_RDATA_INIT;
1182         unsigned int i;
1183         dns_rdata_rrsig_t rrsig;
1184         isc_boolean_t found;
1185
1186         dns_rdataset_init(&rdataset);
1187
1188         result = dns_db_findnode(db, name, ISC_FALSE, &node);
1189         if (result == ISC_R_NOTFOUND)
1190                 return (ISC_R_SUCCESS);
1191         if (result != ISC_R_SUCCESS)
1192                 goto failure;
1193         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig,
1194                                      dns_rdatatype_dnskey, (isc_stdtime_t) 0,
1195                                      &rdataset, NULL);
1196         dns_db_detachnode(db, &node);
1197
1198         if (result == ISC_R_NOTFOUND)
1199                 return (ISC_R_SUCCESS);
1200         if (result != ISC_R_SUCCESS)
1201                 goto failure;
1202
1203         for (result = dns_rdataset_first(&rdataset);
1204              result == ISC_R_SUCCESS;
1205              result = dns_rdataset_next(&rdataset)) {
1206                 dns_rdataset_current(&rdataset, &rdata);
1207                 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
1208                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
1209                 found = ISC_FALSE;
1210                 for (i = 0; i < nkeys; i++) {
1211                         if (rrsig.keyid == dst_key_id(keys[i])) {
1212                                 found = ISC_TRUE;
1213                                 if (!dst_key_isprivate(keys[i]) &&
1214                                     !dst_key_inactive(keys[i]))
1215                                 {
1216                                         /*
1217                                          * The re-signing code in zone.c
1218                                          * will mark this as offline.
1219                                          * Just skip the record for now.
1220                                          */
1221                                         break;
1222                                 }
1223                                 result = update_one_rr(db, ver, diff,
1224                                                        DNS_DIFFOP_DEL, name,
1225                                                        rdataset.ttl, &rdata);
1226                                 break;
1227                         }
1228                 }
1229                 /*
1230                  * If there is not a matching DNSKEY then delete the RRSIG.
1231                  */
1232                 if (!found)
1233                         result = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
1234                                                name, rdataset.ttl, &rdata);
1235                 dns_rdata_reset(&rdata);
1236                 if (result != ISC_R_SUCCESS)
1237                         break;
1238         }
1239         dns_rdataset_disassociate(&rdataset);
1240         if (result == ISC_R_NOMORE)
1241                 result = ISC_R_SUCCESS;
1242 failure:
1243         if (node != NULL)
1244                 dns_db_detachnode(db, &node);
1245         return (result);
1246 }
1247
1248 static isc_result_t
1249 add_exposed_sigs(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
1250                  dns_dbversion_t *ver, dns_name_t *name, isc_boolean_t cut,
1251                  dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys,
1252                  isc_stdtime_t inception, isc_stdtime_t expire,
1253                  isc_boolean_t check_ksk, isc_boolean_t keyset_kskonly)
1254 {
1255         isc_result_t result;
1256         dns_dbnode_t *node;
1257         dns_rdatasetiter_t *iter;
1258
1259         node = NULL;
1260         result = dns_db_findnode(db, name, ISC_FALSE, &node);
1261         if (result == ISC_R_NOTFOUND)
1262                 return (ISC_R_SUCCESS);
1263         if (result != ISC_R_SUCCESS)
1264                 return (result);
1265
1266         iter = NULL;
1267         result = dns_db_allrdatasets(db, node, ver,
1268                                      (isc_stdtime_t) 0, &iter);
1269         if (result != ISC_R_SUCCESS)
1270                 goto cleanup_node;
1271
1272         for (result = dns_rdatasetiter_first(iter);
1273              result == ISC_R_SUCCESS;
1274              result = dns_rdatasetiter_next(iter))
1275         {
1276                 dns_rdataset_t rdataset;
1277                 dns_rdatatype_t type;
1278                 isc_boolean_t flag;
1279
1280                 dns_rdataset_init(&rdataset);
1281                 dns_rdatasetiter_current(iter, &rdataset);
1282                 type = rdataset.type;
1283                 dns_rdataset_disassociate(&rdataset);
1284
1285                 /*
1286                  * We don't need to sign unsigned NSEC records at the cut
1287                  * as they are handled elsewhere.
1288                  */
1289                 if ((type == dns_rdatatype_rrsig) ||
1290                     (cut && type != dns_rdatatype_ds))
1291                         continue;
1292                 result = rrset_exists(db, ver, name, dns_rdatatype_rrsig,
1293                                       type, &flag);
1294                 if (result != ISC_R_SUCCESS)
1295                         goto cleanup_iterator;
1296                 if (flag)
1297                         continue;;
1298                 result = add_sigs(log, zone, db, ver, name, type, diff,
1299                                           keys, nkeys, inception, expire,
1300                                           check_ksk, keyset_kskonly);
1301                 if (result != ISC_R_SUCCESS)
1302                         goto cleanup_iterator;
1303         }
1304         if (result == ISC_R_NOMORE)
1305                 result = ISC_R_SUCCESS;
1306
1307  cleanup_iterator:
1308         dns_rdatasetiter_destroy(&iter);
1309
1310  cleanup_node:
1311         dns_db_detachnode(db, &node);
1312
1313         return (result);
1314 }
1315
1316 /*%
1317  * Update RRSIG, NSEC and NSEC3 records affected by an update.  The original
1318  * update, including the SOA serial update but excluding the RRSIG & NSEC
1319  * changes, is in "diff" and has already been applied to "newver" of "db".
1320  * The database version prior to the update is "oldver".
1321  *
1322  * The necessary RRSIG, NSEC and NSEC3 changes will be applied to "newver"
1323  * and added (as a minimal diff) to "diff".
1324  *
1325  * The RRSIGs generated will be valid for 'sigvalidityinterval' seconds.
1326  */
1327 isc_result_t
1328 dns_update_signatures(dns_update_log_t *log, dns_zone_t *zone, dns_db_t *db,
1329                       dns_dbversion_t *oldver, dns_dbversion_t *newver,
1330                       dns_diff_t *diff, isc_uint32_t sigvalidityinterval)
1331 {
1332         isc_result_t result;
1333         dns_difftuple_t *t;
1334         dns_diff_t diffnames;
1335         dns_diff_t affected;
1336         dns_diff_t sig_diff;
1337         dns_diff_t nsec_diff;
1338         dns_diff_t nsec_mindiff;
1339         isc_boolean_t flag, build_nsec, build_nsec3;
1340         dst_key_t *zone_keys[DNS_MAXZONEKEYS];
1341         unsigned int nkeys = 0;
1342         unsigned int i;
1343         isc_stdtime_t now, inception, expire;
1344         dns_ttl_t nsecttl;
1345         dns_rdata_soa_t soa;
1346         dns_rdata_t rdata = DNS_RDATA_INIT;
1347         dns_rdataset_t rdataset;
1348         dns_dbnode_t *node = NULL;
1349         isc_boolean_t check_ksk, keyset_kskonly;
1350         isc_boolean_t unsecure;
1351         isc_boolean_t cut;
1352         dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
1353
1354         dns_diff_init(diff->mctx, &diffnames);
1355         dns_diff_init(diff->mctx, &affected);
1356
1357         dns_diff_init(diff->mctx, &sig_diff);
1358         dns_diff_init(diff->mctx, &nsec_diff);
1359         dns_diff_init(diff->mctx, &nsec_mindiff);
1360
1361         result = find_zone_keys(zone, db, newver, diff->mctx,
1362                                 DNS_MAXZONEKEYS, zone_keys, &nkeys);
1363         if (result != ISC_R_SUCCESS) {
1364                 update_log(log, zone, ISC_LOG_ERROR,
1365                            "could not get zone keys for secure dynamic update");
1366                 goto failure;
1367         }
1368
1369         isc_stdtime_get(&now);
1370         inception = now - 3600; /* Allow for some clock skew. */
1371         expire = now + sigvalidityinterval;
1372
1373         /*
1374          * Do we look at the KSK flag on the DNSKEY to determining which
1375          * keys sign which RRsets?  First check the zone option then
1376          * check the keys flags to make sure at least one has a ksk set
1377          * and one doesn't.
1378          */
1379         check_ksk = ISC_TF((dns_zone_getoptions(zone) &
1380                             DNS_ZONEOPT_UPDATECHECKKSK) != 0);
1381         keyset_kskonly = ISC_TF((dns_zone_getoptions(zone) &
1382                                 DNS_ZONEOPT_DNSKEYKSKONLY) != 0);
1383
1384         /*
1385          * Get the NSEC/NSEC3 TTL from the SOA MINIMUM field.
1386          */
1387         CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node));
1388         dns_rdataset_init(&rdataset);
1389         CHECK(dns_db_findrdataset(db, node, newver, dns_rdatatype_soa, 0,
1390                                   (isc_stdtime_t) 0, &rdataset, NULL));
1391         CHECK(dns_rdataset_first(&rdataset));
1392         dns_rdataset_current(&rdataset, &rdata);
1393         CHECK(dns_rdata_tostruct(&rdata, &soa, NULL));
1394         nsecttl = soa.minimum;
1395         dns_rdataset_disassociate(&rdataset);
1396         dns_db_detachnode(db, &node);
1397
1398         /*
1399          * Find all RRsets directly affected by the update, and
1400          * update their RRSIGs.  Also build a list of names affected
1401          * by the update in "diffnames".
1402          */
1403         CHECK(dns_diff_sort(diff, temp_order));
1404
1405         t = ISC_LIST_HEAD(diff->tuples);
1406         while (t != NULL) {
1407                 dns_name_t *name = &t->name;
1408                 /* Now "name" is a new, unique name affected by the update. */
1409
1410                 CHECK(namelist_append_name(&diffnames, name));
1411
1412                 while (t != NULL && dns_name_equal(&t->name, name)) {
1413                         dns_rdatatype_t type;
1414                         type = t->rdata.type;
1415
1416                         /*
1417                          * Now "name" and "type" denote a new unique RRset
1418                          * affected by the update.
1419                          */
1420
1421                         /* Don't sign RRSIGs. */
1422                         if (type == dns_rdatatype_rrsig)
1423                                 goto skip;
1424
1425                         /*
1426                          * Delete all old RRSIGs covering this type, since they
1427                          * are all invalid when the signed RRset has changed.
1428                          * We may not be able to recreate all of them - tough.
1429                          * Special case changes to the zone's DNSKEY records
1430                          * to support offline KSKs.
1431                          */
1432                         if (type == dns_rdatatype_dnskey)
1433                                 del_keysigs(db, newver, name, &sig_diff,
1434                                             zone_keys, nkeys);
1435                         else
1436                                 CHECK(delete_if(true_p, db, newver, name,
1437                                                 dns_rdatatype_rrsig, type,
1438                                                 NULL, &sig_diff));
1439
1440                         /*
1441                          * If this RRset is still visible after the update,
1442                          * add a new signature for it.
1443                          */
1444                         CHECK(rrset_visible(db, newver, name, type, &flag));
1445                         if (flag) {
1446                                 CHECK(add_sigs(log, zone, db, newver, name,
1447                                                type, &sig_diff, zone_keys,
1448                                                nkeys, inception, expire,
1449                                                check_ksk, keyset_kskonly));
1450                         }
1451                 skip:
1452                         /* Skip any other updates to the same RRset. */
1453                         while (t != NULL &&
1454                                dns_name_equal(&t->name, name) &&
1455                                t->rdata.type == type)
1456                         {
1457                                 t = ISC_LIST_NEXT(t, link);
1458                         }
1459                 }
1460         }
1461         update_log(log, zone, ISC_LOG_DEBUG(3), "updated data signatures");
1462
1463         /* Remove orphaned NSECs and RRSIG NSECs. */
1464         for (t = ISC_LIST_HEAD(diffnames.tuples);
1465              t != NULL;
1466              t = ISC_LIST_NEXT(t, link))
1467         {
1468                 CHECK(non_nsec_rrset_exists(db, newver, &t->name, &flag));
1469                 if (! flag) {
1470                         CHECK(delete_if(true_p, db, newver, &t->name,
1471                                         dns_rdatatype_any, 0,
1472                                         NULL, &sig_diff));
1473                 }
1474         }
1475         update_log(log, zone, ISC_LOG_DEBUG(3),
1476                    "removed any orphaned NSEC records");
1477
1478         /*
1479          * See if we need to build NSEC or NSEC3 chains.
1480          */
1481         CHECK(dns_private_chains(db, newver, privatetype, &build_nsec,
1482                                  &build_nsec3));
1483         if (!build_nsec)
1484                 goto update_nsec3;
1485
1486         update_log(log, zone, ISC_LOG_DEBUG(3), "rebuilding NSEC chain");
1487
1488         /*
1489          * When a name is created or deleted, its predecessor needs to
1490          * have its NSEC updated.
1491          */
1492         for (t = ISC_LIST_HEAD(diffnames.tuples);
1493              t != NULL;
1494              t = ISC_LIST_NEXT(t, link))
1495         {
1496                 isc_boolean_t existed, exists;
1497                 dns_fixedname_t fixedname;
1498                 dns_name_t *prevname;
1499
1500                 dns_fixedname_init(&fixedname);
1501                 prevname = dns_fixedname_name(&fixedname);
1502
1503                 if (oldver != NULL)
1504                         CHECK(name_exists(db, oldver, &t->name, &existed));
1505                 else
1506                         existed = ISC_FALSE;
1507                 CHECK(name_exists(db, newver, &t->name, &exists));
1508                 if (exists == existed)
1509                         continue;
1510
1511                 /*
1512                  * Find the predecessor.
1513                  * When names become obscured or unobscured in this update
1514                  * transaction, we may find the wrong predecessor because
1515                  * the NSECs have not yet been updated to reflect the delegation
1516                  * change.  This should not matter because in this case,
1517                  * the correct predecessor is either the delegation node or
1518                  * a newly unobscured node, and those nodes are on the
1519                  * "affected" list in any case.
1520                  */
1521                 CHECK(next_active(log, zone, db, newver,
1522                                   &t->name, prevname, ISC_FALSE));
1523                 CHECK(namelist_append_name(&affected, prevname));
1524         }
1525
1526         /*
1527          * Find names potentially affected by delegation changes
1528          * (obscured by adding an NS or DNAME, or unobscured by
1529          * removing one).
1530          */
1531         for (t = ISC_LIST_HEAD(diffnames.tuples);
1532              t != NULL;
1533              t = ISC_LIST_NEXT(t, link))
1534         {
1535                 isc_boolean_t ns_existed, dname_existed;
1536                 isc_boolean_t ns_exists, dname_exists;
1537
1538                 if (oldver != NULL)
1539                         CHECK(rrset_exists(db, oldver, &t->name,
1540                                           dns_rdatatype_ns, 0, &ns_existed));
1541                 else
1542                         ns_existed = ISC_FALSE;
1543                 if (oldver != NULL)
1544                         CHECK(rrset_exists(db, oldver, &t->name,
1545                                            dns_rdatatype_dname, 0,
1546                                            &dname_existed));
1547                 else
1548                         dname_existed = ISC_FALSE;
1549                 CHECK(rrset_exists(db, newver, &t->name, dns_rdatatype_ns, 0,
1550                                    &ns_exists));
1551                 CHECK(rrset_exists(db, newver, &t->name, dns_rdatatype_dname, 0,
1552                                    &dname_exists));
1553                 if ((ns_exists || dname_exists) == (ns_existed || dname_existed))
1554                         continue;
1555                 /*
1556                  * There was a delegation change.  Mark all subdomains
1557                  * of t->name as potentially needing a NSEC update.
1558                  */
1559                 CHECK(namelist_append_subdomain(db, &t->name, &affected));
1560         }
1561
1562         ISC_LIST_APPENDLIST(affected.tuples, diffnames.tuples, link);
1563         INSIST(ISC_LIST_EMPTY(diffnames.tuples));
1564
1565         CHECK(uniqify_name_list(&affected));
1566
1567         /*
1568          * Determine which names should have NSECs, and delete/create
1569          * NSECs to make it so.  We don't know the final NSEC targets yet,
1570          * so we just create placeholder NSECs with arbitrary contents
1571          * to indicate that their respective owner names should be part of
1572          * the NSEC chain.
1573          */
1574         for (t = ISC_LIST_HEAD(affected.tuples);
1575              t != NULL;
1576              t = ISC_LIST_NEXT(t, link))
1577         {
1578                 isc_boolean_t exists;
1579                 dns_name_t *name = &t->name;
1580
1581                 CHECK(name_exists(db, newver, name, &exists));
1582                 if (! exists)
1583                         continue;
1584                 CHECK(is_active(db, newver, name, &flag, &cut, NULL));
1585                 if (!flag) {
1586                         /*
1587                          * This name is obscured.  Delete any
1588                          * existing NSEC record.
1589                          */
1590                         CHECK(delete_if(true_p, db, newver, name,
1591                                         dns_rdatatype_nsec, 0,
1592                                         NULL, &nsec_diff));
1593                         CHECK(delete_if(rrsig_p, db, newver, name,
1594                                         dns_rdatatype_any, 0, NULL, diff));
1595                 } else {
1596                         /*
1597                          * This name is not obscured.  It needs to have a
1598                          * NSEC unless it is the at the origin, in which
1599                          * case it should already exist if there is a complete
1600                          * NSEC chain and if there isn't a complete NSEC chain
1601                          * we don't want to add one as that would signal that
1602                          * there is a complete NSEC chain.
1603                          */
1604                         if (!dns_name_equal(name, dns_db_origin(db))) {
1605                                 CHECK(rrset_exists(db, newver, name,
1606                                                    dns_rdatatype_nsec, 0,
1607                                                    &flag));
1608                                 if (!flag)
1609                                         CHECK(add_placeholder_nsec(db, newver,
1610                                                                    name, diff));
1611                         }
1612                         CHECK(add_exposed_sigs(log, zone, db, newver, name,
1613                                                cut, &sig_diff, zone_keys, nkeys,
1614                                                inception, expire, check_ksk,
1615                                                keyset_kskonly));
1616                 }
1617         }
1618
1619         /*
1620          * Now we know which names are part of the NSEC chain.
1621          * Make them all point at their correct targets.
1622          */
1623         for (t = ISC_LIST_HEAD(affected.tuples);
1624              t != NULL;
1625              t = ISC_LIST_NEXT(t, link))
1626         {
1627                 CHECK(rrset_exists(db, newver, &t->name,
1628                                    dns_rdatatype_nsec, 0, &flag));
1629                 if (flag) {
1630                         /*
1631                          * There is a NSEC, but we don't know if it is correct.
1632                          * Delete it and create a correct one to be sure.
1633                          * If the update was unnecessary, the diff minimization
1634                          * will take care of eliminating it from the journal,
1635                          * IXFRs, etc.
1636                          *
1637                          * The RRSIG bit should always be set in the NSECs
1638                          * we generate, because they will all get RRSIG NSECs.
1639                          * (XXX what if the zone keys are missing?).
1640                          * Because the RRSIG NSECs have not necessarily been
1641                          * created yet, the correctness of the bit mask relies
1642                          * on the assumption that NSECs are only created if
1643                          * there is other data, and if there is other data,
1644                          * there are other RRSIGs.
1645                          */
1646                         CHECK(add_nsec(log, zone, db, newver, &t->name,
1647                                        nsecttl, &nsec_diff));
1648                 }
1649         }
1650
1651         /*
1652          * Minimize the set of NSEC updates so that we don't
1653          * have to regenerate the RRSIG NSECs for NSECs that were
1654          * replaced with identical ones.
1655          */
1656         while ((t = ISC_LIST_HEAD(nsec_diff.tuples)) != NULL) {
1657                 ISC_LIST_UNLINK(nsec_diff.tuples, t, link);
1658                 dns_diff_appendminimal(&nsec_mindiff, &t);
1659         }
1660
1661         update_log(log, zone, ISC_LOG_DEBUG(3), "signing rebuilt NSEC chain");
1662
1663         /* Update RRSIG NSECs. */
1664         for (t = ISC_LIST_HEAD(nsec_mindiff.tuples);
1665              t != NULL;
1666              t = ISC_LIST_NEXT(t, link))
1667         {
1668                 if (t->op == DNS_DIFFOP_DEL) {
1669                         CHECK(delete_if(true_p, db, newver, &t->name,
1670                                         dns_rdatatype_rrsig, dns_rdatatype_nsec,
1671                                         NULL, &sig_diff));
1672                 } else if (t->op == DNS_DIFFOP_ADD) {
1673                         CHECK(add_sigs(log, zone, db, newver, &t->name,
1674                                        dns_rdatatype_nsec, &sig_diff,
1675                                        zone_keys, nkeys, inception, expire,
1676                                        check_ksk, keyset_kskonly));
1677                 } else {
1678                         INSIST(0);
1679                 }
1680         }
1681
1682  update_nsec3:
1683
1684         /* Record our changes for the journal. */
1685         while ((t = ISC_LIST_HEAD(sig_diff.tuples)) != NULL) {
1686                 ISC_LIST_UNLINK(sig_diff.tuples, t, link);
1687                 dns_diff_appendminimal(diff, &t);
1688         }
1689         while ((t = ISC_LIST_HEAD(nsec_mindiff.tuples)) != NULL) {
1690                 ISC_LIST_UNLINK(nsec_mindiff.tuples, t, link);
1691                 dns_diff_appendminimal(diff, &t);
1692         }
1693
1694         INSIST(ISC_LIST_EMPTY(sig_diff.tuples));
1695         INSIST(ISC_LIST_EMPTY(nsec_diff.tuples));
1696         INSIST(ISC_LIST_EMPTY(nsec_mindiff.tuples));
1697
1698         if (!build_nsec3) {
1699                 update_log(log, zone, ISC_LOG_DEBUG(3),
1700                            "no NSEC3 chains to rebuild");
1701                 goto failure;
1702         }
1703
1704         update_log(log, zone, ISC_LOG_DEBUG(3), "rebuilding NSEC3 chains");
1705
1706         dns_diff_clear(&diffnames);
1707         dns_diff_clear(&affected);
1708
1709         CHECK(dns_diff_sort(diff, temp_order));
1710
1711         /*
1712          * Find names potentially affected by delegation changes
1713          * (obscured by adding an NS or DNAME, or unobscured by
1714          * removing one).
1715          */
1716         t = ISC_LIST_HEAD(diff->tuples);
1717         while (t != NULL) {
1718                 dns_name_t *name = &t->name;
1719
1720                 isc_boolean_t ns_existed, dname_existed;
1721                 isc_boolean_t ns_exists, dname_exists;
1722                 isc_boolean_t exists, existed;
1723
1724                 if (t->rdata.type == dns_rdatatype_nsec ||
1725                     t->rdata.type == dns_rdatatype_rrsig) {
1726                         t = ISC_LIST_NEXT(t, link);
1727                         continue;
1728                 }
1729
1730                 CHECK(namelist_append_name(&affected, name));
1731
1732                 if (oldver != NULL)
1733                         CHECK(rrset_exists(db, oldver, name, dns_rdatatype_ns,
1734                                            0, &ns_existed));
1735                 else
1736                         ns_existed = ISC_FALSE;
1737                 if (oldver != NULL)
1738                         CHECK(rrset_exists(db, oldver, name,
1739                                            dns_rdatatype_dname, 0,
1740                                            &dname_existed));
1741                 else
1742                         dname_existed = ISC_FALSE;
1743                 CHECK(rrset_exists(db, newver, name, dns_rdatatype_ns, 0,
1744                                    &ns_exists));
1745                 CHECK(rrset_exists(db, newver, name, dns_rdatatype_dname, 0,
1746                                    &dname_exists));
1747
1748                 exists = ns_exists || dname_exists;
1749                 existed = ns_existed || dname_existed;
1750                 if (exists == existed)
1751                         goto nextname;
1752                 /*
1753                  * There was a delegation change.  Mark all subdomains
1754                  * of t->name as potentially needing a NSEC3 update.
1755                  */
1756                 CHECK(namelist_append_subdomain(db, name, &affected));
1757
1758         nextname:
1759                 while (t != NULL && dns_name_equal(&t->name, name))
1760                         t = ISC_LIST_NEXT(t, link);
1761         }
1762
1763         for (t = ISC_LIST_HEAD(affected.tuples);
1764              t != NULL;
1765              t = ISC_LIST_NEXT(t, link)) {
1766                 dns_name_t *name = &t->name;
1767
1768                 unsecure = ISC_FALSE;   /* Silence compiler warning. */
1769                 CHECK(is_active(db, newver, name, &flag, &cut, &unsecure));
1770
1771                 if (!flag) {
1772                         CHECK(delete_if(rrsig_p, db, newver, name,
1773                                         dns_rdatatype_any, 0, NULL, diff));
1774                         CHECK(dns_nsec3_delnsec3sx(db, newver, name,
1775                                                    privatetype, &nsec_diff));
1776                 } else {
1777                         CHECK(add_exposed_sigs(log, zone, db, newver, name,
1778                                                cut, &sig_diff, zone_keys, nkeys,
1779                                                inception, expire, check_ksk,
1780                                                keyset_kskonly));
1781                         CHECK(dns_nsec3_addnsec3sx(db, newver, name, nsecttl,
1782                                                    unsecure, privatetype,
1783                                                    &nsec_diff));
1784                 }
1785         }
1786
1787         /*
1788          * Minimize the set of NSEC3 updates so that we don't
1789          * have to regenerate the RRSIG NSEC3s for NSEC3s that were
1790          * replaced with identical ones.
1791          */
1792         while ((t = ISC_LIST_HEAD(nsec_diff.tuples)) != NULL) {
1793                 ISC_LIST_UNLINK(nsec_diff.tuples, t, link);
1794                 dns_diff_appendminimal(&nsec_mindiff, &t);
1795         }
1796
1797         update_log(log, zone, ISC_LOG_DEBUG(3),
1798                    "signing rebuilt NSEC3 chain");
1799
1800         /* Update RRSIG NSEC3s. */
1801         for (t = ISC_LIST_HEAD(nsec_mindiff.tuples);
1802              t != NULL;
1803              t = ISC_LIST_NEXT(t, link))
1804         {
1805                 if (t->op == DNS_DIFFOP_DEL) {
1806                         CHECK(delete_if(true_p, db, newver, &t->name,
1807                                         dns_rdatatype_rrsig,
1808                                         dns_rdatatype_nsec3,
1809                                         NULL, &sig_diff));
1810                 } else if (t->op == DNS_DIFFOP_ADD) {
1811                         CHECK(add_sigs(log, zone, db, newver, &t->name,
1812                                        dns_rdatatype_nsec3,
1813                                        &sig_diff, zone_keys, nkeys,
1814                                        inception, expire, check_ksk,
1815                                        keyset_kskonly));
1816                 } else {
1817                         INSIST(0);
1818                 }
1819         }
1820
1821         /* Record our changes for the journal. */
1822         while ((t = ISC_LIST_HEAD(sig_diff.tuples)) != NULL) {
1823                 ISC_LIST_UNLINK(sig_diff.tuples, t, link);
1824                 dns_diff_appendminimal(diff, &t);
1825         }
1826         while ((t = ISC_LIST_HEAD(nsec_mindiff.tuples)) != NULL) {
1827                 ISC_LIST_UNLINK(nsec_mindiff.tuples, t, link);
1828                 dns_diff_appendminimal(diff, &t);
1829         }
1830
1831         INSIST(ISC_LIST_EMPTY(sig_diff.tuples));
1832         INSIST(ISC_LIST_EMPTY(nsec_diff.tuples));
1833         INSIST(ISC_LIST_EMPTY(nsec_mindiff.tuples));
1834
1835  failure:
1836         dns_diff_clear(&sig_diff);
1837         dns_diff_clear(&nsec_diff);
1838         dns_diff_clear(&nsec_mindiff);
1839
1840         dns_diff_clear(&affected);
1841         dns_diff_clear(&diffnames);
1842
1843         for (i = 0; i < nkeys; i++)
1844                 dst_key_free(&zone_keys[i]);
1845
1846         return (result);
1847 }
1848
1849 isc_uint32_t
1850 dns_update_soaserial(isc_uint32_t serial, dns_updatemethod_t method) {
1851         isc_stdtime_t now;
1852
1853         if (method == dns_updatemethod_unixtime) {
1854                 isc_stdtime_get(&now);
1855                 if (now != 0 && isc_serial_gt(now, serial))
1856                         return (now);
1857         }
1858
1859         /* RFC1982 */
1860         serial = (serial + 1) & 0xFFFFFFFF;
1861         if (serial == 0)
1862                 serial = 1;
1863
1864         return (serial);
1865 }