1/* 2 * Copyright (C) 2004-2013 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.199 2011/12/22 07:32:40 each 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/private.h> 42#include <dns/rdataclass.h> 43#include <dns/rdataset.h> 44#include <dns/rdatasetiter.h> 45#include <dns/rdatastruct.h> 46#include <dns/rdatatype.h> 47#include <dns/soa.h> 48#include <dns/ssu.h> 49#include <dns/tsig.h> 50#include <dns/update.h> 51#include <dns/view.h> 52#include <dns/zone.h> 53#include <dns/zt.h> 54 55#include <named/client.h> 56#include <named/log.h> 57#include <named/server.h> 58#include <named/update.h> 59 60/*! \file 61 * \brief 62 * This module implements dynamic update as in RFC2136. 63 */ 64 65/* 66 * XXX TODO: 67 * - document strict minimality 68 */ 69 70/**************************************************************************/ 71 72/*% 73 * Log level for tracing dynamic update protocol requests. 74 */ 75#define LOGLEVEL_PROTOCOL ISC_LOG_INFO 76 77/*% 78 * Log level for low-level debug tracing. 79 */ 80#define LOGLEVEL_DEBUG ISC_LOG_DEBUG(8) 81 82/*% 83 * Check an operation for failure. These macros all assume that 84 * the function using them has a 'result' variable and a 'failure' 85 * label. 86 */ 87#define CHECK(op) \ 88 do { result = (op); \ 89 if (result != ISC_R_SUCCESS) goto failure; \ 90 } while (0) 91 92/*% 93 * Fail unconditionally with result 'code', which must not 94 * be ISC_R_SUCCESS. The reason for failure presumably has 95 * been logged already. 96 * 97 * The test against ISC_R_SUCCESS is there to keep the Solaris compiler 98 * from complaining about "end-of-loop code not reached". 99 */ 100 101#define FAIL(code) \ 102 do { \ 103 result = (code); \ 104 if (result != ISC_R_SUCCESS) goto failure; \ 105 } while (0) 106 107/*% 108 * Fail unconditionally and log as a client error. 109 * The test against ISC_R_SUCCESS is there to keep the Solaris compiler 110 * from complaining about "end-of-loop code not reached". 111 */ 112#define FAILC(code, msg) \ 113 do { \ 114 const char *_what = "failed"; \ 115 result = (code); \ 116 switch (result) { \ 117 case DNS_R_NXDOMAIN: \ 118 case DNS_R_YXDOMAIN: \ 119 case DNS_R_YXRRSET: \ 120 case DNS_R_NXRRSET: \ 121 _what = "unsuccessful"; \ 122 } \ 123 update_log(client, zone, LOGLEVEL_PROTOCOL, \ 124 "update %s: %s (%s)", _what, \ 125 msg, isc_result_totext(result)); \ 126 if (result != ISC_R_SUCCESS) goto failure; \ 127 } while (0) 128#define PREREQFAILC(code, msg) \ 129 do { \ 130 inc_stats(zone, dns_nsstatscounter_updatebadprereq); \ 131 FAILC(code, msg); \ 132 } while (0) 133 134#define FAILN(code, name, msg) \ 135 do { \ 136 const char *_what = "failed"; \ 137 result = (code); \ 138 switch (result) { \ 139 case DNS_R_NXDOMAIN: \ 140 case DNS_R_YXDOMAIN: \ 141 case DNS_R_YXRRSET: \ 142 case DNS_R_NXRRSET: \ 143 _what = "unsuccessful"; \ 144 } \ 145 if (isc_log_wouldlog(ns_g_lctx, LOGLEVEL_PROTOCOL)) { \ 146 char _nbuf[DNS_NAME_FORMATSIZE]; \ 147 dns_name_format(name, _nbuf, sizeof(_nbuf)); \ 148 update_log(client, zone, LOGLEVEL_PROTOCOL, \ 149 "update %s: %s: %s (%s)", _what, _nbuf, \ 150 msg, isc_result_totext(result)); \ 151 } \ 152 if (result != ISC_R_SUCCESS) goto failure; \ 153 } while (0) 154#define PREREQFAILN(code, name, msg) \ 155 do { \ 156 inc_stats(zone, dns_nsstatscounter_updatebadprereq); \ 157 FAILN(code, name, msg); \ 158 } while (0) 159 160#define FAILNT(code, name, type, msg) \ 161 do { \ 162 const char *_what = "failed"; \ 163 result = (code); \ 164 switch (result) { \ 165 case DNS_R_NXDOMAIN: \ 166 case DNS_R_YXDOMAIN: \ 167 case DNS_R_YXRRSET: \ 168 case DNS_R_NXRRSET: \ 169 _what = "unsuccessful"; \ 170 } \ 171 if (isc_log_wouldlog(ns_g_lctx, LOGLEVEL_PROTOCOL)) { \ 172 char _nbuf[DNS_NAME_FORMATSIZE]; \ 173 char _tbuf[DNS_RDATATYPE_FORMATSIZE]; \ 174 dns_name_format(name, _nbuf, sizeof(_nbuf)); \ 175 dns_rdatatype_format(type, _tbuf, sizeof(_tbuf)); \ 176 update_log(client, zone, LOGLEVEL_PROTOCOL, \ 177 "update %s: %s/%s: %s (%s)", \ 178 _what, _nbuf, _tbuf, msg, \ 179 isc_result_totext(result)); \ 180 } \ 181 if (result != ISC_R_SUCCESS) goto failure; \ 182 } while (0) 183#define PREREQFAILNT(code, name, type, msg) \ 184 do { \ 185 inc_stats(zone, dns_nsstatscounter_updatebadprereq); \ 186 FAILNT(code, name, type, msg); \ 187 } while (0) 188 189/*% 190 * Fail unconditionally and log as a server error. 191 * The test against ISC_R_SUCCESS is there to keep the Solaris compiler 192 * from complaining about "end-of-loop code not reached". 193 */ 194#define FAILS(code, msg) \ 195 do { \ 196 result = (code); \ 197 update_log(client, zone, LOGLEVEL_PROTOCOL, \ 198 "error: %s: %s", \ 199 msg, isc_result_totext(result)); \ 200 if (result != ISC_R_SUCCESS) goto failure; \ 201 } while (0) 202 203/* 204 * Return TRUE if NS_CLIENTATTR_TCP is set in the attributes other FALSE. 205 */ 206#define TCPCLIENT(client) (((client)->attributes & NS_CLIENTATTR_TCP) != 0) 207 208/**************************************************************************/ 209 210typedef struct rr rr_t; 211 212struct rr { 213 /* dns_name_t name; */ 214 isc_uint32_t ttl; 215 dns_rdata_t rdata; 216}; 217 218typedef struct update_event update_event_t; 219 220struct update_event { 221 ISC_EVENT_COMMON(update_event_t); 222 dns_zone_t *zone; 223 isc_result_t result; 224 dns_message_t *answer; 225}; 226 227/**************************************************************************/ 228/* 229 * Forward declarations. 230 */ 231 232static void update_action(isc_task_t *task, isc_event_t *event); 233static void updatedone_action(isc_task_t *task, isc_event_t *event); 234static isc_result_t send_forward_event(ns_client_t *client, dns_zone_t *zone); 235static void forward_done(isc_task_t *task, isc_event_t *event); 236 237/**************************************************************************/ 238 239static void 240update_log(ns_client_t *client, dns_zone_t *zone, 241 int level, const char *fmt, ...) ISC_FORMAT_PRINTF(4, 5); 242 243static void 244update_log(ns_client_t *client, dns_zone_t *zone, 245 int level, const char *fmt, ...) 246{ 247 va_list ap; 248 char message[4096]; 249 char namebuf[DNS_NAME_FORMATSIZE]; 250 char classbuf[DNS_RDATACLASS_FORMATSIZE]; 251 252 if (client == NULL || zone == NULL) 253 return; 254 255 if (isc_log_wouldlog(ns_g_lctx, level) == ISC_FALSE) 256 return; 257 258 dns_name_format(dns_zone_getorigin(zone), namebuf, 259 sizeof(namebuf)); 260 dns_rdataclass_format(dns_zone_getclass(zone), classbuf, 261 sizeof(classbuf)); 262 263 va_start(ap, fmt); 264 vsnprintf(message, sizeof(message), fmt, ap); 265 va_end(ap); 266 267 ns_client_log(client, NS_LOGCATEGORY_UPDATE, NS_LOGMODULE_UPDATE, 268 level, "updating zone '%s/%s': %s", 269 namebuf, classbuf, message); 270} 271 272static void 273update_log_cb(void *arg, dns_zone_t *zone, int level, const char *message) { 274 update_log(arg, zone, level, "%s", message); 275} 276 277/*% 278 * Increment updated-related statistics counters. 279 */ 280static inline void 281inc_stats(dns_zone_t *zone, isc_statscounter_t counter) { 282 isc_stats_increment(ns_g_server->nsstats, counter); 283 284 if (zone != NULL) { 285 isc_stats_t *zonestats = dns_zone_getrequeststats(zone); 286 if (zonestats != NULL) 287 isc_stats_increment(zonestats, counter); 288 } 289} 290 291/*% 292 * Check if we could have queried for the contents of this zone or 293 * if the zone is potentially updateable. 294 * If the zone can potentially be updated and the check failed then 295 * log a error otherwise we log a informational message. 296 */ 297static isc_result_t 298checkqueryacl(ns_client_t *client, dns_acl_t *queryacl, dns_name_t *zonename, 299 dns_acl_t *updateacl, dns_ssutable_t *ssutable) 300{ 301 char namebuf[DNS_NAME_FORMATSIZE]; 302 char classbuf[DNS_RDATACLASS_FORMATSIZE]; 303 int level; 304 isc_result_t result; 305 306 result = ns_client_checkaclsilent(client, NULL, queryacl, ISC_TRUE); 307 if (result != ISC_R_SUCCESS) { 308 dns_name_format(zonename, namebuf, sizeof(namebuf)); 309 dns_rdataclass_format(client->view->rdclass, classbuf, 310 sizeof(classbuf)); 311 312 level = (updateacl == NULL && ssutable == NULL) ? 313 ISC_LOG_INFO : ISC_LOG_ERROR; 314 315 ns_client_log(client, NS_LOGCATEGORY_UPDATE_SECURITY, 316 NS_LOGMODULE_UPDATE, level, 317 "update '%s/%s' denied due to allow-query", 318 namebuf, classbuf); 319 } else if (updateacl == NULL && ssutable == NULL) { 320 dns_name_format(zonename, namebuf, sizeof(namebuf)); 321 dns_rdataclass_format(client->view->rdclass, classbuf, 322 sizeof(classbuf)); 323 324 result = DNS_R_REFUSED; 325 ns_client_log(client, NS_LOGCATEGORY_UPDATE_SECURITY, 326 NS_LOGMODULE_UPDATE, ISC_LOG_INFO, 327 "update '%s/%s' denied", namebuf, classbuf); 328 } 329 return (result); 330} 331 332/*% 333 * Override the default acl logging when checking whether a client 334 * can update the zone or whether we can forward the request to the 335 * master based on IP address. 336 * 337 * 'message' contains the type of operation that is being attempted. 338 * 'slave' indicates if this is a slave zone. If 'acl' is NULL then 339 * log at debug=3. 340 * If the zone has no access controls configured ('acl' == NULL && 341 * 'has_ssutable == ISC_FALS) log the attempt at info, otherwise 342 * at error. 343 * 344 * If the request was signed log that we received it. 345 */ 346static isc_result_t 347checkupdateacl(ns_client_t *client, dns_acl_t *acl, const char *message, 348 dns_name_t *zonename, isc_boolean_t slave, 349 isc_boolean_t has_ssutable) 350{ 351 char namebuf[DNS_NAME_FORMATSIZE]; 352 char classbuf[DNS_RDATACLASS_FORMATSIZE]; 353 int level = ISC_LOG_ERROR; 354 const char *msg = "denied"; 355 isc_result_t result; 356 357 if (slave && acl == NULL) { 358 result = DNS_R_NOTIMP; 359 level = ISC_LOG_DEBUG(3); 360 msg = "disabled"; 361 } else { 362 result = ns_client_checkaclsilent(client, NULL, acl, ISC_FALSE); 363 if (result == ISC_R_SUCCESS) { 364 level = ISC_LOG_DEBUG(3); 365 msg = "approved"; 366 } else if (acl == NULL && !has_ssutable) { 367 level = ISC_LOG_INFO; 368 } 369 } 370 371 if (client->signer != NULL) { 372 dns_name_format(client->signer, namebuf, sizeof(namebuf)); 373 ns_client_log(client, NS_LOGCATEGORY_UPDATE_SECURITY, 374 NS_LOGMODULE_UPDATE, ISC_LOG_INFO, 375 "signer \"%s\" %s", namebuf, msg); 376 } 377 378 dns_name_format(zonename, namebuf, sizeof(namebuf)); 379 dns_rdataclass_format(client->view->rdclass, classbuf, 380 sizeof(classbuf)); 381 382 ns_client_log(client, NS_LOGCATEGORY_UPDATE_SECURITY, 383 NS_LOGMODULE_UPDATE, level, "%s '%s/%s' %s", 384 message, namebuf, classbuf, msg); 385 return (result); 386} 387 388/*% 389 * Update a single RR in version 'ver' of 'db' and log the 390 * update in 'diff'. 391 * 392 * Ensures: 393 * \li '*tuple' == NULL. Either the tuple is freed, or its 394 * ownership has been transferred to the diff. 395 */ 396static isc_result_t 397do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver, 398 dns_diff_t *diff) 399{ 400 dns_diff_t temp_diff; 401 isc_result_t result; 402 403 /* 404 * Create a singleton diff. 405 */ 406 dns_diff_init(diff->mctx, &temp_diff); 407 ISC_LIST_APPEND(temp_diff.tuples, *tuple, link); 408 409 /* 410 * Apply it to the database. 411 */ 412 result = dns_diff_apply(&temp_diff, db, ver); 413 ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link); 414 if (result != ISC_R_SUCCESS) { 415 dns_difftuple_free(tuple); 416 return (result); 417 } 418 419 /* 420 * Merge it into the current pending journal entry. 421 */ 422 dns_diff_appendminimal(diff, tuple); 423 424 /* 425 * Do not clear temp_diff. 426 */ 427 return (ISC_R_SUCCESS); 428} 429 430/*% 431 * Perform the updates in 'updates' in version 'ver' of 'db' and log the 432 * update in 'diff'. 433 * 434 * Ensures: 435 * \li 'updates' is empty. 436 */ 437static isc_result_t 438do_diff(dns_diff_t *updates, dns_db_t *db, dns_dbversion_t *ver, 439 dns_diff_t *diff) 440{ 441 isc_result_t result; 442 while (! ISC_LIST_EMPTY(updates->tuples)) { 443 dns_difftuple_t *t = ISC_LIST_HEAD(updates->tuples); 444 ISC_LIST_UNLINK(updates->tuples, t, link); 445 CHECK(do_one_tuple(&t, db, ver, diff)); 446 } 447 return (ISC_R_SUCCESS); 448 449 failure: 450 dns_diff_clear(diff); 451 return (result); 452} 453 454static isc_result_t 455update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff, 456 dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl, 457 dns_rdata_t *rdata) 458{ 459 dns_difftuple_t *tuple = NULL; 460 isc_result_t result; 461 result = dns_difftuple_create(diff->mctx, op, 462 name, ttl, rdata, &tuple); 463 if (result != ISC_R_SUCCESS) 464 return (result); 465 return (do_one_tuple(&tuple, db, ver, diff)); 466} 467 468/**************************************************************************/ 469/* 470 * Callback-style iteration over rdatasets and rdatas. 471 * 472 * foreach_rrset() can be used to iterate over the RRsets 473 * of a name and call a callback function with each 474 * one. Similarly, foreach_rr() can be used to iterate 475 * over the individual RRs at name, optionally restricted 476 * to RRs of a given type. 477 * 478 * The callback functions are called "actions" and take 479 * two arguments: a void pointer for passing arbitrary 480 * context information, and a pointer to the current RRset 481 * or RR. By convention, their names end in "_action". 482 */ 483 484/* 485 * XXXRTH We might want to make this public somewhere in libdns. 486 */ 487 488/*% 489 * Function type for foreach_rrset() iterator actions. 490 */ 491typedef isc_result_t rrset_func(void *data, dns_rdataset_t *rrset); 492 493/*% 494 * Function type for foreach_rr() iterator actions. 495 */ 496typedef isc_result_t rr_func(void *data, rr_t *rr); 497 498/*% 499 * Internal context struct for foreach_node_rr(). 500 */ 501typedef struct { 502 rr_func * rr_action; 503 void * rr_action_data; 504} foreach_node_rr_ctx_t; 505 506/*% 507 * Internal helper function for foreach_node_rr(). 508 */ 509static isc_result_t 510foreach_node_rr_action(void *data, dns_rdataset_t *rdataset) { 511 isc_result_t result; 512 foreach_node_rr_ctx_t *ctx = data; 513 for (result = dns_rdataset_first(rdataset); 514 result == ISC_R_SUCCESS; 515 result = dns_rdataset_next(rdataset)) 516 { 517 rr_t rr = { 0, DNS_RDATA_INIT }; 518 519 dns_rdataset_current(rdataset, &rr.rdata); 520 rr.ttl = rdataset->ttl; 521 result = (*ctx->rr_action)(ctx->rr_action_data, &rr); 522 if (result != ISC_R_SUCCESS) 523 return (result); 524 } 525 if (result != ISC_R_NOMORE) 526 return (result); 527 return (ISC_R_SUCCESS); 528} 529 530/*% 531 * For each rdataset of 'name' in 'ver' of 'db', call 'action' 532 * with the rdataset and 'action_data' as arguments. If the name 533 * does not exist, do nothing. 534 * 535 * If 'action' returns an error, abort iteration and return the error. 536 */ 537static isc_result_t 538foreach_rrset(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, 539 rrset_func *action, void *action_data) 540{ 541 isc_result_t result; 542 dns_dbnode_t *node; 543 dns_rdatasetiter_t *iter; 544 545 node = NULL; 546 result = dns_db_findnode(db, name, ISC_FALSE, &node); 547 if (result == ISC_R_NOTFOUND) 548 return (ISC_R_SUCCESS); 549 if (result != ISC_R_SUCCESS) 550 return (result); 551 552 iter = NULL; 553 result = dns_db_allrdatasets(db, node, ver, 554 (isc_stdtime_t) 0, &iter); 555 if (result != ISC_R_SUCCESS) 556 goto cleanup_node; 557 558 for (result = dns_rdatasetiter_first(iter); 559 result == ISC_R_SUCCESS; 560 result = dns_rdatasetiter_next(iter)) 561 { 562 dns_rdataset_t rdataset; 563 564 dns_rdataset_init(&rdataset); 565 dns_rdatasetiter_current(iter, &rdataset); 566 567 result = (*action)(action_data, &rdataset); 568 569 dns_rdataset_disassociate(&rdataset); 570 if (result != ISC_R_SUCCESS) 571 goto cleanup_iterator; 572 } 573 if (result == ISC_R_NOMORE) 574 result = ISC_R_SUCCESS; 575 576 cleanup_iterator: 577 dns_rdatasetiter_destroy(&iter); 578 579 cleanup_node: 580 dns_db_detachnode(db, &node); 581 582 return (result); 583} 584 585/*% 586 * For each RR of 'name' in 'ver' of 'db', call 'action' 587 * with the RR and 'action_data' as arguments. If the name 588 * does not exist, do nothing. 589 * 590 * If 'action' returns an error, abort iteration 591 * and return the error. 592 */ 593static isc_result_t 594foreach_node_rr(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, 595 rr_func *rr_action, void *rr_action_data) 596{ 597 foreach_node_rr_ctx_t ctx; 598 ctx.rr_action = rr_action; 599 ctx.rr_action_data = rr_action_data; 600 return (foreach_rrset(db, ver, name, 601 foreach_node_rr_action, &ctx)); 602} 603 604 605/*% 606 * For each of the RRs specified by 'db', 'ver', 'name', 'type', 607 * (which can be dns_rdatatype_any to match any type), and 'covers', call 608 * 'action' with the RR and 'action_data' as arguments. If the name 609 * does not exist, or if no RRset of the given type exists at the name, 610 * do nothing. 611 * 612 * If 'action' returns an error, abort iteration and return the error. 613 */ 614static isc_result_t 615foreach_rr(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, 616 dns_rdatatype_t type, dns_rdatatype_t covers, rr_func *rr_action, 617 void *rr_action_data) 618{ 619 620 isc_result_t result; 621 dns_dbnode_t *node; 622 dns_rdataset_t rdataset; 623 624 if (type == dns_rdatatype_any) 625 return (foreach_node_rr(db, ver, name, 626 rr_action, rr_action_data)); 627 628 node = NULL; 629 if (type == dns_rdatatype_nsec3 || 630 (type == dns_rdatatype_rrsig && covers == dns_rdatatype_nsec3)) 631 result = dns_db_findnsec3node(db, name, ISC_FALSE, &node); 632 else 633 result = dns_db_findnode(db, name, ISC_FALSE, &node); 634 if (result == ISC_R_NOTFOUND) 635 return (ISC_R_SUCCESS); 636 if (result != ISC_R_SUCCESS) 637 return (result); 638 639 dns_rdataset_init(&rdataset); 640 result = dns_db_findrdataset(db, node, ver, type, covers, 641 (isc_stdtime_t) 0, &rdataset, NULL); 642 if (result == ISC_R_NOTFOUND) { 643 result = ISC_R_SUCCESS; 644 goto cleanup_node; 645 } 646 if (result != ISC_R_SUCCESS) 647 goto cleanup_node; 648 649 for (result = dns_rdataset_first(&rdataset); 650 result == ISC_R_SUCCESS; 651 result = dns_rdataset_next(&rdataset)) 652 { 653 rr_t rr = { 0, DNS_RDATA_INIT }; 654 dns_rdataset_current(&rdataset, &rr.rdata); 655 rr.ttl = rdataset.ttl; 656 result = (*rr_action)(rr_action_data, &rr); 657 if (result != ISC_R_SUCCESS) 658 goto cleanup_rdataset; 659 } 660 if (result != ISC_R_NOMORE) 661 goto cleanup_rdataset; 662 result = ISC_R_SUCCESS; 663 664 cleanup_rdataset: 665 dns_rdataset_disassociate(&rdataset); 666 cleanup_node: 667 dns_db_detachnode(db, &node); 668 669 return (result); 670} 671 672/**************************************************************************/ 673/* 674 * Various tests on the database contents (for prerequisites, etc). 675 */ 676 677/*% 678 * Function type for predicate functions that compare a database RR 'db_rr' 679 * against an update RR 'update_rr'. 680 */ 681typedef isc_boolean_t rr_predicate(dns_rdata_t *update_rr, dns_rdata_t *db_rr); 682 683/*% 684 * Helper function for rrset_exists(). 685 */ 686static isc_result_t 687rrset_exists_action(void *data, rr_t *rr) { 688 UNUSED(data); 689 UNUSED(rr); 690 return (ISC_R_EXISTS); 691} 692 693/*% 694 * Utility macro for RR existence checking functions. 695 * 696 * If the variable 'result' has the value ISC_R_EXISTS or 697 * ISC_R_SUCCESS, set *exists to ISC_TRUE or ISC_FALSE, 698 * respectively, and return success. 699 * 700 * If 'result' has any other value, there was a failure. 701 * Return the failure result code and do not set *exists. 702 * 703 * This would be more readable as "do { if ... } while(0)", 704 * but that form generates tons of warnings on Solaris 2.6. 705 */ 706#define RETURN_EXISTENCE_FLAG \ 707 return ((result == ISC_R_EXISTS) ? \ 708 (*exists = ISC_TRUE, ISC_R_SUCCESS) : \ 709 ((result == ISC_R_SUCCESS) ? \ 710 (*exists = ISC_FALSE, ISC_R_SUCCESS) : \ 711 result)) 712 713/*% 714 * Set '*exists' to true iff an rrset of the given type exists, 715 * to false otherwise. 716 */ 717static isc_result_t 718rrset_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, 719 dns_rdatatype_t type, dns_rdatatype_t covers, 720 isc_boolean_t *exists) 721{ 722 isc_result_t result; 723 result = foreach_rr(db, ver, name, type, covers, 724 rrset_exists_action, NULL); 725 RETURN_EXISTENCE_FLAG; 726} 727 728/*% 729 * Helper function for cname_incompatible_rrset_exists. 730 */ 731static isc_result_t 732cname_compatibility_action(void *data, dns_rdataset_t *rrset) { 733 UNUSED(data); 734 if (rrset->type != dns_rdatatype_cname && 735 ! dns_rdatatype_isdnssec(rrset->type)) 736 return (ISC_R_EXISTS); 737 return (ISC_R_SUCCESS); 738} 739 740/*% 741 * Check whether there is an rrset incompatible with adding a CNAME RR, 742 * i.e., anything but another CNAME (which can be replaced) or a 743 * DNSSEC RR (which can coexist). 744 * 745 * If such an incompatible rrset exists, set '*exists' to ISC_TRUE. 746 * Otherwise, set it to ISC_FALSE. 747 */ 748static isc_result_t 749cname_incompatible_rrset_exists(dns_db_t *db, dns_dbversion_t *ver, 750 dns_name_t *name, isc_boolean_t *exists) { 751 isc_result_t result; 752 result = foreach_rrset(db, ver, name, 753 cname_compatibility_action, NULL); 754 RETURN_EXISTENCE_FLAG; 755} 756 757/*% 758 * Helper function for rr_count(). 759 */ 760static isc_result_t 761count_rr_action(void *data, rr_t *rr) { 762 int *countp = data; 763 UNUSED(rr); 764 (*countp)++; 765 return (ISC_R_SUCCESS); 766} 767 768/*% 769 * Count the number of RRs of 'type' belonging to 'name' in 'ver' of 'db'. 770 */ 771static isc_result_t 772rr_count(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, 773 dns_rdatatype_t type, dns_rdatatype_t covers, int *countp) 774{ 775 *countp = 0; 776 return (foreach_rr(db, ver, name, type, covers, 777 count_rr_action, countp)); 778} 779 780/*% 781 * Context struct and helper function for name_exists(). 782 */ 783 784static isc_result_t 785name_exists_action(void *data, dns_rdataset_t *rrset) { 786 UNUSED(data); 787 UNUSED(rrset); 788 return (ISC_R_EXISTS); 789} 790 791/*% 792 * Set '*exists' to true iff the given name exists, to false otherwise. 793 */ 794static isc_result_t 795name_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, 796 isc_boolean_t *exists) 797{ 798 isc_result_t result; 799 result = foreach_rrset(db, ver, name, 800 name_exists_action, NULL); 801 RETURN_EXISTENCE_FLAG; 802} 803 804/* 805 * 'ssu_check_t' is used to pass the arguments to 806 * dns_ssutable_checkrules() to the callback function 807 * ssu_checkrule(). 808 */ 809typedef struct { 810 /* The ownername of the record to be updated. */ 811 dns_name_t *name; 812 813 /* The signature's name if the request was signed. */ 814 dns_name_t *signer; 815 816 /* The address of the client if the request was received via TCP. */ 817 isc_netaddr_t *tcpaddr; 818 819 /* The ssu table to check against. */ 820 dns_ssutable_t *table; 821 822 /* the key used for TKEY requests */ 823 dst_key_t *key; 824} ssu_check_t; 825 826static isc_result_t 827ssu_checkrule(void *data, dns_rdataset_t *rrset) { 828 ssu_check_t *ssuinfo = data; 829 isc_boolean_t result; 830 831 /* 832 * If we're deleting all records, it's ok to delete RRSIG and NSEC even 833 * if we're normally not allowed to. 834 */ 835 if (rrset->type == dns_rdatatype_rrsig || 836 rrset->type == dns_rdatatype_nsec) 837 return (ISC_R_SUCCESS); 838 result = dns_ssutable_checkrules(ssuinfo->table, ssuinfo->signer, 839 ssuinfo->name, ssuinfo->tcpaddr, 840 rrset->type, ssuinfo->key); 841 return (result == ISC_TRUE ? ISC_R_SUCCESS : ISC_R_FAILURE); 842} 843 844static isc_boolean_t 845ssu_checkall(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, 846 dns_ssutable_t *ssutable, dns_name_t *signer, 847 isc_netaddr_t *tcpaddr, dst_key_t *key) 848{ 849 isc_result_t result; 850 ssu_check_t ssuinfo; 851 852 ssuinfo.name = name; 853 ssuinfo.table = ssutable; 854 ssuinfo.signer = signer; 855 ssuinfo.tcpaddr = tcpaddr; 856 ssuinfo.key = key; 857 result = foreach_rrset(db, ver, name, ssu_checkrule, &ssuinfo); 858 return (ISC_TF(result == ISC_R_SUCCESS)); 859} 860 861/**************************************************************************/ 862/* 863 * Checking of "RRset exists (value dependent)" prerequisites. 864 * 865 * In the RFC2136 section 3.2.5, this is the pseudocode involving 866 * a variable called "temp", a mapping of <name, type> tuples to rrsets. 867 * 868 * Here, we represent the "temp" data structure as (non-minimal) "dns_diff_t" 869 * where each tuple has op==DNS_DIFFOP_EXISTS. 870 */ 871 872 873/*% 874 * Append a tuple asserting the existence of the RR with 875 * 'name' and 'rdata' to 'diff'. 876 */ 877static isc_result_t 878temp_append(dns_diff_t *diff, dns_name_t *name, dns_rdata_t *rdata) { 879 isc_result_t result; 880 dns_difftuple_t *tuple = NULL; 881 882 REQUIRE(DNS_DIFF_VALID(diff)); 883 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_EXISTS, 884 name, 0, rdata, &tuple)); 885 ISC_LIST_APPEND(diff->tuples, tuple, link); 886 failure: 887 return (result); 888} 889 890/*% 891 * Compare two rdatasets represented as sorted lists of tuples. 892 * All list elements must have the same owner name and type. 893 * Return ISC_R_SUCCESS if the rdatasets are equal, rcode(dns_rcode_nxrrset) 894 * if not. 895 */ 896static isc_result_t 897temp_check_rrset(dns_difftuple_t *a, dns_difftuple_t *b) { 898 for (;;) { 899 if (a == NULL || b == NULL) 900 break; 901 INSIST(a->op == DNS_DIFFOP_EXISTS && 902 b->op == DNS_DIFFOP_EXISTS); 903 INSIST(a->rdata.type == b->rdata.type); 904 INSIST(dns_name_equal(&a->name, &b->name)); 905 if (dns_rdata_casecompare(&a->rdata, &b->rdata) != 0) 906 return (DNS_R_NXRRSET); 907 a = ISC_LIST_NEXT(a, link); 908 b = ISC_LIST_NEXT(b, link); 909 } 910 if (a != NULL || b != NULL) 911 return (DNS_R_NXRRSET); 912 return (ISC_R_SUCCESS); 913} 914 915/*% 916 * A comparison function defining the sorting order for the entries 917 * in the "temp" data structure. The major sort key is the owner name, 918 * followed by the type and rdata. 919 */ 920static int 921temp_order(const void *av, const void *bv) { 922 dns_difftuple_t const * const *ap = av; 923 dns_difftuple_t const * const *bp = bv; 924 dns_difftuple_t const *a = *ap; 925 dns_difftuple_t const *b = *bp; 926 int r; 927 r = dns_name_compare(&a->name, &b->name); 928 if (r != 0) 929 return (r); 930 r = (b->rdata.type - a->rdata.type); 931 if (r != 0) 932 return (r); 933 r = dns_rdata_casecompare(&a->rdata, &b->rdata); 934 return (r); 935} 936 937/*% 938 * Check the "RRset exists (value dependent)" prerequisite information 939 * in 'temp' against the contents of the database 'db'. 940 * 941 * Return ISC_R_SUCCESS if the prerequisites are satisfied, 942 * rcode(dns_rcode_nxrrset) if not. 943 * 944 * 'temp' must be pre-sorted. 945 */ 946 947static isc_result_t 948temp_check(isc_mem_t *mctx, dns_diff_t *temp, dns_db_t *db, 949 dns_dbversion_t *ver, dns_name_t *tmpname, dns_rdatatype_t *typep) 950{ 951 isc_result_t result; 952 dns_name_t *name; 953 dns_dbnode_t *node; 954 dns_difftuple_t *t; 955 dns_diff_t trash; 956 957 dns_diff_init(mctx, &trash); 958 959 /* 960 * For each name and type in the prerequisites, 961 * construct a sorted rdata list of the corresponding 962 * database contents, and compare the lists. 963 */ 964 t = ISC_LIST_HEAD(temp->tuples); 965 while (t != NULL) { 966 name = &t->name; 967 (void)dns_name_copy(name, tmpname, NULL); 968 *typep = t->rdata.type; 969 970 /* A new unique name begins here. */ 971 node = NULL; 972 result = dns_db_findnode(db, name, ISC_FALSE, &node); 973 if (result == ISC_R_NOTFOUND) { 974 dns_diff_clear(&trash); 975 return (DNS_R_NXRRSET); 976 } 977 if (result != ISC_R_SUCCESS) { 978 dns_diff_clear(&trash); 979 return (result); 980 } 981 982 /* A new unique type begins here. */ 983 while (t != NULL && dns_name_equal(&t->name, name)) { 984 dns_rdatatype_t type, covers; 985 dns_rdataset_t rdataset; 986 dns_diff_t d_rrs; /* Database RRs with 987 this name and type */ 988 dns_diff_t u_rrs; /* Update RRs with 989 this name and type */ 990 991 *typep = type = t->rdata.type; 992 if (type == dns_rdatatype_rrsig || 993 type == dns_rdatatype_sig) 994 covers = dns_rdata_covers(&t->rdata); 995 else if (type == dns_rdatatype_any) { 996 dns_db_detachnode(db, &node); 997 dns_diff_clear(&trash); 998 return (DNS_R_NXRRSET); 999 } else 1000 covers = 0; 1001 1002 /* 1003 * Collect all database RRs for this name and type 1004 * onto d_rrs and sort them. 1005 */ 1006 dns_rdataset_init(&rdataset); 1007 result = dns_db_findrdataset(db, node, ver, type, 1008 covers, (isc_stdtime_t) 0, 1009 &rdataset, NULL); 1010 if (result != ISC_R_SUCCESS) { 1011 dns_db_detachnode(db, &node); 1012 dns_diff_clear(&trash); 1013 return (DNS_R_NXRRSET); 1014 } 1015 1016 dns_diff_init(mctx, &d_rrs); 1017 dns_diff_init(mctx, &u_rrs); 1018 1019 for (result = dns_rdataset_first(&rdataset); 1020 result == ISC_R_SUCCESS; 1021 result = dns_rdataset_next(&rdataset)) 1022 { 1023 dns_rdata_t rdata = DNS_RDATA_INIT; 1024 dns_rdataset_current(&rdataset, &rdata); 1025 result = temp_append(&d_rrs, name, &rdata); 1026 if (result != ISC_R_SUCCESS) 1027 goto failure; 1028 } 1029 if (result != ISC_R_NOMORE) 1030 goto failure; 1031 result = dns_diff_sort(&d_rrs, temp_order); 1032 if (result != ISC_R_SUCCESS) 1033 goto failure; 1034 1035 /* 1036 * Collect all update RRs for this name and type 1037 * onto u_rrs. No need to sort them here - 1038 * they are already sorted. 1039 */ 1040 while (t != NULL && 1041 dns_name_equal(&t->name, name) && 1042 t->rdata.type == type) 1043 { 1044 dns_difftuple_t *next = 1045 ISC_LIST_NEXT(t, link); 1046 ISC_LIST_UNLINK(temp->tuples, t, link); 1047 ISC_LIST_APPEND(u_rrs.tuples, t, link); 1048 t = next; 1049 } 1050 1051 /* Compare the two sorted lists. */ 1052 result = temp_check_rrset(ISC_LIST_HEAD(u_rrs.tuples), 1053 ISC_LIST_HEAD(d_rrs.tuples)); 1054 if (result != ISC_R_SUCCESS) 1055 goto failure; 1056 1057 /* 1058 * We are done with the tuples, but we can't free 1059 * them yet because "name" still points into one 1060 * of them. Move them on a temporary list. 1061 */ 1062 ISC_LIST_APPENDLIST(trash.tuples, u_rrs.tuples, link); 1063 ISC_LIST_APPENDLIST(trash.tuples, d_rrs.tuples, link); 1064 dns_rdataset_disassociate(&rdataset); 1065 1066 continue; 1067 1068 failure: 1069 dns_diff_clear(&d_rrs); 1070 dns_diff_clear(&u_rrs); 1071 dns_diff_clear(&trash); 1072 dns_rdataset_disassociate(&rdataset); 1073 dns_db_detachnode(db, &node); 1074 return (result); 1075 } 1076 1077 dns_db_detachnode(db, &node); 1078 } 1079 1080 dns_diff_clear(&trash); 1081 return (ISC_R_SUCCESS); 1082} 1083 1084/**************************************************************************/ 1085/* 1086 * Conditional deletion of RRs. 1087 */ 1088 1089/*% 1090 * Context structure for delete_if(). 1091 */ 1092 1093typedef struct { 1094 rr_predicate *predicate; 1095 dns_db_t *db; 1096 dns_dbversion_t *ver; 1097 dns_diff_t *diff; 1098 dns_name_t *name; 1099 dns_rdata_t *update_rr; 1100} conditional_delete_ctx_t; 1101 1102/*% 1103 * Predicate functions for delete_if(). 1104 */ 1105 1106/*% 1107 * Return true iff 'db_rr' is neither a SOA nor an NS RR nor 1108 * an RRSIG nor an NSEC3PARAM nor a NSEC. 1109 */ 1110static isc_boolean_t 1111type_not_soa_nor_ns_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) { 1112 UNUSED(update_rr); 1113 return ((db_rr->type != dns_rdatatype_soa && 1114 db_rr->type != dns_rdatatype_ns && 1115 db_rr->type != dns_rdatatype_nsec3param && 1116 db_rr->type != dns_rdatatype_rrsig && 1117 db_rr->type != dns_rdatatype_nsec) ? 1118 ISC_TRUE : ISC_FALSE); 1119} 1120 1121/*% 1122 * Return true iff 'db_rr' is neither a RRSIG nor a NSEC. 1123 */ 1124static isc_boolean_t 1125type_not_dnssec(dns_rdata_t *update_rr, dns_rdata_t *db_rr) { 1126 UNUSED(update_rr); 1127 return ((db_rr->type != dns_rdatatype_rrsig && 1128 db_rr->type != dns_rdatatype_nsec) ? 1129 ISC_TRUE : ISC_FALSE); 1130} 1131 1132/*% 1133 * Return true always. 1134 */ 1135static isc_boolean_t 1136true_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) { 1137 UNUSED(update_rr); 1138 UNUSED(db_rr); 1139 return (ISC_TRUE); 1140} 1141 1142/*% 1143 * Return true iff the two RRs have identical rdata. 1144 */ 1145static isc_boolean_t 1146rr_equal_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) { 1147 /* 1148 * XXXRTH This is not a problem, but we should consider creating 1149 * dns_rdata_equal() (that used dns_name_equal()), since it 1150 * would be faster. Not a priority. 1151 */ 1152 return (dns_rdata_casecompare(update_rr, db_rr) == 0 ? 1153 ISC_TRUE : ISC_FALSE); 1154} 1155 1156/*% 1157 * Return true iff 'update_rr' should replace 'db_rr' according 1158 * to the special RFC2136 rules for CNAME, SOA, and WKS records. 1159 * 1160 * RFC2136 does not mention NSEC or DNAME, but multiple NSECs or DNAMEs 1161 * make little sense, so we replace those, too. 1162 * 1163 * Additionally replace RRSIG that have been generated by the same key 1164 * for the same type. This simplifies refreshing a offline KSK by not 1165 * requiring that the old RRSIG be deleted. It also simplifies key 1166 * rollover by only requiring that the new RRSIG be added. 1167 */ 1168static isc_boolean_t 1169replaces_p(dns_rdata_t *update_rr, dns_rdata_t *db_rr) { 1170 dns_rdata_rrsig_t updatesig, dbsig; 1171 isc_result_t result; 1172 1173 if (db_rr->type != update_rr->type) 1174 return (ISC_FALSE); 1175 if (db_rr->type == dns_rdatatype_cname) 1176 return (ISC_TRUE); 1177 if (db_rr->type == dns_rdatatype_dname) 1178 return (ISC_TRUE); 1179 if (db_rr->type == dns_rdatatype_soa) 1180 return (ISC_TRUE); 1181 if (db_rr->type == dns_rdatatype_nsec) 1182 return (ISC_TRUE); 1183 if (db_rr->type == dns_rdatatype_rrsig) { 1184 /* 1185 * Replace existing RRSIG with the same keyid, 1186 * covered and algorithm. 1187 */ 1188 result = dns_rdata_tostruct(db_rr, &dbsig, NULL); 1189 RUNTIME_CHECK(result == ISC_R_SUCCESS); 1190 result = dns_rdata_tostruct(update_rr, &updatesig, NULL); 1191 RUNTIME_CHECK(result == ISC_R_SUCCESS); 1192 if (dbsig.keyid == updatesig.keyid && 1193 dbsig.covered == updatesig.covered && 1194 dbsig.algorithm == updatesig.algorithm) 1195 return (ISC_TRUE); 1196 } 1197 if (db_rr->type == dns_rdatatype_wks) { 1198 /* 1199 * Compare the address and protocol fields only. These 1200 * form the first five bytes of the RR data. Do a 1201 * raw binary comparison; unpacking the WKS RRs using 1202 * dns_rdata_tostruct() might be cleaner in some ways. 1203 */ 1204 INSIST(db_rr->length >= 5 && update_rr->length >= 5); 1205 return (memcmp(db_rr->data, update_rr->data, 5) == 0 ? 1206 ISC_TRUE : ISC_FALSE); 1207 } 1208 1209 if (db_rr->type == dns_rdatatype_nsec3param) { 1210 if (db_rr->length != update_rr->length) 1211 return (ISC_FALSE); 1212 INSIST(db_rr->length >= 4 && update_rr->length >= 4); 1213 /* 1214 * Replace NSEC3PARAM records that only differ by the 1215 * flags field. 1216 */ 1217 if (db_rr->data[0] == update_rr->data[0] && 1218 memcmp(db_rr->data+2, update_rr->data+2, 1219 update_rr->length - 2) == 0) 1220 return (ISC_TRUE); 1221 } 1222 return (ISC_FALSE); 1223} 1224 1225/*% 1226 * Internal helper function for delete_if(). 1227 */ 1228static isc_result_t 1229delete_if_action(void *data, rr_t *rr) { 1230 conditional_delete_ctx_t *ctx = data; 1231 if ((*ctx->predicate)(ctx->update_rr, &rr->rdata)) { 1232 isc_result_t result; 1233 result = update_one_rr(ctx->db, ctx->ver, ctx->diff, 1234 DNS_DIFFOP_DEL, ctx->name, 1235 rr->ttl, &rr->rdata); 1236 return (result); 1237 } else { 1238 return (ISC_R_SUCCESS); 1239 } 1240} 1241 1242/*% 1243 * Conditionally delete RRs. Apply 'predicate' to the RRs 1244 * specified by 'db', 'ver', 'name', and 'type' (which can 1245 * be dns_rdatatype_any to match any type). Delete those 1246 * RRs for which the predicate returns true, and log the 1247 * deletions in 'diff'. 1248 */ 1249static isc_result_t 1250delete_if(rr_predicate *predicate, dns_db_t *db, dns_dbversion_t *ver, 1251 dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers, 1252 dns_rdata_t *update_rr, dns_diff_t *diff) 1253{ 1254 conditional_delete_ctx_t ctx; 1255 ctx.predicate = predicate; 1256 ctx.db = db; 1257 ctx.ver = ver; 1258 ctx.diff = diff; 1259 ctx.name = name; 1260 ctx.update_rr = update_rr; 1261 return (foreach_rr(db, ver, name, type, covers, 1262 delete_if_action, &ctx)); 1263} 1264 1265/**************************************************************************/ 1266/*% 1267 * Prepare an RR for the addition of the new RR 'ctx->update_rr', 1268 * with TTL 'ctx->update_rr_ttl', to its rdataset, by deleting 1269 * the RRs if it is replaced by the new RR or has a conflicting TTL. 1270 * The necessary changes are appended to ctx->del_diff and ctx->add_diff; 1271 * we need to do all deletions before any additions so that we don't run 1272 * into transient states with conflicting TTLs. 1273 */ 1274 1275typedef struct { 1276 dns_db_t *db; 1277 dns_dbversion_t *ver; 1278 dns_diff_t *diff; 1279 dns_name_t *name; 1280 dns_rdata_t *update_rr; 1281 dns_ttl_t update_rr_ttl; 1282 isc_boolean_t ignore_add; 1283 dns_diff_t del_diff; 1284 dns_diff_t add_diff; 1285} add_rr_prepare_ctx_t; 1286 1287static isc_result_t 1288add_rr_prepare_action(void *data, rr_t *rr) { 1289 isc_result_t result = ISC_R_SUCCESS; 1290 add_rr_prepare_ctx_t *ctx = data; 1291 dns_difftuple_t *tuple = NULL; 1292 isc_boolean_t equal; 1293 1294 /* 1295 * If the update RR is a "duplicate" of the update RR, 1296 * the update should be silently ignored. 1297 */ 1298 equal = ISC_TF(dns_rdata_casecompare(&rr->rdata, ctx->update_rr) == 0); 1299 if (equal && rr->ttl == ctx->update_rr_ttl) { 1300 ctx->ignore_add = ISC_TRUE; 1301 return (ISC_R_SUCCESS); 1302 } 1303 1304 /* 1305 * If this RR is "equal" to the update RR, it should 1306 * be deleted before the update RR is added. 1307 */ 1308 if (replaces_p(ctx->update_rr, &rr->rdata)) { 1309 CHECK(dns_difftuple_create(ctx->del_diff.mctx, DNS_DIFFOP_DEL, 1310 ctx->name, rr->ttl, &rr->rdata, 1311 &tuple)); 1312 dns_diff_append(&ctx->del_diff, &tuple); 1313 return (ISC_R_SUCCESS); 1314 } 1315 1316 /* 1317 * If this RR differs in TTL from the update RR, 1318 * its TTL must be adjusted. 1319 */ 1320 if (rr->ttl != ctx->update_rr_ttl) { 1321 CHECK(dns_difftuple_create(ctx->del_diff.mctx, DNS_DIFFOP_DEL, 1322 ctx->name, rr->ttl, &rr->rdata, 1323 &tuple)); 1324 dns_diff_append(&ctx->del_diff, &tuple); 1325 if (!equal) { 1326 CHECK(dns_difftuple_create(ctx->add_diff.mctx, 1327 DNS_DIFFOP_ADD, ctx->name, 1328 ctx->update_rr_ttl, 1329 &rr->rdata, &tuple)); 1330 dns_diff_append(&ctx->add_diff, &tuple); 1331 } 1332 } 1333 failure: 1334 return (result); 1335} 1336 1337/**************************************************************************/ 1338/* 1339 * Miscellaneous subroutines. 1340 */ 1341 1342/*% 1343 * Extract a single update RR from 'section' of dynamic update message 1344 * 'msg', with consistency checking. 1345 * 1346 * Stores the owner name, rdata, and TTL of the update RR at 'name', 1347 * 'rdata', and 'ttl', respectively. 1348 */ 1349static void 1350get_current_rr(dns_message_t *msg, dns_section_t section, 1351 dns_rdataclass_t zoneclass, dns_name_t **name, 1352 dns_rdata_t *rdata, dns_rdatatype_t *covers, 1353 dns_ttl_t *ttl, dns_rdataclass_t *update_class) 1354{ 1355 dns_rdataset_t *rdataset; 1356 isc_result_t result; 1357 dns_message_currentname(msg, section, name); 1358 rdataset = ISC_LIST_HEAD((*name)->list); 1359 INSIST(rdataset != NULL); 1360 INSIST(ISC_LIST_NEXT(rdataset, link) == NULL); 1361 *covers = rdataset->covers; 1362 *ttl = rdataset->ttl; 1363 result = dns_rdataset_first(rdataset); 1364 INSIST(result == ISC_R_SUCCESS); 1365 dns_rdataset_current(rdataset, rdata); 1366 INSIST(dns_rdataset_next(rdataset) == ISC_R_NOMORE); 1367 *update_class = rdata->rdclass; 1368 rdata->rdclass = zoneclass; 1369} 1370 1371/*% 1372 * Increment the SOA serial number of database 'db', version 'ver'. 1373 * Replace the SOA record in the database, and log the 1374 * change in 'diff'. 1375 */ 1376 1377 /* 1378 * XXXRTH Failures in this routine will be worth logging, when 1379 * we have a logging system. Failure to find the zonename 1380 * or the SOA rdataset warrant at least an UNEXPECTED_ERROR(). 1381 */ 1382 1383static isc_result_t 1384update_soa_serial(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff, 1385 isc_mem_t *mctx, dns_updatemethod_t method) 1386{ 1387 dns_difftuple_t *deltuple = NULL; 1388 dns_difftuple_t *addtuple = NULL; 1389 isc_uint32_t serial; 1390 isc_result_t result; 1391 1392 CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple)); 1393 CHECK(dns_difftuple_copy(deltuple, &addtuple)); 1394 addtuple->op = DNS_DIFFOP_ADD; 1395 1396 serial = dns_soa_getserial(&addtuple->rdata); 1397 serial = dns_update_soaserial(serial, method); 1398 dns_soa_setserial(serial, &addtuple->rdata); 1399 CHECK(do_one_tuple(&deltuple, db, ver, diff)); 1400 CHECK(do_one_tuple(&addtuple, db, ver, diff)); 1401 result = ISC_R_SUCCESS; 1402 1403 failure: 1404 if (addtuple != NULL) 1405 dns_difftuple_free(&addtuple); 1406 if (deltuple != NULL) 1407 dns_difftuple_free(&deltuple); 1408 return (result); 1409} 1410 1411/*% 1412 * Check that the new SOA record at 'update_rdata' does not 1413 * illegally cause the SOA serial number to decrease or stay 1414 * unchanged relative to the existing SOA in 'db'. 1415 * 1416 * Sets '*ok' to ISC_TRUE if the update is legal, ISC_FALSE if not. 1417 * 1418 * William King points out that RFC2136 is inconsistent about 1419 * the case where the serial number stays unchanged: 1420 * 1421 * section 3.4.2.2 requires a server to ignore a SOA update request 1422 * if the serial number on the update SOA is less_than_or_equal to 1423 * the zone SOA serial. 1424 * 1425 * section 3.6 requires a server to ignore a SOA update request if 1426 * the serial is less_than the zone SOA serial. 1427 * 1428 * Paul says 3.4.2.2 is correct. 1429 * 1430 */ 1431static isc_result_t 1432check_soa_increment(dns_db_t *db, dns_dbversion_t *ver, 1433 dns_rdata_t *update_rdata, isc_boolean_t *ok) 1434{ 1435 isc_uint32_t db_serial; 1436 isc_uint32_t update_serial; 1437 isc_result_t result; 1438 1439 update_serial = dns_soa_getserial(update_rdata); 1440 1441 result = dns_db_getsoaserial(db, ver, &db_serial); 1442 if (result != ISC_R_SUCCESS) 1443 return (result); 1444 1445 if (DNS_SERIAL_GE(db_serial, update_serial)) { 1446 *ok = ISC_FALSE; 1447 } else { 1448 *ok = ISC_TRUE; 1449 } 1450 1451 return (ISC_R_SUCCESS); 1452 1453} 1454 1455/**************************************************************************/ 1456/*% 1457 * The actual update code in all its glory. We try to follow 1458 * the RFC2136 pseudocode as closely as possible. 1459 */ 1460 1461static isc_result_t 1462send_update_event(ns_client_t *client, dns_zone_t *zone) { 1463 isc_result_t result = ISC_R_SUCCESS; 1464 update_event_t *event = NULL; 1465 isc_task_t *zonetask = NULL; 1466 ns_client_t *evclient; 1467 1468 event = (update_event_t *) 1469 isc_event_allocate(client->mctx, client, DNS_EVENT_UPDATE, 1470 update_action, NULL, sizeof(*event)); 1471 if (event == NULL) 1472 FAIL(ISC_R_NOMEMORY); 1473 event->zone = zone; 1474 event->result = ISC_R_SUCCESS; 1475 1476 evclient = NULL; 1477 ns_client_attach(client, &evclient); 1478 INSIST(client->nupdates == 0); 1479 client->nupdates++; 1480 event->ev_arg = evclient; 1481 1482 dns_zone_gettask(zone, &zonetask); 1483 isc_task_send(zonetask, ISC_EVENT_PTR(&event)); 1484 1485 failure: 1486 if (event != NULL) 1487 isc_event_free(ISC_EVENT_PTR(&event)); 1488 return (result); 1489} 1490 1491static void 1492respond(ns_client_t *client, isc_result_t result) { 1493 isc_result_t msg_result; 1494 1495 msg_result = dns_message_reply(client->message, ISC_TRUE); 1496 if (msg_result != ISC_R_SUCCESS) 1497 goto msg_failure; 1498 client->message->rcode = dns_result_torcode(result); 1499 1500 ns_client_send(client); 1501 return; 1502 1503 msg_failure: 1504 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_UPDATE, NS_LOGMODULE_UPDATE, 1505 ISC_LOG_ERROR, 1506 "could not create update response message: %s", 1507 isc_result_totext(msg_result)); 1508 ns_client_next(client, msg_result); 1509} 1510 1511void 1512ns_update_start(ns_client_t *client, isc_result_t sigresult) { 1513 dns_message_t *request = client->message; 1514 isc_result_t result; 1515 dns_name_t *zonename; 1516 dns_rdataset_t *zone_rdataset; 1517 dns_zone_t *zone = NULL, *raw = NULL; 1518 1519 /* 1520 * Interpret the zone section. 1521 */ 1522 result = dns_message_firstname(request, DNS_SECTION_ZONE); 1523 if (result != ISC_R_SUCCESS) 1524 FAILC(DNS_R_FORMERR, "update zone section empty"); 1525 1526 /* 1527 * The zone section must contain exactly one "question", and 1528 * it must be of type SOA. 1529 */ 1530 zonename = NULL; 1531 dns_message_currentname(request, DNS_SECTION_ZONE, &zonename); 1532 zone_rdataset = ISC_LIST_HEAD(zonename->list); 1533 if (zone_rdataset->type != dns_rdatatype_soa) 1534 FAILC(DNS_R_FORMERR, 1535 "update zone section contains non-SOA"); 1536 if (ISC_LIST_NEXT(zone_rdataset, link) != NULL) 1537 FAILC(DNS_R_FORMERR, 1538 "update zone section contains multiple RRs"); 1539 1540 /* The zone section must have exactly one name. */ 1541 result = dns_message_nextname(request, DNS_SECTION_ZONE); 1542 if (result != ISC_R_NOMORE) 1543 FAILC(DNS_R_FORMERR, 1544 "update zone section contains multiple RRs"); 1545 1546 result = dns_zt_find(client->view->zonetable, zonename, 0, NULL, 1547 &zone); 1548 if (result != ISC_R_SUCCESS) 1549 FAILC(DNS_R_NOTAUTH, "not authoritative for update zone"); 1550 1551 /* 1552 * If there is a raw (unsigned) zone associated with this 1553 * zone then it processes the UPDATE request. 1554 */ 1555 dns_zone_getraw(zone, &raw); 1556 if (raw != NULL) { 1557 dns_zone_detach(&zone); 1558 dns_zone_attach(raw, &zone); 1559 dns_zone_detach(&raw); 1560 } 1561 1562 switch(dns_zone_gettype(zone)) { 1563 case dns_zone_master: 1564 case dns_zone_dlz: 1565 /* 1566 * We can now fail due to a bad signature as we now know 1567 * that we are the master. 1568 */ 1569 if (sigresult != ISC_R_SUCCESS) 1570 FAIL(sigresult); 1571 CHECK(send_update_event(client, zone)); 1572 break; 1573 case dns_zone_slave: 1574 CHECK(checkupdateacl(client, dns_zone_getforwardacl(zone), 1575 "update forwarding", zonename, ISC_TRUE, 1576 ISC_FALSE)); 1577 CHECK(send_forward_event(client, zone)); 1578 break; 1579 default: 1580 FAILC(DNS_R_NOTAUTH, "not authoritative for update zone"); 1581 } 1582 return; 1583 1584 failure: 1585 if (result == DNS_R_REFUSED) { 1586 INSIST(dns_zone_gettype(zone) == dns_zone_slave); 1587 inc_stats(zone, dns_nsstatscounter_updaterej); 1588 } 1589 /* 1590 * We failed without having sent an update event to the zone. 1591 * We are still in the client task context, so we can 1592 * simply give an error response without switching tasks. 1593 */ 1594 respond(client, result); 1595 if (zone != NULL) 1596 dns_zone_detach(&zone); 1597} 1598 1599/*% 1600 * DS records are not allowed to exist without corresponding NS records, 1601 * RFC 3658, 2.2 Protocol Change, 1602 * "DS RRsets MUST NOT appear at non-delegation points or at a zone's apex". 1603 */ 1604 1605static isc_result_t 1606remove_orphaned_ds(dns_db_t *db, dns_dbversion_t *newver, dns_diff_t *diff) { 1607 isc_result_t result; 1608 isc_boolean_t ns_exists; 1609 dns_difftuple_t *tupple; 1610 dns_diff_t temp_diff; 1611 1612 dns_diff_init(diff->mctx, &temp_diff); 1613 1614 for (tupple = ISC_LIST_HEAD(diff->tuples); 1615 tupple != NULL; 1616 tupple = ISC_LIST_NEXT(tupple, link)) { 1617 if (!((tupple->op == DNS_DIFFOP_DEL && 1618 tupple->rdata.type == dns_rdatatype_ns) || 1619 (tupple->op == DNS_DIFFOP_ADD && 1620 tupple->rdata.type == dns_rdatatype_ds))) 1621 continue; 1622 CHECK(rrset_exists(db, newver, &tupple->name, 1623 dns_rdatatype_ns, 0, &ns_exists)); 1624 if (ns_exists && 1625 !dns_name_equal(&tupple->name, dns_db_origin(db))) 1626 continue; 1627 CHECK(delete_if(true_p, db, newver, &tupple->name, 1628 dns_rdatatype_ds, 0, NULL, &temp_diff)); 1629 } 1630 result = ISC_R_SUCCESS; 1631 1632 failure: 1633 for (tupple = ISC_LIST_HEAD(temp_diff.tuples); 1634 tupple != NULL; 1635 tupple = ISC_LIST_HEAD(temp_diff.tuples)) { 1636 ISC_LIST_UNLINK(temp_diff.tuples, tupple, link); 1637 dns_diff_appendminimal(diff, &tupple); 1638 } 1639 return (result); 1640} 1641 1642/* 1643 * This implements the post load integrity checks for mx records. 1644 */ 1645static isc_result_t 1646check_mx(ns_client_t *client, dns_zone_t *zone, 1647 dns_db_t *db, dns_dbversion_t *newver, dns_diff_t *diff) 1648{ 1649 char tmp[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:123.123.123.123.")]; 1650 char ownerbuf[DNS_NAME_FORMATSIZE]; 1651 char namebuf[DNS_NAME_FORMATSIZE]; 1652 char altbuf[DNS_NAME_FORMATSIZE]; 1653 dns_difftuple_t *t; 1654 dns_fixedname_t fixed; 1655 dns_name_t *foundname; 1656 dns_rdata_mx_t mx; 1657 dns_rdata_t rdata; 1658 isc_boolean_t ok = ISC_TRUE; 1659 isc_boolean_t isaddress; 1660 isc_result_t result; 1661 struct in6_addr addr6; 1662 struct in_addr addr; 1663 unsigned int options; 1664 1665 dns_fixedname_init(&fixed); 1666 foundname = dns_fixedname_name(&fixed); 1667 dns_rdata_init(&rdata); 1668 options = dns_zone_getoptions(zone); 1669 1670 for (t = ISC_LIST_HEAD(diff->tuples); 1671 t != NULL; 1672 t = ISC_LIST_NEXT(t, link)) { 1673 if (t->op != DNS_DIFFOP_ADD || 1674 t->rdata.type != dns_rdatatype_mx) 1675 continue; 1676 1677 result = dns_rdata_tostruct(&t->rdata, &mx, NULL); 1678 RUNTIME_CHECK(result == ISC_R_SUCCESS); 1679 /* 1680 * Check if we will error out if we attempt to reload the 1681 * zone. 1682 */ 1683 dns_name_format(&mx.mx, namebuf, sizeof(namebuf)); 1684 dns_name_format(&t->name, ownerbuf, sizeof(ownerbuf)); 1685 isaddress = ISC_FALSE; 1686 if ((options & DNS_RDATA_CHECKMX) != 0 && 1687 strlcpy(tmp, namebuf, sizeof(tmp)) < sizeof(tmp)) { 1688 if (tmp[strlen(tmp) - 1] == '.') 1689 tmp[strlen(tmp) - 1] = '\0'; 1690 if (inet_aton(tmp, &addr) == 1 || 1691 inet_pton(AF_INET6, tmp, &addr6) == 1) 1692 isaddress = ISC_TRUE; 1693 } 1694 1695 if (isaddress && (options & DNS_RDATA_CHECKMXFAIL) != 0) { 1696 update_log(client, zone, ISC_LOG_ERROR, 1697 "%s/MX: '%s': %s", 1698 ownerbuf, namebuf, 1699 dns_result_totext(DNS_R_MXISADDRESS)); 1700 ok = ISC_FALSE; 1701 } else if (isaddress) { 1702 update_log(client, zone, ISC_LOG_WARNING, 1703 "%s/MX: warning: '%s': %s", 1704 ownerbuf, namebuf, 1705 dns_result_totext(DNS_R_MXISADDRESS)); 1706 } 1707 1708 /* 1709 * Check zone integrity checks. 1710 */ 1711 if ((options & DNS_ZONEOPT_CHECKINTEGRITY) == 0) 1712 continue; 1713 result = dns_db_find(db, &mx.mx, newver, dns_rdatatype_a, 1714 0, 0, NULL, foundname, NULL, NULL); 1715 if (result == ISC_R_SUCCESS) 1716 continue; 1717 1718 if (result == DNS_R_NXRRSET) { 1719 result = dns_db_find(db, &mx.mx, newver, 1720 dns_rdatatype_aaaa, 1721 0, 0, NULL, foundname, 1722 NULL, NULL); 1723 if (result == ISC_R_SUCCESS) 1724 continue; 1725 } 1726 1727 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN) { 1728 update_log(client, zone, ISC_LOG_ERROR, 1729 "%s/MX '%s' has no address records " 1730 "(A or AAAA)", ownerbuf, namebuf); 1731 ok = ISC_FALSE; 1732 } else if (result == DNS_R_CNAME) { 1733 update_log(client, zone, ISC_LOG_ERROR, 1734 "%s/MX '%s' is a CNAME (illegal)", 1735 ownerbuf, namebuf); 1736 ok = ISC_FALSE; 1737 } else if (result == DNS_R_DNAME) { 1738 dns_name_format(foundname, altbuf, sizeof altbuf); 1739 update_log(client, zone, ISC_LOG_ERROR, 1740 "%s/MX '%s' is below a DNAME '%s' (illegal)", 1741 ownerbuf, namebuf, altbuf); 1742 ok = ISC_FALSE; 1743 } 1744 } 1745 return (ok ? ISC_R_SUCCESS : DNS_R_REFUSED); 1746} 1747 1748static isc_result_t 1749rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, 1750 const dns_rdata_t *rdata, isc_boolean_t *flag) 1751{ 1752 dns_rdataset_t rdataset; 1753 dns_dbnode_t *node = NULL; 1754 isc_result_t result; 1755 1756 dns_rdataset_init(&rdataset); 1757 if (rdata->type == dns_rdatatype_nsec3) 1758 CHECK(dns_db_findnsec3node(db, name, ISC_FALSE, &node)); 1759 else 1760 CHECK(dns_db_findnode(db, name, ISC_FALSE, &node)); 1761 result = dns_db_findrdataset(db, node, ver, rdata->type, 0, 1762 (isc_stdtime_t) 0, &rdataset, NULL); 1763 if (result == ISC_R_NOTFOUND) { 1764 *flag = ISC_FALSE; 1765 result = ISC_R_SUCCESS; 1766 goto failure; 1767 } 1768 1769 for (result = dns_rdataset_first(&rdataset); 1770 result == ISC_R_SUCCESS; 1771 result = dns_rdataset_next(&rdataset)) { 1772 dns_rdata_t myrdata = DNS_RDATA_INIT; 1773 dns_rdataset_current(&rdataset, &myrdata); 1774 if (!dns_rdata_casecompare(&myrdata, rdata)) 1775 break; 1776 } 1777 dns_rdataset_disassociate(&rdataset); 1778 if (result == ISC_R_SUCCESS) { 1779 *flag = ISC_TRUE; 1780 } else if (result == ISC_R_NOMORE) { 1781 *flag = ISC_FALSE; 1782 result = ISC_R_SUCCESS; 1783 } 1784 1785 failure: 1786 if (node != NULL) 1787 dns_db_detachnode(db, &node); 1788 return (result); 1789} 1790 1791static isc_result_t 1792get_iterations(dns_db_t *db, dns_dbversion_t *ver, dns_rdatatype_t privatetype, 1793 unsigned int *iterationsp) 1794{ 1795 dns_dbnode_t *node = NULL; 1796 dns_rdata_nsec3param_t nsec3param; 1797 dns_rdataset_t rdataset; 1798 isc_result_t result; 1799 unsigned int iterations = 0; 1800 1801 dns_rdataset_init(&rdataset); 1802 1803 result = dns_db_getoriginnode(db, &node); 1804 if (result != ISC_R_SUCCESS) 1805 return (result); 1806 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param, 1807 0, (isc_stdtime_t) 0, &rdataset, NULL); 1808 if (result == ISC_R_NOTFOUND) 1809 goto try_private; 1810 if (result != ISC_R_SUCCESS) 1811 goto failure; 1812 1813 for (result = dns_rdataset_first(&rdataset); 1814 result == ISC_R_SUCCESS; 1815 result = dns_rdataset_next(&rdataset)) { 1816 dns_rdata_t rdata = DNS_RDATA_INIT; 1817 dns_rdataset_current(&rdataset, &rdata); 1818 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL)); 1819 if ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) 1820 continue; 1821 if (nsec3param.iterations > iterations) 1822 iterations = nsec3param.iterations; 1823 } 1824 if (result != ISC_R_NOMORE) 1825 goto failure; 1826 1827 dns_rdataset_disassociate(&rdataset); 1828 1829 try_private: 1830 if (privatetype == 0) 1831 goto success; 1832 1833 result = dns_db_findrdataset(db, node, ver, privatetype, 1834 0, (isc_stdtime_t) 0, &rdataset, NULL); 1835 if (result == ISC_R_NOTFOUND) 1836 goto success; 1837 if (result != ISC_R_SUCCESS) 1838 goto failure; 1839 1840 for (result = dns_rdataset_first(&rdataset); 1841 result == ISC_R_SUCCESS; 1842 result = dns_rdataset_next(&rdataset)) { 1843 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE]; 1844 dns_rdata_t private = DNS_RDATA_INIT; 1845 dns_rdata_t rdata = DNS_RDATA_INIT; 1846 1847 dns_rdataset_current(&rdataset, &rdata); 1848 if (!dns_nsec3param_fromprivate(&private, &rdata, 1849 buf, sizeof(buf))) 1850 continue; 1851 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL)); 1852 if ((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) 1853 continue; 1854 if (nsec3param.iterations > iterations) 1855 iterations = nsec3param.iterations; 1856 } 1857 if (result != ISC_R_NOMORE) 1858 goto failure; 1859 1860 success: 1861 *iterationsp = iterations; 1862 result = ISC_R_SUCCESS; 1863 1864 failure: 1865 if (node != NULL) 1866 dns_db_detachnode(db, &node); 1867 if (dns_rdataset_isassociated(&rdataset)) 1868 dns_rdataset_disassociate(&rdataset); 1869 return (result); 1870} 1871 1872/* 1873 * Prevent the zone entering a inconsistent state where 1874 * NSEC only DNSKEYs are present with NSEC3 chains. 1875 */ 1876static isc_result_t 1877check_dnssec(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, 1878 dns_dbversion_t *ver, dns_diff_t *diff) 1879{ 1880 dns_difftuple_t *tuple; 1881 isc_boolean_t nseconly = ISC_FALSE, nsec3 = ISC_FALSE; 1882 isc_result_t result; 1883 unsigned int iterations = 0, max; 1884 dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone); 1885 1886 /* Scan the tuples for an NSEC-only DNSKEY or an NSEC3PARAM */ 1887 for (tuple = ISC_LIST_HEAD(diff->tuples); 1888 tuple != NULL; 1889 tuple = ISC_LIST_NEXT(tuple, link)) { 1890 if (tuple->op != DNS_DIFFOP_ADD) 1891 continue; 1892 1893 if (tuple->rdata.type == dns_rdatatype_dnskey) { 1894 isc_uint8_t alg; 1895 alg = tuple->rdata.data[3]; 1896 if (alg == DST_ALG_RSAMD5 || alg == DST_ALG_RSASHA1 || 1897 alg == DST_ALG_DSA || alg == DST_ALG_ECC) { 1898 nseconly = ISC_TRUE; 1899 break; 1900 } 1901 } else if (tuple->rdata.type == dns_rdatatype_nsec3param) { 1902 nsec3 = ISC_TRUE; 1903 break; 1904 } 1905 } 1906 1907 /* Check existing DB for NSEC-only DNSKEY */ 1908 if (!nseconly) { 1909 result = dns_nsec_nseconly(db, ver, &nseconly); 1910 1911 /* 1912 * An NSEC3PARAM update can proceed without a DNSKEY (it 1913 * will trigger a delayed change), so we can ignore 1914 * ISC_R_NOTFOUND here. 1915 */ 1916 if (result == ISC_R_NOTFOUND) 1917 result = ISC_R_SUCCESS; 1918 1919 CHECK(result); 1920 } 1921 1922 /* Check existing DB for NSEC3 */ 1923 if (!nsec3) 1924 CHECK(dns_nsec3_activex(db, ver, ISC_FALSE, 1925 privatetype, &nsec3)); 1926 1927 /* Refuse to allow NSEC3 with NSEC-only keys */ 1928 if (nseconly && nsec3) { 1929 update_log(client, zone, ISC_LOG_ERROR, 1930 "NSEC only DNSKEYs and NSEC3 chains not allowed"); 1931 result = DNS_R_REFUSED; 1932 goto failure; 1933 } 1934 1935 /* Verify NSEC3 params */ 1936 CHECK(get_iterations(db, ver, privatetype, &iterations)); 1937 CHECK(dns_nsec3_maxiterations(db, ver, client->mctx, &max)); 1938 if (max != 0 && iterations > max) { 1939 update_log(client, zone, ISC_LOG_ERROR, 1940 "too many NSEC3 iterations (%u) for " 1941 "weakest DNSKEY (%u)", iterations, max); 1942 result = DNS_R_REFUSED; 1943 goto failure; 1944 } 1945 1946 failure: 1947 return (result); 1948} 1949 1950/* 1951 * Delay NSEC3PARAM changes as they need to be applied to the whole zone. 1952 */ 1953static isc_result_t 1954add_nsec3param_records(ns_client_t *client, dns_zone_t *zone, dns_db_t *db, 1955 dns_dbversion_t *ver, dns_diff_t *diff) 1956{ 1957 isc_result_t result = ISC_R_SUCCESS; 1958 dns_difftuple_t *tuple, *newtuple = NULL, *next; 1959 dns_rdata_t rdata = DNS_RDATA_INIT; 1960 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE + 1]; 1961 dns_diff_t temp_diff; 1962 dns_diffop_t op; 1963 isc_boolean_t flag; 1964 dns_name_t *name = dns_zone_getorigin(zone); 1965 dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone); 1966 isc_uint32_t ttl = 0; 1967 isc_boolean_t ttl_good = ISC_FALSE; 1968 1969 update_log(client, zone, ISC_LOG_DEBUG(3), 1970 "checking for NSEC3PARAM changes"); 1971 1972 dns_diff_init(diff->mctx, &temp_diff); 1973 1974 /* 1975 * Extract NSEC3PARAM tuples from list. 1976 */ 1977 for (tuple = ISC_LIST_HEAD(diff->tuples); 1978 tuple != NULL; 1979 tuple = next) { 1980 1981 next = ISC_LIST_NEXT(tuple, link); 1982 1983 if (tuple->rdata.type != dns_rdatatype_nsec3param || 1984 !dns_name_equal(name, &tuple->name)) 1985 continue; 1986 ISC_LIST_UNLINK(diff->tuples, tuple, link); 1987 ISC_LIST_APPEND(temp_diff.tuples, tuple, link); 1988 } 1989 1990 /* 1991 * Extract TTL changes pairs, we don't need to convert these to 1992 * delayed changes. 1993 */ 1994 for (tuple = ISC_LIST_HEAD(temp_diff.tuples); 1995 tuple != NULL; tuple = next) { 1996 if (tuple->op == DNS_DIFFOP_ADD) { 1997 if (!ttl_good) { 1998 /* 1999 * Any adds here will contain the final 2000 * NSEC3PARAM RRset TTL. 2001 */ 2002 ttl = tuple->ttl; 2003 ttl_good = ISC_TRUE; 2004 } 2005 /* 2006 * Walk the temp_diff list looking for the 2007 * corresponding delete. 2008 */ 2009 next = ISC_LIST_HEAD(temp_diff.tuples); 2010 while (next != NULL) { 2011 unsigned char *next_data = next->rdata.data; 2012 unsigned char *tuple_data = tuple->rdata.data; 2013 if (next->op == DNS_DIFFOP_DEL && 2014 next->rdata.length == tuple->rdata.length && 2015 !memcmp(next_data, tuple_data, 2016 next->rdata.length)) { 2017 ISC_LIST_UNLINK(temp_diff.tuples, next, 2018 link); 2019 ISC_LIST_APPEND(diff->tuples, next, 2020 link); 2021 break; 2022 } 2023 next = ISC_LIST_NEXT(next, link); 2024 } 2025 /* 2026 * If we have not found a pair move onto the next 2027 * tuple. 2028 */ 2029 if (next == NULL) { 2030 next = ISC_LIST_NEXT(tuple, link); 2031 continue; 2032 } 2033 /* 2034 * Find the next tuple to be processed before 2035 * unlinking then complete moving the pair to 'diff'. 2036 */ 2037 next = ISC_LIST_NEXT(tuple, link); 2038 ISC_LIST_UNLINK(temp_diff.tuples, tuple, link); 2039 ISC_LIST_APPEND(diff->tuples, tuple, link); 2040 } else 2041 next = ISC_LIST_NEXT(tuple, link); 2042 } 2043 2044 /* 2045 * Preserve any ongoing changes from a BIND 9.6.x upgrade. 2046 * 2047 * Any NSEC3PARAM records with flags other than OPTOUT named 2048 * in managing and should not be touched so revert such changes 2049 * taking into account any TTL change of the NSEC3PARAM RRset. 2050 */ 2051 for (tuple = ISC_LIST_HEAD(temp_diff.tuples); 2052 tuple != NULL; tuple = next) { 2053 next = ISC_LIST_NEXT(tuple, link); 2054 if ((tuple->rdata.data[1] & ~DNS_NSEC3FLAG_OPTOUT) != 0) { 2055 /* 2056 * If we havn't had any adds then the tuple->ttl must 2057 * be the original ttl and should be used for any 2058 * future changes. 2059 */ 2060 if (!ttl_good) { 2061 ttl = tuple->ttl; 2062 ttl_good = ISC_TRUE; 2063 } 2064 op = (tuple->op == DNS_DIFFOP_DEL) ? 2065 DNS_DIFFOP_ADD : DNS_DIFFOP_DEL; 2066 CHECK(dns_difftuple_create(diff->mctx, op, name, 2067 ttl, &tuple->rdata, 2068 &newtuple)); 2069 CHECK(do_one_tuple(&newtuple, db, ver, diff)); 2070 ISC_LIST_UNLINK(temp_diff.tuples, tuple, link); 2071 dns_diff_appendminimal(diff, &tuple); 2072 } 2073 } 2074 2075 /* 2076 * We now have just the actual changes to the NSEC3PARAM RRset. 2077 * Convert the adds to delayed adds and the deletions into delayed 2078 * deletions. 2079 */ 2080 for (tuple = ISC_LIST_HEAD(temp_diff.tuples); 2081 tuple != NULL; tuple = next) { 2082 /* 2083 * If we havn't had any adds then the tuple->ttl must be the 2084 * original ttl and should be used for any future changes. 2085 */ 2086 if (!ttl_good) { 2087 ttl = tuple->ttl; 2088 ttl_good = ISC_TRUE; 2089 } 2090 if (tuple->op == DNS_DIFFOP_ADD) { 2091 isc_boolean_t nseconly = ISC_FALSE; 2092 2093 /* 2094 * Look for any deletes which match this ADD ignoring 2095 * flags. We don't need to explictly remove them as 2096 * they will be removed a side effect of processing 2097 * the add. 2098 */ 2099 next = ISC_LIST_HEAD(temp_diff.tuples); 2100 while (next != NULL) { 2101 unsigned char *next_data = next->rdata.data; 2102 unsigned char *tuple_data = tuple->rdata.data; 2103 if (next->op != DNS_DIFFOP_DEL || 2104 next->rdata.length != tuple->rdata.length || 2105 next_data[0] != tuple_data[0] || 2106 next_data[2] != tuple_data[2] || 2107 next_data[3] != tuple_data[3] || 2108 memcmp(next_data + 4, tuple_data + 4, 2109 tuple->rdata.length - 4)) { 2110 next = ISC_LIST_NEXT(next, link); 2111 continue; 2112 } 2113 ISC_LIST_UNLINK(temp_diff.tuples, next, link); 2114 ISC_LIST_APPEND(diff->tuples, next, link); 2115 next = ISC_LIST_HEAD(temp_diff.tuples); 2116 } 2117 2118 /* 2119 * Create a private-type record to signal that 2120 * we want a delayed NSEC3 chain add/delete 2121 */ 2122 dns_nsec3param_toprivate(&tuple->rdata, &rdata, 2123 privatetype, buf, sizeof(buf)); 2124 buf[2] |= DNS_NSEC3FLAG_CREATE; 2125 2126 /* 2127 * If the zone is not currently capable of 2128 * supporting an NSEC3 chain, then we set the 2129 * INITIAL flag to indicate that these parameters 2130 * are to be used later. 2131 */ 2132 result = dns_nsec_nseconly(db, ver, &nseconly); 2133 if (result == ISC_R_NOTFOUND || nseconly) 2134 buf[2] |= DNS_NSEC3FLAG_INITIAL; 2135 2136 /* 2137 * See if this CREATE request already exists. 2138 */ 2139 CHECK(rr_exists(db, ver, name, &rdata, &flag)); 2140 2141 if (!flag) { 2142 CHECK(dns_difftuple_create(diff->mctx, 2143 DNS_DIFFOP_ADD, 2144 name, 0, &rdata, 2145 &newtuple)); 2146 CHECK(do_one_tuple(&newtuple, db, ver, diff)); 2147 } 2148 2149 /* 2150 * Remove any existing CREATE request to add an 2151 * otherwise indentical chain with a reversed 2152 * OPTOUT state. 2153 */ 2154 buf[2] ^= DNS_NSEC3FLAG_OPTOUT; 2155 CHECK(rr_exists(db, ver, name, &rdata, &flag)); 2156 2157 if (flag) { 2158 CHECK(dns_difftuple_create(diff->mctx, 2159 DNS_DIFFOP_DEL, 2160 name, 0, &rdata, 2161 &newtuple)); 2162 CHECK(do_one_tuple(&newtuple, db, ver, diff)); 2163 } 2164 2165 /* 2166 * Find the next tuple to be processed and remove the 2167 * temporary add record. 2168 */ 2169 next = ISC_LIST_NEXT(tuple, link); 2170 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, 2171 name, ttl, &tuple->rdata, 2172 &newtuple)); 2173 CHECK(do_one_tuple(&newtuple, db, ver, diff)); 2174 ISC_LIST_UNLINK(temp_diff.tuples, tuple, link); 2175 dns_diff_appendminimal(diff, &tuple); 2176 dns_rdata_reset(&rdata); 2177 } else 2178 next = ISC_LIST_NEXT(tuple, link); 2179 } 2180 2181 for (tuple = ISC_LIST_HEAD(temp_diff.tuples); 2182 tuple != NULL; tuple = next) { 2183 2184 INSIST(ttl_good); 2185 2186 next = ISC_LIST_NEXT(tuple, link); 2187 /* 2188 * See if we already have a REMOVE request in progress. 2189 */ 2190 dns_nsec3param_toprivate(&tuple->rdata, &rdata, privatetype, 2191 buf, sizeof(buf)); 2192 2193 buf[2] |= DNS_NSEC3FLAG_REMOVE | DNS_NSEC3FLAG_NONSEC; 2194 2195 CHECK(rr_exists(db, ver, name, &rdata, &flag)); 2196 if (!flag) { 2197 buf[2] &= ~DNS_NSEC3FLAG_NONSEC; 2198 CHECK(rr_exists(db, ver, name, &rdata, &flag)); 2199 } 2200 2201 if (!flag) { 2202 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, 2203 name, 0, &rdata, &newtuple)); 2204 CHECK(do_one_tuple(&newtuple, db, ver, diff)); 2205 } 2206 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, name, 2207 ttl, &tuple->rdata, &newtuple)); 2208 CHECK(do_one_tuple(&newtuple, db, ver, diff)); 2209 ISC_LIST_UNLINK(temp_diff.tuples, tuple, link); 2210 dns_diff_appendminimal(diff, &tuple); 2211 dns_rdata_reset(&rdata); 2212 } 2213 2214 result = ISC_R_SUCCESS; 2215 failure: 2216 dns_diff_clear(&temp_diff); 2217 return (result); 2218} 2219 2220static isc_result_t 2221rollback_private(dns_db_t *db, dns_rdatatype_t privatetype, 2222 dns_dbversion_t *ver, dns_diff_t *diff) 2223{ 2224 dns_diff_t temp_diff; 2225 dns_diffop_t op; 2226 dns_difftuple_t *tuple, *newtuple = NULL, *next; 2227 dns_name_t *name = dns_db_origin(db); 2228 isc_mem_t *mctx = diff->mctx; 2229 isc_result_t result; 2230 2231 if (privatetype == 0) 2232 return (ISC_R_SUCCESS); 2233 2234 dns_diff_init(mctx, &temp_diff); 2235 2236 /* 2237 * Extract the changes to be rolled back. 2238 */ 2239 for (tuple = ISC_LIST_HEAD(diff->tuples); 2240 tuple != NULL; tuple = next) { 2241 2242 next = ISC_LIST_NEXT(tuple, link); 2243 2244 if (tuple->rdata.type != privatetype || 2245 !dns_name_equal(name, &tuple->name)) 2246 continue; 2247 2248 /* 2249 * Allow records which indicate that a zone has been 2250 * signed with a DNSKEY to be removed. 2251 */ 2252 if (tuple->op == DNS_DIFFOP_DEL && 2253 tuple->rdata.length == 5 && 2254 tuple->rdata.data[0] != 0 && 2255 tuple->rdata.data[4] != 0) 2256 continue; 2257 2258 ISC_LIST_UNLINK(diff->tuples, tuple, link); 2259 ISC_LIST_PREPEND(temp_diff.tuples, tuple, link); 2260 } 2261 2262 /* 2263 * Rollback the changes. 2264 */ 2265 while ((tuple = ISC_LIST_HEAD(temp_diff.tuples)) != NULL) { 2266 op = (tuple->op == DNS_DIFFOP_DEL) ? 2267 DNS_DIFFOP_ADD : DNS_DIFFOP_DEL; 2268 CHECK(dns_difftuple_create(mctx, op, name, tuple->ttl, 2269 &tuple->rdata, &newtuple)); 2270 CHECK(do_one_tuple(&newtuple, db, ver, &temp_diff)); 2271 } 2272 result = ISC_R_SUCCESS; 2273 2274 failure: 2275 dns_diff_clear(&temp_diff); 2276 return (result); 2277} 2278 2279/* 2280 * Add records to cause the delayed signing of the zone by added DNSKEY 2281 * to remove the RRSIG records generated by a deleted DNSKEY. 2282 */ 2283static isc_result_t 2284add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype, 2285 dns_dbversion_t *ver, dns_diff_t *diff) 2286{ 2287 dns_difftuple_t *tuple, *newtuple = NULL, *next; 2288 dns_rdata_dnskey_t dnskey; 2289 dns_rdata_t rdata = DNS_RDATA_INIT; 2290 isc_boolean_t flag; 2291 isc_region_t r; 2292 isc_result_t result = ISC_R_SUCCESS; 2293 isc_uint16_t keyid; 2294 unsigned char buf[5]; 2295 dns_name_t *name = dns_db_origin(db); 2296 dns_diff_t temp_diff; 2297 2298 dns_diff_init(diff->mctx, &temp_diff); 2299 2300 /* 2301 * Extract the DNSKEY tuples from the list. 2302 */ 2303 for (tuple = ISC_LIST_HEAD(diff->tuples); 2304 tuple != NULL; tuple = next) { 2305 2306 next = ISC_LIST_NEXT(tuple, link); 2307 2308 if (tuple->rdata.type != dns_rdatatype_dnskey) 2309 continue; 2310 2311 ISC_LIST_UNLINK(diff->tuples, tuple, link); 2312 ISC_LIST_APPEND(temp_diff.tuples, tuple, link); 2313 } 2314 2315 /* 2316 * Extract TTL changes pairs, we don't need signing records for these. 2317 */ 2318 for (tuple = ISC_LIST_HEAD(temp_diff.tuples); 2319 tuple != NULL; tuple = next) { 2320 if (tuple->op == DNS_DIFFOP_ADD) { 2321 /* 2322 * Walk the temp_diff list looking for the 2323 * corresponding delete. 2324 */ 2325 next = ISC_LIST_HEAD(temp_diff.tuples); 2326 while (next != NULL) { 2327 unsigned char *next_data = next->rdata.data; 2328 unsigned char *tuple_data = tuple->rdata.data; 2329 if (next->op == DNS_DIFFOP_DEL && 2330 dns_name_equal(&tuple->name, &next->name) && 2331 next->rdata.length == tuple->rdata.length && 2332 !memcmp(next_data, tuple_data, 2333 next->rdata.length)) { 2334 ISC_LIST_UNLINK(temp_diff.tuples, next, 2335 link); 2336 ISC_LIST_APPEND(diff->tuples, next, 2337 link); 2338 break; 2339 } 2340 next = ISC_LIST_NEXT(next, link); 2341 } 2342 /* 2343 * If we have not found a pair move onto the next 2344 * tuple. 2345 */ 2346 if (next == NULL) { 2347 next = ISC_LIST_NEXT(tuple, link); 2348 continue; 2349 } 2350 /* 2351 * Find the next tuple to be processed before 2352 * unlinking then complete moving the pair to 'diff'. 2353 */ 2354 next = ISC_LIST_NEXT(tuple, link); 2355 ISC_LIST_UNLINK(temp_diff.tuples, tuple, link); 2356 ISC_LIST_APPEND(diff->tuples, tuple, link); 2357 } else 2358 next = ISC_LIST_NEXT(tuple, link); 2359 } 2360 2361 /* 2362 * Process the remaining DNSKEY entries. 2363 */ 2364 for (tuple = ISC_LIST_HEAD(temp_diff.tuples); 2365 tuple != NULL; 2366 tuple = ISC_LIST_HEAD(temp_diff.tuples)) { 2367 2368 ISC_LIST_UNLINK(temp_diff.tuples, tuple, link); 2369 ISC_LIST_APPEND(diff->tuples, tuple, link); 2370 2371 result = dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL); 2372 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2373 if ((dnskey.flags & 2374 (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH)) 2375 != DNS_KEYOWNER_ZONE) 2376 continue; 2377 2378 dns_rdata_toregion(&tuple->rdata, &r); 2379 2380 keyid = dst_region_computeid(&r, dnskey.algorithm); 2381 2382 buf[0] = dnskey.algorithm; 2383 buf[1] = (keyid & 0xff00) >> 8; 2384 buf[2] = (keyid & 0xff); 2385 buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1; 2386 buf[4] = 0; 2387 rdata.data = buf; 2388 rdata.length = sizeof(buf); 2389 rdata.type = privatetype; 2390 rdata.rdclass = tuple->rdata.rdclass; 2391 2392 CHECK(rr_exists(db, ver, name, &rdata, &flag)); 2393 if (flag) 2394 continue; 2395 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD, 2396 name, 0, &rdata, &newtuple)); 2397 CHECK(do_one_tuple(&newtuple, db, ver, diff)); 2398 INSIST(newtuple == NULL); 2399 /* 2400 * Remove any record which says this operation has already 2401 * completed. 2402 */ 2403 buf[4] = 1; 2404 CHECK(rr_exists(db, ver, name, &rdata, &flag)); 2405 if (flag) { 2406 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, 2407 name, 0, &rdata, &newtuple)); 2408 CHECK(do_one_tuple(&newtuple, db, ver, diff)); 2409 INSIST(newtuple == NULL); 2410 } 2411 } 2412 2413 failure: 2414 dns_diff_clear(&temp_diff); 2415 return (result); 2416} 2417 2418static isc_boolean_t 2419isdnssec(dns_db_t *db, dns_dbversion_t *ver, dns_rdatatype_t privatetype) { 2420 isc_result_t result; 2421 isc_boolean_t build_nsec, build_nsec3; 2422 2423 if (dns_db_issecure(db)) 2424 return (ISC_TRUE); 2425 2426 result = dns_private_chains(db, ver, privatetype, 2427 &build_nsec, &build_nsec3); 2428 RUNTIME_CHECK(result == ISC_R_SUCCESS); 2429 return (build_nsec || build_nsec3); 2430} 2431 2432static void 2433update_action(isc_task_t *task, isc_event_t *event) { 2434 update_event_t *uev = (update_event_t *) event; 2435 dns_zone_t *zone = uev->zone; 2436 ns_client_t *client = (ns_client_t *)event->ev_arg; 2437 2438 isc_result_t result; 2439 dns_db_t *db = NULL; 2440 dns_dbversion_t *oldver = NULL; 2441 dns_dbversion_t *ver = NULL; 2442 dns_diff_t diff; /* Pending updates. */ 2443 dns_diff_t temp; /* Pending RR existence assertions. */ 2444 isc_boolean_t soa_serial_changed = ISC_FALSE; 2445 isc_mem_t *mctx = client->mctx; 2446 dns_rdatatype_t covers; 2447 dns_message_t *request = client->message; 2448 dns_rdataclass_t zoneclass; 2449 dns_name_t *zonename; 2450 dns_ssutable_t *ssutable = NULL; 2451 dns_fixedname_t tmpnamefixed; 2452 dns_name_t *tmpname = NULL; 2453 unsigned int options; 2454 dns_difftuple_t *tuple; 2455 dns_rdata_dnskey_t dnskey; 2456 isc_boolean_t had_dnskey; 2457 dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone); 2458 2459 INSIST(event->ev_type == DNS_EVENT_UPDATE); 2460 2461 dns_diff_init(mctx, &diff); 2462 dns_diff_init(mctx, &temp); 2463 2464 CHECK(dns_zone_getdb(zone, &db)); 2465 zonename = dns_db_origin(db); 2466 zoneclass = dns_db_class(db); 2467 dns_zone_getssutable(zone, &ssutable); 2468 2469 /* 2470 * Update message processing can leak record existance information 2471 * so check that we are allowed to query this zone. Additionally 2472 * if we would refuse all updates for this zone we bail out here. 2473 */ 2474 CHECK(checkqueryacl(client, dns_zone_getqueryacl(zone), zonename, 2475 dns_zone_getupdateacl(zone), ssutable)); 2476 2477 /* 2478 * Get old and new versions now that queryacl has been checked. 2479 */ 2480 dns_db_currentversion(db, &oldver); 2481 CHECK(dns_db_newversion(db, &ver)); 2482 2483 /* 2484 * Check prerequisites. 2485 */ 2486 2487 for (result = dns_message_firstname(request, DNS_SECTION_PREREQUISITE); 2488 result == ISC_R_SUCCESS; 2489 result = dns_message_nextname(request, DNS_SECTION_PREREQUISITE)) 2490 { 2491 dns_name_t *name = NULL; 2492 dns_rdata_t rdata = DNS_RDATA_INIT; 2493 dns_ttl_t ttl; 2494 dns_rdataclass_t update_class; 2495 isc_boolean_t flag; 2496 2497 get_current_rr(request, DNS_SECTION_PREREQUISITE, zoneclass, 2498 &name, &rdata, &covers, &ttl, &update_class); 2499 2500 if (ttl != 0) 2501 PREREQFAILC(DNS_R_FORMERR, 2502 "prerequisite TTL is not zero"); 2503 2504 if (! dns_name_issubdomain(name, zonename)) 2505 PREREQFAILN(DNS_R_NOTZONE, name, 2506 "prerequisite name is out of zone"); 2507 2508 if (update_class == dns_rdataclass_any) { 2509 if (rdata.length != 0) 2510 PREREQFAILC(DNS_R_FORMERR, 2511 "class ANY prerequisite " 2512 "RDATA is not empty"); 2513 if (rdata.type == dns_rdatatype_any) { 2514 CHECK(name_exists(db, ver, name, &flag)); 2515 if (! flag) { 2516 PREREQFAILN(DNS_R_NXDOMAIN, name, 2517 "'name in use' " 2518 "prerequisite not " 2519 "satisfied"); 2520 } 2521 } else { 2522 CHECK(rrset_exists(db, ver, name, 2523 rdata.type, covers, &flag)); 2524 if (! flag) { 2525 /* RRset does not exist. */ 2526 PREREQFAILNT(DNS_R_NXRRSET, name, rdata.type, 2527 "'rrset exists (value independent)' " 2528 "prerequisite not satisfied"); 2529 } 2530 } 2531 } else if (update_class == dns_rdataclass_none) { 2532 if (rdata.length != 0) 2533 PREREQFAILC(DNS_R_FORMERR, 2534 "class NONE prerequisite " 2535 "RDATA is not empty"); 2536 if (rdata.type == dns_rdatatype_any) { 2537 CHECK(name_exists(db, ver, name, &flag)); 2538 if (flag) { 2539 PREREQFAILN(DNS_R_YXDOMAIN, name, 2540 "'name not in use' " 2541 "prerequisite not " 2542 "satisfied"); 2543 } 2544 } else { 2545 CHECK(rrset_exists(db, ver, name, 2546 rdata.type, covers, &flag)); 2547 if (flag) { 2548 /* RRset exists. */ 2549 PREREQFAILNT(DNS_R_YXRRSET, name, 2550 rdata.type, 2551 "'rrset does not exist' " 2552 "prerequisite not " 2553 "satisfied"); 2554 } 2555 } 2556 } else if (update_class == zoneclass) { 2557 /* "temp<rr.name, rr.type> += rr;" */ 2558 result = temp_append(&temp, name, &rdata); 2559 if (result != ISC_R_SUCCESS) { 2560 UNEXPECTED_ERROR(__FILE__, __LINE__, 2561 "temp entry creation failed: %s", 2562 dns_result_totext(result)); 2563 FAIL(ISC_R_UNEXPECTED); 2564 } 2565 } else { 2566 PREREQFAILC(DNS_R_FORMERR, "malformed prerequisite"); 2567 } 2568 } 2569 if (result != ISC_R_NOMORE) 2570 FAIL(result); 2571 2572 /* 2573 * Perform the final check of the "rrset exists (value dependent)" 2574 * prerequisites. 2575 */ 2576 if (ISC_LIST_HEAD(temp.tuples) != NULL) { 2577 dns_rdatatype_t type; 2578 2579 /* 2580 * Sort the prerequisite records by owner name, 2581 * type, and rdata. 2582 */ 2583 result = dns_diff_sort(&temp, temp_order); 2584 if (result != ISC_R_SUCCESS) 2585 FAILC(result, "'RRset exists (value dependent)' " 2586 "prerequisite not satisfied"); 2587 2588 dns_fixedname_init(&tmpnamefixed); 2589 tmpname = dns_fixedname_name(&tmpnamefixed); 2590 result = temp_check(mctx, &temp, db, ver, tmpname, &type); 2591 if (result != ISC_R_SUCCESS) 2592 FAILNT(result, tmpname, type, 2593 "'RRset exists (value dependent)' " 2594 "prerequisite not satisfied"); 2595 } 2596 2597 update_log(client, zone, LOGLEVEL_DEBUG, 2598 "prerequisites are OK"); 2599 2600 /* 2601 * Check Requestor's Permissions. It seems a bit silly to do this 2602 * only after prerequisite testing, but that is what RFC2136 says. 2603 */ 2604 if (ssutable == NULL) 2605 CHECK(checkupdateacl(client, dns_zone_getupdateacl(zone), 2606 "update", zonename, ISC_FALSE, ISC_FALSE)); 2607 else if (client->signer == NULL && !TCPCLIENT(client)) 2608 CHECK(checkupdateacl(client, NULL, "update", zonename, 2609 ISC_FALSE, ISC_TRUE)); 2610 2611 if (dns_zone_getupdatedisabled(zone)) 2612 FAILC(DNS_R_REFUSED, "dynamic update temporarily disabled " 2613 "because the zone is frozen. Use " 2614 "'rndc thaw' to re-enable updates."); 2615 2616 /* 2617 * Perform the Update Section Prescan. 2618 */ 2619 2620 for (result = dns_message_firstname(request, DNS_SECTION_UPDATE); 2621 result == ISC_R_SUCCESS; 2622 result = dns_message_nextname(request, DNS_SECTION_UPDATE)) 2623 { 2624 dns_name_t *name = NULL; 2625 dns_rdata_t rdata = DNS_RDATA_INIT; 2626 dns_ttl_t ttl; 2627 dns_rdataclass_t update_class; 2628 get_current_rr(request, DNS_SECTION_UPDATE, zoneclass, 2629 &name, &rdata, &covers, &ttl, &update_class); 2630 2631 if (! dns_name_issubdomain(name, zonename)) 2632 FAILC(DNS_R_NOTZONE, 2633 "update RR is outside zone"); 2634 if (update_class == zoneclass) { 2635 /* 2636 * Check for meta-RRs. The RFC2136 pseudocode says 2637 * check for ANY|AXFR|MAILA|MAILB, but the text adds 2638 * "or any other QUERY metatype" 2639 */ 2640 if (dns_rdatatype_ismeta(rdata.type)) { 2641 FAILC(DNS_R_FORMERR, 2642 "meta-RR in update"); 2643 } 2644 result = dns_zone_checknames(zone, name, &rdata); 2645 if (result != ISC_R_SUCCESS) 2646 FAIL(DNS_R_REFUSED); 2647 } else if (update_class == dns_rdataclass_any) { 2648 if (ttl != 0 || rdata.length != 0 || 2649 (dns_rdatatype_ismeta(rdata.type) && 2650 rdata.type != dns_rdatatype_any)) 2651 FAILC(DNS_R_FORMERR, 2652 "meta-RR in update"); 2653 } else if (update_class == dns_rdataclass_none) { 2654 if (ttl != 0 || 2655 dns_rdatatype_ismeta(rdata.type)) 2656 FAILC(DNS_R_FORMERR, 2657 "meta-RR in update"); 2658 } else { 2659 update_log(client, zone, ISC_LOG_WARNING, 2660 "update RR has incorrect class %d", 2661 update_class); 2662 FAIL(DNS_R_FORMERR); 2663 } 2664 2665 /* 2666 * draft-ietf-dnsind-simple-secure-update-01 says 2667 * "Unlike traditional dynamic update, the client 2668 * is forbidden from updating NSEC records." 2669 */ 2670 if (rdata.type == dns_rdatatype_nsec3) { 2671 FAILC(DNS_R_REFUSED, 2672 "explicit NSEC3 updates are not allowed " 2673 "in secure zones"); 2674 } else if (rdata.type == dns_rdatatype_nsec) { 2675 FAILC(DNS_R_REFUSED, 2676 "explicit NSEC updates are not allowed " 2677 "in secure zones"); 2678 } else if (rdata.type == dns_rdatatype_rrsig && 2679 !dns_name_equal(name, zonename)) { 2680 FAILC(DNS_R_REFUSED, 2681 "explicit RRSIG updates are currently " 2682 "not supported in secure zones except " 2683 "at the apex"); 2684 } 2685 2686 if (ssutable != NULL) { 2687 isc_netaddr_t *tcpaddr, netaddr; 2688 dst_key_t *tsigkey = NULL; 2689 /* 2690 * If this is a TCP connection then pass the 2691 * address of the client through for tcp-self 2692 * and 6to4-self otherwise pass NULL. This 2693 * provides weak address based authentication. 2694 */ 2695 if (TCPCLIENT(client)) { 2696 isc_netaddr_fromsockaddr(&netaddr, 2697 &client->peeraddr); 2698 tcpaddr = &netaddr; 2699 } else 2700 tcpaddr = NULL; 2701 2702 if (client->message->tsigkey != NULL) 2703 tsigkey = client->message->tsigkey->key; 2704 2705 if (rdata.type != dns_rdatatype_any) { 2706 if (!dns_ssutable_checkrules(ssutable, 2707 client->signer, 2708 name, tcpaddr, 2709 rdata.type, 2710 tsigkey)) 2711 FAILC(DNS_R_REFUSED, 2712 "rejected by secure update"); 2713 } else { 2714 if (!ssu_checkall(db, ver, name, ssutable, 2715 client->signer, tcpaddr, 2716 tsigkey)) 2717 FAILC(DNS_R_REFUSED, 2718 "rejected by secure update"); 2719 } 2720 } 2721 } 2722 if (result != ISC_R_NOMORE) 2723 FAIL(result); 2724 2725 update_log(client, zone, LOGLEVEL_DEBUG, 2726 "update section prescan OK"); 2727 2728 /* 2729 * Process the Update Section. 2730 */ 2731 2732 options = dns_zone_getoptions(zone); 2733 for (result = dns_message_firstname(request, DNS_SECTION_UPDATE); 2734 result == ISC_R_SUCCESS; 2735 result = dns_message_nextname(request, DNS_SECTION_UPDATE)) 2736 { 2737 dns_name_t *name = NULL; 2738 dns_rdata_t rdata = DNS_RDATA_INIT; 2739 dns_ttl_t ttl; 2740 dns_rdataclass_t update_class; 2741 isc_boolean_t flag; 2742 2743 get_current_rr(request, DNS_SECTION_UPDATE, zoneclass, 2744 &name, &rdata, &covers, &ttl, &update_class); 2745 2746 if (update_class == zoneclass) { 2747 2748 /* 2749 * RFC1123 doesn't allow MF and MD in master zones. */ 2750 if (rdata.type == dns_rdatatype_md || 2751 rdata.type == dns_rdatatype_mf) { 2752 char typebuf[DNS_RDATATYPE_FORMATSIZE]; 2753 2754 dns_rdatatype_format(rdata.type, typebuf, 2755 sizeof(typebuf)); 2756 update_log(client, zone, LOGLEVEL_PROTOCOL, 2757 "attempt to add %s ignored", 2758 typebuf); 2759 continue; 2760 } 2761 if ((rdata.type == dns_rdatatype_ns || 2762 rdata.type == dns_rdatatype_dname) && 2763 dns_name_iswildcard(name)) { 2764 char typebuf[DNS_RDATATYPE_FORMATSIZE]; 2765 2766 dns_rdatatype_format(rdata.type, typebuf, 2767 sizeof(typebuf)); 2768 update_log(client, zone, 2769 LOGLEVEL_PROTOCOL, 2770 "attempt to add wildcard %s record " 2771 "ignored", typebuf); 2772 continue; 2773 } 2774 if (rdata.type == dns_rdatatype_cname) { 2775 CHECK(cname_incompatible_rrset_exists(db, ver, 2776 name, 2777 &flag)); 2778 if (flag) { 2779 update_log(client, zone, 2780 LOGLEVEL_PROTOCOL, 2781 "attempt to add CNAME " 2782 "alongside non-CNAME " 2783 "ignored"); 2784 continue; 2785 } 2786 } else { 2787 CHECK(rrset_exists(db, ver, name, 2788 dns_rdatatype_cname, 0, 2789 &flag)); 2790 if (flag && 2791 ! dns_rdatatype_isdnssec(rdata.type)) 2792 { 2793 update_log(client, zone, 2794 LOGLEVEL_PROTOCOL, 2795 "attempt to add non-CNAME " 2796 "alongside CNAME ignored"); 2797 continue; 2798 } 2799 } 2800 if (rdata.type == dns_rdatatype_soa) { 2801 isc_boolean_t ok; 2802 CHECK(rrset_exists(db, ver, name, 2803 dns_rdatatype_soa, 0, 2804 &flag)); 2805 if (! flag) { 2806 update_log(client, zone, 2807 LOGLEVEL_PROTOCOL, 2808 "attempt to create 2nd " 2809 "SOA ignored"); 2810 continue; 2811 } 2812 CHECK(check_soa_increment(db, ver, &rdata, 2813 &ok)); 2814 if (! ok) { 2815 update_log(client, zone, 2816 LOGLEVEL_PROTOCOL, 2817 "SOA update failed to " 2818 "increment serial, " 2819 "ignoring it"); 2820 continue; 2821 } 2822 soa_serial_changed = ISC_TRUE; 2823 } 2824 2825 if (rdata.type == privatetype) { 2826 update_log(client, zone, LOGLEVEL_PROTOCOL, 2827 "attempt to add a private type " 2828 "(%u) record rejected internal " 2829 "use only", privatetype); 2830 continue; 2831 } 2832 2833 if (rdata.type == dns_rdatatype_nsec3param) { 2834 /* 2835 * Ignore attempts to add NSEC3PARAM records 2836 * with any flags other than OPTOUT. 2837 */ 2838 if ((rdata.data[1] & ~DNS_NSEC3FLAG_OPTOUT) != 0) { 2839 update_log(client, zone, 2840 LOGLEVEL_PROTOCOL, 2841 "attempt to add NSEC3PARAM " 2842 "record with non OPTOUT " 2843 "flag"); 2844 continue; 2845 } 2846 } 2847 2848 if ((options & DNS_ZONEOPT_CHECKWILDCARD) != 0 && 2849 dns_name_internalwildcard(name)) { 2850 char namestr[DNS_NAME_FORMATSIZE]; 2851 dns_name_format(name, namestr, 2852 sizeof(namestr)); 2853 update_log(client, zone, LOGLEVEL_PROTOCOL, 2854 "warning: ownername '%s' contains " 2855 "a non-terminal wildcard", namestr); 2856 } 2857 2858 if (isc_log_wouldlog(ns_g_lctx, LOGLEVEL_PROTOCOL)) { 2859 char namestr[DNS_NAME_FORMATSIZE]; 2860 char typestr[DNS_RDATATYPE_FORMATSIZE]; 2861 dns_name_format(name, namestr, 2862 sizeof(namestr)); 2863 dns_rdatatype_format(rdata.type, typestr, 2864 sizeof(typestr)); 2865 update_log(client, zone, LOGLEVEL_PROTOCOL, 2866 "adding an RR at '%s' %s", 2867 namestr, typestr); 2868 } 2869 2870 /* Prepare the affected RRset for the addition. */ 2871 { 2872 add_rr_prepare_ctx_t ctx; 2873 ctx.db = db; 2874 ctx.ver = ver; 2875 ctx.diff = &diff; 2876 ctx.name = name; 2877 ctx.update_rr = &rdata; 2878 ctx.update_rr_ttl = ttl; 2879 ctx.ignore_add = ISC_FALSE; 2880 dns_diff_init(mctx, &ctx.del_diff); 2881 dns_diff_init(mctx, &ctx.add_diff); 2882 CHECK(foreach_rr(db, ver, name, rdata.type, 2883 covers, add_rr_prepare_action, 2884 &ctx)); 2885 2886 if (ctx.ignore_add) { 2887 dns_diff_clear(&ctx.del_diff); 2888 dns_diff_clear(&ctx.add_diff); 2889 } else { 2890 CHECK(do_diff(&ctx.del_diff, db, ver, 2891 &diff)); 2892 CHECK(do_diff(&ctx.add_diff, db, ver, 2893 &diff)); 2894 CHECK(update_one_rr(db, ver, &diff, 2895 DNS_DIFFOP_ADD, 2896 name, ttl, &rdata)); 2897 } 2898 } 2899 } else if (update_class == dns_rdataclass_any) { 2900 if (rdata.type == dns_rdatatype_any) { 2901 if (isc_log_wouldlog(ns_g_lctx, 2902 LOGLEVEL_PROTOCOL)) 2903 { 2904 char namestr[DNS_NAME_FORMATSIZE]; 2905 dns_name_format(name, namestr, 2906 sizeof(namestr)); 2907 update_log(client, zone, 2908 LOGLEVEL_PROTOCOL, 2909 "delete all rrsets from " 2910 "name '%s'", namestr); 2911 } 2912 if (dns_name_equal(name, zonename)) { 2913 CHECK(delete_if(type_not_soa_nor_ns_p, 2914 db, ver, name, 2915 dns_rdatatype_any, 0, 2916 &rdata, &diff)); 2917 } else { 2918 CHECK(delete_if(type_not_dnssec, 2919 db, ver, name, 2920 dns_rdatatype_any, 0, 2921 &rdata, &diff)); 2922 } 2923 } else if (dns_name_equal(name, zonename) && 2924 (rdata.type == dns_rdatatype_soa || 2925 rdata.type == dns_rdatatype_ns)) { 2926 update_log(client, zone, LOGLEVEL_PROTOCOL, 2927 "attempt to delete all SOA " 2928 "or NS records ignored"); 2929 continue; 2930 } else { 2931 if (isc_log_wouldlog(ns_g_lctx, 2932 LOGLEVEL_PROTOCOL)) 2933 { 2934 char namestr[DNS_NAME_FORMATSIZE]; 2935 char typestr[DNS_RDATATYPE_FORMATSIZE]; 2936 dns_name_format(name, namestr, 2937 sizeof(namestr)); 2938 dns_rdatatype_format(rdata.type, 2939 typestr, 2940 sizeof(typestr)); 2941 update_log(client, zone, 2942 LOGLEVEL_PROTOCOL, 2943 "deleting rrset at '%s' %s", 2944 namestr, typestr); 2945 } 2946 CHECK(delete_if(true_p, db, ver, name, 2947 rdata.type, covers, &rdata, 2948 &diff)); 2949 } 2950 } else if (update_class == dns_rdataclass_none) { 2951 char namestr[DNS_NAME_FORMATSIZE]; 2952 char typestr[DNS_RDATATYPE_FORMATSIZE]; 2953 2954 /* 2955 * The (name == zonename) condition appears in 2956 * RFC2136 3.4.2.4 but is missing from the pseudocode. 2957 */ 2958 if (dns_name_equal(name, zonename)) { 2959 if (rdata.type == dns_rdatatype_soa) { 2960 update_log(client, zone, 2961 LOGLEVEL_PROTOCOL, 2962 "attempt to delete SOA " 2963 "ignored"); 2964 continue; 2965 } 2966 if (rdata.type == dns_rdatatype_ns) { 2967 int count; 2968 CHECK(rr_count(db, ver, name, 2969 dns_rdatatype_ns, 2970 0, &count)); 2971 if (count == 1) { 2972 update_log(client, zone, 2973 LOGLEVEL_PROTOCOL, 2974 "attempt to " 2975 "delete last " 2976 "NS ignored"); 2977 continue; 2978 } 2979 } 2980 } 2981 dns_name_format(name, namestr, sizeof(namestr)); 2982 dns_rdatatype_format(rdata.type, typestr, 2983 sizeof(typestr)); 2984 update_log(client, zone, LOGLEVEL_PROTOCOL, 2985 "deleting an RR at %s %s", namestr, typestr); 2986 CHECK(delete_if(rr_equal_p, db, ver, name, rdata.type, 2987 covers, &rdata, &diff)); 2988 } 2989 } 2990 if (result != ISC_R_NOMORE) 2991 FAIL(result); 2992 2993 /* 2994 * Check that any changes to DNSKEY/NSEC3PARAM records make sense. 2995 * If they don't then back out all changes to DNSKEY/NSEC3PARAM 2996 * records. 2997 */ 2998 if (! ISC_LIST_EMPTY(diff.tuples)) 2999 CHECK(check_dnssec(client, zone, db, ver, &diff)); 3000 3001 if (! ISC_LIST_EMPTY(diff.tuples)) { 3002 unsigned int errors = 0; 3003 CHECK(dns_zone_nscheck(zone, db, ver, &errors)); 3004 if (errors != 0) { 3005 update_log(client, zone, LOGLEVEL_PROTOCOL, 3006 "update rejected: post update name server " 3007 "sanity check failed"); 3008 result = DNS_R_REFUSED; 3009 goto failure; 3010 } 3011 } 3012 3013 /* 3014 * If any changes were made, increment the SOA serial number, 3015 * update RRSIGs and NSECs (if zone is secure), and write the update 3016 * to the journal. 3017 */ 3018 if (! ISC_LIST_EMPTY(diff.tuples)) { 3019 char *journalfile; 3020 dns_journal_t *journal; 3021 isc_boolean_t has_dnskey; 3022 3023 /* 3024 * Increment the SOA serial, but only if it was not 3025 * changed as a result of an update operation. 3026 */ 3027 if (! soa_serial_changed) { 3028 CHECK(update_soa_serial(db, ver, &diff, mctx, 3029 dns_zone_getserialupdatemethod(zone))); 3030 } 3031 3032 CHECK(check_mx(client, zone, db, ver, &diff)); 3033 3034 CHECK(remove_orphaned_ds(db, ver, &diff)); 3035 3036 CHECK(rrset_exists(db, ver, zonename, dns_rdatatype_dnskey, 3037 0, &has_dnskey)); 3038 3039#define ALLOW_SECURE_TO_INSECURE(zone) \ 3040 ((dns_zone_getoptions(zone) & DNS_ZONEOPT_SECURETOINSECURE) != 0) 3041 3042 if (!ALLOW_SECURE_TO_INSECURE(zone)) { 3043 CHECK(rrset_exists(db, oldver, zonename, 3044 dns_rdatatype_dnskey, 0, 3045 &had_dnskey)); 3046 if (had_dnskey && !has_dnskey) { 3047 update_log(client, zone, LOGLEVEL_PROTOCOL, 3048 "update rejected: all DNSKEY " 3049 "records removed and " 3050 "'dnssec-secure-to-insecure' " 3051 "not set"); 3052 result = DNS_R_REFUSED; 3053 goto failure; 3054 } 3055 } 3056 3057 CHECK(rollback_private(db, privatetype, ver, &diff)); 3058 3059 CHECK(add_signing_records(db, privatetype, ver, &diff)); 3060 3061 CHECK(add_nsec3param_records(client, zone, db, ver, &diff)); 3062 3063 if (had_dnskey && !has_dnskey) { 3064 /* 3065 * We are transitioning from secure to insecure. 3066 * Cause all NSEC3 chains to be deleted. When the 3067 * the last signature for the DNSKEY records are 3068 * remove any NSEC chain present will also be removed. 3069 */ 3070 CHECK(dns_nsec3param_deletechains(db, ver, zone, 3071 ISC_TRUE, &diff)); 3072 } else if (has_dnskey && isdnssec(db, ver, privatetype)) { 3073 isc_uint32_t interval; 3074 dns_update_log_t log; 3075 3076 interval = dns_zone_getsigvalidityinterval(zone); 3077 log.func = update_log_cb; 3078 log.arg = client; 3079 result = dns_update_signatures(&log, zone, db, oldver, 3080 ver, &diff, interval); 3081 3082 if (result != ISC_R_SUCCESS) { 3083 update_log(client, zone, 3084 ISC_LOG_ERROR, 3085 "RRSIG/NSEC/NSEC3 update failed: %s", 3086 isc_result_totext(result)); 3087 goto failure; 3088 } 3089 } 3090 3091 journalfile = dns_zone_getjournal(zone); 3092 if (journalfile != NULL) { 3093 update_log(client, zone, LOGLEVEL_DEBUG, 3094 "writing journal %s", journalfile); 3095 3096 journal = NULL; 3097 result = dns_journal_open(mctx, journalfile, 3098 DNS_JOURNAL_CREATE, &journal); 3099 if (result != ISC_R_SUCCESS) 3100 FAILS(result, "journal open failed"); 3101 3102 result = dns_journal_write_transaction(journal, &diff); 3103 if (result != ISC_R_SUCCESS) { 3104 dns_journal_destroy(&journal); 3105 FAILS(result, "journal write failed"); 3106 } 3107 3108 dns_journal_destroy(&journal); 3109 } 3110 3111 /* 3112 * XXXRTH Just a note that this committing code will have 3113 * to change to handle databases that need two-phase 3114 * commit, but this isn't a priority. 3115 */ 3116 update_log(client, zone, LOGLEVEL_DEBUG, 3117 "committing update transaction"); 3118 3119 dns_db_closeversion(db, &ver, ISC_TRUE); 3120 3121 /* 3122 * Mark the zone as dirty so that it will be written to disk. 3123 */ 3124 dns_zone_markdirty(zone); 3125 3126 /* 3127 * Notify slaves of the change we just made. 3128 */ 3129 dns_zone_notify(zone); 3130 3131 /* 3132 * Cause the zone to be signed with the key that we 3133 * have just added or have the corresponding signatures 3134 * deleted. 3135 * 3136 * Note: we are already committed to this course of action. 3137 */ 3138 for (tuple = ISC_LIST_HEAD(diff.tuples); 3139 tuple != NULL; 3140 tuple = ISC_LIST_NEXT(tuple, link)) { 3141 isc_region_t r; 3142 dns_secalg_t algorithm; 3143 isc_uint16_t keyid; 3144 3145 if (tuple->rdata.type != dns_rdatatype_dnskey) 3146 continue; 3147 3148 dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL); 3149 if ((dnskey.flags & 3150 (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH)) 3151 != DNS_KEYOWNER_ZONE) 3152 continue; 3153 3154 dns_rdata_toregion(&tuple->rdata, &r); 3155 algorithm = dnskey.algorithm; 3156 keyid = dst_region_computeid(&r, algorithm); 3157 3158 result = dns_zone_signwithkey(zone, algorithm, keyid, 3159 ISC_TF(tuple->op == DNS_DIFFOP_DEL)); 3160 if (result != ISC_R_SUCCESS) { 3161 update_log(client, zone, ISC_LOG_ERROR, 3162 "dns_zone_signwithkey failed: %s", 3163 dns_result_totext(result)); 3164 } 3165 } 3166 3167 /* 3168 * Cause the zone to add/delete NSEC3 chains for the 3169 * deferred NSEC3PARAM changes. 3170 * 3171 * Note: we are already committed to this course of action. 3172 */ 3173 for (tuple = ISC_LIST_HEAD(diff.tuples); 3174 tuple != NULL; 3175 tuple = ISC_LIST_NEXT(tuple, link)) { 3176 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE]; 3177 dns_rdata_t rdata = DNS_RDATA_INIT; 3178 dns_rdata_nsec3param_t nsec3param; 3179 3180 if (tuple->rdata.type != privatetype || 3181 tuple->op != DNS_DIFFOP_ADD) 3182 continue; 3183 3184 if (!dns_nsec3param_fromprivate(&tuple->rdata, &rdata, 3185 buf, sizeof(buf))) 3186 continue; 3187 dns_rdata_tostruct(&rdata, &nsec3param, NULL); 3188 if (nsec3param.flags == 0) 3189 continue; 3190 3191 result = dns_zone_addnsec3chain(zone, &nsec3param); 3192 if (result != ISC_R_SUCCESS) { 3193 update_log(client, zone, ISC_LOG_ERROR, 3194 "dns_zone_addnsec3chain failed: %s", 3195 dns_result_totext(result)); 3196 } 3197 } 3198 } else { 3199 update_log(client, zone, LOGLEVEL_DEBUG, "redundant request"); 3200 dns_db_closeversion(db, &ver, ISC_TRUE); 3201 } 3202 result = ISC_R_SUCCESS; 3203 goto common; 3204 3205 failure: 3206 /* 3207 * The reason for failure should have been logged at this point. 3208 */ 3209 if (ver != NULL) { 3210 update_log(client, zone, LOGLEVEL_DEBUG, 3211 "rolling back"); 3212 dns_db_closeversion(db, &ver, ISC_FALSE); 3213 } 3214 3215 common: 3216 dns_diff_clear(&temp); 3217 dns_diff_clear(&diff); 3218 3219 if (oldver != NULL) 3220 dns_db_closeversion(db, &oldver, ISC_FALSE); 3221 3222 if (db != NULL) 3223 dns_db_detach(&db); 3224 3225 if (ssutable != NULL) 3226 dns_ssutable_detach(&ssutable); 3227 3228 isc_task_detach(&task); 3229 uev->result = result; 3230 if (zone != NULL) 3231 INSIST(uev->zone == zone); /* we use this later */ 3232 uev->ev_type = DNS_EVENT_UPDATEDONE; 3233 uev->ev_action = updatedone_action; 3234 isc_task_send(client->task, &event); 3235 INSIST(event == NULL); 3236} 3237 3238static void 3239updatedone_action(isc_task_t *task, isc_event_t *event) { 3240 update_event_t *uev = (update_event_t *) event; 3241 ns_client_t *client = (ns_client_t *) event->ev_arg; 3242 3243 UNUSED(task); 3244 3245 INSIST(event->ev_type == DNS_EVENT_UPDATEDONE); 3246 INSIST(task == client->task); 3247 3248 INSIST(client->nupdates > 0); 3249 switch (uev->result) { 3250 case ISC_R_SUCCESS: 3251 inc_stats(uev->zone, dns_nsstatscounter_updatedone); 3252 break; 3253 case DNS_R_REFUSED: 3254 inc_stats(uev->zone, dns_nsstatscounter_updaterej); 3255 break; 3256 default: 3257 inc_stats(uev->zone, dns_nsstatscounter_updatefail); 3258 break; 3259 } 3260 if (uev->zone != NULL) 3261 dns_zone_detach(&uev->zone); 3262 client->nupdates--; 3263 respond(client, uev->result); 3264 isc_event_free(&event); 3265 ns_client_detach(&client); 3266} 3267 3268/*% 3269 * Update forwarding support. 3270 */ 3271 3272static void 3273forward_fail(isc_task_t *task, isc_event_t *event) { 3274 ns_client_t *client = (ns_client_t *)event->ev_arg; 3275 3276 UNUSED(task); 3277 3278 INSIST(client->nupdates > 0); 3279 client->nupdates--; 3280 respond(client, DNS_R_SERVFAIL); 3281 isc_event_free(&event); 3282 ns_client_detach(&client); 3283} 3284 3285 3286static void 3287forward_callback(void *arg, isc_result_t result, dns_message_t *answer) { 3288 update_event_t *uev = arg; 3289 ns_client_t *client = uev->ev_arg; 3290 dns_zone_t *zone = uev->zone; 3291 3292 if (result != ISC_R_SUCCESS) { 3293 INSIST(answer == NULL); 3294 uev->ev_type = DNS_EVENT_UPDATEDONE; 3295 uev->ev_action = forward_fail; 3296 inc_stats(zone, dns_nsstatscounter_updatefwdfail); 3297 } else { 3298 uev->ev_type = DNS_EVENT_UPDATEDONE; 3299 uev->ev_action = forward_done; 3300 uev->answer = answer; 3301 inc_stats(zone, dns_nsstatscounter_updaterespfwd); 3302 } 3303 isc_task_send(client->task, ISC_EVENT_PTR(&uev)); 3304 dns_zone_detach(&zone); 3305} 3306 3307static void 3308forward_done(isc_task_t *task, isc_event_t *event) { 3309 update_event_t *uev = (update_event_t *) event; 3310 ns_client_t *client = (ns_client_t *)event->ev_arg; 3311 3312 UNUSED(task); 3313 3314 INSIST(client->nupdates > 0); 3315 client->nupdates--; 3316 ns_client_sendraw(client, uev->answer); 3317 dns_message_destroy(&uev->answer); 3318 isc_event_free(&event); 3319 ns_client_detach(&client); 3320} 3321 3322static void 3323forward_action(isc_task_t *task, isc_event_t *event) { 3324 update_event_t *uev = (update_event_t *) event; 3325 dns_zone_t *zone = uev->zone; 3326 ns_client_t *client = (ns_client_t *)event->ev_arg; 3327 isc_result_t result; 3328 3329 result = dns_zone_forwardupdate(zone, client->message, 3330 forward_callback, event); 3331 if (result != ISC_R_SUCCESS) { 3332 uev->ev_type = DNS_EVENT_UPDATEDONE; 3333 uev->ev_action = forward_fail; 3334 isc_task_send(client->task, &event); 3335 inc_stats(zone, dns_nsstatscounter_updatefwdfail); 3336 dns_zone_detach(&zone); 3337 } else 3338 inc_stats(zone, dns_nsstatscounter_updatereqfwd); 3339 isc_task_detach(&task); 3340} 3341 3342static isc_result_t 3343send_forward_event(ns_client_t *client, dns_zone_t *zone) { 3344 char namebuf[DNS_NAME_FORMATSIZE]; 3345 char classbuf[DNS_RDATACLASS_FORMATSIZE]; 3346 isc_result_t result = ISC_R_SUCCESS; 3347 update_event_t *event = NULL; 3348 isc_task_t *zonetask = NULL; 3349 ns_client_t *evclient; 3350 3351 /* 3352 * This may take some time so replace this client. 3353 */ 3354 if (!client->mortal && (client->attributes & NS_CLIENTATTR_TCP) == 0) 3355 CHECK(ns_client_replace(client)); 3356 3357 event = (update_event_t *) 3358 isc_event_allocate(client->mctx, client, DNS_EVENT_UPDATE, 3359 forward_action, NULL, sizeof(*event)); 3360 if (event == NULL) 3361 FAIL(ISC_R_NOMEMORY); 3362 event->zone = zone; 3363 event->result = ISC_R_SUCCESS; 3364 3365 evclient = NULL; 3366 ns_client_attach(client, &evclient); 3367 INSIST(client->nupdates == 0); 3368 client->nupdates++; 3369 event->ev_arg = evclient; 3370 3371 dns_name_format(dns_zone_getorigin(zone), namebuf, 3372 sizeof(namebuf)); 3373 dns_rdataclass_format(dns_zone_getclass(zone), classbuf, 3374 sizeof(classbuf)); 3375 3376 ns_client_log(client, NS_LOGCATEGORY_UPDATE, NS_LOGMODULE_UPDATE, 3377 LOGLEVEL_PROTOCOL, "forwarding update for zone '%s/%s'", 3378 namebuf, classbuf); 3379 3380 dns_zone_gettask(zone, &zonetask); 3381 isc_task_send(zonetask, ISC_EVENT_PTR(&event)); 3382 3383 failure: 3384 if (event != NULL) 3385 isc_event_free(ISC_EVENT_PTR(&event)); 3386 return (result); 3387} 3388