update.c revision 204619
1/* 2 * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 1999-2003 Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 * PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18/* $Id: update.c,v 1.151.12.9 2009/12/30 04:02:56 marka Exp $ */ 19 20#include <config.h> 21 22#include <isc/netaddr.h> 23#include <isc/print.h> 24#include <isc/serial.h> 25#include <isc/stats.h> 26#include <isc/string.h> 27#include <isc/taskpool.h> 28#include <isc/util.h> 29 30#include <dns/db.h> 31#include <dns/dbiterator.h> 32#include <dns/diff.h> 33#include <dns/dnssec.h> 34#include <dns/events.h> 35#include <dns/fixedname.h> 36#include <dns/journal.h> 37#include <dns/keyvalues.h> 38#include <dns/message.h> 39#include <dns/nsec.h> 40#include <dns/nsec3.h> 41#include <dns/rdataclass.h> 42#include <dns/rdataset.h> 43#include <dns/rdatasetiter.h> 44#include <dns/rdatastruct.h> 45#include <dns/rdatatype.h> 46#include <dns/soa.h> 47#include <dns/ssu.h> 48#include <dns/view.h> 49#include <dns/zone.h> 50#include <dns/zt.h> 51 52#include <named/client.h> 53#include <named/log.h> 54#include <named/server.h> 55#include <named/update.h> 56 57/*! \file 58 * \brief 59 * This module implements dynamic update as in RFC2136. 60 */ 61 62/* 63 * XXX TODO: 64 * - document strict minimality 65 */ 66 67/**************************************************************************/ 68 69/*% 70 * Log level for tracing dynamic update protocol requests. 71 */ 72#define LOGLEVEL_PROTOCOL ISC_LOG_INFO 73 74/*% 75 * Log level for low-level debug tracing. 76 */ 77#define LOGLEVEL_DEBUG ISC_LOG_DEBUG(8) 78 79/*% 80 * Check an operation for failure. These macros all assume that 81 * the function using them has a 'result' variable and a 'failure' 82 * label. 83 */ 84#define CHECK(op) \ 85 do { result = (op); \ 86 if (result != ISC_R_SUCCESS) goto failure; \ 87 } while (0) 88 89/*% 90 * Fail unconditionally with result 'code', which must not 91 * be ISC_R_SUCCESS. The reason for failure presumably has 92 * been logged already. 93 * 94 * The test against ISC_R_SUCCESS is there to keep the Solaris compiler 95 * from complaining about "end-of-loop code not reached". 96 */ 97 98#define FAIL(code) \ 99 do { \ 100 result = (code); \ 101 if (result != ISC_R_SUCCESS) goto failure; \ 102 } while (0) 103 104/*% 105 * Fail unconditionally and log as a client error. 106 * The test against ISC_R_SUCCESS is there to keep the Solaris compiler 107 * from complaining about "end-of-loop code not reached". 108 */ 109#define FAILC(code, msg) \ 110 do { \ 111 const char *_what = "failed"; \ 112 result = (code); \ 113 switch (result) { \ 114 case DNS_R_NXDOMAIN: \ 115 case DNS_R_YXDOMAIN: \ 116 case DNS_R_YXRRSET: \ 117 case DNS_R_NXRRSET: \ 118 _what = "unsuccessful"; \ 119 } \ 120 update_log(client, zone, LOGLEVEL_PROTOCOL, \ 121 "update %s: %s (%s)", _what, \ 122 msg, isc_result_totext(result)); \ 123 if (result != ISC_R_SUCCESS) goto failure; \ 124 } while (0) 125#define PREREQFAILC(code, msg) \ 126 do { \ 127 inc_stats(zone, dns_nsstatscounter_updatebadprereq); \ 128 FAILC(code, msg); \ 129 } while (0) 130 131#define FAILN(code, name, msg) \ 132 do { \ 133 const char *_what = "failed"; \ 134 result = (code); \ 135 switch (result) { \ 136 case DNS_R_NXDOMAIN: \ 137 case DNS_R_YXDOMAIN: \ 138 case DNS_R_YXRRSET: \ 139 case DNS_R_NXRRSET: \ 140 _what = "unsuccessful"; \ 141 } \ 142 if (isc_log_wouldlog(ns_g_lctx, LOGLEVEL_PROTOCOL)) { \ 143 char _nbuf[DNS_NAME_FORMATSIZE]; \ 144 dns_name_format(name, _nbuf, sizeof(_nbuf)); \ 145 update_log(client, zone, LOGLEVEL_PROTOCOL, \ 146 "update %s: %s: %s (%s)", _what, _nbuf, \ 147 msg, isc_result_totext(result)); \ 148 } \ 149 if (result != ISC_R_SUCCESS) goto failure; \ 150 } while (0) 151#define PREREQFAILN(code, name, msg) \ 152 do { \ 153 inc_stats(zone, dns_nsstatscounter_updatebadprereq); \ 154 FAILN(code, name, msg); \ 155 } while (0) 156 157#define FAILNT(code, name, type, msg) \ 158 do { \ 159 const char *_what = "failed"; \ 160 result = (code); \ 161 switch (result) { \ 162 case DNS_R_NXDOMAIN: \ 163 case DNS_R_YXDOMAIN: \ 164 case DNS_R_YXRRSET: \ 165 case DNS_R_NXRRSET: \ 166 _what = "unsuccessful"; \ 167 } \ 168 if (isc_log_wouldlog(ns_g_lctx, LOGLEVEL_PROTOCOL)) { \ 169 char _nbuf[DNS_NAME_FORMATSIZE]; \ 170 char _tbuf[DNS_RDATATYPE_FORMATSIZE]; \ 171 dns_name_format(name, _nbuf, sizeof(_nbuf)); \ 172 dns_rdatatype_format(type, _tbuf, sizeof(_tbuf)); \ 173 update_log(client, zone, LOGLEVEL_PROTOCOL, \ 174 "update %s: %s/%s: %s (%s)", \ 175 _what, _nbuf, _tbuf, msg, \ 176 isc_result_totext(result)); \ 177 } \ 178 if (result != ISC_R_SUCCESS) goto failure; \ 179 } while (0) 180#define PREREQFAILNT(code, name, type, msg) \ 181 do { \ 182 inc_stats(zone, dns_nsstatscounter_updatebadprereq); \ 183 FAILNT(code, name, type, msg); \ 184 } while (0) 185 186/*% 187 * Fail unconditionally and log as a server error. 188 * The test against ISC_R_SUCCESS is there to keep the Solaris compiler 189 * from complaining about "end-of-loop code not reached". 190 */ 191#define FAILS(code, msg) \ 192 do { \ 193 result = (code); \ 194 update_log(client, zone, LOGLEVEL_PROTOCOL, \ 195 "error: %s: %s", \ 196 msg, isc_result_totext(result)); \ 197 if (result != ISC_R_SUCCESS) goto failure; \ 198 } while (0) 199 200/* 201 * Return TRUE if NS_CLIENTATTR_TCP is set in the attributes other FALSE. 202 */ 203#define TCPCLIENT(client) (((client)->attributes & NS_CLIENTATTR_TCP) != 0) 204 205/**************************************************************************/ 206 207typedef struct rr rr_t; 208 209struct rr { 210 /* dns_name_t name; */ 211 isc_uint32_t ttl; 212 dns_rdata_t rdata; 213}; 214 215typedef struct update_event update_event_t; 216 217struct update_event { 218 ISC_EVENT_COMMON(update_event_t); 219 dns_zone_t *zone; 220 isc_result_t result; 221 dns_message_t *answer; 222}; 223 224/**************************************************************************/ 225/* 226 * Forward declarations. 227 */ 228 229static void update_action(isc_task_t *task, isc_event_t *event); 230static void updatedone_action(isc_task_t *task, isc_event_t *event); 231static isc_result_t send_forward_event(ns_client_t *client, dns_zone_t *zone); 232static void forward_done(isc_task_t *task, isc_event_t *event); 233 234/**************************************************************************/ 235 236static void 237update_log(ns_client_t *client, dns_zone_t *zone, 238 int level, const char *fmt, ...) ISC_FORMAT_PRINTF(4, 5); 239 240static void 241update_log(ns_client_t *client, dns_zone_t *zone, 242 int level, const char *fmt, ...) 243{ 244 va_list ap; 245 char message[4096]; 246 char namebuf[DNS_NAME_FORMATSIZE]; 247 char classbuf[DNS_RDATACLASS_FORMATSIZE]; 248 249 if (client == NULL || zone == NULL) 250 return; 251 252 if (isc_log_wouldlog(ns_g_lctx, level) == ISC_FALSE) 253 return; 254 255 dns_name_format(dns_zone_getorigin(zone), namebuf, 256 sizeof(namebuf)); 257 dns_rdataclass_format(dns_zone_getclass(zone), classbuf, 258 sizeof(classbuf)); 259 260 va_start(ap, fmt); 261 vsnprintf(message, sizeof(message), fmt, ap); 262 va_end(ap); 263 264 ns_client_log(client, NS_LOGCATEGORY_UPDATE, NS_LOGMODULE_UPDATE, 265 level, "updating zone '%s/%s': %s", 266 namebuf, classbuf, message); 267} 268 269/*% 270 * Increment updated-related statistics counters. 271 */ 272static inline void 273inc_stats(dns_zone_t *zone, isc_statscounter_t counter) { 274 isc_stats_increment(ns_g_server->nsstats, counter); 275 276 if (zone != NULL) { 277 isc_stats_t *zonestats = dns_zone_getrequeststats(zone); 278 if (zonestats != NULL) 279 isc_stats_increment(zonestats, counter); 280 } 281} 282 283/*% 284 * Override the default acl logging when checking whether a client 285 * can update the zone or whether we can forward the request to the 286 * master based on IP address. 287 * 288 * 'message' contains the type of operation that is being attempted. 289 * 'slave' indicates if this is a slave zone. If 'acl' is NULL then 290 * log at debug=3. 291 * If the zone has no access controls configured ('acl' == NULL && 292 * 'has_ssutable == ISC_FALS) log the attempt at info, otherwise 293 * at error. 294 * 295 * If the request was signed log that we received it. 296 */ 297static isc_result_t 298checkupdateacl(ns_client_t *client, dns_acl_t *acl, const char *message, 299 dns_name_t *zonename, isc_boolean_t slave, 300 isc_boolean_t has_ssutable) 301{ 302 char namebuf[DNS_NAME_FORMATSIZE]; 303 char classbuf[DNS_RDATACLASS_FORMATSIZE]; 304 int level = ISC_LOG_ERROR; 305 const char *msg = "denied"; 306 isc_result_t result; 307 308 if (slave && acl == NULL) { 309 result = DNS_R_NOTIMP; 310 level = ISC_LOG_DEBUG(3); 311 msg = "disabled"; 312 } else { 313 result = ns_client_checkaclsilent(client, NULL, acl, ISC_FALSE); 314 if (result == ISC_R_SUCCESS) { 315 level = ISC_LOG_DEBUG(3); 316 msg = "approved"; 317 } else if (acl == NULL && !has_ssutable) { 318 level = ISC_LOG_INFO; 319 } 320 } 321 322 if (client->signer != NULL) { 323 dns_name_format(client->signer, namebuf, sizeof(namebuf)); 324 ns_client_log(client, NS_LOGCATEGORY_UPDATE_SECURITY, 325 NS_LOGMODULE_UPDATE, ISC_LOG_INFO, 326 "signer \"%s\" %s", namebuf, msg); 327 } 328 329 dns_name_format(zonename, namebuf, sizeof(namebuf)); 330 dns_rdataclass_format(client->view->rdclass, classbuf, 331 sizeof(classbuf)); 332 333 ns_client_log(client, NS_LOGCATEGORY_UPDATE_SECURITY, 334 NS_LOGMODULE_UPDATE, level, "%s '%s/%s' %s", 335 message, namebuf, classbuf, msg); 336 return (result); 337} 338 339/*% 340 * Update a single RR in version 'ver' of 'db' and log the 341 * update in 'diff'. 342 * 343 * Ensures: 344 * \li '*tuple' == NULL. Either the tuple is freed, or its 345 * ownership has been transferred to the diff. 346 */ 347static isc_result_t 348do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver, 349 dns_diff_t *diff) 350{ 351 dns_diff_t temp_diff; 352 isc_result_t result; 353 354 /* 355 * Create a singleton diff. 356 */ 357 dns_diff_init(diff->mctx, &temp_diff); 358 temp_diff.resign = diff->resign; 359 ISC_LIST_APPEND(temp_diff.tuples, *tuple, link); 360 361 /* 362 * Apply it to the database. 363 */ 364 result = dns_diff_apply(&temp_diff, db, ver); 365 ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link); 366 if (result != ISC_R_SUCCESS) { 367 dns_difftuple_free(tuple); 368 return (result); 369 } 370 371 /* 372 * Merge it into the current pending journal entry. 373 */ 374 dns_diff_appendminimal(diff, tuple); 375 376 /* 377 * Do not clear temp_diff. 378 */ 379 return (ISC_R_SUCCESS); 380} 381 382/*% 383 * Perform the updates in 'updates' in version 'ver' of 'db' and log the 384 * update in 'diff'. 385 * 386 * Ensures: 387 * \li 'updates' is empty. 388 */ 389static isc_result_t 390do_diff(dns_diff_t *updates, dns_db_t *db, dns_dbversion_t *ver, 391 dns_diff_t *diff) 392{ 393 isc_result_t result; 394 while (! ISC_LIST_EMPTY(updates->tuples)) { 395 dns_difftuple_t *t = ISC_LIST_HEAD(updates->tuples); 396 ISC_LIST_UNLINK(updates->tuples, t, link); 397 CHECK(do_one_tuple(&t, db, ver, diff)); 398 } 399 return (ISC_R_SUCCESS); 400 401 failure: 402 dns_diff_clear(diff); 403 return (result); 404} 405 406static isc_result_t 407update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff, 408 dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl, 409 dns_rdata_t *rdata) 410{ 411 dns_difftuple_t *tuple = NULL; 412 isc_result_t result; 413 result = dns_difftuple_create(diff->mctx, op, 414 name, ttl, rdata, &tuple); 415 if (result != ISC_R_SUCCESS) 416 return (result); 417 return (do_one_tuple(&tuple, db, ver, diff)); 418} 419 420/**************************************************************************/ 421/* 422 * Callback-style iteration over rdatasets and rdatas. 423 * 424 * foreach_rrset() can be used to iterate over the RRsets 425 * of a name and call a callback function with each 426 * one. Similarly, foreach_rr() can be used to iterate 427 * over the individual RRs at name, optionally restricted 428 * to RRs of a given type. 429 * 430 * The callback functions are called "actions" and take 431 * two arguments: a void pointer for passing arbitrary 432 * context information, and a pointer to the current RRset 433 * or RR. By convention, their names end in "_action". 434 */ 435 436/* 437 * XXXRTH We might want to make this public somewhere in libdns. 438 */ 439 440/*% 441 * Function type for foreach_rrset() iterator actions. 442 */ 443typedef isc_result_t rrset_func(void *data, dns_rdataset_t *rrset); 444 445/*% 446 * Function type for foreach_rr() iterator actions. 447 */ 448typedef isc_result_t rr_func(void *data, rr_t *rr); 449 450/*% 451 * Internal context struct for foreach_node_rr(). 452 */ 453typedef struct { 454 rr_func * rr_action; 455 void * rr_action_data; 456} foreach_node_rr_ctx_t; 457 458/*% 459 * Internal helper function for foreach_node_rr(). 460 */ 461static isc_result_t 462foreach_node_rr_action(void *data, dns_rdataset_t *rdataset) { 463 isc_result_t result; 464 foreach_node_rr_ctx_t *ctx = data; 465 for (result = dns_rdataset_first(rdataset); 466 result == ISC_R_SUCCESS; 467 result = dns_rdataset_next(rdataset)) 468 { 469 rr_t rr = { 0, DNS_RDATA_INIT }; 470 471 dns_rdataset_current(rdataset, &rr.rdata); 472 rr.ttl = rdataset->ttl; 473 result = (*ctx->rr_action)(ctx->rr_action_data, &rr); 474 if (result != ISC_R_SUCCESS) 475 return (result); 476 } 477 if (result != ISC_R_NOMORE) 478 return (result); 479 return (ISC_R_SUCCESS); 480} 481 482/*% 483 * For each rdataset of 'name' in 'ver' of 'db', call 'action' 484 * with the rdataset and 'action_data' as arguments. If the name 485 * does not exist, do nothing. 486 * 487 * If 'action' returns an error, abort iteration and return the error. 488 */ 489static isc_result_t 490foreach_rrset(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, 491 rrset_func *action, void *action_data) 492{ 493 isc_result_t result; 494 dns_dbnode_t *node; 495 dns_rdatasetiter_t *iter; 496 497 node = NULL; 498 result = dns_db_findnode(db, name, ISC_FALSE, &node); 499 if (result == ISC_R_NOTFOUND) 500 return (ISC_R_SUCCESS); 501 if (result != ISC_R_SUCCESS) 502 return (result); 503 504 iter = NULL; 505 result = dns_db_allrdatasets(db, node, ver, 506 (isc_stdtime_t) 0, &iter); 507 if (result != ISC_R_SUCCESS) 508 goto cleanup_node; 509 510 for (result = dns_rdatasetiter_first(iter); 511 result == ISC_R_SUCCESS; 512 result = dns_rdatasetiter_next(iter)) 513 { 514 dns_rdataset_t rdataset; 515 516 dns_rdataset_init(&rdataset); 517 dns_rdatasetiter_current(iter, &rdataset); 518 519 result = (*action)(action_data, &rdataset); 520 521 dns_rdataset_disassociate(&rdataset); 522 if (result != ISC_R_SUCCESS) 523 goto cleanup_iterator; 524 } 525 if (result == ISC_R_NOMORE) 526 result = ISC_R_SUCCESS; 527 528 cleanup_iterator: 529 dns_rdatasetiter_destroy(&iter); 530 531 cleanup_node: 532 dns_db_detachnode(db, &node); 533 534 return (result); 535} 536 537/*% 538 * For each RR of 'name' in 'ver' of 'db', call 'action' 539 * with the RR and 'action_data' as arguments. If the name 540 * does not exist, do nothing. 541 * 542 * If 'action' returns an error, abort iteration 543 * and return the error. 544 */ 545static isc_result_t 546foreach_node_rr(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, 547 rr_func *rr_action, void *rr_action_data) 548{ 549 foreach_node_rr_ctx_t ctx; 550 ctx.rr_action = rr_action; 551 ctx.rr_action_data = rr_action_data; 552 return (foreach_rrset(db, ver, name, 553 foreach_node_rr_action, &ctx)); 554} 555 556 557/*% 558 * For each of the RRs specified by 'db', 'ver', 'name', 'type', 559 * (which can be dns_rdatatype_any to match any type), and 'covers', call 560 * 'action' with the RR and 'action_data' as arguments. If the name 561 * does not exist, or if no RRset of the given type exists at the name, 562 * do nothing. 563 * 564 * If 'action' returns an error, abort iteration and return the error. 565 */ 566static isc_result_t 567foreach_rr(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, 568 dns_rdatatype_t type, dns_rdatatype_t covers, rr_func *rr_action, 569 void *rr_action_data) 570{ 571 572 isc_result_t result; 573 dns_dbnode_t *node; 574 dns_rdataset_t rdataset; 575 576 if (type == dns_rdatatype_any) 577 return (foreach_node_rr(db, ver, name, 578 rr_action, rr_action_data)); 579 580 node = NULL; 581 if (type == dns_rdatatype_nsec3 || 582 (type == dns_rdatatype_rrsig && covers == dns_rdatatype_nsec3)) 583 result = dns_db_findnsec3node(db, name, ISC_FALSE, &node); 584 else 585 result = dns_db_findnode(db, name, ISC_FALSE, &node); 586 if (result == ISC_R_NOTFOUND) 587 return (ISC_R_SUCCESS); 588 if (result != ISC_R_SUCCESS) 589 return (result); 590 591 dns_rdataset_init(&rdataset); 592 result = dns_db_findrdataset(db, node, ver, type, covers, 593 (isc_stdtime_t) 0, &rdataset, NULL); 594 if (result == ISC_R_NOTFOUND) { 595 result = ISC_R_SUCCESS; 596 goto cleanup_node; 597 } 598 if (result != ISC_R_SUCCESS) 599 goto cleanup_node; 600 601 for (result = dns_rdataset_first(&rdataset); 602 result == ISC_R_SUCCESS; 603 result = dns_rdataset_next(&rdataset)) 604 { 605 rr_t rr = { 0, DNS_RDATA_INIT }; 606 dns_rdataset_current(&rdataset, &rr.rdata); 607 rr.ttl = rdataset.ttl; 608 result = (*rr_action)(rr_action_data, &rr); 609 if (result != ISC_R_SUCCESS) 610 goto cleanup_rdataset; 611 } 612 if (result != ISC_R_NOMORE) 613 goto cleanup_rdataset; 614 result = ISC_R_SUCCESS; 615 616 cleanup_rdataset: 617 dns_rdataset_disassociate(&rdataset); 618 cleanup_node: 619 dns_db_detachnode(db, &node); 620 621 return (result); 622} 623 624/**************************************************************************/ 625/* 626 * Various tests on the database contents (for prerequisites, etc). 627 */ 628 629/*% 630 * Function type for predicate functions that compare a database RR 'db_rr' 631 * against an update RR 'update_rr'. 632 */ 633typedef isc_boolean_t rr_predicate(dns_rdata_t *update_rr, dns_rdata_t *db_rr); 634 635/*% 636 * Helper function for rrset_exists(). 637 */ 638static isc_result_t 639rrset_exists_action(void *data, rr_t *rr) { 640 UNUSED(data); 641 UNUSED(rr); 642 return (ISC_R_EXISTS); 643} 644 645/*% 646 * Utility macro for RR existence checking functions. 647 * 648 * If the variable 'result' has the value ISC_R_EXISTS or 649 * ISC_R_SUCCESS, set *exists to ISC_TRUE or ISC_FALSE, 650 * respectively, and return success. 651 * 652 * If 'result' has any other value, there was a failure. 653 * Return the failure result code and do not set *exists. 654 * 655 * This would be more readable as "do { if ... } while(0)", 656 * but that form generates tons of warnings on Solaris 2.6. 657 */ 658#define RETURN_EXISTENCE_FLAG \ 659 return ((result == ISC_R_EXISTS) ? \ 660 (*exists = ISC_TRUE, ISC_R_SUCCESS) : \ 661 ((result == ISC_R_SUCCESS) ? \ 662 (*exists = ISC_FALSE, ISC_R_SUCCESS) : \ 663 result)) 664 665/*% 666 * Set '*exists' to true iff an rrset of the given type exists, 667 * to false otherwise. 668 */ 669static isc_result_t 670rrset_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, 671 dns_rdatatype_t type, dns_rdatatype_t covers, 672 isc_boolean_t *exists) 673{ 674 isc_result_t result; 675 result = foreach_rr(db, ver, name, type, covers, 676 rrset_exists_action, NULL); 677 RETURN_EXISTENCE_FLAG; 678} 679 680/*% 681 * Set '*visible' to true if the RRset exists and is part of the 682 * visible zone. Otherwise '*visible' is set to false unless a 683 * error occurs. 684 */ 685static isc_result_t 686rrset_visible(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, 687 dns_rdatatype_t type, isc_boolean_t *visible) 688{ 689 isc_result_t result; 690 dns_fixedname_t fixed; 691 692 dns_fixedname_init(&fixed); 693 result = dns_db_find(db, name, ver, type, DNS_DBFIND_NOWILD, 694 (isc_stdtime_t) 0, NULL, 695 dns_fixedname_name(&fixed), NULL, NULL); 696 switch (result) { 697 case ISC_R_SUCCESS: 698 *visible = ISC_TRUE; 699 break; 700 /* 701 * Glue, obscured, deleted or replaced records. 702 */ 703 case DNS_R_DELEGATION: 704 case DNS_R_DNAME: 705 case DNS_R_CNAME: 706 case DNS_R_NXDOMAIN: 707 case DNS_R_NXRRSET: 708 case DNS_R_EMPTYNAME: 709 case DNS_R_COVERINGNSEC: 710 *visible = ISC_FALSE; 711 result = ISC_R_SUCCESS; 712 break; 713 default: 714 break; 715 } 716 return (result); 717} 718 719/*% 720 * Helper function for cname_incompatible_rrset_exists. 721 */ 722static isc_result_t 723cname_compatibility_action(void *data, dns_rdataset_t *rrset) { 724 UNUSED(data); 725 if (rrset->type != dns_rdatatype_cname && 726 ! dns_rdatatype_isdnssec(rrset->type)) 727 return (ISC_R_EXISTS); 728 return (ISC_R_SUCCESS); 729} 730 731/*% 732 * Check whether there is an rrset incompatible with adding a CNAME RR, 733 * i.e., anything but another CNAME (which can be replaced) or a 734 * DNSSEC RR (which can coexist). 735 * 736 * If such an incompatible rrset exists, set '*exists' to ISC_TRUE. 737 * Otherwise, set it to ISC_FALSE. 738 */ 739static isc_result_t 740cname_incompatible_rrset_exists(dns_db_t *db, dns_dbversion_t *ver, 741 dns_name_t *name, isc_boolean_t *exists) { 742 isc_result_t result; 743 result = foreach_rrset(db, ver, name, 744 cname_compatibility_action, NULL); 745 RETURN_EXISTENCE_FLAG; 746} 747 748/*% 749 * Helper function for rr_count(). 750 */ 751static isc_result_t 752count_rr_action(void *data, rr_t *rr) { 753 int *countp = data; 754 UNUSED(rr); 755 (*countp)++; 756 return (ISC_R_SUCCESS); 757} 758 759/*% 760 * Count the number of RRs of 'type' belonging to 'name' in 'ver' of 'db'. 761 */ 762static isc_result_t 763rr_count(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, 764 dns_rdatatype_t type, dns_rdatatype_t covers, int *countp) 765{ 766 *countp = 0; 767 return (foreach_rr(db, ver, name, type, covers, 768 count_rr_action, countp)); 769} 770 771/*% 772 * Context struct and helper function for name_exists(). 773 */ 774 775static isc_result_t 776name_exists_action(void *data, dns_rdataset_t *rrset) { 777 UNUSED(data); 778 UNUSED(rrset); 779 return (ISC_R_EXISTS); 780} 781 782/*% 783 * Set '*exists' to true iff the given name exists, to false otherwise. 784 */ 785static isc_result_t 786name_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, 787 isc_boolean_t *exists) 788{ 789 isc_result_t result; 790 result = foreach_rrset(db, ver, name, 791 name_exists_action, NULL); 792 RETURN_EXISTENCE_FLAG; 793} 794 795/* 796 * 'ssu_check_t' is used to pass the arguments to 797 * dns_ssutable_checkrules() to the callback function 798 * ssu_checkrule(). 799 */ 800typedef struct { 801 /* The ownername of the record to be updated. */ 802 dns_name_t *name; 803 804 /* The signature's name if the request was signed. */ 805 dns_name_t *signer; 806 807 /* The address of the client if the request was received via TCP. */ 808 isc_netaddr_t *tcpaddr; 809 810 /* The ssu table to check against. */ 811 dns_ssutable_t *table; 812} ssu_check_t; 813 814static isc_result_t 815ssu_checkrule(void *data, dns_rdataset_t *rrset) { 816 ssu_check_t *ssuinfo = data; 817 isc_boolean_t result; 818 819 /* 820 * If we're deleting all records, it's ok to delete RRSIG and NSEC even 821 * if we're normally not allowed to. 822 */ 823 if (rrset->type == dns_rdatatype_rrsig || 824 rrset->type == dns_rdatatype_nsec) 825 return (ISC_R_SUCCESS); 826 result = dns_ssutable_checkrules(ssuinfo->table, ssuinfo->signer, 827 ssuinfo->name, ssuinfo->tcpaddr, 828 rrset->type); 829 return (result == ISC_TRUE ? ISC_R_SUCCESS : ISC_R_FAILURE); 830} 831 832static isc_boolean_t 833ssu_checkall(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, 834 dns_ssutable_t *ssutable, dns_name_t *signer, 835 isc_netaddr_t *tcpaddr) 836{ 837 isc_result_t result; 838 ssu_check_t ssuinfo; 839 840 ssuinfo.name = name; 841 ssuinfo.table = ssutable; 842 ssuinfo.signer = signer; 843 ssuinfo.tcpaddr = tcpaddr; 844 result = foreach_rrset(db, ver, name, ssu_checkrule, &ssuinfo); 845 return (ISC_TF(result == ISC_R_SUCCESS)); 846} 847 848/**************************************************************************/ 849/* 850 * Checking of "RRset exists (value dependent)" prerequisites. 851 * 852 * In the RFC2136 section 3.2.5, this is the pseudocode involving 853 * a variable called "temp", a mapping of <name, type> tuples to rrsets. 854 * 855 * Here, we represent the "temp" data structure as (non-minimal) "dns_diff_t" 856 * where each tuple has op==DNS_DIFFOP_EXISTS. 857 */ 858 859 860/*% 861 * Append a tuple asserting the existence of the RR with 862 * 'name' and 'rdata' to 'diff'. 863 */ 864static isc_result_t 865temp_append(dns_diff_t *diff, dns_name_t *name, dns_rdata_t *rdata) { 866 isc_result_t result; 867 dns_difftuple_t *tuple = NULL; 868 869 REQUIRE(DNS_DIFF_VALID(diff)); 870 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_EXISTS, 871 name, 0, rdata, &tuple)); 872 ISC_LIST_APPEND(diff->tuples, tuple, link); 873 failure: 874 return (result); 875} 876 877/*% 878 * Compare two rdatasets represented as sorted lists of tuples. 879 * All list elements must have the same owner name and type. 880 * Return ISC_R_SUCCESS if the rdatasets are equal, rcode(dns_rcode_nxrrset) 881 * if not. 882 */ 883static isc_result_t 884temp_check_rrset(dns_difftuple_t *a, dns_difftuple_t *b) { 885 for (;;) { 886 if (a == NULL || b == NULL) 887 break; 888 INSIST(a->op == DNS_DIFFOP_EXISTS && 889 b->op == DNS_DIFFOP_EXISTS); 890 INSIST(a->rdata.type == b->rdata.type); 891 INSIST(dns_name_equal(&a->name, &b->name)); 892 if (dns_rdata_compare(&a->rdata, &b->rdata) != 0) 893 return (DNS_R_NXRRSET); 894 a = ISC_LIST_NEXT(a, link); 895 b = ISC_LIST_NEXT(b, link); 896 } 897 if (a != NULL || b != NULL) 898 return (DNS_R_NXRRSET); 899 return (ISC_R_SUCCESS); 900} 901 902/*% 903 * A comparison function defining the sorting order for the entries 904 * in the "temp" data structure. The major sort key is the owner name, 905 * followed by the type and rdata. 906 */ 907static int 908temp_order(const void *av, const void *bv) { 909 dns_difftuple_t const * const *ap = av; 910 dns_difftuple_t const * const *bp = bv; 911 dns_difftuple_t const *a = *ap; 912 dns_difftuple_t const *b = *bp; 913 int r; 914 r = dns_name_compare(&a->name, &b->name); 915 if (r != 0) 916 return (r); 917 r = (b->rdata.type - a->rdata.type); 918 if (r != 0) 919 return (r); 920 r = dns_rdata_compare(&a->rdata, &b->rdata); 921 return (r); 922} 923 924/*% 925 * Check the "RRset exists (value dependent)" prerequisite information 926 * in 'temp' against the contents of the database 'db'. 927 * 928 * Return ISC_R_SUCCESS if the prerequisites are satisfied, 929 * rcode(dns_rcode_nxrrset) if not. 930 * 931 * 'temp' must be pre-sorted. 932 */ 933 934static isc_result_t 935temp_check(isc_mem_t *mctx, dns_diff_t *temp, dns_db_t *db, 936 dns_dbversion_t *ver, dns_name_t *tmpname, dns_rdatatype_t *typep) 937{ 938 isc_result_t result; 939 dns_name_t *name; 940 dns_dbnode_t *node; 941 dns_difftuple_t *t; 942 dns_diff_t trash; 943 944 dns_diff_init(mctx, &trash); 945 946 /* 947 * For each name and type in the prerequisites, 948 * construct a sorted rdata list of the corresponding 949 * database contents, and compare the lists. 950 */ 951 t = ISC_LIST_HEAD(temp->tuples); 952 while (t != NULL) { 953 name = &t->name; 954 (void)dns_name_copy(name, tmpname, NULL); 955 *typep = t->rdata.type; 956 957 /* A new unique name begins here. */ 958 node = NULL; 959 result = dns_db_findnode(db, name, ISC_FALSE, &node); 960 if (result == ISC_R_NOTFOUND) { 961 dns_diff_clear(&trash); 962 return (DNS_R_NXRRSET); 963 } 964 if (result != ISC_R_SUCCESS) { 965 dns_diff_clear(&trash); 966 return (result); 967 } 968 969 /* A new unique type begins here. */ 970 while (t != NULL && dns_name_equal(&t->name, name)) { 971 dns_rdatatype_t type, covers; 972 dns_rdataset_t rdataset; 973 dns_diff_t d_rrs; /* Database RRs with 974 this name and type */ 975 dns_diff_t u_rrs; /* Update RRs with 976 this name and type */ 977 978 *typep = type = t->rdata.type; 979 if (type == dns_rdatatype_rrsig || 980 type == dns_rdatatype_sig) 981 covers = dns_rdata_covers(&t->rdata); 982 else if (type == dns_rdatatype_any) { 983 dns_db_detachnode(db, &node); 984 dns_diff_clear(&trash); 985 return (DNS_R_NXRRSET); 986 } else 987 covers = 0; 988 989 /* 990 * Collect all database RRs for this name and type 991 * onto d_rrs and sort them. 992 */ 993 dns_rdataset_init(&rdataset); 994 result = dns_db_findrdataset(db, node, ver, type, 995 covers, (isc_stdtime_t) 0, 996 &rdataset, NULL); 997 if (result != ISC_R_SUCCESS) { 998 dns_db_detachnode(db, &node); 999 dns_diff_clear(&trash); 1000 return (DNS_R_NXRRSET); 1001 } 1002 1003 dns_diff_init(mctx, &d_rrs); 1004 dns_diff_init(mctx, &u_rrs); 1005 1006 for (result = dns_rdataset_first(&rdataset); 1007 result == ISC_R_SUCCESS; 1008 result = dns_rdataset_next(&rdataset)) 1009 { 1010 dns_rdata_t rdata = DNS_RDATA_INIT; 1011 dns_rdataset_current(&rdataset, &rdata); 1012 result = temp_append(&d_rrs, name, &rdata); 1013 if (result != ISC_R_SUCCESS) 1014 goto failure; 1015 } 1016 if (result != ISC_R_NOMORE) 1017 goto failure; 1018 result = dns_diff_sort(&d_rrs, temp_order); 1019 if (result != ISC_R_SUCCESS) 1020 goto failure; 1021 1022 /* 1023 * Collect all update RRs for this name and type 1024 * onto u_rrs. No need to sort them here - 1025 * they are already sorted. 1026 */ 1027 while (t != NULL && 1028 dns_name_equal(&t->name, name) && 1029 t->rdata.type == type) 1030 { 1031 dns_difftuple_t *next = 1032 ISC_LIST_NEXT(t, link); 1033 ISC_LIST_UNLINK(temp->tuples, t, link); 1034 ISC_LIST_APPEND(u_rrs.tuples, t, link); 1035 t = next; 1036 } 1037 1038 /* Compare the two sorted lists. */ 1039 result = temp_check_rrset(ISC_LIST_HEAD(u_rrs.tuples), 1040 ISC_LIST_HEAD(d_rrs.tuples)); 1041 if (result != ISC_R_SUCCESS) 1042 goto failure; 1043 1044 /* 1045 * We are done with the tuples, but we can't free 1046 * them yet because "name" still points into one 1047 * of them. Move them on a temporary list. 1048 */ 1049 ISC_LIST_APPENDLIST(trash.tuples, u_rrs.tuples, link); 1050 ISC_LIST_APPENDLIST(trash.tuples, d_rrs.tuples, link); 1051 dns_rdataset_disassociate(&rdataset); 1052 1053 continue; 1054 1055 failure: 1056 dns_diff_clear(&d_rrs); 1057 dns_diff_clear(&u_rrs); 1058 dns_diff_clear(&trash); 1059 dns_rdataset_disassociate(&rdataset); 1060 dns_db_detachnode(db, &node); 1061 return (result); 1062 } 1063 1064 dns_db_detachnode(db, &node); 1065 } 1066 1067 dns_diff_clear(&trash); 1068 return (ISC_R_SUCCESS); 1069} 1070 1071/**************************************************************************/ 1072/* 1073 * Conditional deletion of RRs. 1074 */ 1075 1076/*% 1077 * Context structure for delete_if(). 1078 */ 1079 1080typedef struct { 1081 rr_predicate *predicate; 1082 dns_db_t *db; 1083 dns_dbversion_t *ver; 1084 dns_diff_t *diff; 1085 dns_name_t *name; 1086 dns_rdata_t *update_rr; 1087} conditional_delete_ctx_t; 1088 1089/*% 1090 * Predicate functions for delete_if(). 1091 */ 1092 1093/*% 1094 * Return true iff 'db_rr' is neither a SOA nor an NS RR nor 1095 * an RRSIG nor an NSEC3PARAM nor a NSEC. 1096 */ 1097static isc_boolean_t 1098type_not_soa_nor_ns_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) { 1099 UNUSED(update_rr); 1100 return ((db_rr->type != dns_rdatatype_soa && 1101 db_rr->type != dns_rdatatype_ns && 1102 db_rr->type != dns_rdatatype_nsec3param && 1103 db_rr->type != dns_rdatatype_rrsig && 1104 db_rr->type != dns_rdatatype_nsec) ? 1105 ISC_TRUE : ISC_FALSE); 1106} 1107 1108/*% 1109 * Return true iff 'db_rr' is neither a RRSIG nor a NSEC. 1110 */ 1111static isc_boolean_t 1112type_not_dnssec(dns_rdata_t *update_rr, dns_rdata_t *db_rr) { 1113 UNUSED(update_rr); 1114 return ((db_rr->type != dns_rdatatype_rrsig && 1115 db_rr->type != dns_rdatatype_nsec) ? 1116 ISC_TRUE : ISC_FALSE); 1117} 1118 1119/*% 1120 * Return true always. 1121 */ 1122static isc_boolean_t 1123true_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) { 1124 UNUSED(update_rr); 1125 UNUSED(db_rr); 1126 return (ISC_TRUE); 1127} 1128 1129/*% 1130 * Return true if the record is a RRSIG. 1131 */ 1132static isc_boolean_t 1133rrsig_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) { 1134 UNUSED(update_rr); 1135 return ((db_rr->type == dns_rdatatype_rrsig) ? 1136 ISC_TRUE : ISC_FALSE); 1137} 1138 1139/*% 1140 * Return true iff the two RRs have identical rdata. 1141 */ 1142static isc_boolean_t 1143rr_equal_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) { 1144 /* 1145 * XXXRTH This is not a problem, but we should consider creating 1146 * dns_rdata_equal() (that used dns_name_equal()), since it 1147 * would be faster. Not a priority. 1148 */ 1149 return (dns_rdata_compare(update_rr, db_rr) == 0 ? 1150 ISC_TRUE : ISC_FALSE); 1151} 1152 1153/*% 1154 * Return true iff 'update_rr' should replace 'db_rr' according 1155 * to the special RFC2136 rules for CNAME, SOA, and WKS records. 1156 * 1157 * RFC2136 does not mention NSEC or DNAME, but multiple NSECs or DNAMEs 1158 * make little sense, so we replace those, too. 1159 * 1160 * Additionally replace RRSIG that have been generated by the same key 1161 * for the same type. This simplifies refreshing a offline KSK by not 1162 * requiring that the old RRSIG be deleted. It also simplifies key 1163 * rollover by only requiring that the new RRSIG be added. 1164 */ 1165static isc_boolean_t 1166replaces_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) { 1167 dns_rdata_rrsig_t updatesig, dbsig; 1168 isc_result_t result; 1169 1170 if (db_rr->type != update_rr->type) 1171 return (ISC_FALSE); 1172 if (db_rr->type == dns_rdatatype_cname) 1173 return (ISC_TRUE); 1174 if (db_rr->type == dns_rdatatype_dname) 1175 return (ISC_TRUE); 1176 if (db_rr->type == dns_rdatatype_soa) 1177 return (ISC_TRUE); 1178 if (db_rr->type == dns_rdatatype_nsec) 1179 return (ISC_TRUE); 1180 if (db_rr->type == dns_rdatatype_rrsig) { 1181 /* 1182 * Replace existing RRSIG with the same keyid, 1183 * covered and algorithm. 1184 */ 1185 result = dns_rdata_tostruct(db_rr, &dbsig, NULL); 1186 RUNTIME_CHECK(result == ISC_R_SUCCESS); 1187 result = dns_rdata_tostruct(update_rr, &updatesig, NULL); 1188 RUNTIME_CHECK(result == ISC_R_SUCCESS); 1189 if (dbsig.keyid == updatesig.keyid && 1190 dbsig.covered == updatesig.covered && 1191 dbsig.algorithm == updatesig.algorithm) 1192 return (ISC_TRUE); 1193 } 1194 if (db_rr->type == dns_rdatatype_wks) { 1195 /* 1196 * Compare the address and protocol fields only. These 1197 * form the first five bytes of the RR data. Do a 1198 * raw binary comparison; unpacking the WKS RRs using 1199 * dns_rdata_tostruct() might be cleaner in some ways. 1200 */ 1201 INSIST(db_rr->length >= 5 && update_rr->length >= 5); 1202 return (memcmp(db_rr->data, update_rr->data, 5) == 0 ? 1203 ISC_TRUE : ISC_FALSE); 1204 } 1205 1206 if (db_rr->type == dns_rdatatype_nsec3param) { 1207 if (db_rr->length != update_rr->length) 1208 return (ISC_FALSE); 1209 INSIST(db_rr->length >= 4 && update_rr->length >= 4); 1210 /* 1211 * Replace records added in this UPDATE request. 1212 */ 1213 if (db_rr->data[0] == update_rr->data[0] && 1214 db_rr->data[1] & DNS_NSEC3FLAG_UPDATE && 1215 update_rr->data[1] & DNS_NSEC3FLAG_UPDATE && 1216 memcmp(db_rr->data+2, update_rr->data+2, 1217 update_rr->length - 2) == 0) 1218 return (ISC_TRUE); 1219 } 1220 return (ISC_FALSE); 1221} 1222 1223/*% 1224 * Internal helper function for delete_if(). 1225 */ 1226static isc_result_t 1227delete_if_action(void *data, rr_t *rr) { 1228 conditional_delete_ctx_t *ctx = data; 1229 if ((*ctx->predicate)(ctx->update_rr, &rr->rdata)) { 1230 isc_result_t result; 1231 result = update_one_rr(ctx->db, ctx->ver, ctx->diff, 1232 DNS_DIFFOP_DEL, ctx->name, 1233 rr->ttl, &rr->rdata); 1234 return (result); 1235 } else { 1236 return (ISC_R_SUCCESS); 1237 } 1238} 1239 1240/*% 1241 * Conditionally delete RRs. Apply 'predicate' to the RRs 1242 * specified by 'db', 'ver', 'name', and 'type' (which can 1243 * be dns_rdatatype_any to match any type). Delete those 1244 * RRs for which the predicate returns true, and log the 1245 * deletions in 'diff'. 1246 */ 1247static isc_result_t 1248delete_if(rr_predicate *predicate, dns_db_t *db, dns_dbversion_t *ver, 1249 dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers, 1250 dns_rdata_t *update_rr, dns_diff_t *diff) 1251{ 1252 conditional_delete_ctx_t ctx; 1253 ctx.predicate = predicate; 1254 ctx.db = db; 1255 ctx.ver = ver; 1256 ctx.diff = diff; 1257 ctx.name = name; 1258 ctx.update_rr = update_rr; 1259 return (foreach_rr(db, ver, name, type, covers, 1260 delete_if_action, &ctx)); 1261} 1262 1263/**************************************************************************/ 1264/*% 1265 * Prepare an RR for the addition of the new RR 'ctx->update_rr', 1266 * with TTL 'ctx->update_rr_ttl', to its rdataset, by deleting 1267 * the RRs if it is replaced by the new RR or has a conflicting TTL. 1268 * The necessary changes are appended to ctx->del_diff and ctx->add_diff; 1269 * we need to do all deletions before any additions so that we don't run 1270 * into transient states with conflicting TTLs. 1271 */ 1272 1273typedef struct { 1274 dns_db_t *db; 1275 dns_dbversion_t *ver; 1276 dns_diff_t *diff; 1277 dns_name_t *name; 1278 dns_rdata_t *update_rr; 1279 dns_ttl_t update_rr_ttl; 1280 isc_boolean_t ignore_add; 1281 dns_diff_t del_diff; 1282 dns_diff_t add_diff; 1283} add_rr_prepare_ctx_t; 1284 1285static isc_result_t 1286add_rr_prepare_action(void *data, rr_t *rr) { 1287 isc_result_t result = ISC_R_SUCCESS; 1288 add_rr_prepare_ctx_t *ctx = data; 1289 dns_difftuple_t *tuple = NULL; 1290 isc_boolean_t equal; 1291 1292 /* 1293 * If the update RR is a "duplicate" of the update RR, 1294 * the update should be silently ignored. 1295 */ 1296 equal = ISC_TF(dns_rdata_compare(&rr->rdata, ctx->update_rr) == 0); 1297 if (equal && rr->ttl == ctx->update_rr_ttl) { 1298 ctx->ignore_add = ISC_TRUE; 1299 return (ISC_R_SUCCESS); 1300 } 1301 1302 /* 1303 * If this RR is "equal" to the update RR, it should 1304 * be deleted before the update RR is added. 1305 */ 1306 if (replaces_p(ctx->update_rr, &rr->rdata)) { 1307 CHECK(dns_difftuple_create(ctx->del_diff.mctx, DNS_DIFFOP_DEL, 1308 ctx->name, rr->ttl, &rr->rdata, 1309 &tuple)); 1310 dns_diff_append(&ctx->del_diff, &tuple); 1311 return (ISC_R_SUCCESS); 1312 } 1313 1314 /* 1315 * If this RR differs in TTL from the update RR, 1316 * its TTL must be adjusted. 1317 */ 1318 if (rr->ttl != ctx->update_rr_ttl) { 1319 CHECK(dns_difftuple_create(ctx->del_diff.mctx, DNS_DIFFOP_DEL, 1320 ctx->name, rr->ttl, &rr->rdata, 1321 &tuple)); 1322 dns_diff_append(&ctx->del_diff, &tuple); 1323 if (!equal) { 1324 CHECK(dns_difftuple_create(ctx->add_diff.mctx, 1325 DNS_DIFFOP_ADD, ctx->name, 1326 ctx->update_rr_ttl, 1327 &rr->rdata, &tuple)); 1328 dns_diff_append(&ctx->add_diff, &tuple); 1329 } 1330 } 1331 failure: 1332 return (result); 1333} 1334 1335/**************************************************************************/ 1336/* 1337 * Miscellaneous subroutines. 1338 */ 1339 1340/*% 1341 * Extract a single update RR from 'section' of dynamic update message 1342 * 'msg', with consistency checking. 1343 * 1344 * Stores the owner name, rdata, and TTL of the update RR at 'name', 1345 * 'rdata', and 'ttl', respectively. 1346 */ 1347static void 1348get_current_rr(dns_message_t *msg, dns_section_t section, 1349 dns_rdataclass_t zoneclass, dns_name_t **name, 1350 dns_rdata_t *rdata, dns_rdatatype_t *covers, 1351 dns_ttl_t *ttl, dns_rdataclass_t *update_class) 1352{ 1353 dns_rdataset_t *rdataset; 1354 isc_result_t result; 1355 dns_message_currentname(msg, section, name); 1356 rdataset = ISC_LIST_HEAD((*name)->list); 1357 INSIST(rdataset != NULL); 1358 INSIST(ISC_LIST_NEXT(rdataset, link) == NULL); 1359 *covers = rdataset->covers; 1360 *ttl = rdataset->ttl; 1361 result = dns_rdataset_first(rdataset); 1362 INSIST(result == ISC_R_SUCCESS); 1363 dns_rdataset_current(rdataset, rdata); 1364 INSIST(dns_rdataset_next(rdataset) == ISC_R_NOMORE); 1365 *update_class = rdata->rdclass; 1366 rdata->rdclass = zoneclass; 1367} 1368 1369/*% 1370 * Increment the SOA serial number of database 'db', version 'ver'. 1371 * Replace the SOA record in the database, and log the 1372 * change in 'diff'. 1373 */ 1374 1375 /* 1376 * XXXRTH Failures in this routine will be worth logging, when 1377 * we have a logging system. Failure to find the zonename 1378 * or the SOA rdataset warrant at least an UNEXPECTED_ERROR(). 1379 */ 1380 1381static isc_result_t 1382increment_soa_serial(dns_db_t *db, dns_dbversion_t *ver, 1383 dns_diff_t *diff, isc_mem_t *mctx) 1384{ 1385 dns_difftuple_t *deltuple = NULL; 1386 dns_difftuple_t *addtuple = NULL; 1387 isc_uint32_t serial; 1388 isc_result_t result; 1389 1390 CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple)); 1391 CHECK(dns_difftuple_copy(deltuple, &addtuple)); 1392 addtuple->op = DNS_DIFFOP_ADD; 1393 1394 serial = dns_soa_getserial(&addtuple->rdata); 1395 1396 /* RFC1982 */ 1397 serial = (serial + 1) & 0xFFFFFFFF; 1398 if (serial == 0) 1399 serial = 1; 1400 1401 dns_soa_setserial(serial, &addtuple->rdata); 1402 CHECK(do_one_tuple(&deltuple, db, ver, diff)); 1403 CHECK(do_one_tuple(&addtuple, db, ver, diff)); 1404 result = ISC_R_SUCCESS; 1405 1406 failure: 1407 if (addtuple != NULL) 1408 dns_difftuple_free(&addtuple); 1409 if (deltuple != NULL) 1410 dns_difftuple_free(&deltuple); 1411 return (result); 1412} 1413 1414/*% 1415 * Check that the new SOA record at 'update_rdata' does not 1416 * illegally cause the SOA serial number to decrease or stay 1417 * unchanged relative to the existing SOA in 'db'. 1418 * 1419 * Sets '*ok' to ISC_TRUE if the update is legal, ISC_FALSE if not. 1420 * 1421 * William King points out that RFC2136 is inconsistent about 1422 * the case where the serial number stays unchanged: 1423 * 1424 * section 3.4.2.2 requires a server to ignore a SOA update request 1425 * if the serial number on the update SOA is less_than_or_equal to 1426 * the zone SOA serial. 1427 * 1428 * section 3.6 requires a server to ignore a SOA update request if 1429 * the serial is less_than the zone SOA serial. 1430 * 1431 * Paul says 3.4.2.2 is correct. 1432 * 1433 */ 1434static isc_result_t 1435check_soa_increment(dns_db_t *db, dns_dbversion_t *ver, 1436 dns_rdata_t *update_rdata, isc_boolean_t *ok) 1437{ 1438 isc_uint32_t db_serial; 1439 isc_uint32_t update_serial; 1440 isc_result_t result; 1441 1442 update_serial = dns_soa_getserial(update_rdata); 1443 1444 result = dns_db_getsoaserial(db, ver, &db_serial); 1445 if (result != ISC_R_SUCCESS) 1446 return (result); 1447 1448 if (DNS_SERIAL_GE(db_serial, update_serial)) { 1449 *ok = ISC_FALSE; 1450 } else { 1451 *ok = ISC_TRUE; 1452 } 1453 1454 return (ISC_R_SUCCESS); 1455 1456} 1457 1458/**************************************************************************/ 1459/* 1460 * Incremental updating of NSECs and RRSIGs. 1461 */ 1462 1463#define MAXZONEKEYS 32 /*%< Maximum number of zone keys supported. */ 1464 1465/*% 1466 * We abuse the dns_diff_t type to represent a set of domain names 1467 * affected by the update. 1468 */ 1469static isc_result_t 1470namelist_append_name(dns_diff_t *list, dns_name_t *name) { 1471 isc_result_t result; 1472 dns_difftuple_t *tuple = NULL; 1473 static dns_rdata_t dummy_rdata = DNS_RDATA_INIT; 1474 1475 CHECK(dns_difftuple_create(list->mctx, DNS_DIFFOP_EXISTS, name, 0, 1476 &dummy_rdata, &tuple)); 1477 dns_diff_append(list, &tuple); 1478 failure: 1479 return (result); 1480} 1481 1482static isc_result_t 1483namelist_append_subdomain(dns_db_t *db, dns_name_t *name, dns_diff_t *affected) 1484{ 1485 isc_result_t result; 1486 dns_fixedname_t fixedname; 1487 dns_name_t *child; 1488 dns_dbiterator_t *dbit = NULL; 1489 1490 dns_fixedname_init(&fixedname); 1491 child = dns_fixedname_name(&fixedname); 1492 1493 CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit)); 1494 1495 for (result = dns_dbiterator_seek(dbit, name); 1496 result == ISC_R_SUCCESS; 1497 result = dns_dbiterator_next(dbit)) 1498 { 1499 dns_dbnode_t *node = NULL; 1500 CHECK(dns_dbiterator_current(dbit, &node, child)); 1501 dns_db_detachnode(db, &node); 1502 if (! dns_name_issubdomain(child, name)) 1503 break; 1504 CHECK(namelist_append_name(affected, child)); 1505 } 1506 if (result == ISC_R_NOMORE) 1507 result = ISC_R_SUCCESS; 1508 failure: 1509 if (dbit != NULL) 1510 dns_dbiterator_destroy(&dbit); 1511 return (result); 1512} 1513 1514 1515 1516/*% 1517 * Helper function for non_nsec_rrset_exists(). 1518 */ 1519static isc_result_t 1520is_non_nsec_action(void *data, dns_rdataset_t *rrset) { 1521 UNUSED(data); 1522 if (!(rrset->type == dns_rdatatype_nsec || 1523 rrset->type == dns_rdatatype_nsec3 || 1524 (rrset->type == dns_rdatatype_rrsig && 1525 (rrset->covers == dns_rdatatype_nsec || 1526 rrset->covers == dns_rdatatype_nsec3)))) 1527 return (ISC_R_EXISTS); 1528 return (ISC_R_SUCCESS); 1529} 1530 1531/*% 1532 * Check whether there is an rrset other than a NSEC or RRSIG NSEC, 1533 * i.e., anything that justifies the continued existence of a name 1534 * after a secure update. 1535 * 1536 * If such an rrset exists, set '*exists' to ISC_TRUE. 1537 * Otherwise, set it to ISC_FALSE. 1538 */ 1539static isc_result_t 1540non_nsec_rrset_exists(dns_db_t *db, dns_dbversion_t *ver, 1541 dns_name_t *name, isc_boolean_t *exists) 1542{ 1543 isc_result_t result; 1544 result = foreach_rrset(db, ver, name, is_non_nsec_action, NULL); 1545 RETURN_EXISTENCE_FLAG; 1546} 1547 1548/*% 1549 * A comparison function for sorting dns_diff_t:s by name. 1550 */ 1551static int 1552name_order(const void *av, const void *bv) { 1553 dns_difftuple_t const * const *ap = av; 1554 dns_difftuple_t const * const *bp = bv; 1555 dns_difftuple_t const *a = *ap; 1556 dns_difftuple_t const *b = *bp; 1557 return (dns_name_compare(&a->name, &b->name)); 1558} 1559 1560static isc_result_t 1561uniqify_name_list(dns_diff_t *list) { 1562 isc_result_t result; 1563 dns_difftuple_t *p, *q; 1564 1565 CHECK(dns_diff_sort(list, name_order)); 1566 1567 p = ISC_LIST_HEAD(list->tuples); 1568 while (p != NULL) { 1569 do { 1570 q = ISC_LIST_NEXT(p, link); 1571 if (q == NULL || ! dns_name_equal(&p->name, &q->name)) 1572 break; 1573 ISC_LIST_UNLINK(list->tuples, q, link); 1574 dns_difftuple_free(&q); 1575 } while (1); 1576 p = ISC_LIST_NEXT(p, link); 1577 } 1578 failure: 1579 return (result); 1580} 1581 1582static isc_result_t 1583is_active(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, 1584 isc_boolean_t *flag, isc_boolean_t *cut, isc_boolean_t *unsecure) 1585{ 1586 isc_result_t result; 1587 dns_fixedname_t foundname; 1588 dns_fixedname_init(&foundname); 1589 result = dns_db_find(db, name, ver, dns_rdatatype_any, 1590 DNS_DBFIND_GLUEOK | DNS_DBFIND_NOWILD, 1591 (isc_stdtime_t) 0, NULL, 1592 dns_fixedname_name(&foundname), 1593 NULL, NULL); 1594 if (result == ISC_R_SUCCESS || result == DNS_R_EMPTYNAME) { 1595 *flag = ISC_TRUE; 1596 *cut = ISC_FALSE; 1597 if (unsecure != NULL) 1598 *unsecure = ISC_FALSE; 1599 return (ISC_R_SUCCESS); 1600 } else if (result == DNS_R_ZONECUT) { 1601 *flag = ISC_TRUE; 1602 *cut = ISC_TRUE; 1603 if (unsecure != NULL) { 1604 /* 1605 * We are at the zonecut. Check to see if there 1606 * is a DS RRset. 1607 */ 1608 if (dns_db_find(db, name, ver, dns_rdatatype_ds, 0, 1609 (isc_stdtime_t) 0, NULL, 1610 dns_fixedname_name(&foundname), 1611 NULL, NULL) == DNS_R_NXRRSET) 1612 *unsecure = ISC_TRUE; 1613 else 1614 *unsecure = ISC_FALSE; 1615 } 1616 return (ISC_R_SUCCESS); 1617 } else if (result == DNS_R_GLUE || result == DNS_R_DNAME || 1618 result == DNS_R_DELEGATION || result == DNS_R_NXDOMAIN) { 1619 *flag = ISC_FALSE; 1620 *cut = ISC_FALSE; 1621 if (unsecure != NULL) 1622 *unsecure = ISC_FALSE; 1623 return (ISC_R_SUCCESS); 1624 } else { 1625 /* 1626 * Silence compiler. 1627 */ 1628 *flag = ISC_FALSE; 1629 *cut = ISC_FALSE; 1630 if (unsecure != NULL) 1631 *unsecure = ISC_FALSE; 1632 return (result); 1633 } 1634} 1635 1636/*% 1637 * Find the next/previous name that has a NSEC record. 1638 * In other words, skip empty database nodes and names that 1639 * have had their NSECs removed because they are obscured by 1640 * a zone cut. 1641 */ 1642static isc_result_t 1643next_active(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, 1644 dns_dbversion_t *ver, dns_name_t *oldname, dns_name_t *newname, 1645 isc_boolean_t forward) 1646{ 1647 isc_result_t result; 1648 dns_dbiterator_t *dbit = NULL; 1649 isc_boolean_t has_nsec; 1650 unsigned int wraps = 0; 1651 isc_boolean_t secure = dns_db_issecure(db); 1652 1653 CHECK(dns_db_createiterator(db, 0, &dbit)); 1654 1655 CHECK(dns_dbiterator_seek(dbit, oldname)); 1656 do { 1657 dns_dbnode_t *node = NULL; 1658 1659 if (forward) 1660 result = dns_dbiterator_next(dbit); 1661 else 1662 result = dns_dbiterator_prev(dbit); 1663 if (result == ISC_R_NOMORE) { 1664 /* 1665 * Wrap around. 1666 */ 1667 if (forward) 1668 CHECK(dns_dbiterator_first(dbit)); 1669 else 1670 CHECK(dns_dbiterator_last(dbit)); 1671 wraps++; 1672 if (wraps == 2) { 1673 update_log(client, zone, ISC_LOG_ERROR, 1674 "secure zone with no NSECs"); 1675 result = DNS_R_BADZONE; 1676 goto failure; 1677 } 1678 } 1679 CHECK(dns_dbiterator_current(dbit, &node, newname)); 1680 dns_db_detachnode(db, &node); 1681 1682 /* 1683 * The iterator may hold the tree lock, and 1684 * rrset_exists() calls dns_db_findnode() which 1685 * may try to reacquire it. To avoid deadlock 1686 * we must pause the iterator first. 1687 */ 1688 CHECK(dns_dbiterator_pause(dbit)); 1689 if (secure) { 1690 CHECK(rrset_exists(db, ver, newname, 1691 dns_rdatatype_nsec, 0, &has_nsec)); 1692 } else { 1693 dns_fixedname_t ffound; 1694 dns_name_t *found; 1695 dns_fixedname_init(&ffound); 1696 found = dns_fixedname_name(&ffound); 1697 result = dns_db_find(db, newname, ver, 1698 dns_rdatatype_soa, 1699 DNS_DBFIND_NOWILD, 0, NULL, found, 1700 NULL, NULL); 1701 if (result == ISC_R_SUCCESS || 1702 result == DNS_R_EMPTYNAME || 1703 result == DNS_R_NXRRSET || 1704 result == DNS_R_CNAME || 1705 (result == DNS_R_DELEGATION && 1706 dns_name_equal(newname, found))) { 1707 has_nsec = ISC_TRUE; 1708 result = ISC_R_SUCCESS; 1709 } else if (result != DNS_R_NXDOMAIN) 1710 break; 1711 } 1712 } while (! has_nsec); 1713 failure: 1714 if (dbit != NULL) 1715 dns_dbiterator_destroy(&dbit); 1716 1717 return (result); 1718} 1719 1720static isc_boolean_t 1721has_opt_bit(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node) { 1722 isc_result_t result; 1723 dns_rdata_t rdata = DNS_RDATA_INIT; 1724 dns_rdataset_t rdataset; 1725 isc_boolean_t has_bit = ISC_FALSE; 1726 1727 dns_rdataset_init(&rdataset); 1728 CHECK(dns_db_findrdataset(db, node, version, dns_rdatatype_nsec, 1729 dns_rdatatype_none, 0, &rdataset, NULL)); 1730 CHECK(dns_rdataset_first(&rdataset)); 1731 dns_rdataset_current(&rdataset, &rdata); 1732 has_bit = dns_nsec_typepresent(&rdata, dns_rdatatype_opt); 1733 failure: 1734 if (dns_rdataset_isassociated(&rdataset)) 1735 dns_rdataset_disassociate(&rdataset); 1736 return (has_bit); 1737} 1738 1739static void 1740set_bit(unsigned char *array, unsigned int index) { 1741 unsigned int shift, bit; 1742 1743 shift = 7 - (index % 8); 1744 bit = 1 << shift; 1745 1746 array[index / 8] |= bit; 1747} 1748 1749/*% 1750 * Add a NSEC record for "name", recording the change in "diff". 1751 * The existing NSEC is removed. 1752 */ 1753static isc_result_t 1754add_nsec(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, 1755 dns_dbversion_t *ver, dns_name_t *name, dns_ttl_t nsecttl, 1756 dns_diff_t *diff) 1757{ 1758 isc_result_t result; 1759 dns_dbnode_t *node = NULL; 1760 unsigned char buffer[DNS_NSEC_BUFFERSIZE]; 1761 dns_rdata_t rdata = DNS_RDATA_INIT; 1762 dns_difftuple_t *tuple = NULL; 1763 dns_fixedname_t fixedname; 1764 dns_name_t *target; 1765 1766 dns_fixedname_init(&fixedname); 1767 target = dns_fixedname_name(&fixedname); 1768 1769 /* 1770 * Find the successor name, aka NSEC target. 1771 */ 1772 CHECK(next_active(client, zone, db, ver, name, target, ISC_TRUE)); 1773 1774 /* 1775 * Create the NSEC RDATA. 1776 */ 1777 CHECK(dns_db_findnode(db, name, ISC_FALSE, &node)); 1778 dns_rdata_init(&rdata); 1779 CHECK(dns_nsec_buildrdata(db, ver, node, target, buffer, &rdata)); 1780 /* 1781 * Preserve the status of the OPT bit in the origin's NSEC record. 1782 */ 1783 if (dns_name_equal(dns_db_origin(db), name) && 1784 has_opt_bit(db, ver, node)) 1785 { 1786 isc_region_t region; 1787 dns_name_t next; 1788 1789 dns_name_init(&next, NULL); 1790 dns_rdata_toregion(&rdata, ®ion); 1791 dns_name_fromregion(&next, ®ion); 1792 isc_region_consume(®ion, next.length); 1793 INSIST(region.length > (2 + dns_rdatatype_opt / 8) && 1794 region.base[0] == 0 && 1795 region.base[1] > dns_rdatatype_opt / 8); 1796 set_bit(region.base + 2, dns_rdatatype_opt); 1797 } 1798 dns_db_detachnode(db, &node); 1799 1800 /* 1801 * Delete the old NSEC and record the change. 1802 */ 1803 CHECK(delete_if(true_p, db, ver, name, dns_rdatatype_nsec, 0, 1804 NULL, diff)); 1805 /* 1806 * Add the new NSEC and record the change. 1807 */ 1808 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, name, 1809 nsecttl, &rdata, &tuple)); 1810 CHECK(do_one_tuple(&tuple, db, ver, diff)); 1811 INSIST(tuple == NULL); 1812 1813 failure: 1814 if (node != NULL) 1815 dns_db_detachnode(db, &node); 1816 return (result); 1817} 1818 1819/*% 1820 * Add a placeholder NSEC record for "name", recording the change in "diff". 1821 */ 1822static isc_result_t 1823add_placeholder_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, 1824 dns_diff_t *diff) 1825{ 1826 isc_result_t result; 1827 dns_difftuple_t *tuple = NULL; 1828 isc_region_t r; 1829 unsigned char data[1] = { 0 }; /* The root domain, no bits. */ 1830 dns_rdata_t rdata = DNS_RDATA_INIT; 1831 1832 r.base = data; 1833 r.length = sizeof(data); 1834 dns_rdata_fromregion(&rdata, dns_db_class(db), dns_rdatatype_nsec, &r); 1835 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, name, 0, 1836 &rdata, &tuple)); 1837 CHECK(do_one_tuple(&tuple, db, ver, diff)); 1838 failure: 1839 return (result); 1840} 1841 1842static isc_result_t 1843find_zone_keys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, 1844 isc_mem_t *mctx, unsigned int maxkeys, 1845 dst_key_t **keys, unsigned int *nkeys) 1846{ 1847 isc_result_t result; 1848 dns_dbnode_t *node = NULL; 1849 const char *directory = dns_zone_getkeydirectory(zone); 1850 CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node)); 1851 CHECK(dns_dnssec_findzonekeys2(db, ver, node, dns_db_origin(db), 1852 directory, mctx, maxkeys, keys, nkeys)); 1853 failure: 1854 if (node != NULL) 1855 dns_db_detachnode(db, &node); 1856 return (result); 1857} 1858 1859static isc_boolean_t 1860ksk_sanity(dns_db_t *db, dns_dbversion_t *ver) { 1861 isc_boolean_t ret = ISC_FALSE; 1862 isc_boolean_t have_ksk = ISC_FALSE, have_nonksk = ISC_FALSE; 1863 isc_result_t result; 1864 dns_dbnode_t *node = NULL; 1865 dns_rdataset_t rdataset; 1866 dns_rdata_t rdata = DNS_RDATA_INIT; 1867 dns_rdata_dnskey_t dnskey; 1868 1869 dns_rdataset_init(&rdataset); 1870 CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node)); 1871 CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey, 0, 0, 1872 &rdataset, NULL)); 1873 CHECK(dns_rdataset_first(&rdataset)); 1874 while (result == ISC_R_SUCCESS && (!have_ksk || !have_nonksk)) { 1875 dns_rdataset_current(&rdataset, &rdata); 1876 CHECK(dns_rdata_tostruct(&rdata, &dnskey, NULL)); 1877 if ((dnskey.flags & (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH)) 1878 == DNS_KEYOWNER_ZONE) { 1879 if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0) 1880 have_ksk = ISC_TRUE; 1881 else 1882 have_nonksk = ISC_TRUE; 1883 } 1884 dns_rdata_reset(&rdata); 1885 result = dns_rdataset_next(&rdataset); 1886 } 1887 if (have_ksk && have_nonksk) 1888 ret = ISC_TRUE; 1889 failure: 1890 if (dns_rdataset_isassociated(&rdataset)) 1891 dns_rdataset_disassociate(&rdataset); 1892 if (node != NULL) 1893 dns_db_detachnode(db, &node); 1894 return (ret); 1895} 1896 1897/*% 1898 * Add RRSIG records for an RRset, recording the change in "diff". 1899 */ 1900static isc_result_t 1901add_sigs(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, 1902 dns_dbversion_t *ver, dns_name_t *name, dns_rdatatype_t type, 1903 dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys, 1904 isc_stdtime_t inception, isc_stdtime_t expire, 1905 isc_boolean_t check_ksk) 1906{ 1907 isc_result_t result; 1908 dns_dbnode_t *node = NULL; 1909 dns_rdataset_t rdataset; 1910 dns_rdata_t sig_rdata = DNS_RDATA_INIT; 1911 isc_buffer_t buffer; 1912 unsigned char data[1024]; /* XXX */ 1913 unsigned int i; 1914 isc_boolean_t added_sig = ISC_FALSE; 1915 isc_mem_t *mctx = client->mctx; 1916 1917 dns_rdataset_init(&rdataset); 1918 isc_buffer_init(&buffer, data, sizeof(data)); 1919 1920 /* Get the rdataset to sign. */ 1921 if (type == dns_rdatatype_nsec3) 1922 CHECK(dns_db_findnsec3node(db, name, ISC_FALSE, &node)); 1923 else 1924 CHECK(dns_db_findnode(db, name, ISC_FALSE, &node)); 1925 CHECK(dns_db_findrdataset(db, node, ver, type, 0, 1926 (isc_stdtime_t) 0, &rdataset, NULL)); 1927 dns_db_detachnode(db, &node); 1928 1929 for (i = 0; i < nkeys; i++) { 1930 1931 if (check_ksk && type != dns_rdatatype_dnskey && 1932 (dst_key_flags(keys[i]) & DNS_KEYFLAG_KSK) != 0) 1933 continue; 1934 1935 if (!dst_key_isprivate(keys[i])) 1936 continue; 1937 1938 /* Calculate the signature, creating a RRSIG RDATA. */ 1939 CHECK(dns_dnssec_sign(name, &rdataset, keys[i], 1940 &inception, &expire, 1941 mctx, &buffer, &sig_rdata)); 1942 1943 /* Update the database and journal with the RRSIG. */ 1944 /* XXX inefficient - will cause dataset merging */ 1945 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN, name, 1946 rdataset.ttl, &sig_rdata)); 1947 dns_rdata_reset(&sig_rdata); 1948 added_sig = ISC_TRUE; 1949 } 1950 if (!added_sig) { 1951 update_log(client, zone, ISC_LOG_ERROR, 1952 "found no private keys, " 1953 "unable to generate any signatures"); 1954 result = ISC_R_NOTFOUND; 1955 } 1956 1957 failure: 1958 if (dns_rdataset_isassociated(&rdataset)) 1959 dns_rdataset_disassociate(&rdataset); 1960 if (node != NULL) 1961 dns_db_detachnode(db, &node); 1962 return (result); 1963} 1964 1965/* 1966 * Delete expired RRsigs and any RRsigs we are about to re-sign. 1967 * See also zone.c:del_sigs(). 1968 */ 1969static isc_result_t 1970del_keysigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, 1971 dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys) 1972{ 1973 isc_result_t result; 1974 dns_dbnode_t *node = NULL; 1975 dns_rdataset_t rdataset; 1976 dns_rdata_t rdata = DNS_RDATA_INIT; 1977 unsigned int i; 1978 dns_rdata_rrsig_t rrsig; 1979 isc_boolean_t found; 1980 1981 dns_rdataset_init(&rdataset); 1982 1983 result = dns_db_findnode(db, name, ISC_FALSE, &node); 1984 if (result == ISC_R_NOTFOUND) 1985 return (ISC_R_SUCCESS); 1986 if (result != ISC_R_SUCCESS) 1987 goto failure; 1988 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig, 1989 dns_rdatatype_dnskey, (isc_stdtime_t) 0, 1990 &rdataset, NULL); 1991 dns_db_detachnode(db, &node); 1992 1993 if (result == ISC_R_NOTFOUND) 1994 return (ISC_R_SUCCESS); 1995 if (result != ISC_R_SUCCESS) 1996 goto failure; 1997 1998 for (result = dns_rdataset_first(&rdataset); 1999 result == ISC_R_SUCCESS; 2000 result = dns_rdataset_next(&rdataset)) { 2001 dns_rdataset_current(&rdataset, &rdata); 2002 result = dns_rdata_tostruct(&rdata, &rrsig, NULL); 2003 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2004 found = ISC_FALSE; 2005 for (i = 0; i < nkeys; i++) { 2006 if (rrsig.keyid == dst_key_id(keys[i])) { 2007 found = ISC_TRUE; 2008 if (!dst_key_isprivate(keys[i])) { 2009 /* 2010 * The re-signing code in zone.c 2011 * will mark this as offline. 2012 * Just skip the record for now. 2013 */ 2014 break; 2015 } 2016 result = update_one_rr(db, ver, diff, 2017 DNS_DIFFOP_DEL, name, 2018 rdataset.ttl, &rdata); 2019 break; 2020 } 2021 } 2022 /* 2023 * If there is not a matching DNSKEY then delete the RRSIG. 2024 */ 2025 if (!found) 2026 result = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, 2027 name, rdataset.ttl, &rdata); 2028 dns_rdata_reset(&rdata); 2029 if (result != ISC_R_SUCCESS) 2030 break; 2031 } 2032 dns_rdataset_disassociate(&rdataset); 2033 if (result == ISC_R_NOMORE) 2034 result = ISC_R_SUCCESS; 2035failure: 2036 if (node != NULL) 2037 dns_db_detachnode(db, &node); 2038 return (result); 2039} 2040 2041static isc_result_t 2042add_exposed_sigs(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, 2043 dns_dbversion_t *ver, dns_name_t *name, isc_boolean_t cut, 2044 dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys, 2045 isc_stdtime_t inception, isc_stdtime_t expire, 2046 isc_boolean_t check_ksk) 2047{ 2048 isc_result_t result; 2049 dns_dbnode_t *node; 2050 dns_rdatasetiter_t *iter; 2051 2052 node = NULL; 2053 result = dns_db_findnode(db, name, ISC_FALSE, &node); 2054 if (result == ISC_R_NOTFOUND) 2055 return (ISC_R_SUCCESS); 2056 if (result != ISC_R_SUCCESS) 2057 return (result); 2058 2059 iter = NULL; 2060 result = dns_db_allrdatasets(db, node, ver, 2061 (isc_stdtime_t) 0, &iter); 2062 if (result != ISC_R_SUCCESS) 2063 goto cleanup_node; 2064 2065 for (result = dns_rdatasetiter_first(iter); 2066 result == ISC_R_SUCCESS; 2067 result = dns_rdatasetiter_next(iter)) 2068 { 2069 dns_rdataset_t rdataset; 2070 dns_rdatatype_t type; 2071 isc_boolean_t flag; 2072 2073 dns_rdataset_init(&rdataset); 2074 dns_rdatasetiter_current(iter, &rdataset); 2075 type = rdataset.type; 2076 dns_rdataset_disassociate(&rdataset); 2077 2078 /* 2079 * We don't need to sign unsigned NSEC records at the cut 2080 * as they are handled elsewhere. 2081 */ 2082 if ((type == dns_rdatatype_rrsig) || 2083 (cut && type != dns_rdatatype_ds)) 2084 continue; 2085 result = rrset_exists(db, ver, name, dns_rdatatype_rrsig, 2086 type, &flag); 2087 if (result != ISC_R_SUCCESS) 2088 goto cleanup_iterator; 2089 if (flag) 2090 continue;; 2091 result = add_sigs(client, zone, db, ver, name, type, diff, 2092 keys, nkeys, inception, expire, check_ksk); 2093 if (result != ISC_R_SUCCESS) 2094 goto cleanup_iterator; 2095 } 2096 if (result == ISC_R_NOMORE) 2097 result = ISC_R_SUCCESS; 2098 2099 cleanup_iterator: 2100 dns_rdatasetiter_destroy(&iter); 2101 2102 cleanup_node: 2103 dns_db_detachnode(db, &node); 2104 2105 return (result); 2106} 2107 2108/*% 2109 * Update RRSIG, NSEC and NSEC3 records affected by an update. The original 2110 * update, including the SOA serial update but excluding the RRSIG & NSEC 2111 * changes, is in "diff" and has already been applied to "newver" of "db". 2112 * The database version prior to the update is "oldver". 2113 * 2114 * The necessary RRSIG, NSEC and NSEC3 changes will be applied to "newver" 2115 * and added (as a minimal diff) to "diff". 2116 * 2117 * The RRSIGs generated will be valid for 'sigvalidityinterval' seconds. 2118 */ 2119static isc_result_t 2120update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, 2121 dns_dbversion_t *oldver, dns_dbversion_t *newver, 2122 dns_diff_t *diff, isc_uint32_t sigvalidityinterval, 2123 isc_boolean_t *deleted_zsk) 2124{ 2125 isc_result_t result; 2126 dns_difftuple_t *t; 2127 dns_diff_t diffnames; 2128 dns_diff_t affected; 2129 dns_diff_t sig_diff; 2130 dns_diff_t nsec_diff; 2131 dns_diff_t nsec_mindiff; 2132 isc_boolean_t flag; 2133 dst_key_t *zone_keys[MAXZONEKEYS]; 2134 unsigned int nkeys = 0; 2135 unsigned int i; 2136 isc_stdtime_t now, inception, expire; 2137 dns_ttl_t nsecttl; 2138 dns_rdata_soa_t soa; 2139 dns_rdata_t rdata = DNS_RDATA_INIT; 2140 dns_rdataset_t rdataset; 2141 dns_dbnode_t *node = NULL; 2142 isc_boolean_t check_ksk; 2143 isc_boolean_t unsecure; 2144 isc_boolean_t cut; 2145 2146 dns_diff_init(client->mctx, &diffnames); 2147 dns_diff_init(client->mctx, &affected); 2148 2149 dns_diff_init(client->mctx, &sig_diff); 2150 sig_diff.resign = dns_zone_getsigresigninginterval(zone); 2151 dns_diff_init(client->mctx, &nsec_diff); 2152 dns_diff_init(client->mctx, &nsec_mindiff); 2153 2154 result = find_zone_keys(zone, db, newver, client->mctx, 2155 MAXZONEKEYS, zone_keys, &nkeys); 2156 if (result != ISC_R_SUCCESS) { 2157 update_log(client, zone, ISC_LOG_ERROR, 2158 "could not get zone keys for secure dynamic update"); 2159 goto failure; 2160 } 2161 2162 isc_stdtime_get(&now); 2163 inception = now - 3600; /* Allow for some clock skew. */ 2164 expire = now + sigvalidityinterval; 2165 2166 /* 2167 * Do we look at the KSK flag on the DNSKEY to determining which 2168 * keys sign which RRsets? First check the zone option then 2169 * check the keys flags to make sure at least one has a ksk set 2170 * and one doesn't. 2171 */ 2172 check_ksk = ISC_TF((dns_zone_getoptions(zone) & 2173 DNS_ZONEOPT_UPDATECHECKKSK) != 0); 2174 /* 2175 * If we are not checking the ZSK flag then all DNSKEY's are 2176 * already signing all RRsets so we don't need to trigger special 2177 * changes. 2178 */ 2179 if (*deleted_zsk && (!check_ksk || !ksk_sanity(db, oldver))) 2180 *deleted_zsk = ISC_FALSE; 2181 2182 if (check_ksk) { 2183 check_ksk = ksk_sanity(db, newver); 2184 if (!check_ksk && ksk_sanity(db, oldver)) 2185 update_log(client, zone, ISC_LOG_WARNING, 2186 "disabling update-check-ksk"); 2187 } 2188 2189 /* 2190 * If we have deleted a ZSK and we we still have some ZSK's 2191 * we don't need to convert the KSK's to a ZSK's. 2192 */ 2193 if (*deleted_zsk && check_ksk) 2194 *deleted_zsk = ISC_FALSE; 2195 2196 /* 2197 * Get the NSEC/NSEC3 TTL from the SOA MINIMUM field. 2198 */ 2199 CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node)); 2200 dns_rdataset_init(&rdataset); 2201 CHECK(dns_db_findrdataset(db, node, newver, dns_rdatatype_soa, 0, 2202 (isc_stdtime_t) 0, &rdataset, NULL)); 2203 CHECK(dns_rdataset_first(&rdataset)); 2204 dns_rdataset_current(&rdataset, &rdata); 2205 CHECK(dns_rdata_tostruct(&rdata, &soa, NULL)); 2206 nsecttl = soa.minimum; 2207 dns_rdataset_disassociate(&rdataset); 2208 dns_db_detachnode(db, &node); 2209 2210 /* 2211 * Find all RRsets directly affected by the update, and 2212 * update their RRSIGs. Also build a list of names affected 2213 * by the update in "diffnames". 2214 */ 2215 CHECK(dns_diff_sort(diff, temp_order)); 2216 2217 t = ISC_LIST_HEAD(diff->tuples); 2218 while (t != NULL) { 2219 dns_name_t *name = &t->name; 2220 /* Now "name" is a new, unique name affected by the update. */ 2221 2222 CHECK(namelist_append_name(&diffnames, name)); 2223 2224 while (t != NULL && dns_name_equal(&t->name, name)) { 2225 dns_rdatatype_t type; 2226 type = t->rdata.type; 2227 2228 /* 2229 * Now "name" and "type" denote a new unique RRset 2230 * affected by the update. 2231 */ 2232 2233 /* Don't sign RRSIGs. */ 2234 if (type == dns_rdatatype_rrsig) 2235 goto skip; 2236 2237 /* 2238 * Delete all old RRSIGs covering this type, since they 2239 * are all invalid when the signed RRset has changed. 2240 * We may not be able to recreate all of them - tough. 2241 * Special case changes to the zone's DNSKEY records 2242 * to support offline KSKs. 2243 */ 2244 if (type == dns_rdatatype_dnskey) 2245 del_keysigs(db, newver, name, &sig_diff, 2246 zone_keys, nkeys); 2247 else 2248 CHECK(delete_if(true_p, db, newver, name, 2249 dns_rdatatype_rrsig, type, 2250 NULL, &sig_diff)); 2251 2252 /* 2253 * If this RRset is still visible after the update, 2254 * add a new signature for it. 2255 */ 2256 CHECK(rrset_visible(db, newver, name, type, &flag)); 2257 if (flag) { 2258 CHECK(add_sigs(client, zone, db, newver, name, 2259 type, &sig_diff, zone_keys, 2260 nkeys, inception, expire, 2261 check_ksk)); 2262 } 2263 skip: 2264 /* Skip any other updates to the same RRset. */ 2265 while (t != NULL && 2266 dns_name_equal(&t->name, name) && 2267 t->rdata.type == type) 2268 { 2269 t = ISC_LIST_NEXT(t, link); 2270 } 2271 } 2272 } 2273 update_log(client, zone, ISC_LOG_DEBUG(3), "updated data signatures"); 2274 2275 /* Remove orphaned NSECs and RRSIG NSECs. */ 2276 for (t = ISC_LIST_HEAD(diffnames.tuples); 2277 t != NULL; 2278 t = ISC_LIST_NEXT(t, link)) 2279 { 2280 CHECK(non_nsec_rrset_exists(db, newver, &t->name, &flag)); 2281 if (! flag) { 2282 CHECK(delete_if(true_p, db, newver, &t->name, 2283 dns_rdatatype_any, 0, 2284 NULL, &sig_diff)); 2285 } 2286 } 2287 update_log(client, zone, ISC_LOG_DEBUG(3), 2288 "removed any orphaned NSEC records"); 2289 2290 /* 2291 * If we don't have a NSEC record at the origin then we need to 2292 * update the NSEC3 records. 2293 */ 2294 CHECK(rrset_exists(db, newver, dns_db_origin(db), dns_rdatatype_nsec, 2295 0, &flag)); 2296 if (!flag) 2297 goto update_nsec3; 2298 2299 update_log(client, zone, ISC_LOG_DEBUG(3), "rebuilding NSEC chain"); 2300 2301 /* 2302 * When a name is created or deleted, its predecessor needs to 2303 * have its NSEC updated. 2304 */ 2305 for (t = ISC_LIST_HEAD(diffnames.tuples); 2306 t != NULL; 2307 t = ISC_LIST_NEXT(t, link)) 2308 { 2309 isc_boolean_t existed, exists; 2310 dns_fixedname_t fixedname; 2311 dns_name_t *prevname; 2312 2313 dns_fixedname_init(&fixedname); 2314 prevname = dns_fixedname_name(&fixedname); 2315 2316 CHECK(name_exists(db, oldver, &t->name, &existed)); 2317 CHECK(name_exists(db, newver, &t->name, &exists)); 2318 if (exists == existed) 2319 continue; 2320 2321 /* 2322 * Find the predecessor. 2323 * When names become obscured or unobscured in this update 2324 * transaction, we may find the wrong predecessor because 2325 * the NSECs have not yet been updated to reflect the delegation 2326 * change. This should not matter because in this case, 2327 * the correct predecessor is either the delegation node or 2328 * a newly unobscured node, and those nodes are on the 2329 * "affected" list in any case. 2330 */ 2331 CHECK(next_active(client, zone, db, newver, 2332 &t->name, prevname, ISC_FALSE)); 2333 CHECK(namelist_append_name(&affected, prevname)); 2334 } 2335 2336 /* 2337 * Find names potentially affected by delegation changes 2338 * (obscured by adding an NS or DNAME, or unobscured by 2339 * removing one). 2340 */ 2341 for (t = ISC_LIST_HEAD(diffnames.tuples); 2342 t != NULL; 2343 t = ISC_LIST_NEXT(t, link)) 2344 { 2345 isc_boolean_t ns_existed, dname_existed; 2346 isc_boolean_t ns_exists, dname_exists; 2347 2348 CHECK(rrset_exists(db, oldver, &t->name, dns_rdatatype_ns, 0, 2349 &ns_existed)); 2350 CHECK(rrset_exists(db, oldver, &t->name, dns_rdatatype_dname, 0, 2351 &dname_existed)); 2352 CHECK(rrset_exists(db, newver, &t->name, dns_rdatatype_ns, 0, 2353 &ns_exists)); 2354 CHECK(rrset_exists(db, newver, &t->name, dns_rdatatype_dname, 0, 2355 &dname_exists)); 2356 if ((ns_exists || dname_exists) == (ns_existed || dname_existed)) 2357 continue; 2358 /* 2359 * There was a delegation change. Mark all subdomains 2360 * of t->name as potentially needing a NSEC update. 2361 */ 2362 CHECK(namelist_append_subdomain(db, &t->name, &affected)); 2363 } 2364 2365 ISC_LIST_APPENDLIST(affected.tuples, diffnames.tuples, link); 2366 INSIST(ISC_LIST_EMPTY(diffnames.tuples)); 2367 2368 CHECK(uniqify_name_list(&affected)); 2369 2370 /* 2371 * Determine which names should have NSECs, and delete/create 2372 * NSECs to make it so. We don't know the final NSEC targets yet, 2373 * so we just create placeholder NSECs with arbitrary contents 2374 * to indicate that their respective owner names should be part of 2375 * the NSEC chain. 2376 */ 2377 for (t = ISC_LIST_HEAD(affected.tuples); 2378 t != NULL; 2379 t = ISC_LIST_NEXT(t, link)) 2380 { 2381 isc_boolean_t exists; 2382 dns_name_t *name = &t->name; 2383 2384 CHECK(name_exists(db, newver, name, &exists)); 2385 if (! exists) 2386 continue; 2387 CHECK(is_active(db, newver, name, &flag, &cut, NULL)); 2388 if (!flag) { 2389 /* 2390 * This name is obscured. Delete any 2391 * existing NSEC record. 2392 */ 2393 CHECK(delete_if(true_p, db, newver, name, 2394 dns_rdatatype_nsec, 0, 2395 NULL, &nsec_diff)); 2396 CHECK(delete_if(rrsig_p, db, newver, name, 2397 dns_rdatatype_any, 0, NULL, diff)); 2398 } else { 2399 /* 2400 * This name is not obscured. It should have a NSEC. 2401 */ 2402 CHECK(rrset_exists(db, newver, name, 2403 dns_rdatatype_nsec, 0, &flag)); 2404 if (! flag) 2405 CHECK(add_placeholder_nsec(db, newver, name, 2406 diff)); 2407 CHECK(add_exposed_sigs(client, zone, db, newver, name, 2408 cut, diff, zone_keys, nkeys, 2409 inception, expire, check_ksk)); 2410 } 2411 } 2412 2413 /* 2414 * Now we know which names are part of the NSEC chain. 2415 * Make them all point at their correct targets. 2416 */ 2417 for (t = ISC_LIST_HEAD(affected.tuples); 2418 t != NULL; 2419 t = ISC_LIST_NEXT(t, link)) 2420 { 2421 CHECK(rrset_exists(db, newver, &t->name, 2422 dns_rdatatype_nsec, 0, &flag)); 2423 if (flag) { 2424 /* 2425 * There is a NSEC, but we don't know if it is correct. 2426 * Delete it and create a correct one to be sure. 2427 * If the update was unnecessary, the diff minimization 2428 * will take care of eliminating it from the journal, 2429 * IXFRs, etc. 2430 * 2431 * The RRSIG bit should always be set in the NSECs 2432 * we generate, because they will all get RRSIG NSECs. 2433 * (XXX what if the zone keys are missing?). 2434 * Because the RRSIG NSECs have not necessarily been 2435 * created yet, the correctness of the bit mask relies 2436 * on the assumption that NSECs are only created if 2437 * there is other data, and if there is other data, 2438 * there are other RRSIGs. 2439 */ 2440 CHECK(add_nsec(client, zone, db, newver, &t->name, 2441 nsecttl, &nsec_diff)); 2442 } 2443 } 2444 2445 /* 2446 * Minimize the set of NSEC updates so that we don't 2447 * have to regenerate the RRSIG NSECs for NSECs that were 2448 * replaced with identical ones. 2449 */ 2450 while ((t = ISC_LIST_HEAD(nsec_diff.tuples)) != NULL) { 2451 ISC_LIST_UNLINK(nsec_diff.tuples, t, link); 2452 dns_diff_appendminimal(&nsec_mindiff, &t); 2453 } 2454 2455 update_log(client, zone, ISC_LOG_DEBUG(3), 2456 "signing rebuilt NSEC chain"); 2457 2458 /* Update RRSIG NSECs. */ 2459 for (t = ISC_LIST_HEAD(nsec_mindiff.tuples); 2460 t != NULL; 2461 t = ISC_LIST_NEXT(t, link)) 2462 { 2463 if (t->op == DNS_DIFFOP_DEL) { 2464 CHECK(delete_if(true_p, db, newver, &t->name, 2465 dns_rdatatype_rrsig, dns_rdatatype_nsec, 2466 NULL, &sig_diff)); 2467 } else if (t->op == DNS_DIFFOP_ADD) { 2468 CHECK(add_sigs(client, zone, db, newver, &t->name, 2469 dns_rdatatype_nsec, &sig_diff, 2470 zone_keys, nkeys, inception, expire, 2471 check_ksk)); 2472 } else { 2473 INSIST(0); 2474 } 2475 } 2476 2477 update_nsec3: 2478 2479 /* Record our changes for the journal. */ 2480 while ((t = ISC_LIST_HEAD(sig_diff.tuples)) != NULL) { 2481 ISC_LIST_UNLINK(sig_diff.tuples, t, link); 2482 dns_diff_appendminimal(diff, &t); 2483 } 2484 while ((t = ISC_LIST_HEAD(nsec_mindiff.tuples)) != NULL) { 2485 ISC_LIST_UNLINK(nsec_mindiff.tuples, t, link); 2486 dns_diff_appendminimal(diff, &t); 2487 } 2488 2489 INSIST(ISC_LIST_EMPTY(sig_diff.tuples)); 2490 INSIST(ISC_LIST_EMPTY(nsec_diff.tuples)); 2491 INSIST(ISC_LIST_EMPTY(nsec_mindiff.tuples)); 2492 2493 /* 2494 * Check if we have any active NSEC3 chains by looking for a 2495 * NSEC3PARAM RRset. 2496 */ 2497 CHECK(rrset_exists(db, newver, dns_db_origin(db), 2498 dns_rdatatype_nsec3param, 0, &flag)); 2499 if (!flag) { 2500 update_log(client, zone, ISC_LOG_DEBUG(3), 2501 "no NSEC3 chains to rebuild"); 2502 goto failure; 2503 } 2504 2505 update_log(client, zone, ISC_LOG_DEBUG(3), "rebuilding NSEC3 chains"); 2506 2507 dns_diff_clear(&diffnames); 2508 dns_diff_clear(&affected); 2509 2510 CHECK(dns_diff_sort(diff, temp_order)); 2511 2512 /* 2513 * Find names potentially affected by delegation changes 2514 * (obscured by adding an NS or DNAME, or unobscured by 2515 * removing one). 2516 */ 2517 t = ISC_LIST_HEAD(diff->tuples); 2518 while (t != NULL) { 2519 dns_name_t *name = &t->name; 2520 2521 isc_boolean_t ns_existed, dname_existed; 2522 isc_boolean_t ns_exists, dname_exists; 2523 2524 if (t->rdata.type == dns_rdatatype_nsec || 2525 t->rdata.type == dns_rdatatype_rrsig) { 2526 t = ISC_LIST_NEXT(t, link); 2527 continue; 2528 } 2529 2530 CHECK(namelist_append_name(&affected, name)); 2531 2532 CHECK(rrset_exists(db, oldver, name, dns_rdatatype_ns, 0, 2533 &ns_existed)); 2534 CHECK(rrset_exists(db, oldver, name, dns_rdatatype_dname, 0, 2535 &dname_existed)); 2536 CHECK(rrset_exists(db, newver, name, dns_rdatatype_ns, 0, 2537 &ns_exists)); 2538 CHECK(rrset_exists(db, newver, name, dns_rdatatype_dname, 0, 2539 &dname_exists)); 2540 2541 if ((ns_exists || dname_exists) == (ns_existed || dname_existed)) 2542 goto nextname; 2543 /* 2544 * There was a delegation change. Mark all subdomains 2545 * of t->name as potentially needing a NSEC3 update. 2546 */ 2547 CHECK(namelist_append_subdomain(db, name, &affected)); 2548 2549 nextname: 2550 while (t != NULL && dns_name_equal(&t->name, name)) 2551 t = ISC_LIST_NEXT(t, link); 2552 } 2553 2554 for (t = ISC_LIST_HEAD(affected.tuples); 2555 t != NULL; 2556 t = ISC_LIST_NEXT(t, link)) { 2557 dns_name_t *name = &t->name; 2558 2559 unsecure = ISC_FALSE; /* Silence compiler warning. */ 2560 CHECK(is_active(db, newver, name, &flag, &cut, &unsecure)); 2561 2562 if (!flag) { 2563 CHECK(delete_if(rrsig_p, db, newver, name, 2564 dns_rdatatype_any, 0, NULL, diff)); 2565 CHECK(dns_nsec3_delnsec3s(db, newver, name, 2566 &nsec_diff)); 2567 } else { 2568 CHECK(add_exposed_sigs(client, zone, db, newver, name, 2569 cut, diff, zone_keys, nkeys, 2570 inception, expire, check_ksk)); 2571 CHECK(dns_nsec3_addnsec3s(db, newver, name, nsecttl, 2572 unsecure, &nsec_diff)); 2573 } 2574 } 2575 2576 /* 2577 * Minimize the set of NSEC3 updates so that we don't 2578 * have to regenerate the RRSIG NSEC3s for NSEC3s that were 2579 * replaced with identical ones. 2580 */ 2581 while ((t = ISC_LIST_HEAD(nsec_diff.tuples)) != NULL) { 2582 ISC_LIST_UNLINK(nsec_diff.tuples, t, link); 2583 dns_diff_appendminimal(&nsec_mindiff, &t); 2584 } 2585 2586 update_log(client, zone, ISC_LOG_DEBUG(3), 2587 "signing rebuilt NSEC3 chain"); 2588 2589 /* Update RRSIG NSEC3s. */ 2590 for (t = ISC_LIST_HEAD(nsec_mindiff.tuples); 2591 t != NULL; 2592 t = ISC_LIST_NEXT(t, link)) 2593 { 2594 if (t->op == DNS_DIFFOP_DEL) { 2595 CHECK(delete_if(true_p, db, newver, &t->name, 2596 dns_rdatatype_rrsig, 2597 dns_rdatatype_nsec3, 2598 NULL, &sig_diff)); 2599 } else if (t->op == DNS_DIFFOP_ADD) { 2600 CHECK(add_sigs(client, zone, db, newver, &t->name, 2601 dns_rdatatype_nsec3, 2602 &sig_diff, zone_keys, nkeys, 2603 inception, expire, check_ksk)); 2604 } else { 2605 INSIST(0); 2606 } 2607 } 2608 2609 /* Record our changes for the journal. */ 2610 while ((t = ISC_LIST_HEAD(sig_diff.tuples)) != NULL) { 2611 ISC_LIST_UNLINK(sig_diff.tuples, t, link); 2612 dns_diff_appendminimal(diff, &t); 2613 } 2614 while ((t = ISC_LIST_HEAD(nsec_mindiff.tuples)) != NULL) { 2615 ISC_LIST_UNLINK(nsec_mindiff.tuples, t, link); 2616 dns_diff_appendminimal(diff, &t); 2617 } 2618 2619 INSIST(ISC_LIST_EMPTY(sig_diff.tuples)); 2620 INSIST(ISC_LIST_EMPTY(nsec_diff.tuples)); 2621 INSIST(ISC_LIST_EMPTY(nsec_mindiff.tuples)); 2622 2623 failure: 2624 dns_diff_clear(&sig_diff); 2625 dns_diff_clear(&nsec_diff); 2626 dns_diff_clear(&nsec_mindiff); 2627 2628 dns_diff_clear(&affected); 2629 dns_diff_clear(&diffnames); 2630 2631 for (i = 0; i < nkeys; i++) 2632 dst_key_free(&zone_keys[i]); 2633 2634 return (result); 2635} 2636 2637 2638/**************************************************************************/ 2639/*% 2640 * The actual update code in all its glory. We try to follow 2641 * the RFC2136 pseudocode as closely as possible. 2642 */ 2643 2644static isc_result_t 2645send_update_event(ns_client_t *client, dns_zone_t *zone) { 2646 isc_result_t result = ISC_R_SUCCESS; 2647 update_event_t *event = NULL; 2648 isc_task_t *zonetask = NULL; 2649 ns_client_t *evclient; 2650 2651 event = (update_event_t *) 2652 isc_event_allocate(client->mctx, client, DNS_EVENT_UPDATE, 2653 update_action, NULL, sizeof(*event)); 2654 if (event == NULL) 2655 FAIL(ISC_R_NOMEMORY); 2656 event->zone = zone; 2657 event->result = ISC_R_SUCCESS; 2658 2659 evclient = NULL; 2660 ns_client_attach(client, &evclient); 2661 INSIST(client->nupdates == 0); 2662 client->nupdates++; 2663 event->ev_arg = evclient; 2664 2665 dns_zone_gettask(zone, &zonetask); 2666 isc_task_send(zonetask, ISC_EVENT_PTR(&event)); 2667 2668 failure: 2669 if (event != NULL) 2670 isc_event_free(ISC_EVENT_PTR(&event)); 2671 return (result); 2672} 2673 2674static void 2675respond(ns_client_t *client, isc_result_t result) { 2676 isc_result_t msg_result; 2677 2678 msg_result = dns_message_reply(client->message, ISC_TRUE); 2679 if (msg_result != ISC_R_SUCCESS) 2680 goto msg_failure; 2681 client->message->rcode = dns_result_torcode(result); 2682 2683 ns_client_send(client); 2684 return; 2685 2686 msg_failure: 2687 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_UPDATE, NS_LOGMODULE_UPDATE, 2688 ISC_LOG_ERROR, 2689 "could not create update response message: %s", 2690 isc_result_totext(msg_result)); 2691 ns_client_next(client, msg_result); 2692} 2693 2694void 2695ns_update_start(ns_client_t *client, isc_result_t sigresult) { 2696 dns_message_t *request = client->message; 2697 isc_result_t result; 2698 dns_name_t *zonename; 2699 dns_rdataset_t *zone_rdataset; 2700 dns_zone_t *zone = NULL; 2701 2702 /* 2703 * Interpret the zone section. 2704 */ 2705 result = dns_message_firstname(request, DNS_SECTION_ZONE); 2706 if (result != ISC_R_SUCCESS) 2707 FAILC(DNS_R_FORMERR, "update zone section empty"); 2708 2709 /* 2710 * The zone section must contain exactly one "question", and 2711 * it must be of type SOA. 2712 */ 2713 zonename = NULL; 2714 dns_message_currentname(request, DNS_SECTION_ZONE, &zonename); 2715 zone_rdataset = ISC_LIST_HEAD(zonename->list); 2716 if (zone_rdataset->type != dns_rdatatype_soa) 2717 FAILC(DNS_R_FORMERR, 2718 "update zone section contains non-SOA"); 2719 if (ISC_LIST_NEXT(zone_rdataset, link) != NULL) 2720 FAILC(DNS_R_FORMERR, 2721 "update zone section contains multiple RRs"); 2722 2723 /* The zone section must have exactly one name. */ 2724 result = dns_message_nextname(request, DNS_SECTION_ZONE); 2725 if (result != ISC_R_NOMORE) 2726 FAILC(DNS_R_FORMERR, 2727 "update zone section contains multiple RRs"); 2728 2729 result = dns_zt_find(client->view->zonetable, zonename, 0, NULL, 2730 &zone); 2731 if (result != ISC_R_SUCCESS) 2732 FAILC(DNS_R_NOTAUTH, "not authoritative for update zone"); 2733 2734 switch(dns_zone_gettype(zone)) { 2735 case dns_zone_master: 2736 /* 2737 * We can now fail due to a bad signature as we now know 2738 * that we are the master. 2739 */ 2740 if (sigresult != ISC_R_SUCCESS) 2741 FAIL(sigresult); 2742 CHECK(send_update_event(client, zone)); 2743 break; 2744 case dns_zone_slave: 2745 CHECK(checkupdateacl(client, dns_zone_getforwardacl(zone), 2746 "update forwarding", zonename, ISC_TRUE, 2747 ISC_FALSE)); 2748 CHECK(send_forward_event(client, zone)); 2749 break; 2750 default: 2751 FAILC(DNS_R_NOTAUTH, "not authoritative for update zone"); 2752 } 2753 return; 2754 2755 failure: 2756 if (result == DNS_R_REFUSED) { 2757 INSIST(dns_zone_gettype(zone) == dns_zone_slave); 2758 inc_stats(zone, dns_nsstatscounter_updaterej); 2759 } 2760 /* 2761 * We failed without having sent an update event to the zone. 2762 * We are still in the client task context, so we can 2763 * simply give an error response without switching tasks. 2764 */ 2765 respond(client, result); 2766 if (zone != NULL) 2767 dns_zone_detach(&zone); 2768} 2769 2770/*% 2771 * DS records are not allowed to exist without corresponding NS records, 2772 * RFC 3658, 2.2 Protocol Change, 2773 * "DS RRsets MUST NOT appear at non-delegation points or at a zone's apex". 2774 */ 2775 2776static isc_result_t 2777remove_orphaned_ds(dns_db_t *db, dns_dbversion_t *newver, dns_diff_t *diff) { 2778 isc_result_t result; 2779 isc_boolean_t ns_exists; 2780 dns_difftuple_t *tupple; 2781 dns_diff_t temp_diff; 2782 2783 dns_diff_init(diff->mctx, &temp_diff); 2784 2785 for (tupple = ISC_LIST_HEAD(diff->tuples); 2786 tupple != NULL; 2787 tupple = ISC_LIST_NEXT(tupple, link)) { 2788 if (!((tupple->op == DNS_DIFFOP_DEL && 2789 tupple->rdata.type == dns_rdatatype_ns) || 2790 (tupple->op == DNS_DIFFOP_ADD && 2791 tupple->rdata.type == dns_rdatatype_ds))) 2792 continue; 2793 CHECK(rrset_exists(db, newver, &tupple->name, 2794 dns_rdatatype_ns, 0, &ns_exists)); 2795 if (ns_exists && 2796 !dns_name_equal(&tupple->name, dns_db_origin(db))) 2797 continue; 2798 CHECK(delete_if(true_p, db, newver, &tupple->name, 2799 dns_rdatatype_ds, 0, NULL, &temp_diff)); 2800 } 2801 result = ISC_R_SUCCESS; 2802 2803 failure: 2804 for (tupple = ISC_LIST_HEAD(temp_diff.tuples); 2805 tupple != NULL; 2806 tupple = ISC_LIST_HEAD(temp_diff.tuples)) { 2807 ISC_LIST_UNLINK(temp_diff.tuples, tupple, link); 2808 dns_diff_appendminimal(diff, &tupple); 2809 } 2810 return (result); 2811} 2812 2813/* 2814 * This implements the post load integrity checks for mx records. 2815 */ 2816static isc_result_t 2817check_mx(ns_client_t *client, dns_zone_t *zone, 2818 dns_db_t *db, dns_dbversion_t *newver, dns_diff_t *diff) 2819{ 2820 char tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:123.123.123.123.")]; 2821 char ownerbuf[DNS_NAME_FORMATSIZE]; 2822 char namebuf[DNS_NAME_FORMATSIZE]; 2823 char altbuf[DNS_NAME_FORMATSIZE]; 2824 dns_difftuple_t *t; 2825 dns_fixedname_t fixed; 2826 dns_name_t *foundname; 2827 dns_rdata_mx_t mx; 2828 dns_rdata_t rdata; 2829 isc_boolean_t ok = ISC_TRUE; 2830 isc_boolean_t isaddress; 2831 isc_result_t result; 2832 struct in6_addr addr6; 2833 struct in_addr addr; 2834 unsigned int options; 2835 2836 dns_fixedname_init(&fixed); 2837 foundname = dns_fixedname_name(&fixed); 2838 dns_rdata_init(&rdata); 2839 options = dns_zone_getoptions(zone); 2840 2841 for (t = ISC_LIST_HEAD(diff->tuples); 2842 t != NULL; 2843 t = ISC_LIST_NEXT(t, link)) { 2844 if (t->op != DNS_DIFFOP_ADD || 2845 t->rdata.type != dns_rdatatype_mx) 2846 continue; 2847 2848 result = dns_rdata_tostruct(&t->rdata, &mx, NULL); 2849 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2850 /* 2851 * Check if we will error out if we attempt to reload the 2852 * zone. 2853 */ 2854 dns_name_format(&mx.mx, namebuf, sizeof(namebuf)); 2855 dns_name_format(&t->name, ownerbuf, sizeof(ownerbuf)); 2856 isaddress = ISC_FALSE; 2857 if ((options & DNS_RDATA_CHECKMX) != 0 && 2858 strlcpy(tmp, namebuf, sizeof(tmp)) < sizeof(tmp)) { 2859 if (tmp[strlen(tmp) - 1] == '.') 2860 tmp[strlen(tmp) - 1] = '\0'; 2861 if (inet_aton(tmp, &addr) == 1 || 2862 inet_pton(AF_INET6, tmp, &addr6) == 1) 2863 isaddress = ISC_TRUE; 2864 } 2865 2866 if (isaddress && (options & DNS_RDATA_CHECKMXFAIL) != 0) { 2867 update_log(client, zone, ISC_LOG_ERROR, 2868 "%s/MX: '%s': %s", 2869 ownerbuf, namebuf, 2870 dns_result_totext(DNS_R_MXISADDRESS)); 2871 ok = ISC_FALSE; 2872 } else if (isaddress) { 2873 update_log(client, zone, ISC_LOG_WARNING, 2874 "%s/MX: warning: '%s': %s", 2875 ownerbuf, namebuf, 2876 dns_result_totext(DNS_R_MXISADDRESS)); 2877 } 2878 2879 /* 2880 * Check zone integrity checks. 2881 */ 2882 if ((options & DNS_ZONEOPT_CHECKINTEGRITY) == 0) 2883 continue; 2884 result = dns_db_find(db, &mx.mx, newver, dns_rdatatype_a, 2885 0, 0, NULL, foundname, NULL, NULL); 2886 if (result == ISC_R_SUCCESS) 2887 continue; 2888 2889 if (result == DNS_R_NXRRSET) { 2890 result = dns_db_find(db, &mx.mx, newver, 2891 dns_rdatatype_aaaa, 2892 0, 0, NULL, foundname, 2893 NULL, NULL); 2894 if (result == ISC_R_SUCCESS) 2895 continue; 2896 } 2897 2898 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN) { 2899 update_log(client, zone, ISC_LOG_ERROR, 2900 "%s/MX '%s' has no address records " 2901 "(A or AAAA)", ownerbuf, namebuf); 2902 ok = ISC_FALSE; 2903 } else if (result == DNS_R_CNAME) { 2904 update_log(client, zone, ISC_LOG_ERROR, 2905 "%s/MX '%s' is a CNAME (illegal)", 2906 ownerbuf, namebuf); 2907 ok = ISC_FALSE; 2908 } else if (result == DNS_R_DNAME) { 2909 dns_name_format(foundname, altbuf, sizeof altbuf); 2910 update_log(client, zone, ISC_LOG_ERROR, 2911 "%s/MX '%s' is below a DNAME '%s' (illegal)", 2912 ownerbuf, namebuf, altbuf); 2913 ok = ISC_FALSE; 2914 } 2915 } 2916 return (ok ? ISC_R_SUCCESS : DNS_R_REFUSED); 2917} 2918 2919static isc_result_t 2920rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, 2921 const dns_rdata_t *rdata, isc_boolean_t *flag) 2922{ 2923 dns_rdataset_t rdataset; 2924 dns_dbnode_t *node = NULL; 2925 isc_result_t result; 2926 2927 dns_rdataset_init(&rdataset); 2928 if (rdata->type == dns_rdatatype_nsec3) 2929 CHECK(dns_db_findnsec3node(db, name, ISC_FALSE, &node)); 2930 else 2931 CHECK(dns_db_findnode(db, name, ISC_FALSE, &node)); 2932 result = dns_db_findrdataset(db, node, ver, rdata->type, 0, 2933 (isc_stdtime_t) 0, &rdataset, NULL); 2934 if (result == ISC_R_NOTFOUND) { 2935 *flag = ISC_FALSE; 2936 result = ISC_R_SUCCESS; 2937 goto failure; 2938 } 2939 2940 for (result = dns_rdataset_first(&rdataset); 2941 result == ISC_R_SUCCESS; 2942 result = dns_rdataset_next(&rdataset)) { 2943 dns_rdata_t myrdata = DNS_RDATA_INIT; 2944 dns_rdataset_current(&rdataset, &myrdata); 2945 if (!dns_rdata_compare(&myrdata, rdata)) 2946 break; 2947 } 2948 dns_rdataset_disassociate(&rdataset); 2949 if (result == ISC_R_SUCCESS) { 2950 *flag = ISC_TRUE; 2951 } else if (result == ISC_R_NOMORE) { 2952 *flag = ISC_FALSE; 2953 result = ISC_R_SUCCESS; 2954 } 2955 2956 failure: 2957 if (node != NULL) 2958 dns_db_detachnode(db, &node); 2959 return (result); 2960} 2961 2962static isc_result_t 2963get_iterations(dns_db_t *db, dns_dbversion_t *ver, unsigned int *iterationsp) { 2964 dns_dbnode_t *node = NULL; 2965 dns_rdata_nsec3param_t nsec3param; 2966 dns_rdataset_t rdataset; 2967 isc_result_t result; 2968 unsigned int iterations = 0; 2969 2970 dns_rdataset_init(&rdataset); 2971 2972 result = dns_db_getoriginnode(db, &node); 2973 if (result != ISC_R_SUCCESS) 2974 return (result); 2975 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param, 2976 0, (isc_stdtime_t) 0, &rdataset, NULL); 2977 dns_db_detachnode(db, &node); 2978 if (result == ISC_R_NOTFOUND) 2979 goto success; 2980 if (result != ISC_R_SUCCESS) 2981 goto failure; 2982 2983 for (result = dns_rdataset_first(&rdataset); 2984 result == ISC_R_SUCCESS; 2985 result = dns_rdataset_next(&rdataset)) { 2986 dns_rdata_t rdata = DNS_RDATA_INIT; 2987 dns_rdataset_current(&rdataset, &rdata); 2988 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL)); 2989 if ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) 2990 continue; 2991 if (nsec3param.iterations > iterations) 2992 iterations = nsec3param.iterations; 2993 } 2994 if (result != ISC_R_NOMORE) 2995 goto failure; 2996 2997 success: 2998 *iterationsp = iterations; 2999 result = ISC_R_SUCCESS; 3000 3001 failure: 3002 if (dns_rdataset_isassociated(&rdataset)) 3003 dns_rdataset_disassociate(&rdataset); 3004 return (result); 3005} 3006 3007/* 3008 * Prevent the zone entering a inconsistent state where 3009 * NSEC only DNSKEYs are present with NSEC3 chains. 3010 */ 3011static isc_result_t 3012check_dnssec(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, 3013 dns_dbversion_t *ver, dns_diff_t *diff) 3014{ 3015 dns_diff_t temp_diff; 3016 dns_diffop_t op; 3017 dns_difftuple_t *tuple, *newtuple = NULL, *next; 3018 isc_boolean_t flag; 3019 isc_result_t result; 3020 unsigned int iterations = 0, max; 3021 3022 dns_diff_init(diff->mctx, &temp_diff); 3023 3024 CHECK(dns_nsec_nseconly(db, ver, &flag)); 3025 3026 if (flag) 3027 CHECK(dns_nsec3_active(db, ver, ISC_FALSE, &flag)); 3028 if (flag) { 3029 update_log(client, zone, ISC_LOG_WARNING, 3030 "NSEC only DNSKEYs and NSEC3 chains not allowed"); 3031 } else { 3032 CHECK(get_iterations(db, ver, &iterations)); 3033 CHECK(dns_nsec3_maxiterations(db, ver, client->mctx, &max)); 3034 if (max != 0 && iterations > max) { 3035 flag = ISC_TRUE; 3036 update_log(client, zone, ISC_LOG_WARNING, 3037 "too many NSEC3 iterations (%u) for " 3038 "weakest DNSKEY (%u)", iterations, max); 3039 } 3040 } 3041 if (flag) { 3042 for (tuple = ISC_LIST_HEAD(diff->tuples); 3043 tuple != NULL; 3044 tuple = next) { 3045 next = ISC_LIST_NEXT(tuple, link); 3046 if (tuple->rdata.type != dns_rdatatype_dnskey && 3047 tuple->rdata.type != dns_rdatatype_nsec3param) 3048 continue; 3049 op = (tuple->op == DNS_DIFFOP_DEL) ? 3050 DNS_DIFFOP_ADD : DNS_DIFFOP_DEL; 3051 CHECK(dns_difftuple_create(temp_diff.mctx, op, 3052 &tuple->name, tuple->ttl, 3053 &tuple->rdata, &newtuple)); 3054 CHECK(do_one_tuple(&newtuple, db, ver, &temp_diff)); 3055 INSIST(newtuple == NULL); 3056 } 3057 for (tuple = ISC_LIST_HEAD(temp_diff.tuples); 3058 tuple != NULL; 3059 tuple = ISC_LIST_HEAD(temp_diff.tuples)) { 3060 ISC_LIST_UNLINK(temp_diff.tuples, tuple, link); 3061 dns_diff_appendminimal(diff, &tuple); 3062 } 3063 } 3064 3065 3066 failure: 3067 dns_diff_clear(&temp_diff); 3068 return (result); 3069} 3070 3071#ifdef ALLOW_NSEC3PARAM_UPDATE 3072/* 3073 * Delay NSEC3PARAM changes as they need to be applied to the whole zone. 3074 */ 3075static isc_result_t 3076add_nsec3param_records(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, 3077 dns_name_t *name, dns_dbversion_t *ver, dns_diff_t *diff) 3078{ 3079 isc_result_t result = ISC_R_SUCCESS; 3080 dns_difftuple_t *tuple, *newtuple = NULL, *next; 3081 dns_rdata_t rdata = DNS_RDATA_INIT; 3082 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE]; 3083 dns_diff_t temp_diff; 3084 dns_diffop_t op; 3085 isc_boolean_t flag; 3086 3087 update_log(client, zone, ISC_LOG_DEBUG(3), 3088 "checking for NSEC3PARAM changes"); 3089 3090 dns_diff_init(diff->mctx, &temp_diff); 3091 3092 /* 3093 * Extract NSEC3PARAM tuples from list. 3094 */ 3095 for (tuple = ISC_LIST_HEAD(diff->tuples); 3096 tuple != NULL; 3097 tuple = next) { 3098 3099 next = ISC_LIST_NEXT(tuple, link); 3100 3101 if (tuple->rdata.type != dns_rdatatype_nsec3param || 3102 !dns_name_equal(name, &tuple->name)) 3103 continue; 3104 ISC_LIST_UNLINK(diff->tuples, tuple, link); 3105 ISC_LIST_APPEND(temp_diff.tuples, tuple, link); 3106 } 3107 3108 for (tuple = ISC_LIST_HEAD(temp_diff.tuples); 3109 tuple != NULL; tuple = next) { 3110 3111 if (tuple->op == DNS_DIFFOP_ADD) { 3112 next = ISC_LIST_NEXT(tuple, link); 3113 while (next != NULL) { 3114 unsigned char *next_data = next->rdata.data; 3115 unsigned char *tuple_data = tuple->rdata.data; 3116 if (next_data[0] != tuple_data[0] || 3117 /* Ignore flags. */ 3118 next_data[2] != tuple_data[2] || 3119 next_data[3] != tuple_data[3] || 3120 next_data[4] != tuple_data[4] || 3121 !memcmp(&next_data[5], &tuple_data[5], 3122 tuple_data[4])) { 3123 next = ISC_LIST_NEXT(next, link); 3124 continue; 3125 } 3126 op = (next->op == DNS_DIFFOP_DEL) ? 3127 DNS_DIFFOP_ADD : DNS_DIFFOP_DEL; 3128 CHECK(dns_difftuple_create(diff->mctx, op, 3129 name, next->ttl, 3130 &next->rdata, 3131 &newtuple)); 3132 CHECK(do_one_tuple(&newtuple, db, ver, diff)); 3133 ISC_LIST_UNLINK(temp_diff.tuples, next, link); 3134 dns_diff_appendminimal(diff, &next); 3135 next = ISC_LIST_NEXT(tuple, link); 3136 } 3137 3138 INSIST(tuple->rdata.data[1] & DNS_NSEC3FLAG_UPDATE); 3139 3140 /* 3141 * See if we already have a CREATE request in progress. 3142 */ 3143 dns_rdata_clone(&tuple->rdata, &rdata); 3144 INSIST(rdata.length <= sizeof(buf)); 3145 memcpy(buf, rdata.data, rdata.length); 3146 buf[1] |= DNS_NSEC3FLAG_CREATE; 3147 buf[1] &= ~DNS_NSEC3FLAG_UPDATE; 3148 rdata.data = buf; 3149 3150 CHECK(rr_exists(db, ver, name, &rdata, &flag)); 3151 3152 if (!flag) { 3153 CHECK(dns_difftuple_create(diff->mctx, 3154 DNS_DIFFOP_ADD, 3155 name, tuple->ttl, 3156 &rdata, 3157 &newtuple)); 3158 CHECK(do_one_tuple(&newtuple, db, ver, diff)); 3159 } 3160 3161 /* 3162 * Remove any existing CREATE request to add an 3163 * otherwise indentical chain with a reversed 3164 * OPTOUT state. 3165 */ 3166 buf[1] ^= DNS_NSEC3FLAG_OPTOUT; 3167 CHECK(rr_exists(db, ver, name, &rdata, &flag)); 3168 3169 if (flag) { 3170 CHECK(dns_difftuple_create(diff->mctx, 3171 DNS_DIFFOP_DEL, 3172 name, tuple->ttl, 3173 &rdata, 3174 &newtuple)); 3175 CHECK(do_one_tuple(&newtuple, db, ver, diff)); 3176 } 3177 3178 /* 3179 * Remove the temporary add record. 3180 */ 3181 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, 3182 name, tuple->ttl, 3183 &tuple->rdata, &newtuple)); 3184 CHECK(do_one_tuple(&newtuple, db, ver, diff)); 3185 next = ISC_LIST_NEXT(tuple, link); 3186 ISC_LIST_UNLINK(temp_diff.tuples, tuple, link); 3187 dns_diff_appendminimal(diff, &tuple); 3188 dns_rdata_reset(&rdata); 3189 } else 3190 next = ISC_LIST_NEXT(tuple, link); 3191 } 3192 3193 /* 3194 * Reverse any pending changes. 3195 */ 3196 for (tuple = ISC_LIST_HEAD(temp_diff.tuples); 3197 tuple != NULL; tuple = next) { 3198 next = ISC_LIST_NEXT(tuple, link); 3199 if ((tuple->rdata.data[1] & ~DNS_NSEC3FLAG_OPTOUT) != 0) { 3200 op = (tuple->op == DNS_DIFFOP_DEL) ? 3201 DNS_DIFFOP_ADD : DNS_DIFFOP_DEL; 3202 CHECK(dns_difftuple_create(diff->mctx, op, name, 3203 tuple->ttl, &tuple->rdata, 3204 &newtuple)); 3205 CHECK(do_one_tuple(&newtuple, db, ver, diff)); 3206 ISC_LIST_UNLINK(temp_diff.tuples, tuple, link); 3207 dns_diff_appendminimal(diff, &tuple); 3208 } 3209 } 3210 3211 /* 3212 * Convert deletions into delayed deletions. 3213 */ 3214 for (tuple = ISC_LIST_HEAD(temp_diff.tuples); 3215 tuple != NULL; tuple = next) { 3216 next = ISC_LIST_NEXT(tuple, link); 3217 /* 3218 * See if we already have a REMOVE request in progress. 3219 */ 3220 dns_rdata_clone(&tuple->rdata, &rdata); 3221 INSIST(rdata.length <= sizeof(buf)); 3222 memcpy(buf, rdata.data, rdata.length); 3223 buf[1] |= DNS_NSEC3FLAG_REMOVE; 3224 rdata.data = buf; 3225 3226 CHECK(rr_exists(db, ver, name, &rdata, &flag)); 3227 3228 if (!flag) { 3229 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, 3230 name, tuple->ttl, &rdata, 3231 &newtuple)); 3232 CHECK(do_one_tuple(&newtuple, db, ver, diff)); 3233 } 3234 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, name, 3235 tuple->ttl, &tuple->rdata, 3236 &newtuple)); 3237 CHECK(do_one_tuple(&newtuple, db, ver, diff)); 3238 ISC_LIST_UNLINK(temp_diff.tuples, tuple, link); 3239 dns_diff_appendminimal(diff, &tuple); 3240 dns_rdata_reset(&rdata); 3241 } 3242 3243 result = ISC_R_SUCCESS; 3244 failure: 3245 dns_diff_clear(&temp_diff); 3246 return (result); 3247} 3248#endif 3249 3250/* 3251 * Add records to cause the delayed signing of the zone by added DNSKEY 3252 * to remove the RRSIG records generated by a deleted DNSKEY. 3253 */ 3254static isc_result_t 3255add_signing_records(dns_db_t *db, dns_name_t *name, dns_dbversion_t *ver, 3256 dns_rdatatype_t privatetype, dns_diff_t *diff) 3257{ 3258 dns_difftuple_t *tuple, *newtuple = NULL; 3259 dns_rdata_dnskey_t dnskey; 3260 dns_rdata_t rdata = DNS_RDATA_INIT; 3261 isc_boolean_t flag; 3262 isc_region_t r; 3263 isc_result_t result = ISC_R_SUCCESS; 3264 isc_uint16_t keyid; 3265 unsigned char buf[5]; 3266 3267 for (tuple = ISC_LIST_HEAD(diff->tuples); 3268 tuple != NULL; 3269 tuple = ISC_LIST_NEXT(tuple, link)) { 3270 if (tuple->rdata.type != dns_rdatatype_dnskey) 3271 continue; 3272 3273 dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL); 3274 if ((dnskey.flags & 3275 (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH)) 3276 != DNS_KEYOWNER_ZONE) 3277 continue; 3278 3279 dns_rdata_toregion(&tuple->rdata, &r); 3280 keyid = dst_region_computeid(&r, dnskey.algorithm); 3281 3282 buf[0] = dnskey.algorithm; 3283 buf[1] = (keyid & 0xff00) >> 8; 3284 buf[2] = (keyid & 0xff); 3285 buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1; 3286 buf[4] = 0; 3287 rdata.data = buf; 3288 rdata.length = sizeof(buf); 3289 rdata.type = privatetype; 3290 rdata.rdclass = tuple->rdata.rdclass; 3291 3292 CHECK(rr_exists(db, ver, name, &rdata, &flag)); 3293 if (flag) 3294 continue; 3295 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, 3296 name, 0, &rdata, &newtuple)); 3297 CHECK(do_one_tuple(&newtuple, db, ver, diff)); 3298 INSIST(newtuple == NULL); 3299 /* 3300 * Remove any record which says this operation has already 3301 * completed. 3302 */ 3303 buf[4] = 1; 3304 CHECK(rr_exists(db, ver, name, &rdata, &flag)); 3305 if (flag) { 3306 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, 3307 name, 0, &rdata, &newtuple)); 3308 CHECK(do_one_tuple(&newtuple, db, ver, diff)); 3309 INSIST(newtuple == NULL); 3310 } 3311 } 3312 failure: 3313 return (result); 3314} 3315 3316#ifdef ALLOW_NSEC3PARAM_UPDATE 3317/* 3318 * Mark all NSEC3 chains for deletion without creating a NSEC chain as 3319 * a side effect of deleting the last chain. 3320 */ 3321static isc_result_t 3322delete_chains(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin, 3323 dns_diff_t *diff) 3324{ 3325 dns_dbnode_t *node = NULL; 3326 dns_difftuple_t *tuple = NULL; 3327 dns_name_t next; 3328 dns_rdata_t rdata = DNS_RDATA_INIT; 3329 dns_rdataset_t rdataset; 3330 isc_boolean_t flag; 3331 isc_result_t result = ISC_R_SUCCESS; 3332 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE]; 3333 3334 dns_name_init(&next, NULL); 3335 dns_rdataset_init(&rdataset); 3336 3337 result = dns_db_getoriginnode(db, &node); 3338 if (result != ISC_R_SUCCESS) 3339 return (result); 3340 3341 /* 3342 * Cause all NSEC3 chains to be deleted. 3343 */ 3344 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param, 3345 0, (isc_stdtime_t) 0, &rdataset, NULL); 3346 if (result == ISC_R_NOTFOUND) 3347 goto success; 3348 if (result != ISC_R_SUCCESS) 3349 goto failure; 3350 3351 for (result = dns_rdataset_first(&rdataset); 3352 result == ISC_R_SUCCESS; 3353 result = dns_rdataset_next(&rdataset)) { 3354 dns_rdataset_current(&rdataset, &rdata); 3355 INSIST(rdata.length <= sizeof(buf)); 3356 memcpy(buf, rdata.data, rdata.length); 3357 3358 if (buf[1] == (DNS_NSEC3FLAG_REMOVE | DNS_NSEC3FLAG_NONSEC)) { 3359 dns_rdata_reset(&rdata); 3360 continue; 3361 } 3362 3363 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, 3364 origin, 0, &rdata, &tuple)); 3365 CHECK(do_one_tuple(&tuple, db, ver, diff)); 3366 INSIST(tuple == NULL); 3367 3368 buf[1] = DNS_NSEC3FLAG_REMOVE | DNS_NSEC3FLAG_NONSEC; 3369 rdata.data = buf; 3370 3371 CHECK(rr_exists(db, ver, origin, &rdata, &flag)); 3372 3373 if (!flag) { 3374 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, 3375 origin, 0, &rdata, &tuple)); 3376 CHECK(do_one_tuple(&tuple, db, ver, diff)); 3377 INSIST(tuple == NULL); 3378 } 3379 dns_rdata_reset(&rdata); 3380 } 3381 if (result != ISC_R_NOMORE) 3382 goto failure; 3383 success: 3384 result = ISC_R_SUCCESS; 3385 3386 failure: 3387 if (dns_rdataset_isassociated(&rdataset)) 3388 dns_rdataset_disassociate(&rdataset); 3389 dns_db_detachnode(db, &node); 3390 return (result); 3391} 3392#endif 3393 3394static void 3395update_action(isc_task_t *task, isc_event_t *event) { 3396 update_event_t *uev = (update_event_t *) event; 3397 dns_zone_t *zone = uev->zone; 3398 ns_client_t *client = (ns_client_t *)event->ev_arg; 3399 3400 isc_result_t result; 3401 dns_db_t *db = NULL; 3402 dns_dbversion_t *oldver = NULL; 3403 dns_dbversion_t *ver = NULL; 3404 dns_diff_t diff; /* Pending updates. */ 3405 dns_diff_t temp; /* Pending RR existence assertions. */ 3406 isc_boolean_t soa_serial_changed = ISC_FALSE; 3407 isc_mem_t *mctx = client->mctx; 3408 dns_rdatatype_t covers; 3409 dns_message_t *request = client->message; 3410 dns_rdataclass_t zoneclass; 3411 dns_name_t *zonename; 3412 dns_ssutable_t *ssutable = NULL; 3413 dns_fixedname_t tmpnamefixed; 3414 dns_name_t *tmpname = NULL; 3415 unsigned int options; 3416 isc_boolean_t deleted_zsk; 3417 dns_difftuple_t *tuple; 3418 dns_rdata_dnskey_t dnskey; 3419#ifdef ALLOW_NSEC3PARAM_UPDATE 3420 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE]; 3421#endif 3422#if !defined(ALLOW_SECURE_TO_INSECURE) || !defined(ALLOW_INSECURE_TO_SECURE) 3423 isc_boolean_t had_dnskey; 3424#endif 3425 3426 INSIST(event->ev_type == DNS_EVENT_UPDATE); 3427 3428 dns_diff_init(mctx, &diff); 3429 dns_diff_init(mctx, &temp); 3430 3431 CHECK(dns_zone_getdb(zone, &db)); 3432 zonename = dns_db_origin(db); 3433 zoneclass = dns_db_class(db); 3434 dns_zone_getssutable(zone, &ssutable); 3435 dns_db_currentversion(db, &oldver); 3436 CHECK(dns_db_newversion(db, &ver)); 3437 3438 /* 3439 * Check prerequisites. 3440 */ 3441 3442 for (result = dns_message_firstname(request, DNS_SECTION_PREREQUISITE); 3443 result == ISC_R_SUCCESS; 3444 result = dns_message_nextname(request, DNS_SECTION_PREREQUISITE)) 3445 { 3446 dns_name_t *name = NULL; 3447 dns_rdata_t rdata = DNS_RDATA_INIT; 3448 dns_ttl_t ttl; 3449 dns_rdataclass_t update_class; 3450 isc_boolean_t flag; 3451 3452 get_current_rr(request, DNS_SECTION_PREREQUISITE, zoneclass, 3453 &name, &rdata, &covers, &ttl, &update_class); 3454 3455 if (ttl != 0) 3456 PREREQFAILC(DNS_R_FORMERR, 3457 "prerequisite TTL is not zero"); 3458 3459 if (! dns_name_issubdomain(name, zonename)) 3460 PREREQFAILN(DNS_R_NOTZONE, name, 3461 "prerequisite name is out of zone"); 3462 3463 if (update_class == dns_rdataclass_any) { 3464 if (rdata.length != 0) 3465 PREREQFAILC(DNS_R_FORMERR, 3466 "class ANY prerequisite " 3467 "RDATA is not empty"); 3468 if (rdata.type == dns_rdatatype_any) { 3469 CHECK(name_exists(db, ver, name, &flag)); 3470 if (! flag) { 3471 PREREQFAILN(DNS_R_NXDOMAIN, name, 3472 "'name in use' " 3473 "prerequisite not " 3474 "satisfied"); 3475 } 3476 } else { 3477 CHECK(rrset_exists(db, ver, name, 3478 rdata.type, covers, &flag)); 3479 if (! flag) { 3480 /* RRset does not exist. */ 3481 PREREQFAILNT(DNS_R_NXRRSET, name, rdata.type, 3482 "'rrset exists (value independent)' " 3483 "prerequisite not satisfied"); 3484 } 3485 } 3486 } else if (update_class == dns_rdataclass_none) { 3487 if (rdata.length != 0) 3488 PREREQFAILC(DNS_R_FORMERR, 3489 "class NONE prerequisite " 3490 "RDATA is not empty"); 3491 if (rdata.type == dns_rdatatype_any) { 3492 CHECK(name_exists(db, ver, name, &flag)); 3493 if (flag) { 3494 PREREQFAILN(DNS_R_YXDOMAIN, name, 3495 "'name not in use' " 3496 "prerequisite not " 3497 "satisfied"); 3498 } 3499 } else { 3500 CHECK(rrset_exists(db, ver, name, 3501 rdata.type, covers, &flag)); 3502 if (flag) { 3503 /* RRset exists. */ 3504 PREREQFAILNT(DNS_R_YXRRSET, name, 3505 rdata.type, 3506 "'rrset does not exist' " 3507 "prerequisite not " 3508 "satisfied"); 3509 } 3510 } 3511 } else if (update_class == zoneclass) { 3512 /* "temp<rr.name, rr.type> += rr;" */ 3513 result = temp_append(&temp, name, &rdata); 3514 if (result != ISC_R_SUCCESS) { 3515 UNEXPECTED_ERROR(__FILE__, __LINE__, 3516 "temp entry creation failed: %s", 3517 dns_result_totext(result)); 3518 FAIL(ISC_R_UNEXPECTED); 3519 } 3520 } else { 3521 PREREQFAILC(DNS_R_FORMERR, "malformed prerequisite"); 3522 } 3523 } 3524 if (result != ISC_R_NOMORE) 3525 FAIL(result); 3526 3527 3528 /* 3529 * Perform the final check of the "rrset exists (value dependent)" 3530 * prerequisites. 3531 */ 3532 if (ISC_LIST_HEAD(temp.tuples) != NULL) { 3533 dns_rdatatype_t type; 3534 3535 /* 3536 * Sort the prerequisite records by owner name, 3537 * type, and rdata. 3538 */ 3539 result = dns_diff_sort(&temp, temp_order); 3540 if (result != ISC_R_SUCCESS) 3541 FAILC(result, "'RRset exists (value dependent)' " 3542 "prerequisite not satisfied"); 3543 3544 dns_fixedname_init(&tmpnamefixed); 3545 tmpname = dns_fixedname_name(&tmpnamefixed); 3546 result = temp_check(mctx, &temp, db, ver, tmpname, &type); 3547 if (result != ISC_R_SUCCESS) 3548 FAILNT(result, tmpname, type, 3549 "'RRset exists (value dependent)' " 3550 "prerequisite not satisfied"); 3551 } 3552 3553 update_log(client, zone, LOGLEVEL_DEBUG, 3554 "prerequisites are OK"); 3555 3556 /* 3557 * Check Requestor's Permissions. It seems a bit silly to do this 3558 * only after prerequisite testing, but that is what RFC2136 says. 3559 */ 3560 result = ISC_R_SUCCESS; 3561 if (ssutable == NULL) 3562 CHECK(checkupdateacl(client, dns_zone_getupdateacl(zone), 3563 "update", zonename, ISC_FALSE, ISC_FALSE)); 3564 else if (client->signer == NULL && !TCPCLIENT(client)) 3565 CHECK(checkupdateacl(client, NULL, "update", zonename, 3566 ISC_FALSE, ISC_TRUE)); 3567 3568 if (dns_zone_getupdatedisabled(zone)) 3569 FAILC(DNS_R_REFUSED, "dynamic update temporarily disabled " 3570 "because the zone is frozen. Use " 3571 "'rndc thaw' to re-enable updates."); 3572 3573 /* 3574 * Perform the Update Section Prescan. 3575 */ 3576 3577 for (result = dns_message_firstname(request, DNS_SECTION_UPDATE); 3578 result == ISC_R_SUCCESS; 3579 result = dns_message_nextname(request, DNS_SECTION_UPDATE)) 3580 { 3581 dns_name_t *name = NULL; 3582 dns_rdata_t rdata = DNS_RDATA_INIT; 3583 dns_ttl_t ttl; 3584 dns_rdataclass_t update_class; 3585 get_current_rr(request, DNS_SECTION_UPDATE, zoneclass, 3586 &name, &rdata, &covers, &ttl, &update_class); 3587 3588 if (! dns_name_issubdomain(name, zonename)) 3589 FAILC(DNS_R_NOTZONE, 3590 "update RR is outside zone"); 3591 if (update_class == zoneclass) { 3592 /* 3593 * Check for meta-RRs. The RFC2136 pseudocode says 3594 * check for ANY|AXFR|MAILA|MAILB, but the text adds 3595 * "or any other QUERY metatype" 3596 */ 3597 if (dns_rdatatype_ismeta(rdata.type)) { 3598 FAILC(DNS_R_FORMERR, 3599 "meta-RR in update"); 3600 } 3601 result = dns_zone_checknames(zone, name, &rdata); 3602 if (result != ISC_R_SUCCESS) 3603 FAIL(DNS_R_REFUSED); 3604 } else if (update_class == dns_rdataclass_any) { 3605 if (ttl != 0 || rdata.length != 0 || 3606 (dns_rdatatype_ismeta(rdata.type) && 3607 rdata.type != dns_rdatatype_any)) 3608 FAILC(DNS_R_FORMERR, 3609 "meta-RR in update"); 3610 } else if (update_class == dns_rdataclass_none) { 3611 if (ttl != 0 || 3612 dns_rdatatype_ismeta(rdata.type)) 3613 FAILC(DNS_R_FORMERR, 3614 "meta-RR in update"); 3615 } else { 3616 update_log(client, zone, ISC_LOG_WARNING, 3617 "update RR has incorrect class %d", 3618 update_class); 3619 FAIL(DNS_R_FORMERR); 3620 } 3621 /* 3622 * draft-ietf-dnsind-simple-secure-update-01 says 3623 * "Unlike traditional dynamic update, the client 3624 * is forbidden from updating NSEC records." 3625 */ 3626 if (dns_db_issecure(db)) { 3627 if (rdata.type == dns_rdatatype_nsec3) { 3628 FAILC(DNS_R_REFUSED, 3629 "explicit NSEC3 updates are not allowed " 3630 "in secure zones"); 3631 } else if (rdata.type == dns_rdatatype_nsec) { 3632 FAILC(DNS_R_REFUSED, 3633 "explicit NSEC updates are not allowed " 3634 "in secure zones"); 3635 } else if (rdata.type == dns_rdatatype_rrsig && 3636 !dns_name_equal(name, zonename)) { 3637 FAILC(DNS_R_REFUSED, 3638 "explicit RRSIG updates are currently " 3639 "not supported in secure zones except " 3640 "at the apex"); 3641 } 3642 } 3643 3644 if (ssutable != NULL) { 3645 isc_netaddr_t *tcpaddr, netaddr; 3646 /* 3647 * If this is a TCP connection then pass the 3648 * address of the client through for tcp-self 3649 * and 6to4-self otherwise pass NULL. This 3650 * provides weak address based authentication. 3651 */ 3652 if (TCPCLIENT(client)) { 3653 isc_netaddr_fromsockaddr(&netaddr, 3654 &client->peeraddr); 3655 tcpaddr = &netaddr; 3656 } else 3657 tcpaddr = NULL; 3658 if (rdata.type != dns_rdatatype_any) { 3659 if (!dns_ssutable_checkrules(ssutable, 3660 client->signer, 3661 name, tcpaddr, 3662 rdata.type)) 3663 FAILC(DNS_R_REFUSED, 3664 "rejected by secure update"); 3665 } else { 3666 if (!ssu_checkall(db, ver, name, ssutable, 3667 client->signer, tcpaddr)) 3668 FAILC(DNS_R_REFUSED, 3669 "rejected by secure update"); 3670 } 3671 } 3672 } 3673 if (result != ISC_R_NOMORE) 3674 FAIL(result); 3675 3676 update_log(client, zone, LOGLEVEL_DEBUG, 3677 "update section prescan OK"); 3678 3679 /* 3680 * Process the Update Section. 3681 */ 3682 3683 options = dns_zone_getoptions(zone); 3684 for (result = dns_message_firstname(request, DNS_SECTION_UPDATE); 3685 result == ISC_R_SUCCESS; 3686 result = dns_message_nextname(request, DNS_SECTION_UPDATE)) 3687 { 3688 dns_name_t *name = NULL; 3689 dns_rdata_t rdata = DNS_RDATA_INIT; 3690 dns_ttl_t ttl; 3691 dns_rdataclass_t update_class; 3692 isc_boolean_t flag; 3693 3694 get_current_rr(request, DNS_SECTION_UPDATE, zoneclass, 3695 &name, &rdata, &covers, &ttl, &update_class); 3696 3697 if (update_class == zoneclass) { 3698 3699 /* 3700 * RFC1123 doesn't allow MF and MD in master zones. */ 3701 if (rdata.type == dns_rdatatype_md || 3702 rdata.type == dns_rdatatype_mf) { 3703 char typebuf[DNS_RDATATYPE_FORMATSIZE]; 3704 3705 dns_rdatatype_format(rdata.type, typebuf, 3706 sizeof(typebuf)); 3707 update_log(client, zone, LOGLEVEL_PROTOCOL, 3708 "attempt to add %s ignored", 3709 typebuf); 3710 continue; 3711 } 3712 if ((rdata.type == dns_rdatatype_ns || 3713 rdata.type == dns_rdatatype_dname) && 3714 dns_name_iswildcard(name)) { 3715 char typebuf[DNS_RDATATYPE_FORMATSIZE]; 3716 3717 dns_rdatatype_format(rdata.type, typebuf, 3718 sizeof(typebuf)); 3719 update_log(client, zone, 3720 LOGLEVEL_PROTOCOL, 3721 "attempt to add wildcard %s record " 3722 "ignored", typebuf); 3723 continue; 3724 } 3725 if (rdata.type == dns_rdatatype_cname) { 3726 CHECK(cname_incompatible_rrset_exists(db, ver, 3727 name, 3728 &flag)); 3729 if (flag) { 3730 update_log(client, zone, 3731 LOGLEVEL_PROTOCOL, 3732 "attempt to add CNAME " 3733 "alongside non-CNAME " 3734 "ignored"); 3735 continue; 3736 } 3737 } else { 3738 CHECK(rrset_exists(db, ver, name, 3739 dns_rdatatype_cname, 0, 3740 &flag)); 3741 if (flag && 3742 ! dns_rdatatype_isdnssec(rdata.type)) 3743 { 3744 update_log(client, zone, 3745 LOGLEVEL_PROTOCOL, 3746 "attempt to add non-CNAME " 3747 "alongside CNAME ignored"); 3748 continue; 3749 } 3750 } 3751 if (rdata.type == dns_rdatatype_soa) { 3752 isc_boolean_t ok; 3753 CHECK(rrset_exists(db, ver, name, 3754 dns_rdatatype_soa, 0, 3755 &flag)); 3756 if (! flag) { 3757 update_log(client, zone, 3758 LOGLEVEL_PROTOCOL, 3759 "attempt to create 2nd " 3760 "SOA ignored"); 3761 continue; 3762 } 3763 CHECK(check_soa_increment(db, ver, &rdata, 3764 &ok)); 3765 if (! ok) { 3766 update_log(client, zone, 3767 LOGLEVEL_PROTOCOL, 3768 "SOA update failed to " 3769 "increment serial, " 3770 "ignoring it"); 3771 continue; 3772 } 3773 soa_serial_changed = ISC_TRUE; 3774 } 3775 3776#ifdef ALLOW_NSEC3PARAM_UPDATE 3777 if (rdata.type == dns_rdatatype_nsec3param) { 3778 /* 3779 * Ignore attempts to add NSEC3PARAM records 3780 * with any flags other than OPTOUT. 3781 */ 3782 if ((rdata.data[1] & ~DNS_NSEC3FLAG_OPTOUT) != 0) { 3783 update_log(client, zone, 3784 LOGLEVEL_PROTOCOL, 3785 "attempt to add NSEC3PARAM " 3786 "record with non OPTOUT " 3787 "flag"); 3788 continue; 3789 } 3790 3791 /* 3792 * Set the NSEC3CHAIN creation flag. 3793 */ 3794 INSIST(rdata.length <= sizeof(buf)); 3795 memcpy(buf, rdata.data, rdata.length); 3796 buf[1] |= DNS_NSEC3FLAG_UPDATE; 3797 rdata.data = buf; 3798 /* 3799 * Force the TTL to zero for NSEC3PARAM records. 3800 */ 3801 ttl = 0; 3802 } 3803#else 3804 if (rdata.type == dns_rdatatype_nsec3param) { 3805 update_log(client, zone, LOGLEVEL_PROTOCOL, 3806 "attempt to add NSEC3PARAM " 3807 "record ignored"); 3808 continue; 3809 }; 3810#endif 3811 3812 if ((options & DNS_ZONEOPT_CHECKWILDCARD) != 0 && 3813 dns_name_internalwildcard(name)) { 3814 char namestr[DNS_NAME_FORMATSIZE]; 3815 dns_name_format(name, namestr, 3816 sizeof(namestr)); 3817 update_log(client, zone, LOGLEVEL_PROTOCOL, 3818 "warning: ownername '%s' contains " 3819 "a non-terminal wildcard", namestr); 3820 } 3821 3822 if (isc_log_wouldlog(ns_g_lctx, LOGLEVEL_PROTOCOL)) { 3823 char namestr[DNS_NAME_FORMATSIZE]; 3824 char typestr[DNS_RDATATYPE_FORMATSIZE]; 3825 dns_name_format(name, namestr, 3826 sizeof(namestr)); 3827 dns_rdatatype_format(rdata.type, typestr, 3828 sizeof(typestr)); 3829 update_log(client, zone, LOGLEVEL_PROTOCOL, 3830 "adding an RR at '%s' %s", 3831 namestr, typestr); 3832 } 3833 3834 /* Prepare the affected RRset for the addition. */ 3835 { 3836 add_rr_prepare_ctx_t ctx; 3837 ctx.db = db; 3838 ctx.ver = ver; 3839 ctx.diff = &diff; 3840 ctx.name = name; 3841 ctx.update_rr = &rdata; 3842 ctx.update_rr_ttl = ttl; 3843 ctx.ignore_add = ISC_FALSE; 3844 dns_diff_init(mctx, &ctx.del_diff); 3845 dns_diff_init(mctx, &ctx.add_diff); 3846 CHECK(foreach_rr(db, ver, name, rdata.type, 3847 covers, add_rr_prepare_action, 3848 &ctx)); 3849 3850 if (ctx.ignore_add) { 3851 dns_diff_clear(&ctx.del_diff); 3852 dns_diff_clear(&ctx.add_diff); 3853 } else { 3854 CHECK(do_diff(&ctx.del_diff, db, ver, 3855 &diff)); 3856 CHECK(do_diff(&ctx.add_diff, db, ver, 3857 &diff)); 3858 CHECK(update_one_rr(db, ver, &diff, 3859 DNS_DIFFOP_ADD, 3860 name, ttl, &rdata)); 3861 } 3862 } 3863 } else if (update_class == dns_rdataclass_any) { 3864 if (rdata.type == dns_rdatatype_any) { 3865 if (isc_log_wouldlog(ns_g_lctx, 3866 LOGLEVEL_PROTOCOL)) 3867 { 3868 char namestr[DNS_NAME_FORMATSIZE]; 3869 dns_name_format(name, namestr, 3870 sizeof(namestr)); 3871 update_log(client, zone, 3872 LOGLEVEL_PROTOCOL, 3873 "delete all rrsets from " 3874 "name '%s'", namestr); 3875 } 3876 if (dns_name_equal(name, zonename)) { 3877 CHECK(delete_if(type_not_soa_nor_ns_p, 3878 db, ver, name, 3879 dns_rdatatype_any, 0, 3880 &rdata, &diff)); 3881 } else { 3882 CHECK(delete_if(type_not_dnssec, 3883 db, ver, name, 3884 dns_rdatatype_any, 0, 3885 &rdata, &diff)); 3886 } 3887#ifndef ALLOW_NSEC3PARAM_UPDATE 3888 } else if (rdata.type == dns_rdatatype_nsec3param) { 3889 update_log(client, zone, LOGLEVEL_PROTOCOL, 3890 "attempt to delete a NSEC3PARAM " 3891 "records ignored"); 3892 continue; 3893#endif 3894 } else if (dns_name_equal(name, zonename) && 3895 (rdata.type == dns_rdatatype_soa || 3896 rdata.type == dns_rdatatype_ns)) { 3897 update_log(client, zone, LOGLEVEL_PROTOCOL, 3898 "attempt to delete all SOA " 3899 "or NS records ignored"); 3900 continue; 3901 } else { 3902 if (isc_log_wouldlog(ns_g_lctx, 3903 LOGLEVEL_PROTOCOL)) 3904 { 3905 char namestr[DNS_NAME_FORMATSIZE]; 3906 char typestr[DNS_RDATATYPE_FORMATSIZE]; 3907 dns_name_format(name, namestr, 3908 sizeof(namestr)); 3909 dns_rdatatype_format(rdata.type, 3910 typestr, 3911 sizeof(typestr)); 3912 update_log(client, zone, 3913 LOGLEVEL_PROTOCOL, 3914 "deleting rrset at '%s' %s", 3915 namestr, typestr); 3916 } 3917 CHECK(delete_if(true_p, db, ver, name, 3918 rdata.type, covers, &rdata, 3919 &diff)); 3920 } 3921 } else if (update_class == dns_rdataclass_none) { 3922 /* 3923 * The (name == zonename) condition appears in 3924 * RFC2136 3.4.2.4 but is missing from the pseudocode. 3925 */ 3926 if (dns_name_equal(name, zonename)) { 3927 if (rdata.type == dns_rdatatype_soa) { 3928 update_log(client, zone, 3929 LOGLEVEL_PROTOCOL, 3930 "attempt to delete SOA " 3931 "ignored"); 3932 continue; 3933 } 3934 if (rdata.type == dns_rdatatype_ns) { 3935 int count; 3936 CHECK(rr_count(db, ver, name, 3937 dns_rdatatype_ns, 3938 0, &count)); 3939 if (count == 1) { 3940 update_log(client, zone, 3941 LOGLEVEL_PROTOCOL, 3942 "attempt to " 3943 "delete last " 3944 "NS ignored"); 3945 continue; 3946 } 3947 } 3948 } 3949 update_log(client, zone, 3950 LOGLEVEL_PROTOCOL, 3951 "deleting an RR"); 3952 CHECK(delete_if(rr_equal_p, db, ver, name, 3953 rdata.type, covers, &rdata, &diff)); 3954 } 3955 } 3956 if (result != ISC_R_NOMORE) 3957 FAIL(result); 3958 3959 /* 3960 * Check that any changes to DNSKEY/NSEC3PARAM records make sense. 3961 * If they don't then back out all changes to DNSKEY/NSEC3PARAM 3962 * records. 3963 */ 3964 if (! ISC_LIST_EMPTY(diff.tuples)) 3965 CHECK(check_dnssec(client, zone, db, ver, &diff)); 3966 3967 /* 3968 * If any changes were made, increment the SOA serial number, 3969 * update RRSIGs and NSECs (if zone is secure), and write the update 3970 * to the journal. 3971 */ 3972 if (! ISC_LIST_EMPTY(diff.tuples)) { 3973 char *journalfile; 3974 dns_journal_t *journal; 3975 isc_boolean_t has_dnskey; 3976 3977 /* 3978 * Increment the SOA serial, but only if it was not 3979 * changed as a result of an update operation. 3980 */ 3981 if (! soa_serial_changed) { 3982 CHECK(increment_soa_serial(db, ver, &diff, mctx)); 3983 } 3984 3985 CHECK(check_mx(client, zone, db, ver, &diff)); 3986 3987 CHECK(remove_orphaned_ds(db, ver, &diff)); 3988 3989 CHECK(rrset_exists(db, ver, zonename, dns_rdatatype_dnskey, 3990 0, &has_dnskey)); 3991 3992#if !defined(ALLOW_SECURE_TO_INSECURE) || !defined(ALLOW_INSECURE_TO_SECURE) 3993 CHECK(rrset_exists(db, oldver, zonename, dns_rdatatype_dnskey, 3994 0, &had_dnskey)); 3995 3996#ifndef ALLOW_SECURE_TO_INSECURE 3997 if (had_dnskey && !has_dnskey) { 3998 update_log(client, zone, LOGLEVEL_PROTOCOL, 3999 "update rejected: all DNSKEY records " 4000 "removed"); 4001 result = DNS_R_REFUSED; 4002 goto failure; 4003 } 4004#endif 4005#ifndef ALLOW_INSECURE_TO_SECURE 4006 if (!had_dnskey && has_dnskey) { 4007 update_log(client, zone, LOGLEVEL_PROTOCOL, 4008 "update rejected: DNSKEY record added"); 4009 result = DNS_R_REFUSED; 4010 goto failure; 4011 } 4012#endif 4013#endif 4014 4015 CHECK(add_signing_records(db, zonename, ver, 4016 dns_zone_getprivatetype(zone), 4017 &diff)); 4018 4019#ifdef ALLOW_NSEC3PARAM_UPDATE 4020 CHECK(add_nsec3param_records(client, zone, db, zonename, 4021 ver, &diff)); 4022#endif 4023 4024 if (!has_dnskey) { 4025 /* 4026 * We are transitioning from secure to insecure. 4027 * Cause all NSEC3 chains to be deleted. When the 4028 * the last signature for the DNSKEY records are 4029 * remove any NSEC chain present will also be removed. 4030 */ 4031#ifdef ALLOW_NSEC3PARAM_UPDATE 4032 CHECK(delete_chains(db, ver, zonename, &diff)); 4033#endif 4034 } else if (has_dnskey && dns_db_isdnssec(db)) { 4035 isc_uint32_t interval; 4036 interval = dns_zone_getsigvalidityinterval(zone); 4037 result = update_signatures(client, zone, db, oldver, 4038 ver, &diff, interval, 4039 &deleted_zsk); 4040 if (result != ISC_R_SUCCESS) { 4041 update_log(client, zone, 4042 ISC_LOG_ERROR, 4043 "RRSIG/NSEC/NSEC3 update failed: %s", 4044 isc_result_totext(result)); 4045 goto failure; 4046 } 4047 } 4048 4049 journalfile = dns_zone_getjournal(zone); 4050 if (journalfile != NULL) { 4051 update_log(client, zone, LOGLEVEL_DEBUG, 4052 "writing journal %s", journalfile); 4053 4054 journal = NULL; 4055 result = dns_journal_open(mctx, journalfile, 4056 ISC_TRUE, &journal); 4057 if (result != ISC_R_SUCCESS) 4058 FAILS(result, "journal open failed"); 4059 4060 result = dns_journal_write_transaction(journal, &diff); 4061 if (result != ISC_R_SUCCESS) { 4062 dns_journal_destroy(&journal); 4063 FAILS(result, "journal write failed"); 4064 } 4065 4066 dns_journal_destroy(&journal); 4067 } 4068 4069 /* 4070 * XXXRTH Just a note that this committing code will have 4071 * to change to handle databases that need two-phase 4072 * commit, but this isn't a priority. 4073 */ 4074 update_log(client, zone, LOGLEVEL_DEBUG, 4075 "committing update transaction"); 4076 4077 dns_db_closeversion(db, &ver, ISC_TRUE); 4078 4079 /* 4080 * Mark the zone as dirty so that it will be written to disk. 4081 */ 4082 dns_zone_markdirty(zone); 4083 4084 /* 4085 * Notify slaves of the change we just made. 4086 */ 4087 dns_zone_notify(zone); 4088 4089 /* 4090 * Cause the zone to be signed with the key that we 4091 * have just added or have the corresponding signatures 4092 * deleted. 4093 * 4094 * Note: we are already committed to this course of action. 4095 */ 4096 for (tuple = ISC_LIST_HEAD(diff.tuples); 4097 tuple != NULL; 4098 tuple = ISC_LIST_NEXT(tuple, link)) { 4099 isc_region_t r; 4100 dns_secalg_t algorithm; 4101 isc_uint16_t keyid; 4102 4103 if (tuple->rdata.type != dns_rdatatype_dnskey) 4104 continue; 4105 4106 dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL); 4107 if ((dnskey.flags & 4108 (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH)) 4109 != DNS_KEYOWNER_ZONE) 4110 continue; 4111 4112 dns_rdata_toregion(&tuple->rdata, &r); 4113 algorithm = dnskey.algorithm; 4114 keyid = dst_region_computeid(&r, algorithm); 4115 4116 result = dns_zone_signwithkey(zone, algorithm, keyid, 4117 ISC_TF(tuple->op == DNS_DIFFOP_DEL)); 4118 if (result != ISC_R_SUCCESS) { 4119 update_log(client, zone, ISC_LOG_ERROR, 4120 "dns_zone_signwithkey failed: %s", 4121 dns_result_totext(result)); 4122 } 4123 } 4124 4125#ifdef ALLOW_NSEC3PARAM_UPDATE 4126 /* 4127 * Cause the zone to add/delete NSEC3 chains for the 4128 * deferred NSEC3PARAM changes. 4129 * 4130 * Note: we are already committed to this course of action. 4131 */ 4132 for (tuple = ISC_LIST_HEAD(diff.tuples); 4133 tuple != NULL; 4134 tuple = ISC_LIST_NEXT(tuple, link)) { 4135 dns_rdata_nsec3param_t nsec3param; 4136 4137 if (tuple->rdata.type != dns_rdatatype_nsec3param || 4138 tuple->op != DNS_DIFFOP_ADD) 4139 continue; 4140 4141 dns_rdata_tostruct(&tuple->rdata, &nsec3param, NULL); 4142 if (nsec3param.flags == 0) 4143 continue; 4144 4145 result = dns_zone_addnsec3chain(zone, &nsec3param); 4146 if (result != ISC_R_SUCCESS) { 4147 update_log(client, zone, ISC_LOG_ERROR, 4148 "dns_zone_addnsec3chain failed: %s", 4149 dns_result_totext(result)); 4150 } 4151 } 4152#endif 4153 } else { 4154 update_log(client, zone, LOGLEVEL_DEBUG, "redundant request"); 4155 dns_db_closeversion(db, &ver, ISC_TRUE); 4156 } 4157 result = ISC_R_SUCCESS; 4158 goto common; 4159 4160 failure: 4161 /* 4162 * The reason for failure should have been logged at this point. 4163 */ 4164 if (ver != NULL) { 4165 update_log(client, zone, LOGLEVEL_DEBUG, 4166 "rolling back"); 4167 dns_db_closeversion(db, &ver, ISC_FALSE); 4168 } 4169 4170 common: 4171 dns_diff_clear(&temp); 4172 dns_diff_clear(&diff); 4173 4174 if (oldver != NULL) 4175 dns_db_closeversion(db, &oldver, ISC_FALSE); 4176 4177 if (db != NULL) 4178 dns_db_detach(&db); 4179 4180 if (ssutable != NULL) 4181 dns_ssutable_detach(&ssutable); 4182 4183 isc_task_detach(&task); 4184 uev->result = result; 4185 if (zone != NULL) 4186 INSIST(uev->zone == zone); /* we use this later */ 4187 uev->ev_type = DNS_EVENT_UPDATEDONE; 4188 uev->ev_action = updatedone_action; 4189 isc_task_send(client->task, &event); 4190 INSIST(event == NULL); 4191} 4192 4193static void 4194updatedone_action(isc_task_t *task, isc_event_t *event) { 4195 update_event_t *uev = (update_event_t *) event; 4196 ns_client_t *client = (ns_client_t *) event->ev_arg; 4197 4198 UNUSED(task); 4199 4200 INSIST(event->ev_type == DNS_EVENT_UPDATEDONE); 4201 INSIST(task == client->task); 4202 4203 INSIST(client->nupdates > 0); 4204 switch (uev->result) { 4205 case ISC_R_SUCCESS: 4206 inc_stats(uev->zone, dns_nsstatscounter_updatedone); 4207 break; 4208 case DNS_R_REFUSED: 4209 inc_stats(uev->zone, dns_nsstatscounter_updaterej); 4210 break; 4211 default: 4212 inc_stats(uev->zone, dns_nsstatscounter_updatefail); 4213 break; 4214 } 4215 if (uev->zone != NULL) 4216 dns_zone_detach(&uev->zone); 4217 client->nupdates--; 4218 respond(client, uev->result); 4219 isc_event_free(&event); 4220 ns_client_detach(&client); 4221} 4222 4223/*% 4224 * Update forwarding support. 4225 */ 4226 4227static void 4228forward_fail(isc_task_t *task, isc_event_t *event) { 4229 ns_client_t *client = (ns_client_t *)event->ev_arg; 4230 4231 UNUSED(task); 4232 4233 INSIST(client->nupdates > 0); 4234 client->nupdates--; 4235 respond(client, DNS_R_SERVFAIL); 4236 isc_event_free(&event); 4237 ns_client_detach(&client); 4238} 4239 4240 4241static void 4242forward_callback(void *arg, isc_result_t result, dns_message_t *answer) { 4243 update_event_t *uev = arg; 4244 ns_client_t *client = uev->ev_arg; 4245 dns_zone_t *zone = uev->zone; 4246 4247 if (result != ISC_R_SUCCESS) { 4248 INSIST(answer == NULL); 4249 uev->ev_type = DNS_EVENT_UPDATEDONE; 4250 uev->ev_action = forward_fail; 4251 inc_stats(zone, dns_nsstatscounter_updatefwdfail); 4252 } else { 4253 uev->ev_type = DNS_EVENT_UPDATEDONE; 4254 uev->ev_action = forward_done; 4255 uev->answer = answer; 4256 inc_stats(zone, dns_nsstatscounter_updaterespfwd); 4257 } 4258 isc_task_send(client->task, ISC_EVENT_PTR(&uev)); 4259 dns_zone_detach(&zone); 4260} 4261 4262static void 4263forward_done(isc_task_t *task, isc_event_t *event) { 4264 update_event_t *uev = (update_event_t *) event; 4265 ns_client_t *client = (ns_client_t *)event->ev_arg; 4266 4267 UNUSED(task); 4268 4269 INSIST(client->nupdates > 0); 4270 client->nupdates--; 4271 ns_client_sendraw(client, uev->answer); 4272 dns_message_destroy(&uev->answer); 4273 isc_event_free(&event); 4274 ns_client_detach(&client); 4275} 4276 4277static void 4278forward_action(isc_task_t *task, isc_event_t *event) { 4279 update_event_t *uev = (update_event_t *) event; 4280 dns_zone_t *zone = uev->zone; 4281 ns_client_t *client = (ns_client_t *)event->ev_arg; 4282 isc_result_t result; 4283 4284 result = dns_zone_forwardupdate(zone, client->message, 4285 forward_callback, event); 4286 if (result != ISC_R_SUCCESS) { 4287 uev->ev_type = DNS_EVENT_UPDATEDONE; 4288 uev->ev_action = forward_fail; 4289 isc_task_send(client->task, &event); 4290 inc_stats(zone, dns_nsstatscounter_updatefwdfail); 4291 dns_zone_detach(&zone); 4292 } else 4293 inc_stats(zone, dns_nsstatscounter_updatereqfwd); 4294 isc_task_detach(&task); 4295} 4296 4297static isc_result_t 4298send_forward_event(ns_client_t *client, dns_zone_t *zone) { 4299 isc_result_t result = ISC_R_SUCCESS; 4300 update_event_t *event = NULL; 4301 isc_task_t *zonetask = NULL; 4302 ns_client_t *evclient; 4303 4304 event = (update_event_t *) 4305 isc_event_allocate(client->mctx, client, DNS_EVENT_UPDATE, 4306 forward_action, NULL, sizeof(*event)); 4307 if (event == NULL) 4308 FAIL(ISC_R_NOMEMORY); 4309 event->zone = zone; 4310 event->result = ISC_R_SUCCESS; 4311 4312 evclient = NULL; 4313 ns_client_attach(client, &evclient); 4314 INSIST(client->nupdates == 0); 4315 client->nupdates++; 4316 event->ev_arg = evclient; 4317 4318 dns_zone_gettask(zone, &zonetask); 4319 isc_task_send(zonetask, ISC_EVENT_PTR(&event)); 4320 4321 failure: 4322 if (event != NULL) 4323 isc_event_free(ISC_EVENT_PTR(&event)); 4324 return (result); 4325} 4326