00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
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
00091 if (strlen(name) > 1 && name[strlen(name)-1] == '.') {
00092 name[strlen(name)-1] = '\0';
00093 }
00094
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
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
00176 ldns_rr_free(rr);
00177 return ODS_STATUS_OK;
00178 }
00179
00180
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
00213 domain = zonedata_lookup_domain(zone->zonedata, ldns_rr_owner(rr));
00214 if (!domain) {
00215
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
00234 rrset = domain_lookup_rrset(domain, ldns_rr_get_type(rr));
00235 if (!rrset) {
00236
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
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
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
00289 domain = zonedata_lookup_domain(zone->zonedata, ldns_rr_owner(rr));
00290 if (!domain) {
00291
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
00298 rrset = domain_lookup_rrset(domain, ldns_rr_get_type(rr));
00299 if (!rrset) {
00300
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
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
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
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
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
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
00413 if (denial_what == TASK_NSECIFY) {
00414
00415 nsec3params_cleanup(zone->nsec3params);
00416 zone->nsec3params = NULL;
00417
00418 zonedata_wipe_denial(zone->zonedata);
00419 zonedata_cleanup_chain(zone->zonedata);
00420 zonedata_init_denial(zone->zonedata);
00421 }
00422
00423
00424 if (keys_what != TASK_NONE) {
00425 what = keys_what;
00426 } else {
00427 what = denial_what;
00428 }
00429 if (what == TASK_NONE) {
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
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
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
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
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
00764 time_t lastmod = 0;
00765
00766 const char* salt = NULL;
00767 ldns_rr* nsec3params_rr = NULL;
00768 nsec3params_type* nsec3params = NULL;
00769
00770 key_type* key = NULL;
00771
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
00783 if (!backup_read_check_str(fd, ODS_SE_FILE_MAGIC) ||
00784
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
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
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
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
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
00878 free((void*) token);
00879 token = NULL;
00880 break;
00881 } else {
00882
00883 goto recover_error;
00884 }
00885 free((void*) token);
00886 token = NULL;
00887 }
00888
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
00956 zone->zonedata->initialized = 1;
00957 zone->prepared = 1;
00958 if (zone->stats) {
00959 lock_basic_lock(&zone->stats->stats_lock);
00960 stats_clear(zone->stats);
00961 lock_basic_unlock(&zone->stats->stats_lock);
00962 }
00963 return ODS_STATUS_OK;
00964 } else {
00965
00966 filename = ods_build_path(zone->name, ".state", 0);
00967 fd = ods_fopen(filename, NULL, "r");
00968 free((void*)filename);
00969 if (fd) {
00970 if (!backup_read_check_str(fd, ODS_SE_FILE_MAGIC_V1) ||
00971 !backup_read_check_str(fd, ";name:") ||
00972 !backup_read_check_str(fd, zone->name) ||
00973 !backup_read_check_str(fd, ";class:") ||
00974 !backup_read_int(fd, &klass) ||
00975 !backup_read_check_str(fd, ";fetch:") ||
00976 !backup_read_int(fd, &fetch) ||
00977 !backup_read_check_str(fd, ";default_ttl:") ||
00978 !backup_read_uint32_t(fd, &ttl) ||
00979 !backup_read_check_str(fd, ";inbound_serial:") ||
00980 !backup_read_uint32_t(fd, &inbound) ||
00981 !backup_read_check_str(fd, ";internal_serial:") ||
00982 !backup_read_uint32_t(fd, &internal) ||
00983 !backup_read_check_str(fd, ";outbound_serial:") ||
00984 !backup_read_uint32_t(fd, &outbound) ||
00985 !backup_read_check_str(fd, ODS_SE_FILE_MAGIC_V1))
00986 {
00987 goto recover_error;
00988 }
00989 zone->klass = (ldns_rr_class) klass;
00990 zone->zonedata->default_ttl = ttl;
00991 zone->zonedata->inbound_serial = inbound;
00992 zone->zonedata->internal_serial = internal;
00993 zone->zonedata->outbound_serial = outbound;
00994
00995 zone->zonedata->initialized = 1;
00996 zone->prepared = 1;
00997 if (zone->stats) {
00998 lock_basic_lock(&zone->stats->stats_lock);
00999 stats_clear(zone->stats);
01000 lock_basic_unlock(&zone->stats->stats_lock);
01001 }
01002 return ODS_STATUS_UNCHANGED;
01003 }
01004 ods_fclose(fd);
01005 }
01006
01007 return ODS_STATUS_UNCHANGED;
01008
01009 recover_error:
01010 ods_log_error("[%s] unable to recover zone %s: corrupted file",
01011 zone_str, zone->name);
01012 ods_fclose(fd);
01013
01014
01015 signconf_cleanup(zone->signconf);
01016 zone->signconf = signconf_create();
01017 ods_log_assert(zone->signconf);
01018
01019
01020 task_cleanup(task);
01021 task = NULL;
01022
01023
01024 free((void*)salt);
01025 salt = NULL;
01026
01027 ldns_rr_free(nsec3params_rr);
01028 nsec3params_rr = NULL;
01029 nsec3params->rr = NULL;
01030 nsec3params_cleanup(nsec3params);
01031 nsec3params = NULL;
01032
01033
01034 zonedata_cleanup(zone->zonedata);
01035 zone->zonedata = zonedata_create(zone->allocator);
01036 ods_log_assert(zone->zonedata);
01037
01038 if (zone->stats) {
01039 lock_basic_lock(&zone->stats->stats_lock);
01040 stats_clear(zone->stats);
01041 lock_basic_unlock(&zone->stats->stats_lock);
01042 }
01043 return ODS_STATUS_ERR;
01044 }
01045
01046
01051 void
01052 zone_merge(zone_type* z1, zone_type* z2)
01053 {
01054 const char* str;
01055 adapter_type* adtmp = NULL;
01056
01057 if (!z1 || !z2) {
01058 return;
01059 }
01060
01061
01062 if (ods_strcmp(z2->policy_name, z1->policy_name) != 0) {
01063 if (z2->policy_name) {
01064 str = strdup(z2->policy_name);
01065 if (!str) {
01066 ods_log_error("[%s] failed to merge policy %s name to zone "
01067 "%s", zone_str, z2->policy_name, z1->name);
01068 } else {
01069 free((void*)z1->policy_name);
01070 z1->policy_name = str;
01071 z1->just_updated = 1;
01072 }
01073 } else {
01074 free((void*)z1->policy_name);
01075 z1->policy_name = NULL;
01076 z1->just_updated = 1;
01077 }
01078 }
01079
01080
01081 if (ods_strcmp(z2->signconf_filename, z1->signconf_filename) != 0) {
01082 if (z2->signconf_filename) {
01083 str = strdup(z2->signconf_filename);
01084 if (!str) {
01085 ods_log_error("[%s] failed to merge signconf filename %s to "
01086 "zone %s", zone_str, z2->policy_name, z1->name);
01087 } else {
01088 free((void*)z1->signconf_filename);
01089 z1->signconf_filename = str;
01090 z1->just_updated = 1;
01091 }
01092 } else {
01093 free((void*)z1->signconf_filename);
01094 z1->signconf_filename = NULL;
01095 z1->just_updated = 1;
01096 }
01097 }
01098
01099
01100 if (adapter_compare(z2->adinbound, z1->adinbound) != 0) {
01101 adtmp = z2->adinbound;
01102 z2->adinbound = z1->adinbound;
01103 z1->adinbound = adtmp;
01104 adtmp = NULL;
01105 }
01106 if (adapter_compare(z2->adoutbound, z1->adoutbound) != 0) {
01107 adtmp = z2->adoutbound;
01108 z2->adoutbound = z1->adoutbound;
01109 z1->adoutbound = adtmp;
01110 adtmp = NULL;
01111 }
01112 return;
01113 }
01114
01115
01120 ods_status
01121 zone_update_serial(zone_type* zone)
01122 {
01123 ods_status status = ODS_STATUS_OK;
01124 domain_type* domain = NULL;
01125 rrset_type* rrset = NULL;
01126 ldns_rdf* serial = NULL;
01127
01128 if (!zone) {
01129 ods_log_error("[%s] unable to update serial: no zone",
01130 zone_str);
01131 return ODS_STATUS_ASSERT_ERR;
01132 }
01133 ods_log_assert(zone);
01134
01135 if (!zone->signconf) {
01136 ods_log_error("[%s] unable to update serial: no signconf",
01137 zone_str);
01138 return ODS_STATUS_ASSERT_ERR;
01139 }
01140 ods_log_assert(zone->signconf);
01141
01142 if (!zone->zonedata) {
01143 ods_log_error("[%s] unable to update serial: no zonedata",
01144 zone_str);
01145 return ODS_STATUS_ASSERT_ERR;
01146 }
01147 ods_log_assert(zone->zonedata);
01148
01149 status = zonedata_update_serial(zone->zonedata, zone->signconf);
01150 if (status != ODS_STATUS_OK) {
01151 ods_log_error("[%s] unable to update serial: failed to increment",
01152 zone_str);
01153 return status;
01154 }
01155
01156
01157 domain = zonedata_lookup_domain(zone->zonedata, zone->dname);
01158 if (!domain) {
01159 ods_log_error("[%s] unable to update serial: apex not found",
01160 zone_str);
01161 return ODS_STATUS_ERR;
01162 }
01163 ods_log_assert(domain);
01164
01165
01166 rrset = domain_lookup_rrset(domain, LDNS_RR_TYPE_SOA);
01167 if (!rrset) {
01168 ods_log_error("[%s] unable to update serial: SOA RRset not found",
01169 zone_str);
01170 return ODS_STATUS_ERR;
01171 }
01172 ods_log_assert(rrset);
01173 ods_log_assert(rrset->rr_type == LDNS_RR_TYPE_SOA);
01174
01175 if (rrset->rrs && rrset->rrs->rr) {
01176 serial = ldns_rr_set_rdf(rrset->rrs->rr,
01177 ldns_native2rdf_int32(LDNS_RDF_TYPE_INT32,
01178 zone->zonedata->internal_serial), SE_SOA_RDATA_SERIAL);
01179 if (serial) {
01180 if (ldns_rdf2native_int32(serial) !=
01181 zone->zonedata->internal_serial) {
01182 rrset->needs_signing = 1;
01183 }
01184 ldns_rdf_deep_free(serial);
01185 } else {
01186 ods_log_error("[%s] unable to update serial: failed to replace "
01187 "SOA SERIAL rdata", zone_str);
01188 return ODS_STATUS_ERR;
01189 }
01190 }
01191 return ODS_STATUS_OK;
01192 }
01193
01194
01199 ods_status
01200 zone_print(FILE* fd, zone_type* zone)
01201 {
01202 if (fd && zone && zone->zonedata) {
01203 return zonedata_print(fd, zone->zonedata);
01204 }
01205 return ODS_STATUS_ASSERT_ERR;
01206 }
01207
01208
01213 ods_status
01214 zone_examine(zone_type* zone)
01215 {
01216 if (zone && zone->zonedata && zone->adinbound) {
01217 return zonedata_examine(zone->zonedata, zone->dname,
01218 zone->adinbound->type);
01219 }
01220 return ODS_STATUS_ASSERT_ERR;
01221 }
01222
01223
01228 void
01229 zone_cleanup(zone_type* zone)
01230 {
01231 allocator_type* allocator;
01232 lock_basic_type zone_lock;
01233
01234 if (!zone) {
01235 return;
01236 }
01237
01238 allocator = zone->allocator;
01239 zone_lock = zone->zone_lock;
01240
01241 ldns_rdf_deep_free(zone->dname);
01242 adapter_cleanup(zone->adinbound);
01243 adapter_cleanup(zone->adoutbound);
01244 zonedata_cleanup(zone->zonedata);
01245 signconf_cleanup(zone->signconf);
01246 nsec3params_cleanup(zone->nsec3params);
01247 stats_cleanup(zone->stats);
01248 allocator_deallocate(allocator, (void*) zone->notify_ns);
01249 allocator_deallocate(allocator, (void*) zone->policy_name);
01250 allocator_deallocate(allocator, (void*) zone->signconf_filename);
01251 allocator_deallocate(allocator, (void*) zone->name);
01252 allocator_deallocate(allocator, (void*) zone);
01253 allocator_cleanup(allocator);
01254 lock_basic_destroy(&zone_lock);
01255 return;
01256 }