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