OpenDNSSEC-signer 1.3.0rc3
|
00001 /* 00002 * $Id: zone.c 5227 2011-06-12 08:51:24Z jakob $ 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 ods_status 00348 zone_load_signconf(zone_type* zone, task_id* tbs) 00349 { 00350 ods_status status = ODS_STATUS_OK; 00351 signconf_type* signconf = NULL; 00352 ldns_rr_list* del = NULL; 00353 char* datestamp = NULL; 00354 uint32_t ustamp = 0; 00355 task_id denial_what; 00356 task_id keys_what; 00357 task_id what; 00358 00359 if (!zone) { 00360 ods_log_error("[%s] unable to load signconf: no zone", zone_str); 00361 return ODS_STATUS_ASSERT_ERR; 00362 } 00363 ods_log_assert(zone); 00364 if (!zone->signconf_filename) { 00365 ods_log_warning("[%s] zone %s has no signconf filename, treat as " 00366 "insecure?", zone_str, zone->name); 00367 return ODS_STATUS_INSECURE; 00368 } 00369 ods_log_assert(zone->signconf_filename); 00370 00371 status = signconf_update(&signconf, zone->signconf_filename, 00372 zone->signconf->last_modified); 00373 if (status == ODS_STATUS_OK) { 00374 if (!signconf) { 00375 /* this is unexpected */ 00376 ods_log_error("[%s] unable to load signconf: zone %s signconf " 00377 "%s: storage empty", zone_str, zone->name, 00378 zone->signconf_filename); 00379 return ODS_STATUS_ASSERT_ERR; 00380 } 00381 ustamp = time_datestamp(signconf->last_modified, "%Y-%m-%d %T", 00382 &datestamp); 00383 ods_log_debug("[%s] zone %s signconf file %s is modified since %s", 00384 zone_str, zone->name, zone->signconf_filename, 00385 datestamp?datestamp:"Unknown"); 00386 free((void*)datestamp); 00387 00388 /* do stuff */ 00389 del = ldns_rr_list_new(); 00390 if (!del) { 00391 ods_log_error("[%s] unable to load signconf: zone %s " 00392 "signconf %s: ldns_rr_list_new() failed", 00393 zone_str, zone->name, zone->signconf_filename); 00394 return ODS_STATUS_MALLOC_ERR; 00395 } 00396 denial_what = signconf_compare_denial(zone->signconf, signconf); 00397 keys_what = signconf_compare_keys(zone->signconf, signconf, del); 00398 00399 /* Key Rollover? */ 00400 if (keys_what == TASK_READ) { 00401 status = dnskey_withdraw(zone, del); 00402 } 00403 ldns_rr_list_free(del); 00404 if (status != ODS_STATUS_OK) { 00405 ods_log_error("[%s] unable to load signconf: zone %s " 00406 "signconf %s: failed to delete DNSKEY from RRset", 00407 zone_str, zone->name, zone->signconf_filename); 00408 zonedata_rollback(zone->zonedata); 00409 return status; 00410 } 00411 00412 /* Denial of Existence Rollover? */ 00413 if (denial_what == TASK_NSECIFY) { 00414 /* or NSEC -> NSEC3, or NSEC3 -> NSEC, or NSEC3PARAM changed */ 00415 nsec3params_cleanup(zone->nsec3params); 00416 zone->nsec3params = NULL; 00417 /* all NSEC(3)s become invalid */ 00418 zonedata_wipe_denial(zone->zonedata); 00419 zonedata_cleanup_chain(zone->zonedata); 00420 zonedata_init_denial(zone->zonedata); 00421 } 00422 00423 /* all ok, switch to new signconf */ 00424 if (keys_what != TASK_NONE) { 00425 what = keys_what; 00426 } else { 00427 what = denial_what; 00428 } 00429 if (what == TASK_NONE) { /* no major changes, continue signing */ 00430 what = TASK_SIGN; 00431 } 00432 *tbs = what; 00433 ods_log_debug("[%s] tbs for zone %s set to: %s", zone_str, 00434 zone->name, task_what2str(*tbs)); 00435 signconf_cleanup(zone->signconf); 00436 ods_log_debug("[%s] zone %s switch to new signconf", zone_str, 00437 zone->name); 00438 zone->signconf = signconf; 00439 signconf_log(zone->signconf, zone->name); 00440 zone->zonedata->default_ttl = 00441 (uint32_t) duration2time(zone->signconf->soa_min); 00442 } else if (status == ODS_STATUS_UNCHANGED) { 00443 *tbs = TASK_READ; 00444 ods_log_debug("[%s] tbs for zone %s set to: %s", zone_str, 00445 zone->name, task_what2str(*tbs)); 00446 ustamp = time_datestamp(zone->signconf->last_modified, 00447 "%Y-%m-%d %T", &datestamp); 00448 ods_log_verbose("[%s] zone %s signconf file %s is unchanged since " 00449 "%s", zone_str, zone->name, zone->signconf_filename, 00450 datestamp?datestamp:"Unknown"); 00451 free((void*)datestamp); 00452 } else { 00453 ods_log_error("[%s] unable to load signconf: zone %s signconf %s: " 00454 "%s", zone_str, zone->name, zone->signconf_filename, 00455 ods_status2str(status)); 00456 } 00457 return status; 00458 } 00459 00460 00465 ods_status 00466 zone_publish_dnskeys(zone_type* zone, int recover) 00467 { 00468 hsm_ctx_t* ctx = NULL; 00469 key_type* key = NULL; 00470 uint32_t ttl = 0; 00471 size_t count = 0; 00472 ods_status status = ODS_STATUS_OK; 00473 ldns_rr* dnskey = NULL; 00474 int do_publish = 0; 00475 00476 if (!zone) { 00477 ods_log_error("[%s] unable to publish dnskeys: no zone", zone_str); 00478 return ODS_STATUS_ASSERT_ERR; 00479 } 00480 ods_log_assert(zone); 00481 00482 if (!zone->signconf) { 00483 ods_log_error("[%s] unable to publish dnskeys zone %s: no signconf", 00484 zone_str, zone->name); 00485 return ODS_STATUS_ASSERT_ERR; 00486 } 00487 ods_log_assert(zone->signconf); 00488 00489 if (!zone->signconf->keys) { 00490 ods_log_error("[%s] unable to publish dnskeys zone %s: no keys", 00491 zone_str, zone->name); 00492 return ODS_STATUS_ASSERT_ERR; 00493 } 00494 ods_log_assert(zone->signconf->keys); 00495 00496 if (!zone->zonedata) { 00497 ods_log_error("[%s] unable to publish dnskeys zone %s: no zonedata", 00498 zone_str, zone->name); 00499 return ODS_STATUS_ASSERT_ERR; 00500 } 00501 ods_log_assert(zone->zonedata); 00502 00503 ttl = zone->zonedata->default_ttl; 00504 if (zone->signconf->dnskey_ttl) { 00505 ttl = (uint32_t) duration2time(zone->signconf->dnskey_ttl); 00506 } 00507 00508 ctx = hsm_create_context(); 00509 if (ctx == NULL) { 00510 ods_log_error("[%s] unable to publish dnskeys for zone %s: error " 00511 "creating libhsm context", zone_str, zone->name); 00512 return ODS_STATUS_HSM_ERR; 00513 } 00514 00515 key = zone->signconf->keys->first_key; 00516 for (count=0; count < zone->signconf->keys->count; count++) { 00517 if (key->publish) { 00518 do_publish = 0; 00519 if (!key->dnskey) { 00520 do_publish = 1; 00521 } 00522 00523 status = lhsm_get_key(ctx, zone->dname, key); 00524 if (status != ODS_STATUS_OK) { 00525 ods_log_error("[%s] unable to publish dnskeys zone %s: " 00526 "error creating DNSKEY for key %s", zone_str, 00527 zone->name, key->locator?key->locator:"(null)"); 00528 break; 00529 } 00530 ods_log_assert(key->dnskey); 00531 00532 if (recover) { 00533 dnskey = ldns_rr_clone(key->dnskey); 00534 status = zone_add_rr(zone, dnskey, 0); 00535 } else if (do_publish) { 00536 ldns_rr_set_ttl(key->dnskey, ttl); 00537 ldns_rr_set_class(key->dnskey, zone->klass); 00538 ldns_rr2canonical(key->dnskey); 00539 dnskey = ldns_rr_clone(key->dnskey); 00540 status = zone_add_rr(zone, dnskey, 0); 00541 } else { 00542 status = ODS_STATUS_OK; 00543 } 00544 00545 if (status != ODS_STATUS_OK) { 00546 ods_log_error("[%s] unable to publish dnskeys zone %s: " 00547 "error adding DNSKEY[%u] for key %s", zone_str, 00548 zone->name, ldns_calc_keytag(dnskey), 00549 key->locator?key->locator:"(null)"); 00550 break; 00551 } 00552 } 00553 key = key->next; 00554 } 00555 00556 if (status != ODS_STATUS_OK) { 00557 zonedata_rollback(zone->zonedata); 00558 } 00559 00560 hsm_destroy_context(ctx); 00561 ctx = NULL; 00562 return status; 00563 } 00564 00565 00570 ods_status 00571 zone_prepare_nsec3(zone_type* zone, int recover) 00572 { 00573 ldns_rr* nsec3params_rr = NULL; 00574 domain_type* apex = NULL; 00575 rrset_type* rrset = NULL; 00576 ods_status status = ODS_STATUS_OK; 00577 00578 if (!zone) { 00579 ods_log_error("[%s] unable to prepare NSEC3: no zone", zone_str); 00580 return ODS_STATUS_ASSERT_ERR; 00581 } 00582 ods_log_assert(zone); 00583 00584 if (!zone->signconf) { 00585 ods_log_error("[%s] unable to prepare NSEC3: no signconf", zone_str); 00586 return ODS_STATUS_ASSERT_ERR; 00587 } 00588 ods_log_assert(zone->signconf); 00589 00590 if (zone->signconf->nsec_type != LDNS_RR_TYPE_NSEC3) { 00591 /* no preparations needed */ 00592 return ODS_STATUS_OK; 00593 } 00594 00595 if (!zone->nsec3params) { 00596 ods_log_debug("[%s] prepare NSEC3 for zone %s", zone_str, zone->name); 00597 00598 zone->nsec3params = nsec3params_create( 00599 (uint8_t) zone->signconf->nsec3_algo, 00600 (uint8_t) zone->signconf->nsec3_optout, 00601 (uint16_t) zone->signconf->nsec3_iterations, 00602 zone->signconf->nsec3_salt); 00603 } 00604 if (!zone->nsec3params) { 00605 ods_log_error("[%s] unable to prepare zone %s for NSEC3: failed " 00606 "to create NSEC3 parameters", zone_str, zone->name); 00607 return ODS_STATUS_MALLOC_ERR; 00608 } 00609 ods_log_assert(zone->nsec3params); 00610 00611 if (recover) { 00612 nsec3params_rr = ldns_rr_clone(zone->nsec3params->rr); 00613 status = zone_add_rr(zone, nsec3params_rr, 0); 00614 } else { 00615 nsec3params_rr = ldns_rr_new_frm_type(LDNS_RR_TYPE_NSEC3PARAMS); 00616 if (!nsec3params_rr) { 00617 ods_log_error("[%s] unable to prepare zone %s for NSEC3: failed " 00618 "to create NSEC3PARAM RR", zone_str, zone->name); 00619 nsec3params_cleanup(zone->nsec3params); 00620 return ODS_STATUS_MALLOC_ERR; 00621 } 00622 ods_log_assert(nsec3params_rr); 00623 00624 ldns_rr_set_class(nsec3params_rr, zone->klass); 00625 ldns_rr_set_ttl(nsec3params_rr, zone->zonedata->default_ttl); 00626 ldns_rr_set_owner(nsec3params_rr, ldns_rdf_clone(zone->dname)); 00627 ldns_nsec3_add_param_rdfs(nsec3params_rr, 00628 zone->nsec3params->algorithm, 0, 00629 zone->nsec3params->iterations, 00630 zone->nsec3params->salt_len, 00631 zone->nsec3params->salt_data); 00636 ldns_set_bit(ldns_rdf_data(ldns_rr_rdf(nsec3params_rr, 1)), 7, 0); 00637 00638 ldns_rr2canonical(nsec3params_rr); 00639 zone->nsec3params->rr = ldns_rr_clone(nsec3params_rr); 00640 status = zone_add_rr(zone, nsec3params_rr, 0); 00641 } 00642 00643 if (status != ODS_STATUS_OK) { 00644 ods_log_error("[%s] unable to add NSEC3PARAM RR to zone %s", 00645 zone_str, zone->name); 00646 nsec3params_cleanup(zone->nsec3params); 00647 zone->nsec3params = NULL; 00648 ldns_rr_free(nsec3params_rr); 00649 } else if (!recover) { 00650 /* add ok, wipe out previous nsec3params */ 00651 apex = zonedata_lookup_domain(zone->zonedata, zone->dname); 00652 if (!apex) { 00653 ods_log_crit("[%s] unable to delete previous NSEC3PARAM RR " 00654 "from zone %s: apex undefined", zone_str, zone->name); 00655 nsec3params_cleanup(zone->nsec3params); 00656 zone->nsec3params = NULL; 00657 zonedata_rollback(zone->zonedata); 00658 return ODS_STATUS_ASSERT_ERR; 00659 } 00660 ods_log_assert(apex); 00661 00662 rrset = domain_lookup_rrset(apex, LDNS_RR_TYPE_NSEC3PARAMS); 00663 if (rrset) { 00664 status = rrset_wipe_out(rrset); 00665 if (status != ODS_STATUS_OK) { 00666 ods_log_error("[%s] unable to wipe out previous " 00667 "NSEC3PARAM RR from zone %s", zone_str, zone->name); 00668 nsec3params_cleanup(zone->nsec3params); 00669 zone->nsec3params = NULL; 00670 rrset_rollback(rrset); 00671 return status; 00672 } 00673 } 00674 } 00675 return status; 00676 } 00677 00678 00683 ods_status 00684 zone_backup(zone_type* zone) 00685 { 00686 char* filename = NULL; 00687 FILE* fd = NULL; 00688 00689 ods_log_assert(zone); 00690 ods_log_assert(zone->zonedata); 00691 ods_log_assert(zone->signconf); 00692 00693 filename = ods_build_path(zone->name, ".backup", 0); 00694 fd = ods_fopen(filename, NULL, "w"); 00695 free((void*)filename); 00696 00697 if (fd) { 00698 fprintf(fd, "%s\n", ODS_SE_FILE_MAGIC); 00700 fprintf(fd, ";;Zone: name %s class %i ttl %u inbound %u internal " 00701 "%u outbound %u\n", 00702 zone->name?zone->name:"(null)", 00703 (int) zone->klass, 00704 (unsigned) zone->zonedata->default_ttl, 00705 (unsigned) zone->zonedata->inbound_serial, 00706 (unsigned) zone->zonedata->internal_serial, 00707 (unsigned) zone->zonedata->outbound_serial); 00709 if (zone->task) { 00710 task_backup(fd, (task_type*) zone->task); 00711 } 00713 signconf_backup(fd, zone->signconf); 00714 fprintf(fd, ";;\n"); 00716 if (zone->nsec3params) { 00717 nsec3params_backup(fd, 00718 zone->signconf->nsec3_algo, 00719 zone->signconf->nsec3_optout, 00720 zone->signconf->nsec3_iterations, 00721 zone->signconf->nsec3_salt, 00722 zone->nsec3params->rr); 00723 } 00725 keylist_backup(fd, zone->signconf->keys); 00727 zonedata_backup(fd, zone->zonedata); 00729 fprintf(fd, "%s\n", ODS_SE_FILE_MAGIC); 00730 ods_fclose(fd); 00731 } else { 00732 return ODS_STATUS_FOPEN_ERR; 00733 } 00734 return ODS_STATUS_OK; 00735 } 00736 00737 00742 ods_status 00743 zone_recover(zone_type* zone) 00744 { 00745 char* filename = NULL; 00746 FILE* fd = NULL; 00747 const char* token = NULL; 00748 ods_status status = ODS_STATUS_OK; 00749 /* zone part */ 00750 int klass = 0; 00751 uint32_t ttl = 0; 00752 uint32_t inbound = 0; 00753 uint32_t internal = 0; 00754 uint32_t outbound = 0; 00755 /* task part */ 00756 task_type* task = NULL; 00757 time_t when = 0; 00758 time_t backoff = 0; 00759 int what = 0; 00760 int interrupt = 0; 00761 int halted = 0; 00762 int flush = 0; 00763 /* signconf part */ 00764 time_t lastmod = 0; 00765 /* nsec3params part */ 00766 const char* salt = NULL; 00767 ldns_rr* nsec3params_rr = NULL; 00768 nsec3params_type* nsec3params = NULL; 00769 /* keys part */ 00770 key_type* key = NULL; 00771 /* zonedata part */ 00772 int fetch = 0; 00773 00774 ods_log_assert(zone); 00775 ods_log_assert(zone->signconf); 00776 ods_log_assert(zone->zonedata); 00777 00778 filename = ods_build_path(zone->name, ".backup", 0); 00779 fd = ods_fopen(filename, NULL, "r"); 00780 free((void*)filename); 00781 if (fd) { 00782 /* start recovery */ 00783 if (!backup_read_check_str(fd, ODS_SE_FILE_MAGIC) || 00784 /* zone part */ 00785 !backup_read_check_str(fd, ";;Zone:") || 00786 !backup_read_check_str(fd, "name") || 00787 !backup_read_check_str(fd, zone->name) || 00788 !backup_read_check_str(fd, "class") || 00789 !backup_read_int(fd, &klass) || 00790 !backup_read_check_str(fd, "ttl") || 00791 !backup_read_uint32_t(fd, &ttl) || 00792 !backup_read_check_str(fd, "inbound") || 00793 !backup_read_uint32_t(fd, &inbound) || 00794 !backup_read_check_str(fd, "internal") || 00795 !backup_read_uint32_t(fd, &internal) || 00796 !backup_read_check_str(fd, "outbound") || 00797 !backup_read_uint32_t(fd, &outbound) || 00798 /* task part */ 00799 !backup_read_check_str(fd, ";;Task:") || 00800 !backup_read_check_str(fd, "when") || 00801 !backup_read_time_t(fd, &when) || 00802 !backup_read_check_str(fd, "what") || 00803 !backup_read_int(fd, &what) || 00804 !backup_read_check_str(fd, "interrupt") || 00805 !backup_read_int(fd, &interrupt) || 00806 !backup_read_check_str(fd, "halted") || 00807 !backup_read_int(fd, &halted) || 00808 !backup_read_check_str(fd, "backoff") || 00809 !backup_read_time_t(fd, &backoff) || 00810 !backup_read_check_str(fd, "flush") || 00811 !backup_read_int(fd, &flush) || 00812 /* signconf part */ 00813 !backup_read_check_str(fd, ";;Signconf:") || 00814 !backup_read_check_str(fd, "lastmod") || 00815 !backup_read_time_t(fd, &lastmod) || 00816 !backup_read_check_str(fd, "resign") || 00817 !backup_read_duration(fd, 00818 &zone->signconf->sig_resign_interval) || 00819 !backup_read_check_str(fd, "refresh") || 00820 !backup_read_duration(fd, 00821 &zone->signconf->sig_refresh_interval) || 00822 !backup_read_check_str(fd, "valid") || 00823 !backup_read_duration(fd, 00824 &zone->signconf->sig_validity_default) || 00825 !backup_read_check_str(fd, "denial") || 00826 !backup_read_duration(fd, 00827 &zone->signconf->sig_validity_denial) || 00828 !backup_read_check_str(fd, "jitter") || 00829 !backup_read_duration(fd, &zone->signconf->sig_jitter) || 00830 !backup_read_check_str(fd, "offset") || 00831 !backup_read_duration(fd, 00832 &zone->signconf->sig_inception_offset) || 00833 !backup_read_check_str(fd, "nsec") || 00834 !backup_read_rr_type(fd, &zone->signconf->nsec_type) || 00835 !backup_read_check_str(fd, "dnskeyttl") || 00836 !backup_read_duration(fd, &zone->signconf->dnskey_ttl) || 00837 !backup_read_check_str(fd, "soattl") || 00838 !backup_read_duration(fd, &zone->signconf->soa_ttl) || 00839 !backup_read_check_str(fd, "soamin") || 00840 !backup_read_duration(fd, &zone->signconf->soa_min) || 00841 !backup_read_check_str(fd, "serial") || 00842 !backup_read_str(fd, &zone->signconf->soa_serial) || 00843 !backup_read_check_str(fd, "audit") || 00844 !backup_read_int(fd, &zone->signconf->audit) || 00845 !backup_read_check_str(fd, ";;")) { 00846 goto recover_error; 00847 } 00848 /* nsec3params part */ 00849 if (zone->signconf->nsec_type == LDNS_RR_TYPE_NSEC3) { 00850 if (!backup_read_check_str(fd, ";;Nsec3parameters:") || 00851 !backup_read_check_str(fd, "salt") || 00852 !backup_read_str(fd, &salt) || 00853 !backup_read_check_str(fd, "algorithm") || 00854 !backup_read_uint32_t(fd, &zone->signconf->nsec3_algo) || 00855 !backup_read_check_str(fd, "optout") || 00856 !backup_read_int(fd, &zone->signconf->nsec3_optout) || 00857 !backup_read_check_str(fd, "iterations") || 00858 !backup_read_uint32_t(fd, 00859 &zone->signconf->nsec3_iterations) || 00860 ldns_rr_new_frm_fp(&nsec3params_rr, fd, NULL, NULL, NULL) || 00861 !backup_read_check_str(fd, ";;Nsec3done") || 00862 !backup_read_check_str(fd, ";;")) { 00863 goto recover_error; 00864 } 00865 } 00866 /* keys part */ 00867 zone->signconf->keys = keylist_create(zone->signconf->allocator); 00868 while (backup_read_str(fd, &token)) { 00869 if (ods_strcmp(token, ";;Key:") == 0) { 00870 key = key_recover(fd, zone->signconf->allocator); 00871 if (!key || keylist_push(zone->signconf->keys, key) != 00872 ODS_STATUS_OK) { 00873 goto recover_error; 00874 } 00875 key = NULL; 00876 } else if (ods_strcmp(token, ";;") == 0) { 00877 /* keylist done */ 00878 free((void*) token); 00879 token = NULL; 00880 break; 00881 } else { 00882 /* keylist corrupted */ 00883 goto recover_error; 00884 } 00885 free((void*) token); 00886 token = NULL; 00887 } 00888 /* zonedata part */ 00889 filename = ods_build_path(zone->name, ".inbound", 0); 00890 status = adbackup_read(zone, filename); 00891 free((void*)filename); 00892 if (status != ODS_STATUS_OK) { 00893 goto recover_error; 00894 } 00895 00896 zone->klass = (ldns_rr_class) klass; 00897 zone->zonedata->default_ttl = ttl; 00898 zone->zonedata->inbound_serial = inbound; 00899 zone->zonedata->internal_serial = internal; 00900 zone->zonedata->outbound_serial = outbound; 00901 zone->signconf->nsec3_salt = allocator_strdup( 00902 zone->signconf->allocator, salt); 00903 free((void*) salt); 00904 salt = NULL; 00905 task = task_create((task_id) what, when, zone->name, (void*) zone); 00906 if (!task) { 00907 goto recover_error; 00908 } 00909 if (zone->signconf->nsec_type == LDNS_RR_TYPE_NSEC3) { 00910 nsec3params = nsec3params_create(zone->signconf->nsec3_algo, 00911 zone->signconf->nsec3_optout, 00912 zone->signconf->nsec3_iterations, 00913 zone->signconf->nsec3_salt); 00914 if (!nsec3params) { 00915 goto recover_error; 00916 } 00917 nsec3params->rr = nsec3params_rr; 00918 zone->nsec3params = nsec3params; 00919 } 00920 zone->task = (void*) task; 00921 zone->signconf->last_modified = lastmod; 00922 00923 status = zone_publish_dnskeys(zone, 1); 00924 if (status != ODS_STATUS_OK) { 00925 zone->task = NULL; 00926 zone->nsec3params = NULL; 00927 goto recover_error; 00928 } 00929 status = zone_prepare_nsec3(zone, 1); 00930 if (status != ODS_STATUS_OK) { 00931 zone->task = NULL; 00932 zone->nsec3params = NULL; 00933 goto recover_error; 00934 } 00935 status = zonedata_commit(zone->zonedata); 00936 if (status != ODS_STATUS_OK) { 00937 zone->task = NULL; 00938 zone->nsec3params = NULL; 00939 goto recover_error; 00940 } 00941 status = zonedata_entize(zone->zonedata, zone->dname); 00942 if (status != ODS_STATUS_OK) { 00943 zone->task = NULL; 00944 zone->nsec3params = NULL; 00945 goto recover_error; 00946 } 00947 status = zonedata_recover(zone->zonedata, fd); 00948 if (status != ODS_STATUS_OK) { 00949 zone->task = NULL; 00950 zone->nsec3params = NULL; 00951 goto recover_error; 00952 } 00953 ods_fclose(fd); 00954 00955 /* all ok */ 00956 zone->zonedata->initialized = 1; 00957 if (zone->stats) { 00958 lock_basic_lock(&zone->stats->stats_lock); 00959 stats_clear(zone->stats); 00960 lock_basic_unlock(&zone->stats->stats_lock); 00961 } 00962 return ODS_STATUS_OK; 00963 } else { 00964 /* backwards compatible backup recovery (serial) */ 00965 filename = ods_build_path(zone->name, ".state", 0); 00966 fd = ods_fopen(filename, NULL, "r"); 00967 free((void*)filename); 00968 if (fd) { 00969 if (!backup_read_check_str(fd, ODS_SE_FILE_MAGIC_V1) || 00970 !backup_read_check_str(fd, ";name:") || 00971 !backup_read_check_str(fd, zone->name) || 00972 !backup_read_check_str(fd, ";class:") || 00973 !backup_read_int(fd, &klass) || 00974 !backup_read_check_str(fd, ";fetch:") || 00975 !backup_read_int(fd, &fetch) || 00976 !backup_read_check_str(fd, ";default_ttl:") || 00977 !backup_read_uint32_t(fd, &ttl) || 00978 !backup_read_check_str(fd, ";inbound_serial:") || 00979 !backup_read_uint32_t(fd, &inbound) || 00980 !backup_read_check_str(fd, ";internal_serial:") || 00981 !backup_read_uint32_t(fd, &internal) || 00982 !backup_read_check_str(fd, ";outbound_serial:") || 00983 !backup_read_uint32_t(fd, &outbound) || 00984 !backup_read_check_str(fd, ODS_SE_FILE_MAGIC_V1)) 00985 { 00986 goto recover_error; 00987 } 00988 zone->klass = (ldns_rr_class) klass; 00989 zone->zonedata->default_ttl = ttl; 00990 zone->zonedata->inbound_serial = inbound; 00991 zone->zonedata->internal_serial = internal; 00992 zone->zonedata->outbound_serial = outbound; 00993 /* all ok */ 00994 zone->zonedata->initialized = 1; 00995 if (zone->stats) { 00996 lock_basic_lock(&zone->stats->stats_lock); 00997 stats_clear(zone->stats); 00998 lock_basic_unlock(&zone->stats->stats_lock); 00999 } 01000 return ODS_STATUS_UNCHANGED; 01001 } 01002 ods_fclose(fd); 01003 } 01004 01005 return ODS_STATUS_UNCHANGED; 01006 01007 recover_error: 01008 ods_log_error("[%s] unable to recover zone %s: corrupted file", 01009 zone_str, zone->name); 01010 ods_fclose(fd); 01011 01012 /* signconf cleanup */ 01013 signconf_cleanup(zone->signconf); 01014 zone->signconf = signconf_create(); 01015 ods_log_assert(zone->signconf); 01016 01017 /* task cleanup */ 01018 task_cleanup(task); 01019 task = NULL; 01020 01021 /* nsec3params cleanup */ 01022 free((void*)salt); 01023 salt = NULL; 01024 01025 ldns_rr_free(nsec3params_rr); 01026 nsec3params_rr = NULL; 01027 01028 nsec3params_cleanup(nsec3params); 01029 nsec3params = NULL; 01030 01031 /* zonedata cleanup */ 01032 zonedata_cleanup(zone->zonedata); 01033 zone->zonedata = zonedata_create(zone->allocator); 01034 ods_log_assert(zone->zonedata); 01035 01036 if (zone->stats) { 01037 lock_basic_lock(&zone->stats->stats_lock); 01038 stats_clear(zone->stats); 01039 lock_basic_unlock(&zone->stats->stats_lock); 01040 } 01041 return ODS_STATUS_ERR; 01042 } 01043 01044 01049 void 01050 zone_merge(zone_type* z1, zone_type* z2) 01051 { 01052 const char* str; 01053 adapter_type* adtmp = NULL; 01054 01055 if (!z1 || !z2) { 01056 return; 01057 } 01058 01059 /* policy name */ 01060 if (ods_strcmp(z2->policy_name, z1->policy_name) != 0) { 01061 if (z2->policy_name) { 01062 str = strdup(z2->policy_name); 01063 if (!str) { 01064 ods_log_error("[%s] failed to merge policy %s name to zone " 01065 "%s", zone_str, z2->policy_name, z1->name); 01066 } else { 01067 free((void*)z1->policy_name); 01068 z1->policy_name = str; 01069 z1->just_updated = 1; 01070 } 01071 } else { 01072 free((void*)z1->policy_name); 01073 z1->policy_name = NULL; 01074 z1->just_updated = 1; 01075 } 01076 } 01077 01078 /* signconf filename */ 01079 if (ods_strcmp(z2->signconf_filename, z1->signconf_filename) != 0) { 01080 if (z2->signconf_filename) { 01081 str = strdup(z2->signconf_filename); 01082 if (!str) { 01083 ods_log_error("[%s] failed to merge signconf filename %s to " 01084 "zone %s", zone_str, z2->policy_name, z1->name); 01085 } else { 01086 free((void*)z1->signconf_filename); 01087 z1->signconf_filename = str; 01088 z1->just_updated = 1; 01089 } 01090 } else { 01091 free((void*)z1->signconf_filename); 01092 z1->signconf_filename = NULL; 01093 z1->just_updated = 1; 01094 } 01095 } 01096 01097 /* adapters */ 01098 if (adapter_compare(z2->adinbound, z1->adinbound) != 0) { 01099 adtmp = z2->adinbound; 01100 z2->adinbound = z1->adinbound; 01101 z1->adinbound = adtmp; 01102 adtmp = NULL; 01103 } 01104 if (adapter_compare(z2->adoutbound, z1->adoutbound) != 0) { 01105 adtmp = z2->adoutbound; 01106 z2->adoutbound = z1->adoutbound; 01107 z1->adoutbound = adtmp; 01108 adtmp = NULL; 01109 } 01110 return; 01111 } 01112 01113 01118 ods_status 01119 zone_update_serial(zone_type* zone) 01120 { 01121 ods_status status = ODS_STATUS_OK; 01122 domain_type* domain = NULL; 01123 rrset_type* rrset = NULL; 01124 ldns_rdf* serial = NULL; 01125 01126 if (!zone) { 01127 ods_log_error("[%s] unable to update serial: no zone", 01128 zone_str); 01129 return ODS_STATUS_ASSERT_ERR; 01130 } 01131 ods_log_assert(zone); 01132 01133 if (!zone->signconf) { 01134 ods_log_error("[%s] unable to update serial: no signconf", 01135 zone_str); 01136 return ODS_STATUS_ASSERT_ERR; 01137 } 01138 ods_log_assert(zone->signconf); 01139 01140 if (!zone->zonedata) { 01141 ods_log_error("[%s] unable to update serial: no zonedata", 01142 zone_str); 01143 return ODS_STATUS_ASSERT_ERR; 01144 } 01145 ods_log_assert(zone->zonedata); 01146 01147 status = zonedata_update_serial(zone->zonedata, zone->signconf); 01148 if (status != ODS_STATUS_OK) { 01149 ods_log_error("[%s] unable to update serial: failed to increment", 01150 zone_str); 01151 return status; 01152 } 01153 01154 /* lookup domain */ 01155 domain = zonedata_lookup_domain(zone->zonedata, zone->dname); 01156 if (!domain) { 01157 ods_log_error("[%s] unable to update serial: apex not found", 01158 zone_str); 01159 return ODS_STATUS_ERR; 01160 } 01161 ods_log_assert(domain); 01162 01163 /* lookup RRset */ 01164 rrset = domain_lookup_rrset(domain, LDNS_RR_TYPE_SOA); 01165 if (!rrset) { 01166 ods_log_error("[%s] unable to update serial: SOA RRset not found", 01167 zone_str); 01168 return ODS_STATUS_ERR; 01169 } 01170 ods_log_assert(rrset); 01171 ods_log_assert(rrset->rr_type == LDNS_RR_TYPE_SOA); 01172 01173 if (rrset->rrs && rrset->rrs->rr) { 01174 serial = ldns_rr_set_rdf(rrset->rrs->rr, 01175 ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32, 01176 zone->zonedata->internal_serial), SE_SOA_RDATA_SERIAL); 01177 if (serial) { 01178 if (ldns_rdf2native_int32(serial) != 01179 zone->zonedata->internal_serial) { 01180 rrset->needs_signing = 1; 01181 } 01182 ldns_rdf_deep_free(serial); 01183 } else { 01184 ods_log_error("[%s] unable to update serial: failed to replace " 01185 "SOA SERIAL rdata", zone_str); 01186 return ODS_STATUS_ERR; 01187 } 01188 } 01189 return ODS_STATUS_OK; 01190 } 01191 01192 01197 ods_status 01198 zone_print(FILE* fd, zone_type* zone) 01199 { 01200 if (fd && zone && zone->zonedata) { 01201 return zonedata_print(fd, zone->zonedata); 01202 } 01203 return ODS_STATUS_ASSERT_ERR; 01204 } 01205 01206 01211 ods_status 01212 zone_examine(zone_type* zone) 01213 { 01214 if (zone && zone->zonedata && zone->adinbound) { 01215 return zonedata_examine(zone->zonedata, zone->dname, 01216 zone->adinbound->type); 01217 } 01218 return ODS_STATUS_ASSERT_ERR; 01219 } 01220 01221 01226 void 01227 zone_cleanup(zone_type* zone) 01228 { 01229 allocator_type* allocator; 01230 lock_basic_type zone_lock; 01231 01232 if (!zone) { 01233 return; 01234 } 01235 01236 allocator = zone->allocator; 01237 zone_lock = zone->zone_lock; 01238 01239 ldns_rdf_deep_free(zone->dname); 01240 adapter_cleanup(zone->adinbound); 01241 adapter_cleanup(zone->adoutbound); 01242 zonedata_cleanup(zone->zonedata); 01243 signconf_cleanup(zone->signconf); 01244 nsec3params_cleanup(zone->nsec3params); 01245 stats_cleanup(zone->stats); 01246 allocator_deallocate(allocator, (void*) zone->notify_ns); 01247 allocator_deallocate(allocator, (void*) zone->policy_name); 01248 allocator_deallocate(allocator, (void*) zone->signconf_filename); 01249 allocator_deallocate(allocator, (void*) zone->name); 01250 allocator_deallocate(allocator, (void*) zone); 01251 allocator_cleanup(allocator); 01252 lock_basic_destroy(&zone_lock); 01253 return; 01254 }