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