OpenDNSSEC-signer
1.3.8
|
00001 /* 00002 * $Id: zone.c 6244 2012-04-03 13:56:27Z matthijs $ 00003 * 00004 * Copyright (c) 2009 NLNet Labs. All rights reserved. 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions 00008 * are met: 00009 * 1. Redistributions of source code must retain the above copyright 00010 * notice, this list of conditions and the following disclaimer. 00011 * 2. Redistributions in binary form must reproduce the above copyright 00012 * notice, this list of conditions and the following disclaimer in the 00013 * documentation and/or other materials provided with the distribution. 00014 * 00015 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 00016 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00017 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00018 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 00019 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00020 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 00021 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00022 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 00023 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 00024 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 00025 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00026 * 00027 */ 00028 00034 #include "adapter/adapi.h" 00035 #include "adapter/adapter.h" 00036 #include "scheduler/schedule.h" 00037 #include "scheduler/task.h" 00038 #include "shared/allocator.h" 00039 #include "shared/file.h" 00040 #include "shared/hsm.h" 00041 #include "shared/locks.h" 00042 #include "shared/log.h" 00043 #include "shared/status.h" 00044 #include "shared/util.h" 00045 #include "signer/backup.h" 00046 #include "signer/nsec3params.h" 00047 #include "signer/signconf.h" 00048 #include "signer/zone.h" 00049 #include "signer/zonedata.h" 00050 00051 #include <ldns/ldns.h> 00052 00053 static const char* zone_str = "zone"; 00054 00055 00060 zone_type* 00061 zone_create(char* name, ldns_rr_class klass) 00062 { 00063 allocator_type* allocator = NULL; 00064 zone_type* zone = NULL; 00065 00066 if (!name || !klass) { 00067 ods_log_error("[%s] unable to create zone: no name or class", 00068 zone_str); 00069 return NULL; 00070 } 00071 00072 allocator = allocator_create(malloc, free); 00073 if (!allocator) { 00074 ods_log_error("[%s] unable to create zone %s: create allocator " 00075 "failed", zone_str, name); 00076 return NULL; 00077 } 00078 ods_log_assert(allocator); 00079 00080 zone = (zone_type*) allocator_alloc(allocator, sizeof(zone_type)); 00081 if (!zone) { 00082 ods_log_error("[%s] unable to create zone %s: allocator failed", 00083 zone_str, name); 00084 allocator_cleanup(allocator); 00085 return NULL; 00086 } 00087 ods_log_assert(zone); 00088 00089 zone->allocator = allocator; 00090 /* [start] PS 9218653: Drop trailing dot in domain name */ 00091 if (strlen(name) > 1 && name[strlen(name)-1] == '.') { 00092 name[strlen(name)-1] = '\0'; 00093 } 00094 /* [end] PS 9218653 */ 00095 zone->name = allocator_strdup(allocator, name); 00096 zone->klass = klass; 00097 00098 zone->dname = ldns_dname_new_frm_str(name); 00099 ldns_dname2canonical(zone->dname); 00100 zone->notify_ns = NULL; 00101 zone->policy_name = NULL; 00102 zone->signconf_filename = NULL; 00103 00104 zone->adinbound = NULL; 00105 zone->adoutbound = NULL; 00106 zone->nsec3params = NULL; 00107 00108 zone->just_added = 0; 00109 zone->just_updated = 0; 00110 zone->tobe_removed = 0; 00111 zone->processed = 0; 00112 zone->prepared = 0; 00113 zone->fetch = 0; 00114 00115 zone->zonedata = zonedata_create(zone->allocator); 00116 if (!zone->zonedata) { 00117 ods_log_error("[%s] unable to create zone %s: create zonedata " 00118 "failed", zone_str, name); 00119 zone_cleanup(zone); 00120 return NULL; 00121 } 00122 00123 zone->signconf = signconf_create(); 00124 if (!zone->signconf) { 00125 ods_log_error("[%s] unable to create zone %s: create signconf " 00126 "failed", zone_str, name); 00127 zone_cleanup(zone); 00128 return NULL; 00129 } 00130 00131 zone->stats = stats_create(); 00132 zone->task = NULL; 00133 lock_basic_init(&zone->zone_lock); 00134 return zone; 00135 } 00136 00137 00142 ods_status 00143 zone_add_rr(zone_type* zone, ldns_rr* rr, int do_stats) 00144 { 00145 domain_type* domain = NULL; 00146 rrset_type* rrset = NULL; 00147 ldns_rdf* soa_min = NULL; 00148 ldns_rr_type type = LDNS_RR_TYPE_FIRST; 00149 uint32_t tmp = 0; 00150 00151 if (!rr) { 00152 ods_log_error("[%s] unable to add RR: no RR", zone_str); 00153 return ODS_STATUS_ASSERT_ERR; 00154 } 00155 ods_log_assert(rr); 00156 00157 if (!zone || !zone->zonedata) { 00158 ods_log_error("[%s] unable to add RR: no storage", zone_str); 00159 return ODS_STATUS_ASSERT_ERR; 00160 } 00161 ods_log_assert(zone); 00162 ods_log_assert(zone->zonedata); 00163 00164 if (!zone->signconf) { 00165 ods_log_error("[%s] unable to add RR: no signconf", zone_str); 00166 return ODS_STATUS_ASSERT_ERR; 00167 } 00168 ods_log_assert(zone->signconf); 00169 00170 /* in-zone? */ 00171 if (ldns_dname_compare(zone->dname, ldns_rr_owner(rr)) != 0 && 00172 !ldns_dname_is_subdomain(ldns_rr_owner(rr), zone->dname)) { 00173 ods_log_warning("[%s] zone %s contains out-of-zone data, skipping", 00174 zone_str, zone->name?zone->name:"(null)"); 00175 /* ok, just filter */ 00176 ldns_rr_free(rr); 00177 return ODS_STATUS_OK; 00178 } 00179 00180 /* type specific configuration */ 00181 type = ldns_rr_get_type(rr); 00182 if (type == LDNS_RR_TYPE_DNSKEY && zone->signconf->dnskey_ttl) { 00183 tmp = (uint32_t) duration2time(zone->signconf->dnskey_ttl); 00184 ods_log_verbose("[%s] zone %s set DNSKEY TTL to %u", 00185 zone_str, zone->name?zone->name:"(null)", tmp); 00186 ldns_rr_set_ttl(rr, tmp); 00187 } 00188 if (type == LDNS_RR_TYPE_SOA) { 00189 if (zone->signconf->soa_ttl) { 00190 tmp = (uint32_t) duration2time(zone->signconf->soa_ttl); 00191 ods_log_verbose("[%s] zone %s set SOA TTL to %u", 00192 zone_str, zone->name?zone->name:"(null)", tmp); 00193 ldns_rr_set_ttl(rr, tmp); 00194 } 00195 if (zone->signconf->soa_min) { 00196 tmp = (uint32_t) duration2time(zone->signconf->soa_min); 00197 ods_log_verbose("[%s] zone %s set SOA MINIMUM to %u", 00198 zone_str, zone->name?zone->name:"(null)", tmp); 00199 soa_min = ldns_rr_set_rdf(rr, 00200 ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, tmp), 00201 SE_SOA_RDATA_MINIMUM); 00202 if (soa_min) { 00203 ldns_rdf_deep_free(soa_min); 00204 } else { 00205 ods_log_error("[%s] zone %s failed to replace SOA MINIMUM " 00206 "rdata", zone_str, zone->name?zone->name:"(null)"); 00207 return ODS_STATUS_ASSERT_ERR; 00208 } 00209 } 00210 } 00211 00212 /* lookup domain */ 00213 domain = zonedata_lookup_domain(zone->zonedata, ldns_rr_owner(rr)); 00214 if (!domain) { 00215 /* add domain */ 00216 domain = domain_create(ldns_rr_owner(rr)); 00217 if (!domain) { 00218 ods_log_error("[%s] unable to add RR: create domain failed", 00219 zone_str); 00220 return ODS_STATUS_ERR; 00221 } 00222 if (zonedata_add_domain(zone->zonedata, domain) == NULL) { 00223 ods_log_error("[%s] unable to add RR: add domain failed", 00224 zone_str); 00225 return ODS_STATUS_ERR; 00226 } 00227 if (ldns_dname_compare(domain->dname, zone->dname) == 0) { 00228 domain->dstatus = DOMAIN_STATUS_APEX; 00229 } 00230 } 00231 ods_log_assert(domain); 00232 00233 /* lookup RRset */ 00234 rrset = domain_lookup_rrset(domain, ldns_rr_get_type(rr)); 00235 if (!rrset) { 00236 /* add RRset */ 00237 rrset = rrset_create(ldns_rr_get_type(rr)); 00238 if (!rrset) { 00239 ods_log_error("[%s] unable to add RR: create RRset failed", 00240 zone_str); 00241 return ODS_STATUS_ERR; 00242 } 00243 if (domain_add_rrset(domain, rrset) == NULL) { 00244 ods_log_error("[%s] unable to add RR: add RRset failed", 00245 zone_str); 00246 return ODS_STATUS_ERR; 00247 } 00248 } 00249 ods_log_assert(rrset); 00250 00251 /* add RR */ 00252 if (rrset_add_rr(rrset, rr) == NULL) { 00253 ods_log_error("[%s] unable to add RR: pend RR failed", zone_str); 00254 return ODS_STATUS_ERR; 00255 } 00256 00257 /* update stats */ 00258 if (zone->stats && do_stats) { 00259 zone->stats->sort_count += 1; 00260 } 00261 return ODS_STATUS_OK; 00262 } 00263 00264 00269 ods_status 00270 zone_del_rr(zone_type* zone, ldns_rr* rr, int do_stats) 00271 { 00272 domain_type* domain = NULL; 00273 rrset_type* rrset = NULL; 00274 00275 if (!rr) { 00276 ods_log_error("[%s] unable to del RR: no RR", zone_str); 00277 return ODS_STATUS_ASSERT_ERR; 00278 } 00279 ods_log_assert(rr); 00280 00281 if (!zone || !zone->zonedata) { 00282 ods_log_error("[%s] unable to del RR: no storage", zone_str); 00283 return ODS_STATUS_ASSERT_ERR; 00284 } 00285 ods_log_assert(zone); 00286 ods_log_assert(zone->zonedata); 00287 00288 /* lookup domain */ 00289 domain = zonedata_lookup_domain(zone->zonedata, ldns_rr_owner(rr)); 00290 if (!domain) { 00291 /* no domain, no del */ 00292 ods_log_warning("[%s] unable to del RR: no such domain", zone_str); 00293 return ODS_STATUS_UNCHANGED; 00294 } 00295 ods_log_assert(domain); 00296 00297 /* lookup RRset */ 00298 rrset = domain_lookup_rrset(domain, ldns_rr_get_type(rr)); 00299 if (!rrset) { 00300 /* no RRset, no del */ 00301 ods_log_warning("[%s] unable to del RR: no such RRset", zone_str); 00302 return ODS_STATUS_UNCHANGED; 00303 } 00304 ods_log_assert(rrset); 00305 00306 /* del RR */ 00307 if (rrset_del_rr(rrset, rr, (ldns_rr_get_type(rr) == LDNS_RR_TYPE_DNSKEY)) 00308 == NULL) { 00309 ods_log_error("[%s] unable to del RR: pend RR failed", zone_str); 00310 return ODS_STATUS_ERR; 00311 } 00312 00313 /* update stats */ 00314 if (do_stats && zone->stats) { 00315 zone->stats->sort_count -= 1; 00316 } 00317 return ODS_STATUS_OK; 00318 } 00319 00320 00325 static ods_status 00326 dnskey_withdraw(zone_type* zone, ldns_rr_list* del) 00327 { 00328 ldns_rr* clone = NULL; 00329 ods_status status = ODS_STATUS_OK; 00330 size_t i = 0; 00331 00332 for (i=0; i < ldns_rr_list_rr_count(del); i++) { 00333 clone = ldns_rr_clone(ldns_rr_list_rr(del, i)); 00334 status = zone_del_rr(zone, clone, 0); 00335 if (status != ODS_STATUS_OK) { 00336 return status; 00337 } 00338 } 00339 return status; 00340 } 00341 00342 00347 static ods_status 00348 nsec3param_withdraw(zone_type* zone, ldns_rr* rr) 00349 { 00350 ldns_rr* clone = NULL; 00351 ods_status status = ODS_STATUS_OK; 00352 00353 if (!rr) { /* no nsec3param, nothing to withdraw */ 00354 return status; 00355 } 00356 clone = ldns_rr_clone(rr); 00357 status = zone_del_rr(zone, clone, 0); 00358 if (status != ODS_STATUS_OK) { 00359 return status; 00360 } 00361 return status; 00362 } 00363 00364 00369 ods_status 00370 zone_load_signconf(zone_type* zone, task_id* tbs) 00371 { 00372 ods_status status = ODS_STATUS_OK; 00373 signconf_type* signconf = NULL; 00374 ldns_rr_list* del = NULL; 00375 char* datestamp = NULL; 00376 uint32_t ustamp; 00377 task_id denial_what; 00378 task_id keys_what; 00379 task_id what; 00380 00381 if (!zone) { 00382 ods_log_error("[%s] unable to load signconf: no zone", zone_str); 00383 return ODS_STATUS_ASSERT_ERR; 00384 } 00385 ods_log_assert(zone); 00386 if (!zone->signconf_filename) { 00387 ods_log_warning("[%s] zone %s has no signconf filename, treat as " 00388 "insecure?", zone_str, zone->name); 00389 return ODS_STATUS_INSECURE; 00390 } 00391 ods_log_assert(zone->signconf_filename); 00392 00393 status = signconf_update(&signconf, zone->signconf_filename, 00394 zone->signconf->last_modified); 00395 if (status == ODS_STATUS_OK) { 00396 if (!signconf) { 00397 /* this is unexpected */ 00398 ods_log_error("[%s] unable to load signconf: zone %s signconf " 00399 "%s: storage empty", zone_str, zone->name, 00400 zone->signconf_filename); 00401 return ODS_STATUS_ASSERT_ERR; 00402 } 00403 ustamp = time_datestamp(signconf->last_modified, "%Y-%m-%d %T", 00404 &datestamp); 00405 ods_log_debug("[%s] zone %s signconf file %s is modified since %s", 00406 zone_str, zone->name, zone->signconf_filename, 00407 datestamp?datestamp:"Unknown"); 00408 free((void*)datestamp); 00409 00410 /* do stuff */ 00411 del = ldns_rr_list_new(); 00412 if (!del) { 00413 ods_log_error("[%s] unable to load signconf: zone %s " 00414 "signconf %s: ldns_rr_list_new() failed", 00415 zone_str, zone->name, zone->signconf_filename); 00416 return ODS_STATUS_MALLOC_ERR; 00417 } 00418 denial_what = signconf_compare_denial(zone->signconf, signconf); 00419 keys_what = signconf_compare_keys(zone->signconf, signconf, del); 00420 00421 /* Key Rollover? */ 00422 if (keys_what == TASK_READ) { 00423 status = dnskey_withdraw(zone, del); 00424 } 00425 ldns_rr_list_free(del); 00426 if (status != ODS_STATUS_OK) { 00427 ods_log_error("[%s] unable to load signconf: zone %s " 00428 "signconf %s: failed to delete DNSKEY from RRset", 00429 zone_str, zone->name, zone->signconf_filename); 00430 zonedata_rollback(zone->zonedata); 00431 return status; 00432 } 00433 00434 /* Denial of Existence Rollover? */ 00435 if (denial_what == TASK_NSECIFY) { 00436 status = ODS_STATUS_OK; 00437 if (denial_what == TASK_NSECIFY && zone->nsec3params) { 00438 status = nsec3param_withdraw(zone, zone->nsec3params->rr); 00439 } 00440 if (status != ODS_STATUS_OK) { 00441 ods_log_error("[%s] unable to load signconf: zone %s " 00442 "signconf %s: failed to delete NSEC3PARAM RRset", 00443 zone_str, zone->name, zone->signconf_filename); 00444 zonedata_rollback(zone->zonedata); 00445 return status; 00446 } 00447 /* or NSEC -> NSEC3, or NSEC3 -> NSEC, or NSEC3PARAM changed */ 00448 nsec3params_cleanup(zone->nsec3params); 00449 zone->nsec3params = NULL; 00450 /* all NSEC(3)s become invalid */ 00451 zonedata_wipe_denial(zone->zonedata); 00452 zonedata_cleanup_chain(zone->zonedata); 00453 zonedata_init_denial(zone->zonedata); 00454 } 00455 00456 /* all ok, switch to new signconf */ 00457 if (keys_what != TASK_NONE) { 00458 what = keys_what; 00459 } else { 00460 what = denial_what; 00461 } 00462 if (what == TASK_NONE) { /* no major changes, continue signing */ 00463 what = TASK_SIGN; 00464 } 00465 *tbs = what; 00466 ods_log_debug("[%s] tbs for zone %s set to: %s", zone_str, 00467 zone->name, task_what2str(*tbs)); 00468 signconf_cleanup(zone->signconf); 00469 ods_log_debug("[%s] zone %s switch to new signconf", zone_str, 00470 zone->name); 00471 zone->signconf = signconf; 00472 signconf_log(zone->signconf, zone->name); 00473 zone->zonedata->default_ttl = 00474 (uint32_t) duration2time(zone->signconf->soa_min); 00475 } else if (status == ODS_STATUS_UNCHANGED) { 00476 *tbs = TASK_READ; 00477 ods_log_debug("[%s] tbs for zone %s set to: %s", zone_str, 00478 zone->name, task_what2str(*tbs)); 00479 ustamp = time_datestamp(zone->signconf->last_modified, 00480 "%Y-%m-%d %T", &datestamp); 00481 ods_log_verbose("[%s] zone %s signconf file %s is unchanged since " 00482 "%s", zone_str, zone->name, zone->signconf_filename, 00483 datestamp?datestamp:"Unknown"); 00484 free((void*)datestamp); 00485 } else { 00486 ods_log_error("[%s] unable to load signconf: zone %s signconf %s: " 00487 "%s", zone_str, zone->name, zone->signconf_filename, 00488 ods_status2str(status)); 00489 } 00490 return status; 00491 } 00492 00493 00498 ods_status 00499 zone_publish_dnskeys(zone_type* zone, int recover) 00500 { 00501 hsm_ctx_t* ctx = NULL; 00502 key_type* key = NULL; 00503 uint32_t ttl = 0; 00504 size_t count = 0; 00505 ods_status status = ODS_STATUS_OK; 00506 ldns_rr* dnskey = NULL; 00507 int do_publish = 0; 00508 00509 if (!zone) { 00510 ods_log_error("[%s] unable to publish dnskeys: no zone", zone_str); 00511 return ODS_STATUS_ASSERT_ERR; 00512 } 00513 ods_log_assert(zone); 00514 00515 if (!zone->signconf) { 00516 ods_log_error("[%s] unable to publish dnskeys zone %s: no signconf", 00517 zone_str, zone->name); 00518 return ODS_STATUS_ASSERT_ERR; 00519 } 00520 ods_log_assert(zone->signconf); 00521 00522 if (!zone->signconf->keys) { 00523 ods_log_error("[%s] unable to publish dnskeys zone %s: no keys", 00524 zone_str, zone->name); 00525 return ODS_STATUS_ASSERT_ERR; 00526 } 00527 ods_log_assert(zone->signconf->keys); 00528 00529 if (!zone->zonedata) { 00530 ods_log_error("[%s] unable to publish dnskeys zone %s: no zonedata", 00531 zone_str, zone->name); 00532 return ODS_STATUS_ASSERT_ERR; 00533 } 00534 ods_log_assert(zone->zonedata); 00535 00536 ttl = zone->zonedata->default_ttl; 00537 if (zone->signconf->dnskey_ttl) { 00538 ttl = (uint32_t) duration2time(zone->signconf->dnskey_ttl); 00539 } 00540 00541 /* check connection here? */ 00542 ctx = hsm_create_context(); 00543 if (ctx == NULL) { 00544 ods_log_error("[%s] unable to publish dnskeys for zone %s: error " 00545 "creating libhsm context", zone_str, zone->name); 00546 return ODS_STATUS_HSM_ERR; 00547 } 00548 00549 key = zone->signconf->keys->first_key; 00550 for (count=0; count < zone->signconf->keys->count; count++) { 00551 if (key->publish) { 00552 do_publish = 0; 00553 if (!key->dnskey) { 00554 do_publish = 1; 00555 } 00556 00557 status = lhsm_get_key(ctx, zone->dname, key); 00558 if (status != ODS_STATUS_OK) { 00559 ods_log_error("[%s] unable to publish dnskeys zone %s: " 00560 "error creating DNSKEY for key %s", zone_str, 00561 zone->name, key->locator?key->locator:"(null)"); 00562 break; 00563 } 00564 ods_log_assert(key->dnskey); 00565 00566 if (recover) { 00567 dnskey = ldns_rr_clone(key->dnskey); 00568 status = zone_add_rr(zone, dnskey, 0); 00569 } else if (do_publish) { 00570 ldns_rr_set_ttl(key->dnskey, ttl); 00571 ldns_rr_set_class(key->dnskey, zone->klass); 00572 ldns_rr2canonical(key->dnskey); 00573 dnskey = ldns_rr_clone(key->dnskey); 00574 status = zone_add_rr(zone, dnskey, 0); 00575 } else { 00576 status = ODS_STATUS_OK; 00577 } 00578 00579 if (status != ODS_STATUS_OK) { 00580 ods_log_error("[%s] unable to publish dnskeys zone %s: " 00581 "error adding DNSKEY[%u] for key %s", zone_str, 00582 zone->name, ldns_calc_keytag(dnskey), 00583 key->locator?key->locator:"(null)"); 00584 break; 00585 } 00586 } 00587 key = key->next; 00588 } 00589 00590 if (status != ODS_STATUS_OK) { 00591 zonedata_rollback(zone->zonedata); 00592 } 00593 00594 hsm_destroy_context(ctx); 00595 ctx = NULL; 00596 return status; 00597 } 00598 00599 00604 ods_status 00605 zone_prepare_nsec3(zone_type* zone, int recover) 00606 { 00607 ldns_rr* nsec3params_rr = NULL; 00608 ods_status status = ODS_STATUS_OK; 00609 int doe_rollover = 0; 00610 00611 if (!zone) { 00612 ods_log_error("[%s] unable to prepare NSEC3: no zone", zone_str); 00613 return ODS_STATUS_ASSERT_ERR; 00614 } 00615 ods_log_assert(zone); 00616 00617 if (!zone->signconf) { 00618 ods_log_error("[%s] unable to prepare NSEC3: no signconf", zone_str); 00619 return ODS_STATUS_ASSERT_ERR; 00620 } 00621 ods_log_assert(zone->signconf); 00622 00623 if (zone->signconf->nsec_type != LDNS_RR_TYPE_NSEC3) { 00624 /* no preparations needed */ 00625 return ODS_STATUS_OK; 00626 } 00627 00628 if (!zone->nsec3params) { 00629 ods_log_debug("[%s] prepare NSEC3 for zone %s", zone_str, zone->name); 00630 00631 zone->nsec3params = nsec3params_create( 00632 (uint8_t) zone->signconf->nsec3_algo, 00633 (uint8_t) zone->signconf->nsec3_optout, 00634 (uint16_t) zone->signconf->nsec3_iterations, 00635 zone->signconf->nsec3_salt); 00636 doe_rollover = 1; 00637 } 00638 if (!zone->nsec3params) { 00639 ods_log_error("[%s] unable to prepare zone %s for NSEC3: failed " 00640 "to create NSEC3 parameters", zone_str, zone->name); 00641 return ODS_STATUS_MALLOC_ERR; 00642 } 00643 ods_log_assert(zone->nsec3params); 00644 00645 if (recover) { 00646 nsec3params_rr = ldns_rr_clone(zone->nsec3params->rr); 00647 status = zone_add_rr(zone, nsec3params_rr, 0); 00648 } else if (doe_rollover) { 00649 nsec3params_rr = ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3PARAMS); 00650 if (!nsec3params_rr) { 00651 ods_log_error("[%s] unable to prepare zone %s for NSEC3: failed " 00652 "to create NSEC3PARAM RR", zone_str, zone->name); 00653 nsec3params_cleanup(zone->nsec3params); 00654 zone->nsec3params = NULL; 00655 return ODS_STATUS_MALLOC_ERR; 00656 } 00657 ods_log_assert(nsec3params_rr); 00658 00659 ldns_rr_set_class(nsec3params_rr, zone->klass); 00660 ldns_rr_set_ttl(nsec3params_rr, zone->zonedata->default_ttl); 00661 ldns_rr_set_owner(nsec3params_rr, ldns_rdf_clone(zone->dname)); 00662 ldns_nsec3_add_param_rdfs(nsec3params_rr, 00663 zone->nsec3params->algorithm, 0, 00664 zone->nsec3params->iterations, 00665 zone->nsec3params->salt_len, 00666 zone->nsec3params->salt_data); 00671 ldns_set_bit(ldns_rdf_data(ldns_rr_rdf(nsec3params_rr, 1)), 7, 0); 00672 00673 ldns_rr2canonical(nsec3params_rr); 00674 zone->nsec3params->rr = ldns_rr_clone(nsec3params_rr); 00675 status = zone_add_rr(zone, nsec3params_rr, 0); 00676 } 00677 00678 if (status != ODS_STATUS_OK) { 00679 ods_log_error("[%s] unable to add NSEC3PARAM RR to zone %s", 00680 zone_str, zone->name); 00681 nsec3params_cleanup(zone->nsec3params); 00682 zone->nsec3params = NULL; 00683 ldns_rr_free(nsec3params_rr); 00684 } 00685 /* previous nsec3params is already withdrawn during load signconf */ 00686 00687 return status; 00688 } 00689 00690 00695 ods_status 00696 zone_backup(zone_type* zone) 00697 { 00698 char* filename = NULL; 00699 FILE* fd = NULL; 00700 00701 ods_log_assert(zone); 00702 ods_log_assert(zone->zonedata); 00703 ods_log_assert(zone->signconf); 00704 00705 filename = ods_build_path(zone->name, ".backup", 0, 1); 00706 fd = ods_fopen(filename, NULL, "w"); 00707 free((void*)filename); 00708 00709 if (fd) { 00710 fprintf(fd, "%s\n", ODS_SE_FILE_MAGIC); 00712 fprintf(fd, ";;Zone: name %s class %i ttl %u inbound %u internal " 00713 "%u outbound %u\n", 00714 zone->name?zone->name:"(null)", 00715 (int) zone->klass, 00716 (unsigned) zone->zonedata->default_ttl, 00717 (unsigned) zone->zonedata->inbound_serial, 00718 (unsigned) zone->zonedata->internal_serial, 00719 (unsigned) zone->zonedata->outbound_serial); 00721 if (zone->task) { 00722 task_backup(fd, (task_type*) zone->task); 00723 } 00725 signconf_backup(fd, zone->signconf); 00726 fprintf(fd, ";;\n"); 00728 if (zone->nsec3params) { 00729 nsec3params_backup(fd, 00730 zone->signconf->nsec3_algo, 00731 zone->signconf->nsec3_optout, 00732 zone->signconf->nsec3_iterations, 00733 zone->signconf->nsec3_salt, 00734 zone->nsec3params->rr); 00735 } 00737 keylist_backup(fd, zone->signconf->keys); 00739 zonedata_backup(fd, zone->zonedata); 00741 fprintf(fd, "%s\n", ODS_SE_FILE_MAGIC); 00742 ods_fclose(fd); 00743 } else { 00744 return ODS_STATUS_FOPEN_ERR; 00745 } 00746 return ODS_STATUS_OK; 00747 } 00748 00749 00754 ods_status 00755 zone_recover(zone_type* zone) 00756 { 00757 char* filename = NULL; 00758 FILE* fd = NULL; 00759 const char* token = NULL; 00760 ods_status status = ODS_STATUS_OK; 00761 /* zone part */ 00762 int klass = 0; 00763 uint32_t ttl = 0; 00764 uint32_t inbound = 0; 00765 uint32_t internal = 0; 00766 uint32_t outbound = 0; 00767 /* task part */ 00768 task_type* task = NULL; 00769 time_t when = 0; 00770 time_t backoff = 0; 00771 int what = 0; 00772 int interrupt = 0; 00773 int halted = 0; 00774 int flush = 0; 00775 /* signconf part */ 00776 time_t lastmod = 0; 00777 /* nsec3params part */ 00778 const char* salt = NULL; 00779 ldns_rr* nsec3params_rr = NULL; 00780 nsec3params_type* nsec3params = NULL; 00781 /* keys part */ 00782 key_type* key = NULL; 00783 /* zonedata part */ 00784 int fetch = 0; 00785 00786 ods_log_assert(zone); 00787 ods_log_assert(zone->signconf); 00788 ods_log_assert(zone->zonedata); 00789 00790 filename = ods_build_path(zone->name, ".backup", 0, 1); 00791 fd = ods_fopen(filename, NULL, "r"); 00792 free((void*)filename); 00793 if (fd) { 00794 /* start recovery */ 00795 if (!backup_read_check_str(fd, ODS_SE_FILE_MAGIC) || 00796 /* zone part */ 00797 !backup_read_check_str(fd, ";;Zone:") || 00798 !backup_read_check_str(fd, "name") || 00799 !backup_read_check_str(fd, zone->name) || 00800 !backup_read_check_str(fd, "class") || 00801 !backup_read_int(fd, &klass) || 00802 !backup_read_check_str(fd, "ttl") || 00803 !backup_read_uint32_t(fd, &ttl) || 00804 !backup_read_check_str(fd, "inbound") || 00805 !backup_read_uint32_t(fd, &inbound) || 00806 !backup_read_check_str(fd, "internal") || 00807 !backup_read_uint32_t(fd, &internal) || 00808 !backup_read_check_str(fd, "outbound") || 00809 !backup_read_uint32_t(fd, &outbound) || 00810 /* task part */ 00811 !backup_read_check_str(fd, ";;Task:") || 00812 !backup_read_check_str(fd, "when") || 00813 !backup_read_time_t(fd, &when) || 00814 !backup_read_check_str(fd, "what") || 00815 !backup_read_int(fd, &what) || 00816 !backup_read_check_str(fd, "interrupt") || 00817 !backup_read_int(fd, &interrupt) || 00818 !backup_read_check_str(fd, "halted") || 00819 !backup_read_int(fd, &halted) || 00820 !backup_read_check_str(fd, "backoff") || 00821 !backup_read_time_t(fd, &backoff) || 00822 !backup_read_check_str(fd, "flush") || 00823 !backup_read_int(fd, &flush) || 00824 /* signconf part */ 00825 !backup_read_check_str(fd, ";;Signconf:") || 00826 !backup_read_check_str(fd, "lastmod") || 00827 !backup_read_time_t(fd, &lastmod) || 00828 !backup_read_check_str(fd, "resign") || 00829 !backup_read_duration(fd, 00830 &zone->signconf->sig_resign_interval) || 00831 !backup_read_check_str(fd, "refresh") || 00832 !backup_read_duration(fd, 00833 &zone->signconf->sig_refresh_interval) || 00834 !backup_read_check_str(fd, "valid") || 00835 !backup_read_duration(fd, 00836 &zone->signconf->sig_validity_default) || 00837 !backup_read_check_str(fd, "denial") || 00838 !backup_read_duration(fd, 00839 &zone->signconf->sig_validity_denial) || 00840 !backup_read_check_str(fd, "jitter") || 00841 !backup_read_duration(fd, &zone->signconf->sig_jitter) || 00842 !backup_read_check_str(fd, "offset") || 00843 !backup_read_duration(fd, 00844 &zone->signconf->sig_inception_offset) || 00845 !backup_read_check_str(fd, "nsec") || 00846 !backup_read_rr_type(fd, &zone->signconf->nsec_type) || 00847 !backup_read_check_str(fd, "dnskeyttl") || 00848 !backup_read_duration(fd, &zone->signconf->dnskey_ttl) || 00849 !backup_read_check_str(fd, "soattl") || 00850 !backup_read_duration(fd, &zone->signconf->soa_ttl) || 00851 !backup_read_check_str(fd, "soamin") || 00852 !backup_read_duration(fd, &zone->signconf->soa_min) || 00853 !backup_read_check_str(fd, "serial") || 00854 !backup_read_str(fd, &zone->signconf->soa_serial) || 00855 !backup_read_check_str(fd, "audit") || 00856 !backup_read_int(fd, &zone->signconf->audit) || 00857 !backup_read_check_str(fd, ";;")) { 00858 goto recover_error; 00859 } 00860 /* nsec3params part */ 00861 if (zone->signconf->nsec_type == LDNS_RR_TYPE_NSEC3) { 00862 if (!backup_read_check_str(fd, ";;Nsec3parameters:") || 00863 !backup_read_check_str(fd, "salt") || 00864 !backup_read_str(fd, &salt) || 00865 !backup_read_check_str(fd, "algorithm") || 00866 !backup_read_uint32_t(fd, &zone->signconf->nsec3_algo) || 00867 !backup_read_check_str(fd, "optout") || 00868 !backup_read_int(fd, &zone->signconf->nsec3_optout) || 00869 !backup_read_check_str(fd, "iterations") || 00870 !backup_read_uint32_t(fd, 00871 &zone->signconf->nsec3_iterations) || 00872 ldns_rr_new_frm_fp(&nsec3params_rr, fd, NULL, NULL, NULL) || 00873 !backup_read_check_str(fd, ";;Nsec3done") || 00874 !backup_read_check_str(fd, ";;")) { 00875 goto recover_error; 00876 } 00877 } 00878 /* keys part */ 00879 zone->signconf->keys = keylist_create(zone->signconf->allocator); 00880 while (backup_read_str(fd, &token)) { 00881 if (ods_strcmp(token, ";;Key:") == 0) { 00882 key = key_recover(fd, zone->signconf->allocator); 00883 if (!key || keylist_push(zone->signconf->keys, key) != 00884 ODS_STATUS_OK) { 00885 goto recover_error; 00886 } 00887 key = NULL; 00888 } else if (ods_strcmp(token, ";;") == 0) { 00889 /* keylist done */ 00890 free((void*) token); 00891 token = NULL; 00892 break; 00893 } else { 00894 /* keylist corrupted */ 00895 goto recover_error; 00896 } 00897 free((void*) token); 00898 token = NULL; 00899 } 00900 /* zonedata part */ 00901 filename = ods_build_path(zone->name, ".inbound", 0, 1); 00902 status = adbackup_read(zone, filename); 00903 free((void*)filename); 00904 if (status != ODS_STATUS_OK) { 00905 goto recover_error; 00906 } 00907 00908 zone->klass = (ldns_rr_class) klass; 00909 zone->zonedata->default_ttl = ttl; 00910 zone->zonedata->inbound_serial = inbound; 00911 zone->zonedata->internal_serial = internal; 00912 zone->zonedata->outbound_serial = outbound; 00913 zone->signconf->nsec3_salt = allocator_strdup( 00914 zone->signconf->allocator, salt); 00915 free((void*) salt); 00916 salt = NULL; 00917 task = task_create((task_id) what, when, zone->name, (void*) zone); 00918 if (!task) { 00919 goto recover_error; 00920 } 00921 if (zone->signconf->nsec_type == LDNS_RR_TYPE_NSEC3) { 00922 nsec3params = nsec3params_create(zone->signconf->nsec3_algo, 00923 zone->signconf->nsec3_optout, 00924 zone->signconf->nsec3_iterations, 00925 zone->signconf->nsec3_salt); 00926 if (!nsec3params) { 00927 goto recover_error; 00928 } 00929 nsec3params->rr = nsec3params_rr; 00930 zone->nsec3params = nsec3params; 00931 } 00932 zone->task = (void*) task; 00933 zone->signconf->last_modified = lastmod; 00934 00940 status = zone_publish_dnskeys(zone, 1); 00941 if (status != ODS_STATUS_OK) { 00942 zone->task = NULL; 00943 zone->nsec3params = NULL; 00944 goto recover_error; 00945 } 00946 status = zone_prepare_nsec3(zone, 1); 00947 if (status != ODS_STATUS_OK) { 00948 zone->task = NULL; 00949 zone->nsec3params = NULL; 00950 goto recover_error; 00951 } 00952 status = zonedata_commit(zone->zonedata); 00953 if (status != ODS_STATUS_OK) { 00954 zone->task = NULL; 00955 zone->nsec3params = NULL; 00956 goto recover_error; 00957 } 00958 status = zonedata_entize(zone->zonedata, zone->dname); 00959 if (status != ODS_STATUS_OK) { 00960 zone->task = NULL; 00961 zone->nsec3params = NULL; 00962 goto recover_error; 00963 } 00964 status = zonedata_recover(zone->zonedata, fd); 00965 if (status != ODS_STATUS_OK) { 00966 zone->task = NULL; 00967 zone->nsec3params = NULL; 00968 goto recover_error; 00969 } 00970 ods_fclose(fd); 00971 00972 /* all ok */ 00973 zone->zonedata->initialized = 1; 00974 zone->prepared = 1; 00975 if (zone->stats) { 00976 lock_basic_lock(&zone->stats->stats_lock); 00977 stats_clear(zone->stats); 00978 lock_basic_unlock(&zone->stats->stats_lock); 00979 } 00980 return ODS_STATUS_OK; 00981 } else { 00982 /* backwards compatible backup recovery (serial) */ 00983 filename = ods_build_path(zone->name, ".state", 0, 1); 00984 fd = ods_fopen(filename, NULL, "r"); 00985 free((void*)filename); 00986 if (fd) { 00987 if (!backup_read_check_str(fd, ODS_SE_FILE_MAGIC_V1) || 00988 !backup_read_check_str(fd, ";name:") || 00989 !backup_read_check_str(fd, zone->name) || 00990 !backup_read_check_str(fd, ";class:") || 00991 !backup_read_int(fd, &klass) || 00992 !backup_read_check_str(fd, ";fetch:") || 00993 !backup_read_int(fd, &fetch) || 00994 !backup_read_check_str(fd, ";default_ttl:") || 00995 !backup_read_uint32_t(fd, &ttl) || 00996 !backup_read_check_str(fd, ";inbound_serial:") || 00997 !backup_read_uint32_t(fd, &inbound) || 00998 !backup_read_check_str(fd, ";internal_serial:") || 00999 !backup_read_uint32_t(fd, &internal) || 01000 !backup_read_check_str(fd, ";outbound_serial:") || 01001 !backup_read_uint32_t(fd, &outbound) || 01002 !backup_read_check_str(fd, ODS_SE_FILE_MAGIC_V1)) 01003 { 01004 goto recover_error; 01005 } 01006 zone->klass = (ldns_rr_class) klass; 01007 zone->zonedata->default_ttl = ttl; 01008 zone->zonedata->inbound_serial = inbound; 01009 zone->zonedata->internal_serial = internal; 01010 zone->zonedata->outbound_serial = outbound; 01011 /* all ok */ 01012 zone->zonedata->initialized = 1; 01013 zone->prepared = 1; 01014 if (zone->stats) { 01015 lock_basic_lock(&zone->stats->stats_lock); 01016 stats_clear(zone->stats); 01017 lock_basic_unlock(&zone->stats->stats_lock); 01018 } 01019 return ODS_STATUS_UNCHANGED; 01020 } 01021 ods_fclose(fd); 01022 } 01023 01024 return ODS_STATUS_UNCHANGED; 01025 01026 recover_error: 01027 ods_log_error("[%s] unable to recover zone %s: corrupted file", 01028 zone_str, zone->name); 01029 ods_fclose(fd); 01030 01031 /* signconf cleanup */ 01032 signconf_cleanup(zone->signconf); 01033 zone->signconf = signconf_create(); 01034 ods_log_assert(zone->signconf); 01035 01036 /* task cleanup */ 01037 task_cleanup(task); 01038 task = NULL; 01039 01040 /* nsec3params cleanup */ 01041 free((void*)salt); 01042 salt = NULL; 01043 01044 ldns_rr_free(nsec3params_rr); 01045 nsec3params_rr = NULL; 01046 if (nsec3params) { 01047 nsec3params->rr = NULL; 01048 } 01049 nsec3params_cleanup(nsec3params); 01050 nsec3params = NULL; 01051 01052 /* zonedata cleanup */ 01053 zonedata_cleanup(zone->zonedata); 01054 zone->zonedata = zonedata_create(zone->allocator); 01055 ods_log_assert(zone->zonedata); 01056 /* do keep serial information */ 01057 zone->zonedata->inbound_serial = inbound; 01058 zone->zonedata->internal_serial = internal; 01059 zone->zonedata->outbound_serial = outbound; 01060 zone->zonedata->initialized = 1; 01061 01062 if (zone->stats) { 01063 lock_basic_lock(&zone->stats->stats_lock); 01064 stats_clear(zone->stats); 01065 lock_basic_unlock(&zone->stats->stats_lock); 01066 } 01067 return ODS_STATUS_ERR; 01068 } 01069 01070 01075 void 01076 zone_merge(zone_type* z1, zone_type* z2) 01077 { 01078 const char* str; 01079 adapter_type* adtmp = NULL; 01080 01081 if (!z1 || !z2) { 01082 return; 01083 } 01084 01085 /* policy name */ 01086 if (ods_strcmp(z2->policy_name, z1->policy_name) != 0) { 01087 if (z2->policy_name) { 01088 str = strdup(z2->policy_name); 01089 if (!str) { 01090 ods_log_error("[%s] failed to merge policy %s name to zone " 01091 "%s", zone_str, z2->policy_name, z1->name); 01092 } else { 01093 free((void*)z1->policy_name); 01094 z1->policy_name = str; 01095 z1->just_updated = 1; 01096 } 01097 } else { 01098 free((void*)z1->policy_name); 01099 z1->policy_name = NULL; 01100 z1->just_updated = 1; 01101 } 01102 } 01103 01104 /* signconf filename */ 01105 if (ods_strcmp(z2->signconf_filename, z1->signconf_filename) != 0) { 01106 if (z2->signconf_filename) { 01107 str = strdup(z2->signconf_filename); 01108 if (!str) { 01109 ods_log_error("[%s] failed to merge signconf filename %s to " 01110 "zone %s", zone_str, z2->policy_name, z1->name); 01111 } else { 01112 free((void*)z1->signconf_filename); 01113 z1->signconf_filename = str; 01114 z1->just_updated = 1; 01115 } 01116 } else { 01117 free((void*)z1->signconf_filename); 01118 z1->signconf_filename = NULL; 01119 z1->just_updated = 1; 01120 } 01121 } 01122 01123 /* adapters */ 01124 if (adapter_compare(z2->adinbound, z1->adinbound) != 0) { 01125 adtmp = z2->adinbound; 01126 z2->adinbound = z1->adinbound; 01127 z1->adinbound = adtmp; 01128 adtmp = NULL; 01129 } 01130 if (adapter_compare(z2->adoutbound, z1->adoutbound) != 0) { 01131 adtmp = z2->adoutbound; 01132 z2->adoutbound = z1->adoutbound; 01133 z1->adoutbound = adtmp; 01134 adtmp = NULL; 01135 } 01136 return; 01137 } 01138 01139 01144 ods_status 01145 zone_update_serial(zone_type* zone) 01146 { 01147 ods_status status = ODS_STATUS_OK; 01148 domain_type* domain = NULL; 01149 rrset_type* rrset = NULL; 01150 ldns_rdf* serial = NULL; 01151 01152 if (!zone) { 01153 ods_log_error("[%s] unable to update serial: no zone", 01154 zone_str); 01155 return ODS_STATUS_ASSERT_ERR; 01156 } 01157 ods_log_assert(zone); 01158 01159 if (!zone->signconf) { 01160 ods_log_error("[%s] unable to update serial: no signconf", 01161 zone_str); 01162 return ODS_STATUS_ASSERT_ERR; 01163 } 01164 ods_log_assert(zone->signconf); 01165 01166 if (!zone->zonedata) { 01167 ods_log_error("[%s] unable to update serial: no zonedata", 01168 zone_str); 01169 return ODS_STATUS_ASSERT_ERR; 01170 } 01171 ods_log_assert(zone->zonedata); 01172 01173 status = zonedata_update_serial(zone->zonedata, zone->signconf); 01174 if (status != ODS_STATUS_OK) { 01175 ods_log_error("[%s] unable to update serial: failed to increment", 01176 zone_str); 01177 return status; 01178 } 01179 01180 /* lookup domain */ 01181 domain = zonedata_lookup_domain(zone->zonedata, zone->dname); 01182 if (!domain) { 01183 ods_log_error("[%s] unable to update serial: apex not found", 01184 zone_str); 01185 return ODS_STATUS_ERR; 01186 } 01187 ods_log_assert(domain); 01188 01189 /* lookup RRset */ 01190 rrset = domain_lookup_rrset(domain, LDNS_RR_TYPE_SOA); 01191 if (!rrset) { 01192 ods_log_error("[%s] unable to update serial: SOA RRset not found", 01193 zone_str); 01194 return ODS_STATUS_ERR; 01195 } 01196 ods_log_assert(rrset); 01197 ods_log_assert(rrset->rr_type == LDNS_RR_TYPE_SOA); 01198 01199 if (rrset->rrs && rrset->rrs->rr) { 01200 serial = ldns_rr_set_rdf(rrset->rrs->rr, 01201 ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 01202 zone->zonedata->internal_serial), SE_SOA_RDATA_SERIAL); 01203 if (serial) { 01204 if (ldns_rdf2native_int32(serial) != 01205 zone->zonedata->internal_serial) { 01206 rrset->needs_signing = 1; 01207 } 01208 ldns_rdf_deep_free(serial); 01209 } else { 01210 ods_log_error("[%s] unable to update serial: failed to replace " 01211 "SOA SERIAL rdata", zone_str); 01212 return ODS_STATUS_ERR; 01213 } 01214 } 01215 return ODS_STATUS_OK; 01216 } 01217 01218 01223 ods_status 01224 zone_print(FILE* fd, zone_type* zone) 01225 { 01226 if (fd && zone && zone->zonedata) { 01227 return zonedata_print(fd, zone->zonedata); 01228 } 01229 return ODS_STATUS_ASSERT_ERR; 01230 } 01231 01232 01237 ods_status 01238 zone_examine(zone_type* zone) 01239 { 01240 if (zone && zone->zonedata && zone->adinbound) { 01241 return zonedata_examine(zone->zonedata, zone->dname, 01242 zone->adinbound->type); 01243 } 01244 return ODS_STATUS_ASSERT_ERR; 01245 } 01246 01247 01252 void 01253 zone_cleanup(zone_type* zone) 01254 { 01255 allocator_type* allocator; 01256 lock_basic_type zone_lock; 01257 01258 if (!zone) { 01259 return; 01260 } 01261 01262 allocator = zone->allocator; 01263 zone_lock = zone->zone_lock; 01264 01265 ldns_rdf_deep_free(zone->dname); 01266 adapter_cleanup(zone->adinbound); 01267 adapter_cleanup(zone->adoutbound); 01268 zonedata_cleanup(zone->zonedata); 01269 signconf_cleanup(zone->signconf); 01270 nsec3params_cleanup(zone->nsec3params); 01271 stats_cleanup(zone->stats); 01272 allocator_deallocate(allocator, (void*) zone->notify_ns); 01273 allocator_deallocate(allocator, (void*) zone->policy_name); 01274 allocator_deallocate(allocator, (void*) zone->signconf_filename); 01275 allocator_deallocate(allocator, (void*) zone->name); 01276 allocator_deallocate(allocator, (void*) zone); 01277 allocator_cleanup(allocator); 01278 lock_basic_destroy(&zone_lock); 01279 return; 01280 }