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