• Main Page
  • Data Structures
  • Files
  • File List
  • Globals

/build/buildd-opendnssec_1.3.2-1~bpo60+1-sparc-g2IJWF/opendnssec-1.3.2/signer/src/signer/zone.c

Go to the documentation of this file.
00001 /*
00002  * $Id: zone.c 5611 2011-09-12 14:15:58Z 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 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         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         /* backwards compatible backup recovery (serial) */
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             /* all ok */
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     /* signconf cleanup */
01015     signconf_cleanup(zone->signconf);
01016     zone->signconf = signconf_create();
01017     ods_log_assert(zone->signconf);
01018 
01019     /* task cleanup */
01020     task_cleanup(task);
01021     task = NULL;
01022 
01023     /* nsec3params cleanup */
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     /* zonedata cleanup */
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     /* policy name */
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     /* signconf filename */
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     /* adapters */
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     /* lookup domain */
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     /* lookup RRset */
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 }

Generated on Sat Dec 17 2011 11:48:48 for OpenDNSSEC-signer by  doxygen 1.7.1