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