update.c revision 193149
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.5 2009/04/30 07:03:37 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 983 covers = 0; 984 985 /* 986 * Collect all database RRs for this name and type 987 * onto d_rrs and sort them. 988 */ 989 dns_rdataset_init(&rdataset); 990 result = dns_db_findrdataset(db, node, ver, type, 991 covers, (isc_stdtime_t) 0, 992 &rdataset, NULL); 993 if (result != ISC_R_SUCCESS) { 994 dns_db_detachnode(db, &node); 995 dns_diff_clear(&trash); 996 return (DNS_R_NXRRSET); 997 } 998 999 dns_diff_init(mctx, &d_rrs); 1000 dns_diff_init(mctx, &u_rrs); 1001 1002 for (result = dns_rdataset_first(&rdataset); 1003 result == ISC_R_SUCCESS; 1004 result = dns_rdataset_next(&rdataset)) 1005 { 1006 dns_rdata_t rdata = DNS_RDATA_INIT; 1007 dns_rdataset_current(&rdataset, &rdata); 1008 result = temp_append(&d_rrs, name, &rdata); 1009 if (result != ISC_R_SUCCESS) 1010 goto failure; 1011 } 1012 if (result != ISC_R_NOMORE) 1013 goto failure; 1014 result = dns_diff_sort(&d_rrs, temp_order); 1015 if (result != ISC_R_SUCCESS) 1016 goto failure; 1017 1018 /* 1019 * Collect all update RRs for this name and type 1020 * onto u_rrs. No need to sort them here - 1021 * they are already sorted. 1022 */ 1023 while (t != NULL && 1024 dns_name_equal(&t->name, name) && 1025 t->rdata.type == type) 1026 { 1027 dns_difftuple_t *next = 1028 ISC_LIST_NEXT(t, link); 1029 ISC_LIST_UNLINK(temp->tuples, t, link); 1030 ISC_LIST_APPEND(u_rrs.tuples, t, link); 1031 t = next; 1032 } 1033 1034 /* Compare the two sorted lists. */ 1035 result = temp_check_rrset(ISC_LIST_HEAD(u_rrs.tuples), 1036 ISC_LIST_HEAD(d_rrs.tuples)); 1037 if (result != ISC_R_SUCCESS) 1038 goto failure; 1039 1040 /* 1041 * We are done with the tuples, but we can't free 1042 * them yet because "name" still points into one 1043 * of them. Move them on a temporary list. 1044 */ 1045 ISC_LIST_APPENDLIST(trash.tuples, u_rrs.tuples, link); 1046 ISC_LIST_APPENDLIST(trash.tuples, d_rrs.tuples, link); 1047 dns_rdataset_disassociate(&rdataset); 1048 1049 continue; 1050 1051 failure: 1052 dns_diff_clear(&d_rrs); 1053 dns_diff_clear(&u_rrs); 1054 dns_diff_clear(&trash); 1055 dns_rdataset_disassociate(&rdataset); 1056 dns_db_detachnode(db, &node); 1057 return (result); 1058 } 1059 1060 dns_db_detachnode(db, &node); 1061 } 1062 1063 dns_diff_clear(&trash); 1064 return (ISC_R_SUCCESS); 1065} 1066 1067/**************************************************************************/ 1068/* 1069 * Conditional deletion of RRs. 1070 */ 1071 1072/*% 1073 * Context structure for delete_if(). 1074 */ 1075 1076typedef struct { 1077 rr_predicate *predicate; 1078 dns_db_t *db; 1079 dns_dbversion_t *ver; 1080 dns_diff_t *diff; 1081 dns_name_t *name; 1082 dns_rdata_t *update_rr; 1083} conditional_delete_ctx_t; 1084 1085/*% 1086 * Predicate functions for delete_if(). 1087 */ 1088 1089/*% 1090 * Return true iff 'db_rr' is neither a SOA nor an NS RR nor 1091 * an RRSIG nor an NSEC3PARAM nor a NSEC. 1092 */ 1093static isc_boolean_t 1094type_not_soa_nor_ns_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) { 1095 UNUSED(update_rr); 1096 return ((db_rr->type != dns_rdatatype_soa && 1097 db_rr->type != dns_rdatatype_ns && 1098 db_rr->type != dns_rdatatype_nsec3param && 1099 db_rr->type != dns_rdatatype_rrsig && 1100 db_rr->type != dns_rdatatype_nsec) ? 1101 ISC_TRUE : ISC_FALSE); 1102} 1103 1104/*% 1105 * Return true iff 'db_rr' is neither a RRSIG nor a NSEC. 1106 */ 1107static isc_boolean_t 1108type_not_dnssec(dns_rdata_t *update_rr, dns_rdata_t *db_rr) { 1109 UNUSED(update_rr); 1110 return ((db_rr->type != dns_rdatatype_rrsig && 1111 db_rr->type != dns_rdatatype_nsec) ? 1112 ISC_TRUE : ISC_FALSE); 1113} 1114 1115/*% 1116 * Return true always. 1117 */ 1118static isc_boolean_t 1119true_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) { 1120 UNUSED(update_rr); 1121 UNUSED(db_rr); 1122 return (ISC_TRUE); 1123} 1124 1125/*% 1126 * Return true if the record is a RRSIG. 1127 */ 1128static isc_boolean_t 1129rrsig_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) { 1130 UNUSED(update_rr); 1131 return ((db_rr->type == dns_rdatatype_rrsig) ? 1132 ISC_TRUE : ISC_FALSE); 1133} 1134 1135/*% 1136 * Return true iff the two RRs have identical rdata. 1137 */ 1138static isc_boolean_t 1139rr_equal_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) { 1140 /* 1141 * XXXRTH This is not a problem, but we should consider creating 1142 * dns_rdata_equal() (that used dns_name_equal()), since it 1143 * would be faster. Not a priority. 1144 */ 1145 return (dns_rdata_compare(update_rr, db_rr) == 0 ? 1146 ISC_TRUE : ISC_FALSE); 1147} 1148 1149/*% 1150 * Return true iff 'update_rr' should replace 'db_rr' according 1151 * to the special RFC2136 rules for CNAME, SOA, and WKS records. 1152 * 1153 * RFC2136 does not mention NSEC or DNAME, but multiple NSECs or DNAMEs 1154 * make little sense, so we replace those, too. 1155 * 1156 * Additionally replace RRSIG that have been generated by the same key 1157 * for the same type. This simplifies refreshing a offline KSK by not 1158 * requiring that the old RRSIG be deleted. It also simplifies key 1159 * rollover by only requiring that the new RRSIG be added. 1160 */ 1161static isc_boolean_t 1162replaces_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) { 1163 dns_rdata_rrsig_t updatesig, dbsig; 1164 isc_result_t result; 1165 1166 if (db_rr->type != update_rr->type) 1167 return (ISC_FALSE); 1168 if (db_rr->type == dns_rdatatype_cname) 1169 return (ISC_TRUE); 1170 if (db_rr->type == dns_rdatatype_dname) 1171 return (ISC_TRUE); 1172 if (db_rr->type == dns_rdatatype_soa) 1173 return (ISC_TRUE); 1174 if (db_rr->type == dns_rdatatype_nsec) 1175 return (ISC_TRUE); 1176 if (db_rr->type == dns_rdatatype_rrsig) { 1177 /* 1178 * Replace existing RRSIG with the same keyid, 1179 * covered and algorithm. 1180 */ 1181 result = dns_rdata_tostruct(db_rr, &dbsig, NULL); 1182 RUNTIME_CHECK(result == ISC_R_SUCCESS); 1183 result = dns_rdata_tostruct(update_rr, &updatesig, NULL); 1184 RUNTIME_CHECK(result == ISC_R_SUCCESS); 1185 if (dbsig.keyid == updatesig.keyid && 1186 dbsig.covered == updatesig.covered && 1187 dbsig.algorithm == updatesig.algorithm) 1188 return (ISC_TRUE); 1189 } 1190 if (db_rr->type == dns_rdatatype_wks) { 1191 /* 1192 * Compare the address and protocol fields only. These 1193 * form the first five bytes of the RR data. Do a 1194 * raw binary comparison; unpacking the WKS RRs using 1195 * dns_rdata_tostruct() might be cleaner in some ways. 1196 */ 1197 INSIST(db_rr->length >= 5 && update_rr->length >= 5); 1198 return (memcmp(db_rr->data, update_rr->data, 5) == 0 ? 1199 ISC_TRUE : ISC_FALSE); 1200 } 1201 1202 if (db_rr->type == dns_rdatatype_nsec3param) { 1203 if (db_rr->length != update_rr->length) 1204 return (ISC_FALSE); 1205 INSIST(db_rr->length >= 4 && update_rr->length >= 4); 1206 /* 1207 * Replace records added in this UPDATE request. 1208 */ 1209 if (db_rr->data[0] == update_rr->data[0] && 1210 db_rr->data[1] & DNS_NSEC3FLAG_UPDATE && 1211 update_rr->data[1] & DNS_NSEC3FLAG_UPDATE && 1212 memcmp(db_rr->data+2, update_rr->data+2, 1213 update_rr->length - 2) == 0) 1214 return (ISC_TRUE); 1215 } 1216 return (ISC_FALSE); 1217} 1218 1219/*% 1220 * Internal helper function for delete_if(). 1221 */ 1222static isc_result_t 1223delete_if_action(void *data, rr_t *rr) { 1224 conditional_delete_ctx_t *ctx = data; 1225 if ((*ctx->predicate)(ctx->update_rr, &rr->rdata)) { 1226 isc_result_t result; 1227 result = update_one_rr(ctx->db, ctx->ver, ctx->diff, 1228 DNS_DIFFOP_DEL, ctx->name, 1229 rr->ttl, &rr->rdata); 1230 return (result); 1231 } else { 1232 return (ISC_R_SUCCESS); 1233 } 1234} 1235 1236/*% 1237 * Conditionally delete RRs. Apply 'predicate' to the RRs 1238 * specified by 'db', 'ver', 'name', and 'type' (which can 1239 * be dns_rdatatype_any to match any type). Delete those 1240 * RRs for which the predicate returns true, and log the 1241 * deletions in 'diff'. 1242 */ 1243static isc_result_t 1244delete_if(rr_predicate *predicate, dns_db_t *db, dns_dbversion_t *ver, 1245 dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers, 1246 dns_rdata_t *update_rr, dns_diff_t *diff) 1247{ 1248 conditional_delete_ctx_t ctx; 1249 ctx.predicate = predicate; 1250 ctx.db = db; 1251 ctx.ver = ver; 1252 ctx.diff = diff; 1253 ctx.name = name; 1254 ctx.update_rr = update_rr; 1255 return (foreach_rr(db, ver, name, type, covers, 1256 delete_if_action, &ctx)); 1257} 1258 1259/**************************************************************************/ 1260/*% 1261 * Prepare an RR for the addition of the new RR 'ctx->update_rr', 1262 * with TTL 'ctx->update_rr_ttl', to its rdataset, by deleting 1263 * the RRs if it is replaced by the new RR or has a conflicting TTL. 1264 * The necessary changes are appended to ctx->del_diff and ctx->add_diff; 1265 * we need to do all deletions before any additions so that we don't run 1266 * into transient states with conflicting TTLs. 1267 */ 1268 1269typedef struct { 1270 dns_db_t *db; 1271 dns_dbversion_t *ver; 1272 dns_diff_t *diff; 1273 dns_name_t *name; 1274 dns_rdata_t *update_rr; 1275 dns_ttl_t update_rr_ttl; 1276 isc_boolean_t ignore_add; 1277 dns_diff_t del_diff; 1278 dns_diff_t add_diff; 1279} add_rr_prepare_ctx_t; 1280 1281static isc_result_t 1282add_rr_prepare_action(void *data, rr_t *rr) { 1283 isc_result_t result = ISC_R_SUCCESS; 1284 add_rr_prepare_ctx_t *ctx = data; 1285 dns_difftuple_t *tuple = NULL; 1286 isc_boolean_t equal; 1287 1288 /* 1289 * If the update RR is a "duplicate" of the update RR, 1290 * the update should be silently ignored. 1291 */ 1292 equal = ISC_TF(dns_rdata_compare(&rr->rdata, ctx->update_rr) == 0); 1293 if (equal && rr->ttl == ctx->update_rr_ttl) { 1294 ctx->ignore_add = ISC_TRUE; 1295 return (ISC_R_SUCCESS); 1296 } 1297 1298 /* 1299 * If this RR is "equal" to the update RR, it should 1300 * be deleted before the update RR is added. 1301 */ 1302 if (replaces_p(ctx->update_rr, &rr->rdata)) { 1303 CHECK(dns_difftuple_create(ctx->del_diff.mctx, DNS_DIFFOP_DEL, 1304 ctx->name, rr->ttl, &rr->rdata, 1305 &tuple)); 1306 dns_diff_append(&ctx->del_diff, &tuple); 1307 return (ISC_R_SUCCESS); 1308 } 1309 1310 /* 1311 * If this RR differs in TTL from the update RR, 1312 * its TTL must be adjusted. 1313 */ 1314 if (rr->ttl != ctx->update_rr_ttl) { 1315 CHECK(dns_difftuple_create(ctx->del_diff.mctx, DNS_DIFFOP_DEL, 1316 ctx->name, rr->ttl, &rr->rdata, 1317 &tuple)); 1318 dns_diff_append(&ctx->del_diff, &tuple); 1319 if (!equal) { 1320 CHECK(dns_difftuple_create(ctx->add_diff.mctx, 1321 DNS_DIFFOP_ADD, ctx->name, 1322 ctx->update_rr_ttl, 1323 &rr->rdata, &tuple)); 1324 dns_diff_append(&ctx->add_diff, &tuple); 1325 } 1326 } 1327 failure: 1328 return (result); 1329} 1330 1331/**************************************************************************/ 1332/* 1333 * Miscellaneous subroutines. 1334 */ 1335 1336/*% 1337 * Extract a single update RR from 'section' of dynamic update message 1338 * 'msg', with consistency checking. 1339 * 1340 * Stores the owner name, rdata, and TTL of the update RR at 'name', 1341 * 'rdata', and 'ttl', respectively. 1342 */ 1343static void 1344get_current_rr(dns_message_t *msg, dns_section_t section, 1345 dns_rdataclass_t zoneclass, dns_name_t **name, 1346 dns_rdata_t *rdata, dns_rdatatype_t *covers, 1347 dns_ttl_t *ttl, dns_rdataclass_t *update_class) 1348{ 1349 dns_rdataset_t *rdataset; 1350 isc_result_t result; 1351 dns_message_currentname(msg, section, name); 1352 rdataset = ISC_LIST_HEAD((*name)->list); 1353 INSIST(rdataset != NULL); 1354 INSIST(ISC_LIST_NEXT(rdataset, link) == NULL); 1355 *covers = rdataset->covers; 1356 *ttl = rdataset->ttl; 1357 result = dns_rdataset_first(rdataset); 1358 INSIST(result == ISC_R_SUCCESS); 1359 dns_rdataset_current(rdataset, rdata); 1360 INSIST(dns_rdataset_next(rdataset) == ISC_R_NOMORE); 1361 *update_class = rdata->rdclass; 1362 rdata->rdclass = zoneclass; 1363} 1364 1365/*% 1366 * Increment the SOA serial number of database 'db', version 'ver'. 1367 * Replace the SOA record in the database, and log the 1368 * change in 'diff'. 1369 */ 1370 1371 /* 1372 * XXXRTH Failures in this routine will be worth logging, when 1373 * we have a logging system. Failure to find the zonename 1374 * or the SOA rdataset warrant at least an UNEXPECTED_ERROR(). 1375 */ 1376 1377static isc_result_t 1378increment_soa_serial(dns_db_t *db, dns_dbversion_t *ver, 1379 dns_diff_t *diff, isc_mem_t *mctx) 1380{ 1381 dns_difftuple_t *deltuple = NULL; 1382 dns_difftuple_t *addtuple = NULL; 1383 isc_uint32_t serial; 1384 isc_result_t result; 1385 1386 CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple)); 1387 CHECK(dns_difftuple_copy(deltuple, &addtuple)); 1388 addtuple->op = DNS_DIFFOP_ADD; 1389 1390 serial = dns_soa_getserial(&addtuple->rdata); 1391 1392 /* RFC1982 */ 1393 serial = (serial + 1) & 0xFFFFFFFF; 1394 if (serial == 0) 1395 serial = 1; 1396 1397 dns_soa_setserial(serial, &addtuple->rdata); 1398 CHECK(do_one_tuple(&deltuple, db, ver, diff)); 1399 CHECK(do_one_tuple(&addtuple, db, ver, diff)); 1400 result = ISC_R_SUCCESS; 1401 1402 failure: 1403 if (addtuple != NULL) 1404 dns_difftuple_free(&addtuple); 1405 if (deltuple != NULL) 1406 dns_difftuple_free(&deltuple); 1407 return (result); 1408} 1409 1410/*% 1411 * Check that the new SOA record at 'update_rdata' does not 1412 * illegally cause the SOA serial number to decrease or stay 1413 * unchanged relative to the existing SOA in 'db'. 1414 * 1415 * Sets '*ok' to ISC_TRUE if the update is legal, ISC_FALSE if not. 1416 * 1417 * William King points out that RFC2136 is inconsistent about 1418 * the case where the serial number stays unchanged: 1419 * 1420 * section 3.4.2.2 requires a server to ignore a SOA update request 1421 * if the serial number on the update SOA is less_than_or_equal to 1422 * the zone SOA serial. 1423 * 1424 * section 3.6 requires a server to ignore a SOA update request if 1425 * the serial is less_than the zone SOA serial. 1426 * 1427 * Paul says 3.4.2.2 is correct. 1428 * 1429 */ 1430static isc_result_t 1431check_soa_increment(dns_db_t *db, dns_dbversion_t *ver, 1432 dns_rdata_t *update_rdata, isc_boolean_t *ok) 1433{ 1434 isc_uint32_t db_serial; 1435 isc_uint32_t update_serial; 1436 isc_result_t result; 1437 1438 update_serial = dns_soa_getserial(update_rdata); 1439 1440 result = dns_db_getsoaserial(db, ver, &db_serial); 1441 if (result != ISC_R_SUCCESS) 1442 return (result); 1443 1444 if (DNS_SERIAL_GE(db_serial, update_serial)) { 1445 *ok = ISC_FALSE; 1446 } else { 1447 *ok = ISC_TRUE; 1448 } 1449 1450 return (ISC_R_SUCCESS); 1451 1452} 1453 1454/**************************************************************************/ 1455/* 1456 * Incremental updating of NSECs and RRSIGs. 1457 */ 1458 1459#define MAXZONEKEYS 32 /*%< Maximum number of zone keys supported. */ 1460 1461/*% 1462 * We abuse the dns_diff_t type to represent a set of domain names 1463 * affected by the update. 1464 */ 1465static isc_result_t 1466namelist_append_name(dns_diff_t *list, dns_name_t *name) { 1467 isc_result_t result; 1468 dns_difftuple_t *tuple = NULL; 1469 static dns_rdata_t dummy_rdata = DNS_RDATA_INIT; 1470 1471 CHECK(dns_difftuple_create(list->mctx, DNS_DIFFOP_EXISTS, name, 0, 1472 &dummy_rdata, &tuple)); 1473 dns_diff_append(list, &tuple); 1474 failure: 1475 return (result); 1476} 1477 1478static isc_result_t 1479namelist_append_subdomain(dns_db_t *db, dns_name_t *name, dns_diff_t *affected) 1480{ 1481 isc_result_t result; 1482 dns_fixedname_t fixedname; 1483 dns_name_t *child; 1484 dns_dbiterator_t *dbit = NULL; 1485 1486 dns_fixedname_init(&fixedname); 1487 child = dns_fixedname_name(&fixedname); 1488 1489 CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit)); 1490 1491 for (result = dns_dbiterator_seek(dbit, name); 1492 result == ISC_R_SUCCESS; 1493 result = dns_dbiterator_next(dbit)) 1494 { 1495 dns_dbnode_t *node = NULL; 1496 CHECK(dns_dbiterator_current(dbit, &node, child)); 1497 dns_db_detachnode(db, &node); 1498 if (! dns_name_issubdomain(child, name)) 1499 break; 1500 CHECK(namelist_append_name(affected, child)); 1501 } 1502 if (result == ISC_R_NOMORE) 1503 result = ISC_R_SUCCESS; 1504 failure: 1505 if (dbit != NULL) 1506 dns_dbiterator_destroy(&dbit); 1507 return (result); 1508} 1509 1510 1511 1512/*% 1513 * Helper function for non_nsec_rrset_exists(). 1514 */ 1515static isc_result_t 1516is_non_nsec_action(void *data, dns_rdataset_t *rrset) { 1517 UNUSED(data); 1518 if (!(rrset->type == dns_rdatatype_nsec || 1519 rrset->type == dns_rdatatype_nsec3 || 1520 (rrset->type == dns_rdatatype_rrsig && 1521 (rrset->covers == dns_rdatatype_nsec || 1522 rrset->covers == dns_rdatatype_nsec3)))) 1523 return (ISC_R_EXISTS); 1524 return (ISC_R_SUCCESS); 1525} 1526 1527/*% 1528 * Check whether there is an rrset other than a NSEC or RRSIG NSEC, 1529 * i.e., anything that justifies the continued existence of a name 1530 * after a secure update. 1531 * 1532 * If such an rrset exists, set '*exists' to ISC_TRUE. 1533 * Otherwise, set it to ISC_FALSE. 1534 */ 1535static isc_result_t 1536non_nsec_rrset_exists(dns_db_t *db, dns_dbversion_t *ver, 1537 dns_name_t *name, isc_boolean_t *exists) 1538{ 1539 isc_result_t result; 1540 result = foreach_rrset(db, ver, name, is_non_nsec_action, NULL); 1541 RETURN_EXISTENCE_FLAG; 1542} 1543 1544/*% 1545 * A comparison function for sorting dns_diff_t:s by name. 1546 */ 1547static int 1548name_order(const void *av, const void *bv) { 1549 dns_difftuple_t const * const *ap = av; 1550 dns_difftuple_t const * const *bp = bv; 1551 dns_difftuple_t const *a = *ap; 1552 dns_difftuple_t const *b = *bp; 1553 return (dns_name_compare(&a->name, &b->name)); 1554} 1555 1556static isc_result_t 1557uniqify_name_list(dns_diff_t *list) { 1558 isc_result_t result; 1559 dns_difftuple_t *p, *q; 1560 1561 CHECK(dns_diff_sort(list, name_order)); 1562 1563 p = ISC_LIST_HEAD(list->tuples); 1564 while (p != NULL) { 1565 do { 1566 q = ISC_LIST_NEXT(p, link); 1567 if (q == NULL || ! dns_name_equal(&p->name, &q->name)) 1568 break; 1569 ISC_LIST_UNLINK(list->tuples, q, link); 1570 dns_difftuple_free(&q); 1571 } while (1); 1572 p = ISC_LIST_NEXT(p, link); 1573 } 1574 failure: 1575 return (result); 1576} 1577 1578static isc_result_t 1579is_active(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, 1580 isc_boolean_t *flag, isc_boolean_t *cut, isc_boolean_t *unsecure) 1581{ 1582 isc_result_t result; 1583 dns_fixedname_t foundname; 1584 dns_fixedname_init(&foundname); 1585 result = dns_db_find(db, name, ver, dns_rdatatype_any, 1586 DNS_DBFIND_GLUEOK | DNS_DBFIND_NOWILD, 1587 (isc_stdtime_t) 0, NULL, 1588 dns_fixedname_name(&foundname), 1589 NULL, NULL); 1590 if (result == ISC_R_SUCCESS || result == DNS_R_EMPTYNAME) { 1591 *flag = ISC_TRUE; 1592 *cut = ISC_FALSE; 1593 if (unsecure != NULL) 1594 *unsecure = ISC_FALSE; 1595 return (ISC_R_SUCCESS); 1596 } else if (result == DNS_R_ZONECUT) { 1597 *flag = ISC_TRUE; 1598 *cut = ISC_TRUE; 1599 if (unsecure != NULL) { 1600 /* 1601 * We are at the zonecut. Check to see if there 1602 * is a DS RRset. 1603 */ 1604 if (dns_db_find(db, name, ver, dns_rdatatype_ds, 0, 1605 (isc_stdtime_t) 0, NULL, 1606 dns_fixedname_name(&foundname), 1607 NULL, NULL) == DNS_R_NXRRSET) 1608 *unsecure = ISC_TRUE; 1609 else 1610 *unsecure = ISC_FALSE; 1611 } 1612 return (ISC_R_SUCCESS); 1613 } else if (result == DNS_R_GLUE || result == DNS_R_DNAME || 1614 result == DNS_R_DELEGATION || result == DNS_R_NXDOMAIN) { 1615 *flag = ISC_FALSE; 1616 *cut = ISC_FALSE; 1617 if (unsecure != NULL) 1618 *unsecure = ISC_FALSE; 1619 return (ISC_R_SUCCESS); 1620 } else { 1621 /* 1622 * Silence compiler. 1623 */ 1624 *flag = ISC_FALSE; 1625 *cut = ISC_FALSE; 1626 if (unsecure != NULL) 1627 *unsecure = ISC_FALSE; 1628 return (result); 1629 } 1630} 1631 1632/*% 1633 * Find the next/previous name that has a NSEC record. 1634 * In other words, skip empty database nodes and names that 1635 * have had their NSECs removed because they are obscured by 1636 * a zone cut. 1637 */ 1638static isc_result_t 1639next_active(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, 1640 dns_dbversion_t *ver, dns_name_t *oldname, dns_name_t *newname, 1641 isc_boolean_t forward) 1642{ 1643 isc_result_t result; 1644 dns_dbiterator_t *dbit = NULL; 1645 isc_boolean_t has_nsec; 1646 unsigned int wraps = 0; 1647 isc_boolean_t secure = dns_db_issecure(db); 1648 1649 CHECK(dns_db_createiterator(db, 0, &dbit)); 1650 1651 CHECK(dns_dbiterator_seek(dbit, oldname)); 1652 do { 1653 dns_dbnode_t *node = NULL; 1654 1655 if (forward) 1656 result = dns_dbiterator_next(dbit); 1657 else 1658 result = dns_dbiterator_prev(dbit); 1659 if (result == ISC_R_NOMORE) { 1660 /* 1661 * Wrap around. 1662 */ 1663 if (forward) 1664 CHECK(dns_dbiterator_first(dbit)); 1665 else 1666 CHECK(dns_dbiterator_last(dbit)); 1667 wraps++; 1668 if (wraps == 2) { 1669 update_log(client, zone, ISC_LOG_ERROR, 1670 "secure zone with no NSECs"); 1671 result = DNS_R_BADZONE; 1672 goto failure; 1673 } 1674 } 1675 CHECK(dns_dbiterator_current(dbit, &node, newname)); 1676 dns_db_detachnode(db, &node); 1677 1678 /* 1679 * The iterator may hold the tree lock, and 1680 * rrset_exists() calls dns_db_findnode() which 1681 * may try to reacquire it. To avoid deadlock 1682 * we must pause the iterator first. 1683 */ 1684 CHECK(dns_dbiterator_pause(dbit)); 1685 if (secure) { 1686 CHECK(rrset_exists(db, ver, newname, 1687 dns_rdatatype_nsec, 0, &has_nsec)); 1688 } else { 1689 dns_fixedname_t ffound; 1690 dns_name_t *found; 1691 dns_fixedname_init(&ffound); 1692 found = dns_fixedname_name(&ffound); 1693 result = dns_db_find(db, newname, ver, 1694 dns_rdatatype_soa, 1695 DNS_DBFIND_NOWILD, 0, NULL, found, 1696 NULL, NULL); 1697 if (result == ISC_R_SUCCESS || 1698 result == DNS_R_EMPTYNAME || 1699 result == DNS_R_NXRRSET || 1700 result == DNS_R_CNAME || 1701 (result == DNS_R_DELEGATION && 1702 dns_name_equal(newname, found))) { 1703 has_nsec = ISC_TRUE; 1704 result = ISC_R_SUCCESS; 1705 } else if (result != DNS_R_NXDOMAIN) 1706 break; 1707 } 1708 } while (! has_nsec); 1709 failure: 1710 if (dbit != NULL) 1711 dns_dbiterator_destroy(&dbit); 1712 1713 return (result); 1714} 1715 1716static isc_boolean_t 1717has_opt_bit(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node) { 1718 isc_result_t result; 1719 dns_rdata_t rdata = DNS_RDATA_INIT; 1720 dns_rdataset_t rdataset; 1721 isc_boolean_t has_bit = ISC_FALSE; 1722 1723 dns_rdataset_init(&rdataset); 1724 CHECK(dns_db_findrdataset(db, node, version, dns_rdatatype_nsec, 1725 dns_rdatatype_none, 0, &rdataset, NULL)); 1726 CHECK(dns_rdataset_first(&rdataset)); 1727 dns_rdataset_current(&rdataset, &rdata); 1728 has_bit = dns_nsec_typepresent(&rdata, dns_rdatatype_opt); 1729 failure: 1730 if (dns_rdataset_isassociated(&rdataset)) 1731 dns_rdataset_disassociate(&rdataset); 1732 return (has_bit); 1733} 1734 1735static void 1736set_bit(unsigned char *array, unsigned int index) { 1737 unsigned int shift, bit; 1738 1739 shift = 7 - (index % 8); 1740 bit = 1 << shift; 1741 1742 array[index / 8] |= bit; 1743} 1744 1745/*% 1746 * Add a NSEC record for "name", recording the change in "diff". 1747 * The existing NSEC is removed. 1748 */ 1749static isc_result_t 1750add_nsec(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, 1751 dns_dbversion_t *ver, dns_name_t *name, dns_ttl_t nsecttl, 1752 dns_diff_t *diff) 1753{ 1754 isc_result_t result; 1755 dns_dbnode_t *node = NULL; 1756 unsigned char buffer[DNS_NSEC_BUFFERSIZE]; 1757 dns_rdata_t rdata = DNS_RDATA_INIT; 1758 dns_difftuple_t *tuple = NULL; 1759 dns_fixedname_t fixedname; 1760 dns_name_t *target; 1761 1762 dns_fixedname_init(&fixedname); 1763 target = dns_fixedname_name(&fixedname); 1764 1765 /* 1766 * Find the successor name, aka NSEC target. 1767 */ 1768 CHECK(next_active(client, zone, db, ver, name, target, ISC_TRUE)); 1769 1770 /* 1771 * Create the NSEC RDATA. 1772 */ 1773 CHECK(dns_db_findnode(db, name, ISC_FALSE, &node)); 1774 dns_rdata_init(&rdata); 1775 CHECK(dns_nsec_buildrdata(db, ver, node, target, buffer, &rdata)); 1776 /* 1777 * Preserve the status of the OPT bit in the origin's NSEC record. 1778 */ 1779 if (dns_name_equal(dns_db_origin(db), name) && 1780 has_opt_bit(db, ver, node)) 1781 { 1782 isc_region_t region; 1783 dns_name_t next; 1784 1785 dns_name_init(&next, NULL); 1786 dns_rdata_toregion(&rdata, ®ion); 1787 dns_name_fromregion(&next, ®ion); 1788 isc_region_consume(®ion, next.length); 1789 INSIST(region.length > (2 + dns_rdatatype_opt / 8) && 1790 region.base[0] == 0 && 1791 region.base[1] > dns_rdatatype_opt / 8); 1792 set_bit(region.base + 2, dns_rdatatype_opt); 1793 } 1794 dns_db_detachnode(db, &node); 1795 1796 /* 1797 * Delete the old NSEC and record the change. 1798 */ 1799 CHECK(delete_if(true_p, db, ver, name, dns_rdatatype_nsec, 0, 1800 NULL, diff)); 1801 /* 1802 * Add the new NSEC and record the change. 1803 */ 1804 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, name, 1805 nsecttl, &rdata, &tuple)); 1806 CHECK(do_one_tuple(&tuple, db, ver, diff)); 1807 INSIST(tuple == NULL); 1808 1809 failure: 1810 if (node != NULL) 1811 dns_db_detachnode(db, &node); 1812 return (result); 1813} 1814 1815/*% 1816 * Add a placeholder NSEC record for "name", recording the change in "diff". 1817 */ 1818static isc_result_t 1819add_placeholder_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, 1820 dns_diff_t *diff) 1821{ 1822 isc_result_t result; 1823 dns_difftuple_t *tuple = NULL; 1824 isc_region_t r; 1825 unsigned char data[1] = { 0 }; /* The root domain, no bits. */ 1826 dns_rdata_t rdata = DNS_RDATA_INIT; 1827 1828 r.base = data; 1829 r.length = sizeof(data); 1830 dns_rdata_fromregion(&rdata, dns_db_class(db), dns_rdatatype_nsec, &r); 1831 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, name, 0, 1832 &rdata, &tuple)); 1833 CHECK(do_one_tuple(&tuple, db, ver, diff)); 1834 failure: 1835 return (result); 1836} 1837 1838static isc_result_t 1839find_zone_keys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, 1840 isc_mem_t *mctx, unsigned int maxkeys, 1841 dst_key_t **keys, unsigned int *nkeys) 1842{ 1843 isc_result_t result; 1844 dns_dbnode_t *node = NULL; 1845 const char *directory = dns_zone_getkeydirectory(zone); 1846 CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node)); 1847 CHECK(dns_dnssec_findzonekeys2(db, ver, node, dns_db_origin(db), 1848 directory, mctx, maxkeys, keys, nkeys)); 1849 failure: 1850 if (node != NULL) 1851 dns_db_detachnode(db, &node); 1852 return (result); 1853} 1854 1855static isc_boolean_t 1856ksk_sanity(dns_db_t *db, dns_dbversion_t *ver) { 1857 isc_boolean_t ret = ISC_FALSE; 1858 isc_boolean_t have_ksk = ISC_FALSE, have_nonksk = ISC_FALSE; 1859 isc_result_t result; 1860 dns_dbnode_t *node = NULL; 1861 dns_rdataset_t rdataset; 1862 dns_rdata_t rdata = DNS_RDATA_INIT; 1863 dns_rdata_dnskey_t dnskey; 1864 1865 dns_rdataset_init(&rdataset); 1866 CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node)); 1867 CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey, 0, 0, 1868 &rdataset, NULL)); 1869 CHECK(dns_rdataset_first(&rdataset)); 1870 while (result == ISC_R_SUCCESS && (!have_ksk || !have_nonksk)) { 1871 dns_rdataset_current(&rdataset, &rdata); 1872 CHECK(dns_rdata_tostruct(&rdata, &dnskey, NULL)); 1873 if ((dnskey.flags & (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH)) 1874 == DNS_KEYOWNER_ZONE) { 1875 if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0) 1876 have_ksk = ISC_TRUE; 1877 else 1878 have_nonksk = ISC_TRUE; 1879 } 1880 dns_rdata_reset(&rdata); 1881 result = dns_rdataset_next(&rdataset); 1882 } 1883 if (have_ksk && have_nonksk) 1884 ret = ISC_TRUE; 1885 failure: 1886 if (dns_rdataset_isassociated(&rdataset)) 1887 dns_rdataset_disassociate(&rdataset); 1888 if (node != NULL) 1889 dns_db_detachnode(db, &node); 1890 return (ret); 1891} 1892 1893/*% 1894 * Add RRSIG records for an RRset, recording the change in "diff". 1895 */ 1896static isc_result_t 1897add_sigs(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, 1898 dns_dbversion_t *ver, dns_name_t *name, dns_rdatatype_t type, 1899 dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys, 1900 isc_stdtime_t inception, isc_stdtime_t expire, 1901 isc_boolean_t check_ksk) 1902{ 1903 isc_result_t result; 1904 dns_dbnode_t *node = NULL; 1905 dns_rdataset_t rdataset; 1906 dns_rdata_t sig_rdata = DNS_RDATA_INIT; 1907 isc_buffer_t buffer; 1908 unsigned char data[1024]; /* XXX */ 1909 unsigned int i; 1910 isc_boolean_t added_sig = ISC_FALSE; 1911 isc_mem_t *mctx = client->mctx; 1912 1913 dns_rdataset_init(&rdataset); 1914 isc_buffer_init(&buffer, data, sizeof(data)); 1915 1916 /* Get the rdataset to sign. */ 1917 if (type == dns_rdatatype_nsec3) 1918 CHECK(dns_db_findnsec3node(db, name, ISC_FALSE, &node)); 1919 else 1920 CHECK(dns_db_findnode(db, name, ISC_FALSE, &node)); 1921 CHECK(dns_db_findrdataset(db, node, ver, type, 0, 1922 (isc_stdtime_t) 0, &rdataset, NULL)); 1923 dns_db_detachnode(db, &node); 1924 1925 for (i = 0; i < nkeys; i++) { 1926 1927 if (check_ksk && type != dns_rdatatype_dnskey && 1928 (dst_key_flags(keys[i]) & DNS_KEYFLAG_KSK) != 0) 1929 continue; 1930 1931 if (!dst_key_isprivate(keys[i])) 1932 continue; 1933 1934 /* Calculate the signature, creating a RRSIG RDATA. */ 1935 CHECK(dns_dnssec_sign(name, &rdataset, keys[i], 1936 &inception, &expire, 1937 mctx, &buffer, &sig_rdata)); 1938 1939 /* Update the database and journal with the RRSIG. */ 1940 /* XXX inefficient - will cause dataset merging */ 1941 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN, name, 1942 rdataset.ttl, &sig_rdata)); 1943 dns_rdata_reset(&sig_rdata); 1944 added_sig = ISC_TRUE; 1945 } 1946 if (!added_sig) { 1947 update_log(client, zone, ISC_LOG_ERROR, 1948 "found no private keys, " 1949 "unable to generate any signatures"); 1950 result = ISC_R_NOTFOUND; 1951 } 1952 1953 failure: 1954 if (dns_rdataset_isassociated(&rdataset)) 1955 dns_rdataset_disassociate(&rdataset); 1956 if (node != NULL) 1957 dns_db_detachnode(db, &node); 1958 return (result); 1959} 1960 1961/* 1962 * Delete expired RRsigs and any RRsigs we are about to re-sign. 1963 * See also zone.c:del_sigs(). 1964 */ 1965static isc_result_t 1966del_keysigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, 1967 dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys) 1968{ 1969 isc_result_t result; 1970 dns_dbnode_t *node = NULL; 1971 dns_rdataset_t rdataset; 1972 dns_rdata_t rdata = DNS_RDATA_INIT; 1973 unsigned int i; 1974 dns_rdata_rrsig_t rrsig; 1975 isc_boolean_t found; 1976 1977 dns_rdataset_init(&rdataset); 1978 1979 result = dns_db_findnode(db, name, ISC_FALSE, &node); 1980 if (result == ISC_R_NOTFOUND) 1981 return (ISC_R_SUCCESS); 1982 if (result != ISC_R_SUCCESS) 1983 goto failure; 1984 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig, 1985 dns_rdatatype_dnskey, (isc_stdtime_t) 0, 1986 &rdataset, NULL); 1987 dns_db_detachnode(db, &node); 1988 1989 if (result == ISC_R_NOTFOUND) 1990 return (ISC_R_SUCCESS); 1991 if (result != ISC_R_SUCCESS) 1992 goto failure; 1993 1994 for (result = dns_rdataset_first(&rdataset); 1995 result == ISC_R_SUCCESS; 1996 result = dns_rdataset_next(&rdataset)) { 1997 dns_rdataset_current(&rdataset, &rdata); 1998 result = dns_rdata_tostruct(&rdata, &rrsig, NULL); 1999 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2000 found = ISC_FALSE; 2001 for (i = 0; i < nkeys; i++) { 2002 if (rrsig.keyid == dst_key_id(keys[i])) { 2003 found = ISC_TRUE; 2004 if (!dst_key_isprivate(keys[i])) { 2005 /* 2006 * The re-signing code in zone.c 2007 * will mark this as offline. 2008 * Just skip the record for now. 2009 */ 2010 break; 2011 } 2012 result = update_one_rr(db, ver, diff, 2013 DNS_DIFFOP_DEL, name, 2014 rdataset.ttl, &rdata); 2015 break; 2016 } 2017 } 2018 /* 2019 * If there is not a matching DNSKEY then delete the RRSIG. 2020 */ 2021 if (!found) 2022 result = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, 2023 name, rdataset.ttl, &rdata); 2024 dns_rdata_reset(&rdata); 2025 if (result != ISC_R_SUCCESS) 2026 break; 2027 } 2028 dns_rdataset_disassociate(&rdataset); 2029 if (result == ISC_R_NOMORE) 2030 result = ISC_R_SUCCESS; 2031failure: 2032 if (node != NULL) 2033 dns_db_detachnode(db, &node); 2034 return (result); 2035} 2036 2037static isc_result_t 2038add_exposed_sigs(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, 2039 dns_dbversion_t *ver, dns_name_t *name, isc_boolean_t cut, 2040 dns_diff_t *diff, dst_key_t **keys, unsigned int nkeys, 2041 isc_stdtime_t inception, isc_stdtime_t expire, 2042 isc_boolean_t check_ksk) 2043{ 2044 isc_result_t result; 2045 dns_dbnode_t *node; 2046 dns_rdatasetiter_t *iter; 2047 2048 node = NULL; 2049 result = dns_db_findnode(db, name, ISC_FALSE, &node); 2050 if (result == ISC_R_NOTFOUND) 2051 return (ISC_R_SUCCESS); 2052 if (result != ISC_R_SUCCESS) 2053 return (result); 2054 2055 iter = NULL; 2056 result = dns_db_allrdatasets(db, node, ver, 2057 (isc_stdtime_t) 0, &iter); 2058 if (result != ISC_R_SUCCESS) 2059 goto cleanup_node; 2060 2061 for (result = dns_rdatasetiter_first(iter); 2062 result == ISC_R_SUCCESS; 2063 result = dns_rdatasetiter_next(iter)) 2064 { 2065 dns_rdataset_t rdataset; 2066 dns_rdatatype_t type; 2067 isc_boolean_t flag; 2068 2069 dns_rdataset_init(&rdataset); 2070 dns_rdatasetiter_current(iter, &rdataset); 2071 type = rdataset.type; 2072 dns_rdataset_disassociate(&rdataset); 2073 2074 /* 2075 * We don't need to sign unsigned NSEC records at the cut 2076 * as they are handled elsewhere. 2077 */ 2078 if ((type == dns_rdatatype_rrsig) || 2079 (cut && type != dns_rdatatype_ds)) 2080 continue; 2081 result = rrset_exists(db, ver, name, dns_rdatatype_rrsig, 2082 type, &flag); 2083 if (result != ISC_R_SUCCESS) 2084 goto cleanup_iterator; 2085 if (flag) 2086 continue;; 2087 result = add_sigs(client, zone, db, ver, name, type, diff, 2088 keys, nkeys, inception, expire, check_ksk); 2089 if (result != ISC_R_SUCCESS) 2090 goto cleanup_iterator; 2091 } 2092 if (result == ISC_R_NOMORE) 2093 result = ISC_R_SUCCESS; 2094 2095 cleanup_iterator: 2096 dns_rdatasetiter_destroy(&iter); 2097 2098 cleanup_node: 2099 dns_db_detachnode(db, &node); 2100 2101 return (result); 2102} 2103 2104/*% 2105 * Update RRSIG, NSEC and NSEC3 records affected by an update. The original 2106 * update, including the SOA serial update but excluding the RRSIG & NSEC 2107 * changes, is in "diff" and has already been applied to "newver" of "db". 2108 * The database version prior to the update is "oldver". 2109 * 2110 * The necessary RRSIG, NSEC and NSEC3 changes will be applied to "newver" 2111 * and added (as a minimal diff) to "diff". 2112 * 2113 * The RRSIGs generated will be valid for 'sigvalidityinterval' seconds. 2114 */ 2115static isc_result_t 2116update_signatures(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, 2117 dns_dbversion_t *oldver, dns_dbversion_t *newver, 2118 dns_diff_t *diff, isc_uint32_t sigvalidityinterval, 2119 isc_boolean_t *deleted_zsk) 2120{ 2121 isc_result_t result; 2122 dns_difftuple_t *t; 2123 dns_diff_t diffnames; 2124 dns_diff_t affected; 2125 dns_diff_t sig_diff; 2126 dns_diff_t nsec_diff; 2127 dns_diff_t nsec_mindiff; 2128 isc_boolean_t flag; 2129 dst_key_t *zone_keys[MAXZONEKEYS]; 2130 unsigned int nkeys = 0; 2131 unsigned int i; 2132 isc_stdtime_t now, inception, expire; 2133 dns_ttl_t nsecttl; 2134 dns_rdata_soa_t soa; 2135 dns_rdata_t rdata = DNS_RDATA_INIT; 2136 dns_rdataset_t rdataset; 2137 dns_dbnode_t *node = NULL; 2138 isc_boolean_t check_ksk; 2139 isc_boolean_t unsecure; 2140 isc_boolean_t cut; 2141 2142 dns_diff_init(client->mctx, &diffnames); 2143 dns_diff_init(client->mctx, &affected); 2144 2145 dns_diff_init(client->mctx, &sig_diff); 2146 sig_diff.resign = dns_zone_getsigresigninginterval(zone); 2147 dns_diff_init(client->mctx, &nsec_diff); 2148 dns_diff_init(client->mctx, &nsec_mindiff); 2149 2150 result = find_zone_keys(zone, db, newver, client->mctx, 2151 MAXZONEKEYS, zone_keys, &nkeys); 2152 if (result != ISC_R_SUCCESS) { 2153 update_log(client, zone, ISC_LOG_ERROR, 2154 "could not get zone keys for secure dynamic update"); 2155 goto failure; 2156 } 2157 2158 isc_stdtime_get(&now); 2159 inception = now - 3600; /* Allow for some clock skew. */ 2160 expire = now + sigvalidityinterval; 2161 2162 /* 2163 * Do we look at the KSK flag on the DNSKEY to determining which 2164 * keys sign which RRsets? First check the zone option then 2165 * check the keys flags to make sure at least one has a ksk set 2166 * and one doesn't. 2167 */ 2168 check_ksk = ISC_TF((dns_zone_getoptions(zone) & 2169 DNS_ZONEOPT_UPDATECHECKKSK) != 0); 2170 /* 2171 * If we are not checking the ZSK flag then all DNSKEY's are 2172 * already signing all RRsets so we don't need to trigger special 2173 * changes. 2174 */ 2175 if (*deleted_zsk && (!check_ksk || !ksk_sanity(db, oldver))) 2176 *deleted_zsk = ISC_FALSE; 2177 2178 if (check_ksk) { 2179 check_ksk = ksk_sanity(db, newver); 2180 if (!check_ksk && ksk_sanity(db, oldver)) 2181 update_log(client, zone, ISC_LOG_WARNING, 2182 "disabling update-check-ksk"); 2183 } 2184 2185 /* 2186 * If we have deleted a ZSK and we we still have some ZSK's 2187 * we don't need to convert the KSK's to a ZSK's. 2188 */ 2189 if (*deleted_zsk && check_ksk) 2190 *deleted_zsk = ISC_FALSE; 2191 2192 /* 2193 * Get the NSEC/NSEC3 TTL from the SOA MINIMUM field. 2194 */ 2195 CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node)); 2196 dns_rdataset_init(&rdataset); 2197 CHECK(dns_db_findrdataset(db, node, newver, dns_rdatatype_soa, 0, 2198 (isc_stdtime_t) 0, &rdataset, NULL)); 2199 CHECK(dns_rdataset_first(&rdataset)); 2200 dns_rdataset_current(&rdataset, &rdata); 2201 CHECK(dns_rdata_tostruct(&rdata, &soa, NULL)); 2202 nsecttl = soa.minimum; 2203 dns_rdataset_disassociate(&rdataset); 2204 dns_db_detachnode(db, &node); 2205 2206 /* 2207 * Find all RRsets directly affected by the update, and 2208 * update their RRSIGs. Also build a list of names affected 2209 * by the update in "diffnames". 2210 */ 2211 CHECK(dns_diff_sort(diff, temp_order)); 2212 2213 t = ISC_LIST_HEAD(diff->tuples); 2214 while (t != NULL) { 2215 dns_name_t *name = &t->name; 2216 /* Now "name" is a new, unique name affected by the update. */ 2217 2218 CHECK(namelist_append_name(&diffnames, name)); 2219 2220 while (t != NULL && dns_name_equal(&t->name, name)) { 2221 dns_rdatatype_t type; 2222 type = t->rdata.type; 2223 2224 /* 2225 * Now "name" and "type" denote a new unique RRset 2226 * affected by the update. 2227 */ 2228 2229 /* Don't sign RRSIGs. */ 2230 if (type == dns_rdatatype_rrsig) 2231 goto skip; 2232 2233 /* 2234 * Delete all old RRSIGs covering this type, since they 2235 * are all invalid when the signed RRset has changed. 2236 * We may not be able to recreate all of them - tough. 2237 * Special case changes to the zone's DNSKEY records 2238 * to support offline KSKs. 2239 */ 2240 if (type == dns_rdatatype_dnskey) 2241 del_keysigs(db, newver, name, &sig_diff, 2242 zone_keys, nkeys); 2243 else 2244 CHECK(delete_if(true_p, db, newver, name, 2245 dns_rdatatype_rrsig, type, 2246 NULL, &sig_diff)); 2247 2248 /* 2249 * If this RRset is still visible after the update, 2250 * add a new signature for it. 2251 */ 2252 CHECK(rrset_visible(db, newver, name, type, &flag)); 2253 if (flag) { 2254 CHECK(add_sigs(client, zone, db, newver, name, 2255 type, &sig_diff, zone_keys, 2256 nkeys, inception, expire, 2257 check_ksk)); 2258 } 2259 skip: 2260 /* Skip any other updates to the same RRset. */ 2261 while (t != NULL && 2262 dns_name_equal(&t->name, name) && 2263 t->rdata.type == type) 2264 { 2265 t = ISC_LIST_NEXT(t, link); 2266 } 2267 } 2268 } 2269 update_log(client, zone, ISC_LOG_DEBUG(3), "updated data signatures"); 2270 2271 /* Remove orphaned NSECs and RRSIG NSECs. */ 2272 for (t = ISC_LIST_HEAD(diffnames.tuples); 2273 t != NULL; 2274 t = ISC_LIST_NEXT(t, link)) 2275 { 2276 CHECK(non_nsec_rrset_exists(db, newver, &t->name, &flag)); 2277 if (! flag) { 2278 CHECK(delete_if(true_p, db, newver, &t->name, 2279 dns_rdatatype_any, 0, 2280 NULL, &sig_diff)); 2281 } 2282 } 2283 update_log(client, zone, ISC_LOG_DEBUG(3), 2284 "removed any orphaned NSEC records"); 2285 2286 /* 2287 * If we don't have a NSEC record at the origin then we need to 2288 * update the NSEC3 records. 2289 */ 2290 CHECK(rrset_exists(db, newver, dns_db_origin(db), dns_rdatatype_nsec, 2291 0, &flag)); 2292 if (!flag) 2293 goto update_nsec3; 2294 2295 update_log(client, zone, ISC_LOG_DEBUG(3), "rebuilding NSEC chain"); 2296 2297 /* 2298 * When a name is created or deleted, its predecessor needs to 2299 * have its NSEC updated. 2300 */ 2301 for (t = ISC_LIST_HEAD(diffnames.tuples); 2302 t != NULL; 2303 t = ISC_LIST_NEXT(t, link)) 2304 { 2305 isc_boolean_t existed, exists; 2306 dns_fixedname_t fixedname; 2307 dns_name_t *prevname; 2308 2309 dns_fixedname_init(&fixedname); 2310 prevname = dns_fixedname_name(&fixedname); 2311 2312 CHECK(name_exists(db, oldver, &t->name, &existed)); 2313 CHECK(name_exists(db, newver, &t->name, &exists)); 2314 if (exists == existed) 2315 continue; 2316 2317 /* 2318 * Find the predecessor. 2319 * When names become obscured or unobscured in this update 2320 * transaction, we may find the wrong predecessor because 2321 * the NSECs have not yet been updated to reflect the delegation 2322 * change. This should not matter because in this case, 2323 * the correct predecessor is either the delegation node or 2324 * a newly unobscured node, and those nodes are on the 2325 * "affected" list in any case. 2326 */ 2327 CHECK(next_active(client, zone, db, newver, 2328 &t->name, prevname, ISC_FALSE)); 2329 CHECK(namelist_append_name(&affected, prevname)); 2330 } 2331 2332 /* 2333 * Find names potentially affected by delegation changes 2334 * (obscured by adding an NS or DNAME, or unobscured by 2335 * removing one). 2336 */ 2337 for (t = ISC_LIST_HEAD(diffnames.tuples); 2338 t != NULL; 2339 t = ISC_LIST_NEXT(t, link)) 2340 { 2341 isc_boolean_t ns_existed, dname_existed; 2342 isc_boolean_t ns_exists, dname_exists; 2343 2344 CHECK(rrset_exists(db, oldver, &t->name, dns_rdatatype_ns, 0, 2345 &ns_existed)); 2346 CHECK(rrset_exists(db, oldver, &t->name, dns_rdatatype_dname, 0, 2347 &dname_existed)); 2348 CHECK(rrset_exists(db, newver, &t->name, dns_rdatatype_ns, 0, 2349 &ns_exists)); 2350 CHECK(rrset_exists(db, newver, &t->name, dns_rdatatype_dname, 0, 2351 &dname_exists)); 2352 if ((ns_exists || dname_exists) == (ns_existed || dname_existed)) 2353 continue; 2354 /* 2355 * There was a delegation change. Mark all subdomains 2356 * of t->name as potentially needing a NSEC update. 2357 */ 2358 CHECK(namelist_append_subdomain(db, &t->name, &affected)); 2359 } 2360 2361 ISC_LIST_APPENDLIST(affected.tuples, diffnames.tuples, link); 2362 INSIST(ISC_LIST_EMPTY(diffnames.tuples)); 2363 2364 CHECK(uniqify_name_list(&affected)); 2365 2366 /* 2367 * Determine which names should have NSECs, and delete/create 2368 * NSECs to make it so. We don't know the final NSEC targets yet, 2369 * so we just create placeholder NSECs with arbitrary contents 2370 * to indicate that their respective owner names should be part of 2371 * the NSEC chain. 2372 */ 2373 for (t = ISC_LIST_HEAD(affected.tuples); 2374 t != NULL; 2375 t = ISC_LIST_NEXT(t, link)) 2376 { 2377 isc_boolean_t exists; 2378 dns_name_t *name = &t->name; 2379 2380 CHECK(name_exists(db, newver, name, &exists)); 2381 if (! exists) 2382 continue; 2383 CHECK(is_active(db, newver, name, &flag, &cut, NULL)); 2384 if (!flag) { 2385 /* 2386 * This name is obscured. Delete any 2387 * existing NSEC record. 2388 */ 2389 CHECK(delete_if(true_p, db, newver, name, 2390 dns_rdatatype_nsec, 0, 2391 NULL, &nsec_diff)); 2392 CHECK(delete_if(rrsig_p, db, newver, name, 2393 dns_rdatatype_any, 0, NULL, diff)); 2394 } else { 2395 /* 2396 * This name is not obscured. It should have a NSEC. 2397 */ 2398 CHECK(rrset_exists(db, newver, name, 2399 dns_rdatatype_nsec, 0, &flag)); 2400 if (! flag) 2401 CHECK(add_placeholder_nsec(db, newver, name, 2402 diff)); 2403 CHECK(add_exposed_sigs(client, zone, db, newver, name, 2404 cut, diff, zone_keys, nkeys, 2405 inception, expire, check_ksk)); 2406 } 2407 } 2408 2409 /* 2410 * Now we know which names are part of the NSEC chain. 2411 * Make them all point at their correct targets. 2412 */ 2413 for (t = ISC_LIST_HEAD(affected.tuples); 2414 t != NULL; 2415 t = ISC_LIST_NEXT(t, link)) 2416 { 2417 CHECK(rrset_exists(db, newver, &t->name, 2418 dns_rdatatype_nsec, 0, &flag)); 2419 if (flag) { 2420 /* 2421 * There is a NSEC, but we don't know if it is correct. 2422 * Delete it and create a correct one to be sure. 2423 * If the update was unnecessary, the diff minimization 2424 * will take care of eliminating it from the journal, 2425 * IXFRs, etc. 2426 * 2427 * The RRSIG bit should always be set in the NSECs 2428 * we generate, because they will all get RRSIG NSECs. 2429 * (XXX what if the zone keys are missing?). 2430 * Because the RRSIG NSECs have not necessarily been 2431 * created yet, the correctness of the bit mask relies 2432 * on the assumption that NSECs are only created if 2433 * there is other data, and if there is other data, 2434 * there are other RRSIGs. 2435 */ 2436 CHECK(add_nsec(client, zone, db, newver, &t->name, 2437 nsecttl, &nsec_diff)); 2438 } 2439 } 2440 2441 /* 2442 * Minimize the set of NSEC updates so that we don't 2443 * have to regenerate the RRSIG NSECs for NSECs that were 2444 * replaced with identical ones. 2445 */ 2446 while ((t = ISC_LIST_HEAD(nsec_diff.tuples)) != NULL) { 2447 ISC_LIST_UNLINK(nsec_diff.tuples, t, link); 2448 dns_diff_appendminimal(&nsec_mindiff, &t); 2449 } 2450 2451 update_log(client, zone, ISC_LOG_DEBUG(3), 2452 "signing rebuilt NSEC chain"); 2453 2454 /* Update RRSIG NSECs. */ 2455 for (t = ISC_LIST_HEAD(nsec_mindiff.tuples); 2456 t != NULL; 2457 t = ISC_LIST_NEXT(t, link)) 2458 { 2459 if (t->op == DNS_DIFFOP_DEL) { 2460 CHECK(delete_if(true_p, db, newver, &t->name, 2461 dns_rdatatype_rrsig, dns_rdatatype_nsec, 2462 NULL, &sig_diff)); 2463 } else if (t->op == DNS_DIFFOP_ADD) { 2464 CHECK(add_sigs(client, zone, db, newver, &t->name, 2465 dns_rdatatype_nsec, &sig_diff, 2466 zone_keys, nkeys, inception, expire, 2467 check_ksk)); 2468 } else { 2469 INSIST(0); 2470 } 2471 } 2472 2473 update_nsec3: 2474 2475 /* Record our changes for the journal. */ 2476 while ((t = ISC_LIST_HEAD(sig_diff.tuples)) != NULL) { 2477 ISC_LIST_UNLINK(sig_diff.tuples, t, link); 2478 dns_diff_appendminimal(diff, &t); 2479 } 2480 while ((t = ISC_LIST_HEAD(nsec_mindiff.tuples)) != NULL) { 2481 ISC_LIST_UNLINK(nsec_mindiff.tuples, t, link); 2482 dns_diff_appendminimal(diff, &t); 2483 } 2484 2485 INSIST(ISC_LIST_EMPTY(sig_diff.tuples)); 2486 INSIST(ISC_LIST_EMPTY(nsec_diff.tuples)); 2487 INSIST(ISC_LIST_EMPTY(nsec_mindiff.tuples)); 2488 2489 /* 2490 * Check if we have any active NSEC3 chains by looking for a 2491 * NSEC3PARAM RRset. 2492 */ 2493 CHECK(rrset_exists(db, newver, dns_db_origin(db), 2494 dns_rdatatype_nsec3param, 0, &flag)); 2495 if (!flag) { 2496 update_log(client, zone, ISC_LOG_DEBUG(3), 2497 "no NSEC3 chains to rebuild"); 2498 goto failure; 2499 } 2500 2501 update_log(client, zone, ISC_LOG_DEBUG(3), "rebuilding NSEC3 chains"); 2502 2503 dns_diff_clear(&diffnames); 2504 dns_diff_clear(&affected); 2505 2506 CHECK(dns_diff_sort(diff, temp_order)); 2507 2508 /* 2509 * Find names potentially affected by delegation changes 2510 * (obscured by adding an NS or DNAME, or unobscured by 2511 * removing one). 2512 */ 2513 t = ISC_LIST_HEAD(diff->tuples); 2514 while (t != NULL) { 2515 dns_name_t *name = &t->name; 2516 2517 isc_boolean_t ns_existed, dname_existed; 2518 isc_boolean_t ns_exists, dname_exists; 2519 2520 if (t->rdata.type == dns_rdatatype_nsec || 2521 t->rdata.type == dns_rdatatype_rrsig) { 2522 t = ISC_LIST_NEXT(t, link); 2523 continue; 2524 } 2525 2526 CHECK(namelist_append_name(&affected, name)); 2527 2528 CHECK(rrset_exists(db, oldver, name, dns_rdatatype_ns, 0, 2529 &ns_existed)); 2530 CHECK(rrset_exists(db, oldver, name, dns_rdatatype_dname, 0, 2531 &dname_existed)); 2532 CHECK(rrset_exists(db, newver, name, dns_rdatatype_ns, 0, 2533 &ns_exists)); 2534 CHECK(rrset_exists(db, newver, name, dns_rdatatype_dname, 0, 2535 &dname_exists)); 2536 2537 if ((ns_exists || dname_exists) == (ns_existed || dname_existed)) 2538 goto nextname; 2539 /* 2540 * There was a delegation change. Mark all subdomains 2541 * of t->name as potentially needing a NSEC3 update. 2542 */ 2543 CHECK(namelist_append_subdomain(db, name, &affected)); 2544 2545 nextname: 2546 while (t != NULL && dns_name_equal(&t->name, name)) 2547 t = ISC_LIST_NEXT(t, link); 2548 } 2549 2550 for (t = ISC_LIST_HEAD(affected.tuples); 2551 t != NULL; 2552 t = ISC_LIST_NEXT(t, link)) { 2553 dns_name_t *name = &t->name; 2554 2555 unsecure = ISC_FALSE; /* Silence compiler warning. */ 2556 CHECK(is_active(db, newver, name, &flag, &cut, &unsecure)); 2557 2558 if (!flag) { 2559 CHECK(delete_if(rrsig_p, db, newver, name, 2560 dns_rdatatype_any, 0, NULL, diff)); 2561 CHECK(dns_nsec3_delnsec3s(db, newver, name, 2562 &nsec_diff)); 2563 } else { 2564 CHECK(add_exposed_sigs(client, zone, db, newver, name, 2565 cut, diff, zone_keys, nkeys, 2566 inception, expire, check_ksk)); 2567 CHECK(dns_nsec3_addnsec3s(db, newver, name, nsecttl, 2568 unsecure, &nsec_diff)); 2569 } 2570 } 2571 2572 /* 2573 * Minimize the set of NSEC3 updates so that we don't 2574 * have to regenerate the RRSIG NSEC3s for NSEC3s that were 2575 * replaced with identical ones. 2576 */ 2577 while ((t = ISC_LIST_HEAD(nsec_diff.tuples)) != NULL) { 2578 ISC_LIST_UNLINK(nsec_diff.tuples, t, link); 2579 dns_diff_appendminimal(&nsec_mindiff, &t); 2580 } 2581 2582 update_log(client, zone, ISC_LOG_DEBUG(3), 2583 "signing rebuilt NSEC3 chain"); 2584 2585 /* Update RRSIG NSEC3s. */ 2586 for (t = ISC_LIST_HEAD(nsec_mindiff.tuples); 2587 t != NULL; 2588 t = ISC_LIST_NEXT(t, link)) 2589 { 2590 if (t->op == DNS_DIFFOP_DEL) { 2591 CHECK(delete_if(true_p, db, newver, &t->name, 2592 dns_rdatatype_rrsig, 2593 dns_rdatatype_nsec3, 2594 NULL, &sig_diff)); 2595 } else if (t->op == DNS_DIFFOP_ADD) { 2596 CHECK(add_sigs(client, zone, db, newver, &t->name, 2597 dns_rdatatype_nsec3, 2598 &sig_diff, zone_keys, nkeys, 2599 inception, expire, check_ksk)); 2600 } else { 2601 INSIST(0); 2602 } 2603 } 2604 2605 /* Record our changes for the journal. */ 2606 while ((t = ISC_LIST_HEAD(sig_diff.tuples)) != NULL) { 2607 ISC_LIST_UNLINK(sig_diff.tuples, t, link); 2608 dns_diff_appendminimal(diff, &t); 2609 } 2610 while ((t = ISC_LIST_HEAD(nsec_mindiff.tuples)) != NULL) { 2611 ISC_LIST_UNLINK(nsec_mindiff.tuples, t, link); 2612 dns_diff_appendminimal(diff, &t); 2613 } 2614 2615 INSIST(ISC_LIST_EMPTY(sig_diff.tuples)); 2616 INSIST(ISC_LIST_EMPTY(nsec_diff.tuples)); 2617 INSIST(ISC_LIST_EMPTY(nsec_mindiff.tuples)); 2618 2619 failure: 2620 dns_diff_clear(&sig_diff); 2621 dns_diff_clear(&nsec_diff); 2622 dns_diff_clear(&nsec_mindiff); 2623 2624 dns_diff_clear(&affected); 2625 dns_diff_clear(&diffnames); 2626 2627 for (i = 0; i < nkeys; i++) 2628 dst_key_free(&zone_keys[i]); 2629 2630 return (result); 2631} 2632 2633 2634/**************************************************************************/ 2635/*% 2636 * The actual update code in all its glory. We try to follow 2637 * the RFC2136 pseudocode as closely as possible. 2638 */ 2639 2640static isc_result_t 2641send_update_event(ns_client_t *client, dns_zone_t *zone) { 2642 isc_result_t result = ISC_R_SUCCESS; 2643 update_event_t *event = NULL; 2644 isc_task_t *zonetask = NULL; 2645 ns_client_t *evclient; 2646 2647 event = (update_event_t *) 2648 isc_event_allocate(client->mctx, client, DNS_EVENT_UPDATE, 2649 update_action, NULL, sizeof(*event)); 2650 if (event == NULL) 2651 FAIL(ISC_R_NOMEMORY); 2652 event->zone = zone; 2653 event->result = ISC_R_SUCCESS; 2654 2655 evclient = NULL; 2656 ns_client_attach(client, &evclient); 2657 INSIST(client->nupdates == 0); 2658 client->nupdates++; 2659 event->ev_arg = evclient; 2660 2661 dns_zone_gettask(zone, &zonetask); 2662 isc_task_send(zonetask, ISC_EVENT_PTR(&event)); 2663 2664 failure: 2665 if (event != NULL) 2666 isc_event_free(ISC_EVENT_PTR(&event)); 2667 return (result); 2668} 2669 2670static void 2671respond(ns_client_t *client, isc_result_t result) { 2672 isc_result_t msg_result; 2673 2674 msg_result = dns_message_reply(client->message, ISC_TRUE); 2675 if (msg_result != ISC_R_SUCCESS) 2676 goto msg_failure; 2677 client->message->rcode = dns_result_torcode(result); 2678 2679 ns_client_send(client); 2680 return; 2681 2682 msg_failure: 2683 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_UPDATE, NS_LOGMODULE_UPDATE, 2684 ISC_LOG_ERROR, 2685 "could not create update response message: %s", 2686 isc_result_totext(msg_result)); 2687 ns_client_next(client, msg_result); 2688} 2689 2690void 2691ns_update_start(ns_client_t *client, isc_result_t sigresult) { 2692 dns_message_t *request = client->message; 2693 isc_result_t result; 2694 dns_name_t *zonename; 2695 dns_rdataset_t *zone_rdataset; 2696 dns_zone_t *zone = NULL; 2697 2698 /* 2699 * Interpret the zone section. 2700 */ 2701 result = dns_message_firstname(request, DNS_SECTION_ZONE); 2702 if (result != ISC_R_SUCCESS) 2703 FAILC(DNS_R_FORMERR, "update zone section empty"); 2704 2705 /* 2706 * The zone section must contain exactly one "question", and 2707 * it must be of type SOA. 2708 */ 2709 zonename = NULL; 2710 dns_message_currentname(request, DNS_SECTION_ZONE, &zonename); 2711 zone_rdataset = ISC_LIST_HEAD(zonename->list); 2712 if (zone_rdataset->type != dns_rdatatype_soa) 2713 FAILC(DNS_R_FORMERR, 2714 "update zone section contains non-SOA"); 2715 if (ISC_LIST_NEXT(zone_rdataset, link) != NULL) 2716 FAILC(DNS_R_FORMERR, 2717 "update zone section contains multiple RRs"); 2718 2719 /* The zone section must have exactly one name. */ 2720 result = dns_message_nextname(request, DNS_SECTION_ZONE); 2721 if (result != ISC_R_NOMORE) 2722 FAILC(DNS_R_FORMERR, 2723 "update zone section contains multiple RRs"); 2724 2725 result = dns_zt_find(client->view->zonetable, zonename, 0, NULL, 2726 &zone); 2727 if (result != ISC_R_SUCCESS) 2728 FAILC(DNS_R_NOTAUTH, "not authoritative for update zone"); 2729 2730 switch(dns_zone_gettype(zone)) { 2731 case dns_zone_master: 2732 /* 2733 * We can now fail due to a bad signature as we now know 2734 * that we are the master. 2735 */ 2736 if (sigresult != ISC_R_SUCCESS) 2737 FAIL(sigresult); 2738 CHECK(send_update_event(client, zone)); 2739 break; 2740 case dns_zone_slave: 2741 CHECK(checkupdateacl(client, dns_zone_getforwardacl(zone), 2742 "update forwarding", zonename, ISC_TRUE, 2743 ISC_FALSE)); 2744 CHECK(send_forward_event(client, zone)); 2745 break; 2746 default: 2747 FAILC(DNS_R_NOTAUTH, "not authoritative for update zone"); 2748 } 2749 return; 2750 2751 failure: 2752 if (result == DNS_R_REFUSED) { 2753 INSIST(dns_zone_gettype(zone) == dns_zone_slave); 2754 inc_stats(zone, dns_nsstatscounter_updaterej); 2755 } 2756 /* 2757 * We failed without having sent an update event to the zone. 2758 * We are still in the client task context, so we can 2759 * simply give an error response without switching tasks. 2760 */ 2761 respond(client, result); 2762 if (zone != NULL) 2763 dns_zone_detach(&zone); 2764} 2765 2766/*% 2767 * DS records are not allowed to exist without corresponding NS records, 2768 * RFC 3658, 2.2 Protocol Change, 2769 * "DS RRsets MUST NOT appear at non-delegation points or at a zone's apex". 2770 */ 2771 2772static isc_result_t 2773remove_orphaned_ds(dns_db_t *db, dns_dbversion_t *newver, dns_diff_t *diff) { 2774 isc_result_t result; 2775 isc_boolean_t ns_exists; 2776 dns_difftuple_t *tupple; 2777 dns_diff_t temp_diff; 2778 2779 dns_diff_init(diff->mctx, &temp_diff); 2780 2781 for (tupple = ISC_LIST_HEAD(diff->tuples); 2782 tupple != NULL; 2783 tupple = ISC_LIST_NEXT(tupple, link)) { 2784 if (!((tupple->op == DNS_DIFFOP_DEL && 2785 tupple->rdata.type == dns_rdatatype_ns) || 2786 (tupple->op == DNS_DIFFOP_ADD && 2787 tupple->rdata.type == dns_rdatatype_ds))) 2788 continue; 2789 CHECK(rrset_exists(db, newver, &tupple->name, 2790 dns_rdatatype_ns, 0, &ns_exists)); 2791 if (ns_exists && 2792 !dns_name_equal(&tupple->name, dns_db_origin(db))) 2793 continue; 2794 CHECK(delete_if(true_p, db, newver, &tupple->name, 2795 dns_rdatatype_ds, 0, NULL, &temp_diff)); 2796 } 2797 result = ISC_R_SUCCESS; 2798 2799 failure: 2800 for (tupple = ISC_LIST_HEAD(temp_diff.tuples); 2801 tupple != NULL; 2802 tupple = ISC_LIST_HEAD(temp_diff.tuples)) { 2803 ISC_LIST_UNLINK(temp_diff.tuples, tupple, link); 2804 dns_diff_appendminimal(diff, &tupple); 2805 } 2806 return (result); 2807} 2808 2809/* 2810 * This implements the post load integrity checks for mx records. 2811 */ 2812static isc_result_t 2813check_mx(ns_client_t *client, dns_zone_t *zone, 2814 dns_db_t *db, dns_dbversion_t *newver, dns_diff_t *diff) 2815{ 2816 char tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:123.123.123.123.")]; 2817 char ownerbuf[DNS_NAME_FORMATSIZE]; 2818 char namebuf[DNS_NAME_FORMATSIZE]; 2819 char altbuf[DNS_NAME_FORMATSIZE]; 2820 dns_difftuple_t *t; 2821 dns_fixedname_t fixed; 2822 dns_name_t *foundname; 2823 dns_rdata_mx_t mx; 2824 dns_rdata_t rdata; 2825 isc_boolean_t ok = ISC_TRUE; 2826 isc_boolean_t isaddress; 2827 isc_result_t result; 2828 struct in6_addr addr6; 2829 struct in_addr addr; 2830 unsigned int options; 2831 2832 dns_fixedname_init(&fixed); 2833 foundname = dns_fixedname_name(&fixed); 2834 dns_rdata_init(&rdata); 2835 options = dns_zone_getoptions(zone); 2836 2837 for (t = ISC_LIST_HEAD(diff->tuples); 2838 t != NULL; 2839 t = ISC_LIST_NEXT(t, link)) { 2840 if (t->op != DNS_DIFFOP_ADD || 2841 t->rdata.type != dns_rdatatype_mx) 2842 continue; 2843 2844 result = dns_rdata_tostruct(&t->rdata, &mx, NULL); 2845 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2846 /* 2847 * Check if we will error out if we attempt to reload the 2848 * zone. 2849 */ 2850 dns_name_format(&mx.mx, namebuf, sizeof(namebuf)); 2851 dns_name_format(&t->name, ownerbuf, sizeof(ownerbuf)); 2852 isaddress = ISC_FALSE; 2853 if ((options & DNS_RDATA_CHECKMX) != 0 && 2854 strlcpy(tmp, namebuf, sizeof(tmp)) < sizeof(tmp)) { 2855 if (tmp[strlen(tmp) - 1] == '.') 2856 tmp[strlen(tmp) - 1] = '\0'; 2857 if (inet_aton(tmp, &addr) == 1 || 2858 inet_pton(AF_INET6, tmp, &addr6) == 1) 2859 isaddress = ISC_TRUE; 2860 } 2861 2862 if (isaddress && (options & DNS_RDATA_CHECKMXFAIL) != 0) { 2863 update_log(client, zone, ISC_LOG_ERROR, 2864 "%s/MX: '%s': %s", 2865 ownerbuf, namebuf, 2866 dns_result_totext(DNS_R_MXISADDRESS)); 2867 ok = ISC_FALSE; 2868 } else if (isaddress) { 2869 update_log(client, zone, ISC_LOG_WARNING, 2870 "%s/MX: warning: '%s': %s", 2871 ownerbuf, namebuf, 2872 dns_result_totext(DNS_R_MXISADDRESS)); 2873 } 2874 2875 /* 2876 * Check zone integrity checks. 2877 */ 2878 if ((options & DNS_ZONEOPT_CHECKINTEGRITY) == 0) 2879 continue; 2880 result = dns_db_find(db, &mx.mx, newver, dns_rdatatype_a, 2881 0, 0, NULL, foundname, NULL, NULL); 2882 if (result == ISC_R_SUCCESS) 2883 continue; 2884 2885 if (result == DNS_R_NXRRSET) { 2886 result = dns_db_find(db, &mx.mx, newver, 2887 dns_rdatatype_aaaa, 2888 0, 0, NULL, foundname, 2889 NULL, NULL); 2890 if (result == ISC_R_SUCCESS) 2891 continue; 2892 } 2893 2894 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN) { 2895 update_log(client, zone, ISC_LOG_ERROR, 2896 "%s/MX '%s' has no address records " 2897 "(A or AAAA)", ownerbuf, namebuf); 2898 ok = ISC_FALSE; 2899 } else if (result == DNS_R_CNAME) { 2900 update_log(client, zone, ISC_LOG_ERROR, 2901 "%s/MX '%s' is a CNAME (illegal)", 2902 ownerbuf, namebuf); 2903 ok = ISC_FALSE; 2904 } else if (result == DNS_R_DNAME) { 2905 dns_name_format(foundname, altbuf, sizeof altbuf); 2906 update_log(client, zone, ISC_LOG_ERROR, 2907 "%s/MX '%s' is below a DNAME '%s' (illegal)", 2908 ownerbuf, namebuf, altbuf); 2909 ok = ISC_FALSE; 2910 } 2911 } 2912 return (ok ? ISC_R_SUCCESS : DNS_R_REFUSED); 2913} 2914 2915static isc_result_t 2916rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, 2917 const dns_rdata_t *rdata, isc_boolean_t *flag) 2918{ 2919 dns_rdataset_t rdataset; 2920 dns_dbnode_t *node = NULL; 2921 isc_result_t result; 2922 2923 dns_rdataset_init(&rdataset); 2924 if (rdata->type == dns_rdatatype_nsec3) 2925 CHECK(dns_db_findnsec3node(db, name, ISC_FALSE, &node)); 2926 else 2927 CHECK(dns_db_findnode(db, name, ISC_FALSE, &node)); 2928 result = dns_db_findrdataset(db, node, ver, rdata->type, 0, 2929 (isc_stdtime_t) 0, &rdataset, NULL); 2930 if (result == ISC_R_NOTFOUND) { 2931 *flag = ISC_FALSE; 2932 result = ISC_R_SUCCESS; 2933 goto failure; 2934 } 2935 2936 for (result = dns_rdataset_first(&rdataset); 2937 result == ISC_R_SUCCESS; 2938 result = dns_rdataset_next(&rdataset)) { 2939 dns_rdata_t myrdata = DNS_RDATA_INIT; 2940 dns_rdataset_current(&rdataset, &myrdata); 2941 if (!dns_rdata_compare(&myrdata, rdata)) 2942 break; 2943 } 2944 dns_rdataset_disassociate(&rdataset); 2945 if (result == ISC_R_SUCCESS) { 2946 *flag = ISC_TRUE; 2947 } else if (result == ISC_R_NOMORE) { 2948 *flag = ISC_FALSE; 2949 result = ISC_R_SUCCESS; 2950 } 2951 2952 failure: 2953 if (node != NULL) 2954 dns_db_detachnode(db, &node); 2955 return (result); 2956} 2957 2958static isc_result_t 2959get_iterations(dns_db_t *db, dns_dbversion_t *ver, unsigned int *iterationsp) { 2960 dns_dbnode_t *node = NULL; 2961 dns_rdata_nsec3param_t nsec3param; 2962 dns_rdataset_t rdataset; 2963 isc_result_t result; 2964 unsigned int iterations = 0; 2965 2966 dns_rdataset_init(&rdataset); 2967 2968 result = dns_db_getoriginnode(db, &node); 2969 if (result != ISC_R_SUCCESS) 2970 return (result); 2971 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param, 2972 0, (isc_stdtime_t) 0, &rdataset, NULL); 2973 dns_db_detachnode(db, &node); 2974 if (result == ISC_R_NOTFOUND) 2975 goto success; 2976 if (result != ISC_R_SUCCESS) 2977 goto failure; 2978 2979 for (result = dns_rdataset_first(&rdataset); 2980 result == ISC_R_SUCCESS; 2981 result = dns_rdataset_next(&rdataset)) { 2982 dns_rdata_t rdata = DNS_RDATA_INIT; 2983 dns_rdataset_current(&rdataset, &rdata); 2984 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL)); 2985 if ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) 2986 continue; 2987 if (nsec3param.iterations > iterations) 2988 iterations = nsec3param.iterations; 2989 } 2990 if (result != ISC_R_NOMORE) 2991 goto failure; 2992 2993 success: 2994 *iterationsp = iterations; 2995 result = ISC_R_SUCCESS; 2996 2997 failure: 2998 if (dns_rdataset_isassociated(&rdataset)) 2999 dns_rdataset_disassociate(&rdataset); 3000 return (result); 3001} 3002 3003/* 3004 * Prevent the zone entering a inconsistent state where 3005 * NSEC only DNSKEYs are present with NSEC3 chains. 3006 */ 3007static isc_result_t 3008check_dnssec(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, 3009 dns_dbversion_t *ver, dns_diff_t *diff) 3010{ 3011 dns_diff_t temp_diff; 3012 dns_diffop_t op; 3013 dns_difftuple_t *tuple, *newtuple = NULL, *next; 3014 isc_boolean_t flag; 3015 isc_result_t result; 3016 unsigned int iterations = 0, max; 3017 3018 dns_diff_init(diff->mctx, &temp_diff); 3019 3020 CHECK(dns_nsec_nseconly(db, ver, &flag)); 3021 3022 if (flag) 3023 CHECK(dns_nsec3_active(db, ver, ISC_FALSE, &flag)); 3024 if (flag) { 3025 update_log(client, zone, ISC_LOG_WARNING, 3026 "NSEC only DNSKEYs and NSEC3 chains not allowed"); 3027 } else { 3028 CHECK(get_iterations(db, ver, &iterations)); 3029 CHECK(dns_nsec3_maxiterations(db, ver, client->mctx, &max)); 3030 if (iterations > max) { 3031 flag = ISC_TRUE; 3032 update_log(client, zone, ISC_LOG_WARNING, 3033 "too many NSEC3 iterations (%u) for " 3034 "weakest DNSKEY (%u)", iterations, max); 3035 } 3036 } 3037 if (flag) { 3038 for (tuple = ISC_LIST_HEAD(diff->tuples); 3039 tuple != NULL; 3040 tuple = next) { 3041 next = ISC_LIST_NEXT(tuple, link); 3042 if (tuple->rdata.type != dns_rdatatype_dnskey && 3043 tuple->rdata.type != dns_rdatatype_nsec3param) 3044 continue; 3045 op = (tuple->op == DNS_DIFFOP_DEL) ? 3046 DNS_DIFFOP_ADD : DNS_DIFFOP_DEL; 3047 CHECK(dns_difftuple_create(temp_diff.mctx, op, 3048 &tuple->name, tuple->ttl, 3049 &tuple->rdata, &newtuple)); 3050 CHECK(do_one_tuple(&newtuple, db, ver, &temp_diff)); 3051 INSIST(newtuple == NULL); 3052 } 3053 for (tuple = ISC_LIST_HEAD(temp_diff.tuples); 3054 tuple != NULL; 3055 tuple = ISC_LIST_HEAD(temp_diff.tuples)) { 3056 ISC_LIST_UNLINK(temp_diff.tuples, tuple, link); 3057 dns_diff_appendminimal(diff, &tuple); 3058 } 3059 } 3060 3061 3062 failure: 3063 dns_diff_clear(&temp_diff); 3064 return (result); 3065} 3066 3067#ifdef ALLOW_NSEC3PARAM_UPDATE 3068/* 3069 * Delay NSEC3PARAM changes as they need to be applied to the whole zone. 3070 */ 3071static isc_result_t 3072add_nsec3param_records(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, 3073 dns_name_t *name, dns_dbversion_t *ver, dns_diff_t *diff) 3074{ 3075 isc_result_t result = ISC_R_SUCCESS; 3076 dns_difftuple_t *tuple, *newtuple = NULL, *next; 3077 dns_rdata_t rdata = DNS_RDATA_INIT; 3078 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE]; 3079 dns_diff_t temp_diff; 3080 dns_diffop_t op; 3081 isc_boolean_t flag; 3082 3083 update_log(client, zone, ISC_LOG_DEBUG(3), 3084 "checking for NSEC3PARAM changes"); 3085 3086 dns_diff_init(diff->mctx, &temp_diff); 3087 3088 /* 3089 * Extract NSEC3PARAM tuples from list. 3090 */ 3091 for (tuple = ISC_LIST_HEAD(diff->tuples); 3092 tuple != NULL; 3093 tuple = next) { 3094 3095 next = ISC_LIST_NEXT(tuple, link); 3096 3097 if (tuple->rdata.type != dns_rdatatype_nsec3param || 3098 !dns_name_equal(name, &tuple->name)) 3099 continue; 3100 ISC_LIST_UNLINK(diff->tuples, tuple, link); 3101 ISC_LIST_APPEND(temp_diff.tuples, tuple, link); 3102 } 3103 3104 for (tuple = ISC_LIST_HEAD(temp_diff.tuples); 3105 tuple != NULL; tuple = next) { 3106 3107 if (tuple->op == DNS_DIFFOP_ADD) { 3108 next = ISC_LIST_NEXT(tuple, link); 3109 while (next != NULL) { 3110 unsigned char *next_data = next->rdata.data; 3111 unsigned char *tuple_data = tuple->rdata.data; 3112 if (next_data[0] != tuple_data[0] || 3113 /* Ignore flags. */ 3114 next_data[2] != tuple_data[2] || 3115 next_data[3] != tuple_data[3] || 3116 next_data[4] != tuple_data[4] || 3117 !memcmp(&next_data[5], &tuple_data[5], 3118 tuple_data[4])) { 3119 next = ISC_LIST_NEXT(next, link); 3120 continue; 3121 } 3122 op = (next->op == DNS_DIFFOP_DEL) ? 3123 DNS_DIFFOP_ADD : DNS_DIFFOP_DEL; 3124 CHECK(dns_difftuple_create(diff->mctx, op, 3125 name, next->ttl, 3126 &next->rdata, 3127 &newtuple)); 3128 CHECK(do_one_tuple(&newtuple, db, ver, diff)); 3129 ISC_LIST_UNLINK(temp_diff.tuples, next, link); 3130 dns_diff_appendminimal(diff, &next); 3131 next = ISC_LIST_NEXT(tuple, link); 3132 } 3133 3134 INSIST(tuple->rdata.data[1] & DNS_NSEC3FLAG_UPDATE); 3135 3136 /* 3137 * See if we already have a CREATE request in progress. 3138 */ 3139 dns_rdata_clone(&tuple->rdata, &rdata); 3140 INSIST(rdata.length <= sizeof(buf)); 3141 memcpy(buf, rdata.data, rdata.length); 3142 buf[1] |= DNS_NSEC3FLAG_CREATE; 3143 buf[1] &= ~DNS_NSEC3FLAG_UPDATE; 3144 rdata.data = buf; 3145 3146 CHECK(rr_exists(db, ver, name, &rdata, &flag)); 3147 3148 if (!flag) { 3149 CHECK(dns_difftuple_create(diff->mctx, 3150 DNS_DIFFOP_ADD, 3151 name, tuple->ttl, 3152 &rdata, 3153 &newtuple)); 3154 CHECK(do_one_tuple(&newtuple, db, ver, diff)); 3155 } 3156 /* 3157 * Remove the temporary add record. 3158 */ 3159 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, 3160 name, tuple->ttl, 3161 &tuple->rdata, &newtuple)); 3162 CHECK(do_one_tuple(&newtuple, db, ver, diff)); 3163 next = ISC_LIST_NEXT(tuple, link); 3164 ISC_LIST_UNLINK(temp_diff.tuples, tuple, link); 3165 dns_diff_appendminimal(diff, &tuple); 3166 dns_rdata_reset(&rdata); 3167 } else 3168 next = ISC_LIST_NEXT(tuple, link); 3169 } 3170 3171 /* 3172 * Reverse any pending changes. 3173 */ 3174 for (tuple = ISC_LIST_HEAD(temp_diff.tuples); 3175 tuple != NULL; tuple = next) { 3176 next = ISC_LIST_NEXT(tuple, link); 3177 if ((tuple->rdata.data[1] & ~DNS_NSEC3FLAG_OPTOUT) != 0) { 3178 op = (tuple->op == DNS_DIFFOP_DEL) ? 3179 DNS_DIFFOP_ADD : DNS_DIFFOP_DEL; 3180 CHECK(dns_difftuple_create(diff->mctx, op, name, 3181 tuple->ttl, &tuple->rdata, 3182 &newtuple)); 3183 CHECK(do_one_tuple(&newtuple, db, ver, diff)); 3184 ISC_LIST_UNLINK(temp_diff.tuples, tuple, link); 3185 dns_diff_appendminimal(diff, &tuple); 3186 } 3187 } 3188 3189 /* 3190 * Convert deletions into delayed deletions. 3191 */ 3192 for (tuple = ISC_LIST_HEAD(temp_diff.tuples); 3193 tuple != NULL; tuple = next) { 3194 next = ISC_LIST_NEXT(tuple, link); 3195 /* 3196 * See if we already have a REMOVE request in progress. 3197 */ 3198 dns_rdata_clone(&tuple->rdata, &rdata); 3199 INSIST(rdata.length <= sizeof(buf)); 3200 memcpy(buf, rdata.data, rdata.length); 3201 buf[1] |= DNS_NSEC3FLAG_REMOVE; 3202 rdata.data = buf; 3203 3204 CHECK(rr_exists(db, ver, name, &rdata, &flag)); 3205 3206 if (!flag) { 3207 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, 3208 name, tuple->ttl, &rdata, 3209 &newtuple)); 3210 CHECK(do_one_tuple(&newtuple, db, ver, diff)); 3211 } 3212 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, name, 3213 tuple->ttl, &tuple->rdata, 3214 &newtuple)); 3215 CHECK(do_one_tuple(&newtuple, db, ver, diff)); 3216 ISC_LIST_UNLINK(temp_diff.tuples, tuple, link); 3217 dns_diff_appendminimal(diff, &tuple); 3218 dns_rdata_reset(&rdata); 3219 } 3220 3221 result = ISC_R_SUCCESS; 3222 failure: 3223 dns_diff_clear(&temp_diff); 3224 return (result); 3225} 3226#endif 3227 3228/* 3229 * Add records to cause the delayed signing of the zone by added DNSKEY 3230 * to remove the RRSIG records generated by a deleted DNSKEY. 3231 */ 3232static isc_result_t 3233add_signing_records(dns_db_t *db, dns_name_t *name, dns_dbversion_t *ver, 3234 dns_rdatatype_t privatetype, dns_diff_t *diff) 3235{ 3236 dns_difftuple_t *tuple, *newtuple = NULL; 3237 dns_rdata_dnskey_t dnskey; 3238 dns_rdata_t rdata = DNS_RDATA_INIT; 3239 isc_boolean_t flag; 3240 isc_region_t r; 3241 isc_result_t result = ISC_R_SUCCESS; 3242 isc_uint16_t keyid; 3243 unsigned char buf[5]; 3244 3245 for (tuple = ISC_LIST_HEAD(diff->tuples); 3246 tuple != NULL; 3247 tuple = ISC_LIST_NEXT(tuple, link)) { 3248 if (tuple->rdata.type != dns_rdatatype_dnskey) 3249 continue; 3250 3251 dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL); 3252 if ((dnskey.flags & 3253 (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH)) 3254 != DNS_KEYOWNER_ZONE) 3255 continue; 3256 3257 dns_rdata_toregion(&tuple->rdata, &r); 3258 keyid = dst_region_computeid(&r, dnskey.algorithm); 3259 3260 buf[0] = dnskey.algorithm; 3261 buf[1] = (keyid & 0xff00) >> 8; 3262 buf[2] = (keyid & 0xff); 3263 buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1; 3264 buf[4] = 0; 3265 rdata.data = buf; 3266 rdata.length = sizeof(buf); 3267 rdata.type = privatetype; 3268 rdata.rdclass = tuple->rdata.rdclass; 3269 3270 CHECK(rr_exists(db, ver, name, &rdata, &flag)); 3271 if (flag) 3272 continue; 3273 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, 3274 name, 0, &rdata, &newtuple)); 3275 CHECK(do_one_tuple(&newtuple, db, ver, diff)); 3276 INSIST(newtuple == NULL); 3277 /* 3278 * Remove any record which says this operation has already 3279 * completed. 3280 */ 3281 buf[4] = 1; 3282 CHECK(rr_exists(db, ver, name, &rdata, &flag)); 3283 if (flag) { 3284 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, 3285 name, 0, &rdata, &newtuple)); 3286 CHECK(do_one_tuple(&newtuple, db, ver, diff)); 3287 INSIST(newtuple == NULL); 3288 } 3289 } 3290 failure: 3291 return (result); 3292} 3293 3294#ifdef ALLOW_NSEC3PARAM_UPDATE 3295/* 3296 * Mark all NSEC3 chains for deletion without creating a NSEC chain as 3297 * a side effect of deleting the last chain. 3298 */ 3299static isc_result_t 3300delete_chains(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *origin, 3301 dns_diff_t *diff) 3302{ 3303 dns_dbnode_t *node = NULL; 3304 dns_difftuple_t *tuple = NULL; 3305 dns_name_t next; 3306 dns_rdata_t rdata = DNS_RDATA_INIT; 3307 dns_rdataset_t rdataset; 3308 isc_boolean_t flag; 3309 isc_result_t result = ISC_R_SUCCESS; 3310 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE]; 3311 3312 dns_name_init(&next, NULL); 3313 dns_rdataset_init(&rdataset); 3314 3315 result = dns_db_getoriginnode(db, &node); 3316 if (result != ISC_R_SUCCESS) 3317 return (result); 3318 3319 /* 3320 * Cause all NSEC3 chains to be deleted. 3321 */ 3322 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param, 3323 0, (isc_stdtime_t) 0, &rdataset, NULL); 3324 if (result == ISC_R_NOTFOUND) 3325 goto success; 3326 if (result != ISC_R_SUCCESS) 3327 goto failure; 3328 3329 for (result = dns_rdataset_first(&rdataset); 3330 result == ISC_R_SUCCESS; 3331 result = dns_rdataset_next(&rdataset)) { 3332 dns_rdataset_current(&rdataset, &rdata); 3333 INSIST(rdata.length <= sizeof(buf)); 3334 memcpy(buf, rdata.data, rdata.length); 3335 3336 if (buf[1] == (DNS_NSEC3FLAG_REMOVE | DNS_NSEC3FLAG_NONSEC)) { 3337 dns_rdata_reset(&rdata); 3338 continue; 3339 } 3340 3341 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, 3342 origin, 0, &rdata, &tuple)); 3343 CHECK(do_one_tuple(&tuple, db, ver, diff)); 3344 INSIST(tuple == NULL); 3345 3346 buf[1] = DNS_NSEC3FLAG_REMOVE | DNS_NSEC3FLAG_NONSEC; 3347 rdata.data = buf; 3348 3349 CHECK(rr_exists(db, ver, origin, &rdata, &flag)); 3350 3351 if (!flag) { 3352 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, 3353 origin, 0, &rdata, &tuple)); 3354 CHECK(do_one_tuple(&tuple, db, ver, diff)); 3355 INSIST(tuple == NULL); 3356 } 3357 dns_rdata_reset(&rdata); 3358 } 3359 if (result != ISC_R_NOMORE) 3360 goto failure; 3361 success: 3362 result = ISC_R_SUCCESS; 3363 3364 failure: 3365 if (dns_rdataset_isassociated(&rdataset)) 3366 dns_rdataset_disassociate(&rdataset); 3367 dns_db_detachnode(db, &node); 3368 return (result); 3369} 3370#endif 3371 3372static void 3373update_action(isc_task_t *task, isc_event_t *event) { 3374 update_event_t *uev = (update_event_t *) event; 3375 dns_zone_t *zone = uev->zone; 3376 ns_client_t *client = (ns_client_t *)event->ev_arg; 3377 3378 isc_result_t result; 3379 dns_db_t *db = NULL; 3380 dns_dbversion_t *oldver = NULL; 3381 dns_dbversion_t *ver = NULL; 3382 dns_diff_t diff; /* Pending updates. */ 3383 dns_diff_t temp; /* Pending RR existence assertions. */ 3384 isc_boolean_t soa_serial_changed = ISC_FALSE; 3385 isc_mem_t *mctx = client->mctx; 3386 dns_rdatatype_t covers; 3387 dns_message_t *request = client->message; 3388 dns_rdataclass_t zoneclass; 3389 dns_name_t *zonename; 3390 dns_ssutable_t *ssutable = NULL; 3391 dns_fixedname_t tmpnamefixed; 3392 dns_name_t *tmpname = NULL; 3393 unsigned int options; 3394 isc_boolean_t deleted_zsk; 3395 dns_difftuple_t *tuple; 3396 dns_rdata_dnskey_t dnskey; 3397#ifdef ALLOW_NSEC3PARAM_UPDATE 3398 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE]; 3399#endif 3400#if !defined(ALLOW_SECURE_TO_INSECURE) || !defined(ALLOW_INSECURE_TO_SECURE) 3401 isc_boolean_t had_dnskey; 3402#endif 3403 3404 INSIST(event->ev_type == DNS_EVENT_UPDATE); 3405 3406 dns_diff_init(mctx, &diff); 3407 dns_diff_init(mctx, &temp); 3408 3409 CHECK(dns_zone_getdb(zone, &db)); 3410 zonename = dns_db_origin(db); 3411 zoneclass = dns_db_class(db); 3412 dns_zone_getssutable(zone, &ssutable); 3413 dns_db_currentversion(db, &oldver); 3414 CHECK(dns_db_newversion(db, &ver)); 3415 3416 /* 3417 * Check prerequisites. 3418 */ 3419 3420 for (result = dns_message_firstname(request, DNS_SECTION_PREREQUISITE); 3421 result == ISC_R_SUCCESS; 3422 result = dns_message_nextname(request, DNS_SECTION_PREREQUISITE)) 3423 { 3424 dns_name_t *name = NULL; 3425 dns_rdata_t rdata = DNS_RDATA_INIT; 3426 dns_ttl_t ttl; 3427 dns_rdataclass_t update_class; 3428 isc_boolean_t flag; 3429 3430 get_current_rr(request, DNS_SECTION_PREREQUISITE, zoneclass, 3431 &name, &rdata, &covers, &ttl, &update_class); 3432 3433 if (ttl != 0) 3434 PREREQFAILC(DNS_R_FORMERR, 3435 "prerequisite TTL is not zero"); 3436 3437 if (! dns_name_issubdomain(name, zonename)) 3438 PREREQFAILN(DNS_R_NOTZONE, name, 3439 "prerequisite name is out of zone"); 3440 3441 if (update_class == dns_rdataclass_any) { 3442 if (rdata.length != 0) 3443 PREREQFAILC(DNS_R_FORMERR, 3444 "class ANY prerequisite " 3445 "RDATA is not empty"); 3446 if (rdata.type == dns_rdatatype_any) { 3447 CHECK(name_exists(db, ver, name, &flag)); 3448 if (! flag) { 3449 PREREQFAILN(DNS_R_NXDOMAIN, name, 3450 "'name in use' " 3451 "prerequisite not " 3452 "satisfied"); 3453 } 3454 } else { 3455 CHECK(rrset_exists(db, ver, name, 3456 rdata.type, covers, &flag)); 3457 if (! flag) { 3458 /* RRset does not exist. */ 3459 PREREQFAILNT(DNS_R_NXRRSET, name, rdata.type, 3460 "'rrset exists (value independent)' " 3461 "prerequisite not satisfied"); 3462 } 3463 } 3464 } else if (update_class == dns_rdataclass_none) { 3465 if (rdata.length != 0) 3466 PREREQFAILC(DNS_R_FORMERR, 3467 "class NONE prerequisite " 3468 "RDATA is not empty"); 3469 if (rdata.type == dns_rdatatype_any) { 3470 CHECK(name_exists(db, ver, name, &flag)); 3471 if (flag) { 3472 PREREQFAILN(DNS_R_YXDOMAIN, name, 3473 "'name not in use' " 3474 "prerequisite not " 3475 "satisfied"); 3476 } 3477 } else { 3478 CHECK(rrset_exists(db, ver, name, 3479 rdata.type, covers, &flag)); 3480 if (flag) { 3481 /* RRset exists. */ 3482 PREREQFAILNT(DNS_R_YXRRSET, name, 3483 rdata.type, 3484 "'rrset does not exist' " 3485 "prerequisite not " 3486 "satisfied"); 3487 } 3488 } 3489 } else if (update_class == zoneclass) { 3490 /* "temp<rr.name, rr.type> += rr;" */ 3491 result = temp_append(&temp, name, &rdata); 3492 if (result != ISC_R_SUCCESS) { 3493 UNEXPECTED_ERROR(__FILE__, __LINE__, 3494 "temp entry creation failed: %s", 3495 dns_result_totext(result)); 3496 FAIL(ISC_R_UNEXPECTED); 3497 } 3498 } else { 3499 PREREQFAILC(DNS_R_FORMERR, "malformed prerequisite"); 3500 } 3501 } 3502 if (result != ISC_R_NOMORE) 3503 FAIL(result); 3504 3505 3506 /* 3507 * Perform the final check of the "rrset exists (value dependent)" 3508 * prerequisites. 3509 */ 3510 if (ISC_LIST_HEAD(temp.tuples) != NULL) { 3511 dns_rdatatype_t type; 3512 3513 /* 3514 * Sort the prerequisite records by owner name, 3515 * type, and rdata. 3516 */ 3517 result = dns_diff_sort(&temp, temp_order); 3518 if (result != ISC_R_SUCCESS) 3519 FAILC(result, "'RRset exists (value dependent)' " 3520 "prerequisite not satisfied"); 3521 3522 dns_fixedname_init(&tmpnamefixed); 3523 tmpname = dns_fixedname_name(&tmpnamefixed); 3524 result = temp_check(mctx, &temp, db, ver, tmpname, &type); 3525 if (result != ISC_R_SUCCESS) 3526 FAILNT(result, tmpname, type, 3527 "'RRset exists (value dependent)' " 3528 "prerequisite not satisfied"); 3529 } 3530 3531 update_log(client, zone, LOGLEVEL_DEBUG, 3532 "prerequisites are OK"); 3533 3534 /* 3535 * Check Requestor's Permissions. It seems a bit silly to do this 3536 * only after prerequisite testing, but that is what RFC2136 says. 3537 */ 3538 result = ISC_R_SUCCESS; 3539 if (ssutable == NULL) 3540 CHECK(checkupdateacl(client, dns_zone_getupdateacl(zone), 3541 "update", zonename, ISC_FALSE, ISC_FALSE)); 3542 else if (client->signer == NULL && !TCPCLIENT(client)) 3543 CHECK(checkupdateacl(client, NULL, "update", zonename, 3544 ISC_FALSE, ISC_TRUE)); 3545 3546 if (dns_zone_getupdatedisabled(zone)) 3547 FAILC(DNS_R_REFUSED, "dynamic update temporarily disabled " 3548 "because the zone is frozen. Use " 3549 "'rndc thaw' to re-enable updates."); 3550 3551 /* 3552 * Perform the Update Section Prescan. 3553 */ 3554 3555 for (result = dns_message_firstname(request, DNS_SECTION_UPDATE); 3556 result == ISC_R_SUCCESS; 3557 result = dns_message_nextname(request, DNS_SECTION_UPDATE)) 3558 { 3559 dns_name_t *name = NULL; 3560 dns_rdata_t rdata = DNS_RDATA_INIT; 3561 dns_ttl_t ttl; 3562 dns_rdataclass_t update_class; 3563 get_current_rr(request, DNS_SECTION_UPDATE, zoneclass, 3564 &name, &rdata, &covers, &ttl, &update_class); 3565 3566 if (! dns_name_issubdomain(name, zonename)) 3567 FAILC(DNS_R_NOTZONE, 3568 "update RR is outside zone"); 3569 if (update_class == zoneclass) { 3570 /* 3571 * Check for meta-RRs. The RFC2136 pseudocode says 3572 * check for ANY|AXFR|MAILA|MAILB, but the text adds 3573 * "or any other QUERY metatype" 3574 */ 3575 if (dns_rdatatype_ismeta(rdata.type)) { 3576 FAILC(DNS_R_FORMERR, 3577 "meta-RR in update"); 3578 } 3579 result = dns_zone_checknames(zone, name, &rdata); 3580 if (result != ISC_R_SUCCESS) 3581 FAIL(DNS_R_REFUSED); 3582 } else if (update_class == dns_rdataclass_any) { 3583 if (ttl != 0 || rdata.length != 0 || 3584 (dns_rdatatype_ismeta(rdata.type) && 3585 rdata.type != dns_rdatatype_any)) 3586 FAILC(DNS_R_FORMERR, 3587 "meta-RR in update"); 3588 } else if (update_class == dns_rdataclass_none) { 3589 if (ttl != 0 || 3590 dns_rdatatype_ismeta(rdata.type)) 3591 FAILC(DNS_R_FORMERR, 3592 "meta-RR in update"); 3593 } else { 3594 update_log(client, zone, ISC_LOG_WARNING, 3595 "update RR has incorrect class %d", 3596 update_class); 3597 FAIL(DNS_R_FORMERR); 3598 } 3599 /* 3600 * draft-ietf-dnsind-simple-secure-update-01 says 3601 * "Unlike traditional dynamic update, the client 3602 * is forbidden from updating NSEC records." 3603 */ 3604 if (dns_db_issecure(db)) { 3605 if (rdata.type == dns_rdatatype_nsec3) { 3606 FAILC(DNS_R_REFUSED, 3607 "explicit NSEC3 updates are not allowed " 3608 "in secure zones"); 3609 } else if (rdata.type == dns_rdatatype_nsec) { 3610 FAILC(DNS_R_REFUSED, 3611 "explicit NSEC updates are not allowed " 3612 "in secure zones"); 3613 } else if (rdata.type == dns_rdatatype_rrsig && 3614 !dns_name_equal(name, zonename)) { 3615 FAILC(DNS_R_REFUSED, 3616 "explicit RRSIG updates are currently " 3617 "not supported in secure zones except " 3618 "at the apex"); 3619 } 3620 } 3621 3622 if (ssutable != NULL) { 3623 isc_netaddr_t *tcpaddr, netaddr; 3624 /* 3625 * If this is a TCP connection then pass the 3626 * address of the client through for tcp-self 3627 * and 6to4-self otherwise pass NULL. This 3628 * provides weak address based authentication. 3629 */ 3630 if (TCPCLIENT(client)) { 3631 isc_netaddr_fromsockaddr(&netaddr, 3632 &client->peeraddr); 3633 tcpaddr = &netaddr; 3634 } else 3635 tcpaddr = NULL; 3636 if (rdata.type != dns_rdatatype_any) { 3637 if (!dns_ssutable_checkrules(ssutable, 3638 client->signer, 3639 name, tcpaddr, 3640 rdata.type)) 3641 FAILC(DNS_R_REFUSED, 3642 "rejected by secure update"); 3643 } else { 3644 if (!ssu_checkall(db, ver, name, ssutable, 3645 client->signer, tcpaddr)) 3646 FAILC(DNS_R_REFUSED, 3647 "rejected by secure update"); 3648 } 3649 } 3650 } 3651 if (result != ISC_R_NOMORE) 3652 FAIL(result); 3653 3654 update_log(client, zone, LOGLEVEL_DEBUG, 3655 "update section prescan OK"); 3656 3657 /* 3658 * Process the Update Section. 3659 */ 3660 3661 options = dns_zone_getoptions(zone); 3662 for (result = dns_message_firstname(request, DNS_SECTION_UPDATE); 3663 result == ISC_R_SUCCESS; 3664 result = dns_message_nextname(request, DNS_SECTION_UPDATE)) 3665 { 3666 dns_name_t *name = NULL; 3667 dns_rdata_t rdata = DNS_RDATA_INIT; 3668 dns_ttl_t ttl; 3669 dns_rdataclass_t update_class; 3670 isc_boolean_t flag; 3671 3672 get_current_rr(request, DNS_SECTION_UPDATE, zoneclass, 3673 &name, &rdata, &covers, &ttl, &update_class); 3674 3675 if (update_class == zoneclass) { 3676 3677 /* 3678 * RFC1123 doesn't allow MF and MD in master zones. */ 3679 if (rdata.type == dns_rdatatype_md || 3680 rdata.type == dns_rdatatype_mf) { 3681 char typebuf[DNS_RDATATYPE_FORMATSIZE]; 3682 3683 dns_rdatatype_format(rdata.type, typebuf, 3684 sizeof(typebuf)); 3685 update_log(client, zone, LOGLEVEL_PROTOCOL, 3686 "attempt to add %s ignored", 3687 typebuf); 3688 continue; 3689 } 3690 if ((rdata.type == dns_rdatatype_ns || 3691 rdata.type == dns_rdatatype_dname) && 3692 dns_name_iswildcard(name)) { 3693 char typebuf[DNS_RDATATYPE_FORMATSIZE]; 3694 3695 dns_rdatatype_format(rdata.type, typebuf, 3696 sizeof(typebuf)); 3697 update_log(client, zone, 3698 LOGLEVEL_PROTOCOL, 3699 "attempt to add wildcard %s record " 3700 "ignored", typebuf); 3701 continue; 3702 } 3703 if (rdata.type == dns_rdatatype_cname) { 3704 CHECK(cname_incompatible_rrset_exists(db, ver, 3705 name, 3706 &flag)); 3707 if (flag) { 3708 update_log(client, zone, 3709 LOGLEVEL_PROTOCOL, 3710 "attempt to add CNAME " 3711 "alongside non-CNAME " 3712 "ignored"); 3713 continue; 3714 } 3715 } else { 3716 CHECK(rrset_exists(db, ver, name, 3717 dns_rdatatype_cname, 0, 3718 &flag)); 3719 if (flag && 3720 ! dns_rdatatype_isdnssec(rdata.type)) 3721 { 3722 update_log(client, zone, 3723 LOGLEVEL_PROTOCOL, 3724 "attempt to add non-CNAME " 3725 "alongside CNAME ignored"); 3726 continue; 3727 } 3728 } 3729 if (rdata.type == dns_rdatatype_soa) { 3730 isc_boolean_t ok; 3731 CHECK(rrset_exists(db, ver, name, 3732 dns_rdatatype_soa, 0, 3733 &flag)); 3734 if (! flag) { 3735 update_log(client, zone, 3736 LOGLEVEL_PROTOCOL, 3737 "attempt to create 2nd " 3738 "SOA ignored"); 3739 continue; 3740 } 3741 CHECK(check_soa_increment(db, ver, &rdata, 3742 &ok)); 3743 if (! ok) { 3744 update_log(client, zone, 3745 LOGLEVEL_PROTOCOL, 3746 "SOA update failed to " 3747 "increment serial, " 3748 "ignoring it"); 3749 continue; 3750 } 3751 soa_serial_changed = ISC_TRUE; 3752 } 3753 3754#ifdef ALLOW_NSEC3PARAM_UPDATE 3755 if (rdata.type == dns_rdatatype_nsec3param) { 3756 /* 3757 * Ignore attempts to add NSEC3PARAM records 3758 * with any flags other than OPTOUT. 3759 */ 3760 if ((rdata.data[1] & ~DNS_NSEC3FLAG_OPTOUT) != 0) { 3761 update_log(client, zone, 3762 LOGLEVEL_PROTOCOL, 3763 "attempt to add NSEC3PARAM " 3764 "record with non OPTOUT " 3765 "flag"); 3766 continue; 3767 } 3768 3769 /* 3770 * Set the NSEC3CHAIN creation flag. 3771 */ 3772 INSIST(rdata.length <= sizeof(buf)); 3773 memcpy(buf, rdata.data, rdata.length); 3774 buf[1] |= DNS_NSEC3FLAG_UPDATE; 3775 rdata.data = buf; 3776 /* 3777 * Force the TTL to zero for NSEC3PARAM records. 3778 */ 3779 ttl = 0; 3780 } 3781#else 3782 if (rdata.type == dns_rdatatype_nsec3param) { 3783 update_log(client, zone, LOGLEVEL_PROTOCOL, 3784 "attempt to add NSEC3PARAM " 3785 "record ignored"); 3786 continue; 3787 }; 3788#endif 3789 3790 if ((options & DNS_ZONEOPT_CHECKWILDCARD) != 0 && 3791 dns_name_internalwildcard(name)) { 3792 char namestr[DNS_NAME_FORMATSIZE]; 3793 dns_name_format(name, namestr, 3794 sizeof(namestr)); 3795 update_log(client, zone, LOGLEVEL_PROTOCOL, 3796 "warning: ownername '%s' contains " 3797 "a non-terminal wildcard", namestr); 3798 } 3799 3800 if (isc_log_wouldlog(ns_g_lctx, LOGLEVEL_PROTOCOL)) { 3801 char namestr[DNS_NAME_FORMATSIZE]; 3802 char typestr[DNS_RDATATYPE_FORMATSIZE]; 3803 dns_name_format(name, namestr, 3804 sizeof(namestr)); 3805 dns_rdatatype_format(rdata.type, typestr, 3806 sizeof(typestr)); 3807 update_log(client, zone, LOGLEVEL_PROTOCOL, 3808 "adding an RR at '%s' %s", 3809 namestr, typestr); 3810 } 3811 3812 /* Prepare the affected RRset for the addition. */ 3813 { 3814 add_rr_prepare_ctx_t ctx; 3815 ctx.db = db; 3816 ctx.ver = ver; 3817 ctx.diff = &diff; 3818 ctx.name = name; 3819 ctx.update_rr = &rdata; 3820 ctx.update_rr_ttl = ttl; 3821 ctx.ignore_add = ISC_FALSE; 3822 dns_diff_init(mctx, &ctx.del_diff); 3823 dns_diff_init(mctx, &ctx.add_diff); 3824 CHECK(foreach_rr(db, ver, name, rdata.type, 3825 covers, add_rr_prepare_action, 3826 &ctx)); 3827 3828 if (ctx.ignore_add) { 3829 dns_diff_clear(&ctx.del_diff); 3830 dns_diff_clear(&ctx.add_diff); 3831 } else { 3832 CHECK(do_diff(&ctx.del_diff, db, ver, 3833 &diff)); 3834 CHECK(do_diff(&ctx.add_diff, db, ver, 3835 &diff)); 3836 CHECK(update_one_rr(db, ver, &diff, 3837 DNS_DIFFOP_ADD, 3838 name, ttl, &rdata)); 3839 } 3840 } 3841 } else if (update_class == dns_rdataclass_any) { 3842 if (rdata.type == dns_rdatatype_any) { 3843 if (isc_log_wouldlog(ns_g_lctx, 3844 LOGLEVEL_PROTOCOL)) 3845 { 3846 char namestr[DNS_NAME_FORMATSIZE]; 3847 dns_name_format(name, namestr, 3848 sizeof(namestr)); 3849 update_log(client, zone, 3850 LOGLEVEL_PROTOCOL, 3851 "delete all rrsets from " 3852 "name '%s'", namestr); 3853 } 3854 if (dns_name_equal(name, zonename)) { 3855 CHECK(delete_if(type_not_soa_nor_ns_p, 3856 db, ver, name, 3857 dns_rdatatype_any, 0, 3858 &rdata, &diff)); 3859 } else { 3860 CHECK(delete_if(type_not_dnssec, 3861 db, ver, name, 3862 dns_rdatatype_any, 0, 3863 &rdata, &diff)); 3864 } 3865#ifndef ALLOW_NSEC3PARAM_UPDATE 3866 } else if (rdata.type == dns_rdatatype_nsec3param) { 3867 update_log(client, zone, LOGLEVEL_PROTOCOL, 3868 "attempt to delete a NSEC3PARAM " 3869 "records ignored"); 3870 continue; 3871#endif 3872 } else if (dns_name_equal(name, zonename) && 3873 (rdata.type == dns_rdatatype_soa || 3874 rdata.type == dns_rdatatype_ns)) { 3875 update_log(client, zone, LOGLEVEL_PROTOCOL, 3876 "attempt to delete all SOA " 3877 "or NS records ignored"); 3878 continue; 3879 } else { 3880 if (isc_log_wouldlog(ns_g_lctx, 3881 LOGLEVEL_PROTOCOL)) 3882 { 3883 char namestr[DNS_NAME_FORMATSIZE]; 3884 char typestr[DNS_RDATATYPE_FORMATSIZE]; 3885 dns_name_format(name, namestr, 3886 sizeof(namestr)); 3887 dns_rdatatype_format(rdata.type, 3888 typestr, 3889 sizeof(typestr)); 3890 update_log(client, zone, 3891 LOGLEVEL_PROTOCOL, 3892 "deleting rrset at '%s' %s", 3893 namestr, typestr); 3894 } 3895 CHECK(delete_if(true_p, db, ver, name, 3896 rdata.type, covers, &rdata, 3897 &diff)); 3898 } 3899 } else if (update_class == dns_rdataclass_none) { 3900 /* 3901 * The (name == zonename) condition appears in 3902 * RFC2136 3.4.2.4 but is missing from the pseudocode. 3903 */ 3904 if (dns_name_equal(name, zonename)) { 3905 if (rdata.type == dns_rdatatype_soa) { 3906 update_log(client, zone, 3907 LOGLEVEL_PROTOCOL, 3908 "attempt to delete SOA " 3909 "ignored"); 3910 continue; 3911 } 3912 if (rdata.type == dns_rdatatype_ns) { 3913 int count; 3914 CHECK(rr_count(db, ver, name, 3915 dns_rdatatype_ns, 3916 0, &count)); 3917 if (count == 1) { 3918 update_log(client, zone, 3919 LOGLEVEL_PROTOCOL, 3920 "attempt to " 3921 "delete last " 3922 "NS ignored"); 3923 continue; 3924 } 3925 } 3926 } 3927 update_log(client, zone, 3928 LOGLEVEL_PROTOCOL, 3929 "deleting an RR"); 3930 CHECK(delete_if(rr_equal_p, db, ver, name, 3931 rdata.type, covers, &rdata, &diff)); 3932 } 3933 } 3934 if (result != ISC_R_NOMORE) 3935 FAIL(result); 3936 3937 /* 3938 * Check that any changes to DNSKEY/NSEC3PARAM records make sense. 3939 * If they don't then back out all changes to DNSKEY/NSEC3PARAM 3940 * records. 3941 */ 3942 if (! ISC_LIST_EMPTY(diff.tuples)) 3943 CHECK(check_dnssec(client, zone, db, ver, &diff)); 3944 3945 /* 3946 * If any changes were made, increment the SOA serial number, 3947 * update RRSIGs and NSECs (if zone is secure), and write the update 3948 * to the journal. 3949 */ 3950 if (! ISC_LIST_EMPTY(diff.tuples)) { 3951 char *journalfile; 3952 dns_journal_t *journal; 3953 isc_boolean_t has_dnskey; 3954 3955 /* 3956 * Increment the SOA serial, but only if it was not 3957 * changed as a result of an update operation. 3958 */ 3959 if (! soa_serial_changed) { 3960 CHECK(increment_soa_serial(db, ver, &diff, mctx)); 3961 } 3962 3963 CHECK(check_mx(client, zone, db, ver, &diff)); 3964 3965 CHECK(remove_orphaned_ds(db, ver, &diff)); 3966 3967 CHECK(rrset_exists(db, ver, zonename, dns_rdatatype_dnskey, 3968 0, &has_dnskey)); 3969 3970#if !defined(ALLOW_SECURE_TO_INSECURE) || !defined(ALLOW_INSECURE_TO_SECURE) 3971 CHECK(rrset_exists(db, oldver, zonename, dns_rdatatype_dnskey, 3972 0, &had_dnskey)); 3973 3974#ifndef ALLOW_SECURE_TO_INSECURE 3975 if (had_dnskey && !has_dnskey) { 3976 update_log(client, zone, LOGLEVEL_PROTOCOL, 3977 "update rejected: all DNSKEY records " 3978 "removed"); 3979 result = DNS_R_REFUSED; 3980 goto failure; 3981 } 3982#endif 3983#ifndef ALLOW_INSECURE_TO_SECURE 3984 if (!had_dnskey && has_dnskey) { 3985 update_log(client, zone, LOGLEVEL_PROTOCOL, 3986 "update rejected: DNSKEY record added"); 3987 result = DNS_R_REFUSED; 3988 goto failure; 3989 } 3990#endif 3991#endif 3992 3993 CHECK(add_signing_records(db, zonename, ver, 3994 dns_zone_getprivatetype(zone), 3995 &diff)); 3996 3997#ifdef ALLOW_NSEC3PARAM_UPDATE 3998 CHECK(add_nsec3param_records(client, zone, db, zonename, 3999 ver, &diff)); 4000#endif 4001 4002 if (!has_dnskey) { 4003 /* 4004 * We are transitioning from secure to insecure. 4005 * Cause all NSEC3 chains to be deleted. When the 4006 * the last signature for the DNSKEY records are 4007 * remove any NSEC chain present will also be removed. 4008 */ 4009#ifdef ALLOW_NSEC3PARAM_UPDATE 4010 CHECK(delete_chains(db, ver, zonename, &diff)); 4011#endif 4012 } else if (has_dnskey && dns_db_isdnssec(db)) { 4013 isc_uint32_t interval; 4014 interval = dns_zone_getsigvalidityinterval(zone); 4015 result = update_signatures(client, zone, db, oldver, 4016 ver, &diff, interval, 4017 &deleted_zsk); 4018 if (result != ISC_R_SUCCESS) { 4019 update_log(client, zone, 4020 ISC_LOG_ERROR, 4021 "RRSIG/NSEC/NSEC3 update failed: %s", 4022 isc_result_totext(result)); 4023 goto failure; 4024 } 4025 } 4026 4027 journalfile = dns_zone_getjournal(zone); 4028 if (journalfile != NULL) { 4029 update_log(client, zone, LOGLEVEL_DEBUG, 4030 "writing journal %s", journalfile); 4031 4032 journal = NULL; 4033 result = dns_journal_open(mctx, journalfile, 4034 ISC_TRUE, &journal); 4035 if (result != ISC_R_SUCCESS) 4036 FAILS(result, "journal open failed"); 4037 4038 result = dns_journal_write_transaction(journal, &diff); 4039 if (result != ISC_R_SUCCESS) { 4040 dns_journal_destroy(&journal); 4041 FAILS(result, "journal write failed"); 4042 } 4043 4044 dns_journal_destroy(&journal); 4045 } 4046 4047 /* 4048 * XXXRTH Just a note that this committing code will have 4049 * to change to handle databases that need two-phase 4050 * commit, but this isn't a priority. 4051 */ 4052 update_log(client, zone, LOGLEVEL_DEBUG, 4053 "committing update transaction"); 4054 4055 dns_db_closeversion(db, &ver, ISC_TRUE); 4056 4057 /* 4058 * Mark the zone as dirty so that it will be written to disk. 4059 */ 4060 dns_zone_markdirty(zone); 4061 4062 /* 4063 * Notify slaves of the change we just made. 4064 */ 4065 dns_zone_notify(zone); 4066 4067 /* 4068 * Cause the zone to be signed with the key that we 4069 * have just added or have the corresponding signatures 4070 * deleted. 4071 * 4072 * Note: we are already committed to this course of action. 4073 */ 4074 for (tuple = ISC_LIST_HEAD(diff.tuples); 4075 tuple != NULL; 4076 tuple = ISC_LIST_NEXT(tuple, link)) { 4077 isc_region_t r; 4078 dns_secalg_t algorithm; 4079 isc_uint16_t keyid; 4080 4081 if (tuple->rdata.type != dns_rdatatype_dnskey) 4082 continue; 4083 4084 dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL); 4085 if ((dnskey.flags & 4086 (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH)) 4087 != DNS_KEYOWNER_ZONE) 4088 continue; 4089 4090 dns_rdata_toregion(&tuple->rdata, &r); 4091 algorithm = dnskey.algorithm; 4092 keyid = dst_region_computeid(&r, algorithm); 4093 4094 result = dns_zone_signwithkey(zone, algorithm, keyid, 4095 ISC_TF(tuple->op == DNS_DIFFOP_DEL)); 4096 if (result != ISC_R_SUCCESS) { 4097 update_log(client, zone, ISC_LOG_ERROR, 4098 "dns_zone_signwithkey failed: %s", 4099 dns_result_totext(result)); 4100 } 4101 } 4102 4103#ifdef ALLOW_NSEC3PARAM_UPDATE 4104 /* 4105 * Cause the zone to add/delete NSEC3 chains for the 4106 * deferred NSEC3PARAM changes. 4107 * 4108 * Note: we are already committed to this course of action. 4109 */ 4110 for (tuple = ISC_LIST_HEAD(diff.tuples); 4111 tuple != NULL; 4112 tuple = ISC_LIST_NEXT(tuple, link)) { 4113 dns_rdata_nsec3param_t nsec3param; 4114 4115 if (tuple->rdata.type != dns_rdatatype_nsec3param || 4116 tuple->op != DNS_DIFFOP_ADD) 4117 continue; 4118 4119 dns_rdata_tostruct(&tuple->rdata, &nsec3param, NULL); 4120 if (nsec3param.flags == 0) 4121 continue; 4122 4123 result = dns_zone_addnsec3chain(zone, &nsec3param); 4124 if (result != ISC_R_SUCCESS) { 4125 update_log(client, zone, ISC_LOG_ERROR, 4126 "dns_zone_addnsec3chain failed: %s", 4127 dns_result_totext(result)); 4128 } 4129 } 4130#endif 4131 } else { 4132 update_log(client, zone, LOGLEVEL_DEBUG, "redundant request"); 4133 dns_db_closeversion(db, &ver, ISC_TRUE); 4134 } 4135 result = ISC_R_SUCCESS; 4136 goto common; 4137 4138 failure: 4139 if (result == DNS_R_REFUSED) 4140 inc_stats(zone, dns_nsstatscounter_updaterej); 4141 4142 /* 4143 * The reason for failure should have been logged at this point. 4144 */ 4145 if (ver != NULL) { 4146 update_log(client, zone, LOGLEVEL_DEBUG, 4147 "rolling back"); 4148 dns_db_closeversion(db, &ver, ISC_FALSE); 4149 } 4150 4151 common: 4152 dns_diff_clear(&temp); 4153 dns_diff_clear(&diff); 4154 4155 if (oldver != NULL) 4156 dns_db_closeversion(db, &oldver, ISC_FALSE); 4157 4158 if (db != NULL) 4159 dns_db_detach(&db); 4160 4161 if (ssutable != NULL) 4162 dns_ssutable_detach(&ssutable); 4163 4164 isc_task_detach(&task); 4165 uev->result = result; 4166 if (zone != NULL) 4167 INSIST(uev->zone == zone); /* we use this later */ 4168 uev->ev_type = DNS_EVENT_UPDATEDONE; 4169 uev->ev_action = updatedone_action; 4170 isc_task_send(client->task, &event); 4171 INSIST(event == NULL); 4172} 4173 4174static void 4175updatedone_action(isc_task_t *task, isc_event_t *event) { 4176 update_event_t *uev = (update_event_t *) event; 4177 ns_client_t *client = (ns_client_t *) event->ev_arg; 4178 4179 UNUSED(task); 4180 4181 INSIST(event->ev_type == DNS_EVENT_UPDATEDONE); 4182 INSIST(task == client->task); 4183 4184 INSIST(client->nupdates > 0); 4185 switch (uev->result) { 4186 case ISC_R_SUCCESS: 4187 inc_stats(uev->zone, dns_nsstatscounter_updatedone); 4188 break; 4189 case DNS_R_REFUSED: 4190 inc_stats(uev->zone, dns_nsstatscounter_updaterej); 4191 break; 4192 default: 4193 inc_stats(uev->zone, dns_nsstatscounter_updatefail); 4194 break; 4195 } 4196 if (uev->zone != NULL) 4197 dns_zone_detach(&uev->zone); 4198 client->nupdates--; 4199 respond(client, uev->result); 4200 isc_event_free(&event); 4201 ns_client_detach(&client); 4202} 4203 4204/*% 4205 * Update forwarding support. 4206 */ 4207 4208static void 4209forward_fail(isc_task_t *task, isc_event_t *event) { 4210 ns_client_t *client = (ns_client_t *)event->ev_arg; 4211 4212 UNUSED(task); 4213 4214 INSIST(client->nupdates > 0); 4215 client->nupdates--; 4216 respond(client, DNS_R_SERVFAIL); 4217 isc_event_free(&event); 4218 ns_client_detach(&client); 4219} 4220 4221 4222static void 4223forward_callback(void *arg, isc_result_t result, dns_message_t *answer) { 4224 update_event_t *uev = arg; 4225 ns_client_t *client = uev->ev_arg; 4226 dns_zone_t *zone = uev->zone; 4227 4228 if (result != ISC_R_SUCCESS) { 4229 INSIST(answer == NULL); 4230 uev->ev_type = DNS_EVENT_UPDATEDONE; 4231 uev->ev_action = forward_fail; 4232 inc_stats(zone, dns_nsstatscounter_updatefwdfail); 4233 } else { 4234 uev->ev_type = DNS_EVENT_UPDATEDONE; 4235 uev->ev_action = forward_done; 4236 uev->answer = answer; 4237 inc_stats(zone, dns_nsstatscounter_updaterespfwd); 4238 } 4239 isc_task_send(client->task, ISC_EVENT_PTR(&uev)); 4240 dns_zone_detach(&zone); 4241} 4242 4243static void 4244forward_done(isc_task_t *task, isc_event_t *event) { 4245 update_event_t *uev = (update_event_t *) event; 4246 ns_client_t *client = (ns_client_t *)event->ev_arg; 4247 4248 UNUSED(task); 4249 4250 INSIST(client->nupdates > 0); 4251 client->nupdates--; 4252 ns_client_sendraw(client, uev->answer); 4253 dns_message_destroy(&uev->answer); 4254 isc_event_free(&event); 4255 ns_client_detach(&client); 4256} 4257 4258static void 4259forward_action(isc_task_t *task, isc_event_t *event) { 4260 update_event_t *uev = (update_event_t *) event; 4261 dns_zone_t *zone = uev->zone; 4262 ns_client_t *client = (ns_client_t *)event->ev_arg; 4263 isc_result_t result; 4264 4265 result = dns_zone_forwardupdate(zone, client->message, 4266 forward_callback, event); 4267 if (result != ISC_R_SUCCESS) { 4268 uev->ev_type = DNS_EVENT_UPDATEDONE; 4269 uev->ev_action = forward_fail; 4270 isc_task_send(client->task, &event); 4271 inc_stats(zone, dns_nsstatscounter_updatefwdfail); 4272 dns_zone_detach(&zone); 4273 } else 4274 inc_stats(zone, dns_nsstatscounter_updatereqfwd); 4275 isc_task_detach(&task); 4276} 4277 4278static isc_result_t 4279send_forward_event(ns_client_t *client, dns_zone_t *zone) { 4280 isc_result_t result = ISC_R_SUCCESS; 4281 update_event_t *event = NULL; 4282 isc_task_t *zonetask = NULL; 4283 ns_client_t *evclient; 4284 4285 event = (update_event_t *) 4286 isc_event_allocate(client->mctx, client, DNS_EVENT_UPDATE, 4287 forward_action, NULL, sizeof(*event)); 4288 if (event == NULL) 4289 FAIL(ISC_R_NOMEMORY); 4290 event->zone = zone; 4291 event->result = ISC_R_SUCCESS; 4292 4293 evclient = NULL; 4294 ns_client_attach(client, &evclient); 4295 INSIST(client->nupdates == 0); 4296 client->nupdates++; 4297 event->ev_arg = evclient; 4298 4299 dns_zone_gettask(zone, &zonetask); 4300 isc_task_send(zonetask, ISC_EVENT_PTR(&event)); 4301 4302 failure: 4303 if (event != NULL) 4304 isc_event_free(ISC_EVENT_PTR(&event)); 4305 return (result); 4306} 4307