OpenDNSSEC-signer  1.3.8
/build/buildd/opendnssec-1.3.8/signer/src/signer/rrset.c
Go to the documentation of this file.
00001 /*
00002  * $Id: rrset.c 6253 2012-04-10 09:17:28Z 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 "config.h"
00035 #include "daemon/worker.h"
00036 #include "scheduler/fifoq.h"
00037 #include "shared/allocator.h"
00038 #include "shared/duration.h"
00039 #include "shared/file.h"
00040 #include "shared/hsm.h"
00041 #include "shared/log.h"
00042 #include "shared/status.h"
00043 #include "shared/util.h"
00044 #include "signer/rrset.h"
00045 
00046 #include <ldns/ldns.h>
00047 #include <stdlib.h>
00048 #include <unistd.h>
00049 
00050 static const char* rrset_str = "rrset";
00051 
00052 
00057 void
00058 log_rr(ldns_rr* rr, const char* pre, int level)
00059 {
00060     char* str = NULL;
00061     size_t i = 0;
00062 
00063     if (ods_log_get_level() < level + 2) return;
00064 
00065     str = ldns_rr2str(rr);
00066     if (str) {
00067         str[(strlen(str))-1] = '\0';
00068         /* replace tabs with white space */
00069         for (i=0; i < strlen(str); i++) {
00070             if (str[i] == '\t') {
00071                 str[i] = ' ';
00072             }
00073         }
00074 
00075         if (level == 1) { /* LOG_ERR */
00076             ods_log_error("%s %s", pre?pre:"", str);
00077         } else if (level == 2) { /* LOG_WARNING */
00078             ods_log_warning("%s %s", pre?pre:"", str);
00079         } else if (level == 3) { /* LOG_NOTICE */
00080             ods_log_info("%s %s", pre?pre:"", str);
00081         } else if (level == 4) { /* LOG_INFO */
00082             ods_log_verbose("%s %s", pre?pre:"", str);
00083         } else if (level == 5) { /* LOG_DEBUG */
00084             ods_log_debug("%s %s", pre?pre:"", str);
00085         } else if (level == 6) { /* more debugging */
00086             ods_log_deeebug("%s %s", pre?pre:"", str);
00087         } else { /* hardcore debugging */
00088             ods_log_deeebug("%s %s", pre?pre:"", str);
00089         }
00090         free((void*)str);
00091     }
00092     return;
00093 }
00094 
00095 
00100 rrset_type*
00101 rrset_create(ldns_rr_type rrtype)
00102 {
00103     allocator_type* allocator = NULL;
00104     rrset_type* rrset = NULL;
00105 
00106     if (!rrtype) {
00107         ods_log_error("[%s] unable to create RRset: no RRtype", rrset_str);
00108         return NULL;
00109     }
00110     ods_log_assert(rrtype);
00111 
00112     allocator = allocator_create(malloc, free);
00113     if (!allocator) {
00114         ods_log_error("[%s] unable to create RRset %u: create allocator "
00115             "failed", rrset_str, (unsigned) rrtype);
00116         return NULL;
00117     }
00118     ods_log_assert(allocator);
00119 
00120     rrset = (rrset_type*) allocator_alloc(allocator, sizeof(rrset_type));
00121     if (!rrset) {
00122         ods_log_error("[%s] unable to create RRset %u: allocator failed",
00123             rrset_str, (unsigned) rrtype);
00124         allocator_cleanup(allocator);
00125         return NULL;
00126     }
00127     ods_log_assert(rrset);
00128 
00129     rrset->allocator = allocator;
00130     rrset->rr_type = rrtype;
00131     rrset->rr_count = 0;
00132     rrset->add_count = 0;
00133     rrset->del_count = 0;
00134     rrset->rrsig_count = 0;
00135     rrset->needs_signing = 0;
00136     rrset->rrs = ldns_dnssec_rrs_new();
00137     rrset->add = NULL;
00138     rrset->del = NULL;
00139     rrset->rrsigs = NULL;
00140     return rrset;
00141 }
00142 
00143 
00148 ods_status
00149 rrset_recover(rrset_type* rrset, ldns_rr* rrsig, const char* locator,
00150     uint32_t flags)
00151 {
00152     ods_status status = ODS_STATUS_OK;
00153 
00154     if (!rrset || !rrsig || !locator || !flags) {
00155         ods_log_error("[%s] unable to recover RRSIG: missing parameters",
00156             rrset_str);
00157         return ODS_STATUS_ASSERT_ERR;
00158     }
00159 
00160     if (!rrset->rrsigs) {
00161         rrset->rrsigs = rrsigs_create();
00162     }
00163 
00164     status = rrsigs_add_sig(rrset->rrsigs, rrsig, locator, flags);
00165     if (status != ODS_STATUS_OK) {
00166         ods_log_error("[%s] unable to recover RRSIG: failed to add", rrset_str);
00167         log_rr(rrsig, "+RRSIG", 1);
00168     } else {
00169         rrset->rrsig_count += 1;
00175         rrset->needs_signing = 0;
00176     }
00177     return status;
00178 }
00179 
00180 
00185 static int
00186 rrs_examine_ns_rdata(ldns_dnssec_rrs* rrs, ldns_rdf* nsdname)
00187 {
00188     ldns_dnssec_rrs* walk = NULL;
00189     if (!rrs || !nsdname) {
00190         return 0;
00191     }
00192     walk = rrs;
00193     while (walk) {
00194         if (walk->rr &&
00195             ldns_dname_compare(ldns_rr_rdf(walk->rr, 0), nsdname) == 0) {
00196             return 1;
00197         }
00198         walk = walk->next;
00199     }
00200     return 0;
00201 }
00202 
00203 
00208 int
00209 rrset_examine_ns_rdata(rrset_type* rrset, ldns_rdf* nsdname)
00210 {
00211     if (!rrset || !nsdname || rrset->rr_type != LDNS_RR_TYPE_NS) {
00212         return 0;
00213     }
00214     if (rrs_examine_ns_rdata(rrset->add, nsdname)) {
00215         return 1;
00216     }
00217     if (rrs_examine_ns_rdata(rrset->del, nsdname)) {
00218         return 0;
00219     }
00220     return rrs_examine_ns_rdata(rrset->rrs, nsdname);
00221 }
00222 
00223 
00228 size_t
00229 rrset_count_RR(rrset_type* rrset)
00230 {
00231     ods_log_assert(rrset);
00232     return ((rrset->rr_count + rrset->add_count) - rrset->del_count);
00233 }
00234 
00235 
00240 size_t
00241 rrset_count_rr(rrset_type* rrset, int which)
00242 {
00243     if (!rrset) {
00244         return 0;
00245     }
00246     switch (which) {
00247         case COUNT_ADD:
00248             return rrset->add_count;
00249         case COUNT_DEL:
00250             return rrset->del_count;
00251         case COUNT_RR:
00252         default:
00253             return rrset->rr_count;
00254     }
00255     /* not reached */
00256     return rrset->rr_count;
00257 }
00258 
00259 
00264 ldns_rr*
00265 rrset_add_rr(rrset_type* rrset, ldns_rr* rr)
00266 {
00267     ldns_status status = LDNS_STATUS_OK;
00268 
00269     if (!rr) {
00270         ods_log_error("[%s] unable to add RR: no RR", rrset_str);
00271         return NULL;
00272     }
00273     ods_log_assert(rr);
00274 
00275     if (!rrset) {
00276         ods_log_error("[%s] unable to add RR: no storage", rrset_str);
00277         return NULL;
00278     }
00279     ods_log_assert(rrset);
00280 
00281     if (rrset->rr_type != ldns_rr_get_type(rr)) {
00282         ods_log_error("[%s] unable to add RR: RRtype mismatch", rrset_str);
00283         return NULL;
00284     }
00285 
00286     if (!rrset->add) {
00287         rrset->add = ldns_dnssec_rrs_new();
00288     }
00289 
00290     if (!rrset->add->rr) {
00291         rrset->add->rr = rr;
00292         rrset->add_count = 1;
00293         log_rr(rr, "+rr", 7);
00294     } else {
00295         status = util_dnssec_rrs_add_rr(rrset->add, rr);
00296         if (status != LDNS_STATUS_OK) {
00297             if (status == LDNS_STATUS_NO_DATA) {
00298                 ods_log_warning("[%s] unable to add RR to RRset (%i): "
00299                       "duplicate", rrset_str, rrset->rr_type);
00300                 log_rr(rr, "+rr", 2);
00301                 /* filter out duplicates */
00302                 return rr;
00303             } else {
00304                 ods_log_error("[%s] unable to add RR to RRset (%i): %s",
00305                     rrset_str, rrset->rr_type,
00306                     ldns_get_errorstr_by_id(status));
00307                 log_rr(rr, "+rr", 1);
00308                 ldns_dnssec_rrs_deep_free(rrset->add);
00309                 rrset->add = NULL;
00310                 rrset->add_count = 0;
00311                 return NULL;
00312             }
00313         }
00314         rrset->add_count += 1;
00315         log_rr(rr, "+rr", 7);
00316     }
00317     return rr;
00318 }
00319 
00320 
00325 ldns_rr*
00326 rrset_del_rr(rrset_type* rrset, ldns_rr* rr, int dupallowed)
00327 {
00328     ldns_status status = LDNS_STATUS_OK;
00329 
00330     if (!rr) {
00331         ods_log_error("[%s] unable to delete RR: no RR", rrset_str);
00332         return NULL;
00333     }
00334     ods_log_assert(rr);
00335 
00336     if (!rrset) {
00337         ods_log_error("[%s] unable to delete RR: no storage", rrset_str);
00338         return NULL;
00339     }
00340     ods_log_assert(rrset);
00341 
00342     if (rrset->rr_type != ldns_rr_get_type(rr)) {
00343         ods_log_error("[%s] unable to delete RR: RRtype mismatch", rrset_str);
00344         return NULL;
00345     }
00346 
00347     if (!rrset->del) {
00348         rrset->del = ldns_dnssec_rrs_new();
00349     }
00350 
00351     if (!rrset->del->rr) {
00352         rrset->del->rr = rr;
00353         rrset->del_count = 1;
00354         log_rr(rr, "-rr", 7);
00355     } else {
00356         status = util_dnssec_rrs_add_rr(rrset->del, rr);
00357         if (status != LDNS_STATUS_OK) {
00358             if (status == LDNS_STATUS_NO_DATA) {
00359                 if (dupallowed) {
00360                     return rr;
00361                 }
00362                 ods_log_warning("[%s] unable to delete RR from RRset (%i): "
00363                     "duplicate", rrset_str, rrset->rr_type);
00364                 log_rr(rr, "-rr", 2);
00365                 /* filter out duplicates */
00366                 return rr;
00367             } else {
00368                 ods_log_error("[%s] unable to delete RR from RRset (%i): %s",
00369                    rrset_str, rrset->rr_type,
00370                    ldns_get_errorstr_by_id(status));
00371                 log_rr(rr, "-rr", 1);
00372                 ldns_dnssec_rrs_deep_free(rrset->del);
00373                 rrset->del = NULL;
00374                 rrset->del_count = 0;
00375                 return NULL;
00376             }
00377         }
00378         rrset->del_count += 1;
00379         log_rr(rr, "-rr", 7);
00380     }
00381     return rr;
00382 }
00383 
00384 
00389 ods_status
00390 rrset_wipe_out(rrset_type* rrset)
00391 {
00392     ldns_dnssec_rrs* rrs = NULL;
00393     ldns_rr* del_rr = NULL;
00394     int error = 0;
00395 
00396     if (rrset) {
00397         rrs = rrset->rrs;
00398     }
00399 
00400     while (rrs) {
00401         if (rrs->rr) {
00402             del_rr = ldns_rr_clone(rrs->rr);
00403             if (rrset_del_rr(rrset, del_rr,
00404                 (ldns_rr_get_type(del_rr) == LDNS_RR_TYPE_DNSKEY)) == NULL) {
00405                 ods_log_error("[%s] unable to wipe RR from RRset (%i)",
00406                     rrset_str, rrset->rr_type);
00407                 ldns_rr_free(del_rr);
00408                 error = 1;
00409             }
00410             del_rr = NULL;
00411         }
00412         rrs = rrs->next;
00413     }
00414 
00415     if (error) {
00416         return ODS_STATUS_ERR;
00417     }
00418     return ODS_STATUS_OK;
00419 }
00420 
00421 
00426 ods_status
00427 rrset_diff(rrset_type* rrset, keylist_type* kl)
00428 {
00429     ods_status status = ODS_STATUS_OK;
00430     ldns_status lstatus = LDNS_STATUS_OK;
00431     ldns_dnssec_rrs* current = NULL;
00432     ldns_dnssec_rrs* pending = NULL;
00433     ldns_dnssec_rrs* prev = NULL;
00434     ldns_rr* rr = NULL;
00435     int cmp = 0;
00436 
00437     if (!rrset) {
00438         return status;
00439     }
00440 
00441     current = rrset->rrs;
00442     pending = rrset->add;
00443 
00444     if (!current || !current->rr) {
00445         current = NULL;
00446     }
00447     if (!pending || !pending->rr) {
00448         pending = NULL;
00449     }
00450 
00451     while (current && pending) {
00452         lstatus = util_dnssec_rrs_compare(current->rr, pending->rr, &cmp);
00453         if (lstatus != LDNS_STATUS_OK) {
00454                 ods_log_error("[%s] diff failed: compare failed (%s)",
00455                     rrset_str, ldns_get_errorstr_by_id(lstatus));
00456                 return ODS_STATUS_ERR;
00457         }
00458 
00459         if (cmp > 0) {
00460             prev = pending;
00461             pending = pending->next;
00462         } else if (cmp < 0) {
00463             /* pend current RR to be removed */
00464             if (rrset->rr_type != LDNS_RR_TYPE_DNSKEY ||
00465                 !keylist_lookup_by_dnskey(kl, current->rr)) {
00466 
00467                 rr = ldns_rr_clone(current->rr);
00468                 rr = rrset_del_rr(rrset, rr,
00469                     (ldns_rr_get_type(rr) == LDNS_RR_TYPE_DNSKEY));
00470                 if (!rr) {
00471                     ods_log_error("[%s] diff failed: failed to delete RR",
00472                         rrset_str);
00473                     return ODS_STATUS_ERR;
00474                 }
00475             }
00476 
00477             current = current->next;
00478         } else { /* equal RRs */
00479             /* TTL is not compared in util_dnssec_rrs_compare() so we copy it */
00480             if (ldns_rr_ttl(current->rr) != ldns_rr_ttl(pending->rr)) {
00481                 ldns_rr_set_ttl(current->rr, ldns_rr_ttl(pending->rr));
00482                 rrset->needs_signing = 1;
00483             }
00484             /* remove pending RR */
00485             if (!prev) {
00486                 rrset->add = pending->next;
00487             } else {
00488                 prev->next = pending->next;
00489             }
00490             pending->next = NULL;
00491             rrset->add_count -= 1;
00492 
00493             ldns_dnssec_rrs_deep_free(pending);
00494             pending = NULL;
00495 
00496             current = current->next;
00497             if (!prev) {
00498                 pending = rrset->add;
00499             } else {
00500                 pending = prev->next;
00501             }
00502         }
00503     }
00504 
00505     if (pending) {
00506         ods_log_assert(!current);
00507         /* all newly added RRs */
00508     }
00509 
00510     if (current) {
00511         ods_log_assert(!pending);
00512         while (current) {
00513             /* pend current RR to be removed */
00514             if (rrset->rr_type != LDNS_RR_TYPE_DNSKEY ||
00515                 !keylist_lookup_by_dnskey(kl, current->rr)) {
00516 
00517                 rr = ldns_rr_clone(current->rr);
00518                 rr = rrset_del_rr(rrset, rr,
00519                     (ldns_rr_get_type(rr) == LDNS_RR_TYPE_DNSKEY));
00520                 if (!rr) {
00521                     ods_log_error("[%s] diff failed: failed to delete RR",
00522                         rrset_str);
00523                     return ODS_STATUS_ERR;
00524                 }
00525             }
00526             current = current->next;
00527         }
00528     }
00529     return ODS_STATUS_OK;
00530 }
00531 
00532 
00537 static ods_status
00538 rrset_commit_del(rrset_type* rrset, ldns_rr* rr)
00539 {
00540     ldns_status status = LDNS_STATUS_OK;
00541     ldns_dnssec_rrs* rrs = NULL;
00542     ldns_dnssec_rrs* prev_rrs = NULL;
00543     int cmp = 0;
00544 
00545     if (!rr) {
00546         ods_log_error("[%s] unable to commit del RR: no RR", rrset_str);
00547         return ODS_STATUS_ASSERT_ERR;
00548     }
00549     ods_log_assert(rr);
00550     if (!rrset) {
00551         ods_log_error("[%s] unable to commit del RR: no storage", rrset_str);
00552         return ODS_STATUS_ASSERT_ERR;
00553     }
00554     ods_log_assert(rrset);
00555 
00556     rrs = rrset->rrs;
00557     while (rrs) {
00558         status = util_dnssec_rrs_compare(rrs->rr, rr, &cmp);
00559         if (status != LDNS_STATUS_OK) {
00560             ods_log_error("[%s] unable to commit del RR: compare failed",
00561                 rrset_str);
00562             return ODS_STATUS_ERR;
00563         }
00564 
00565         if (cmp == 0) {
00566             /* this is it */
00567             if (prev_rrs) {
00568                 prev_rrs->next = rrs->next;
00569             } else {
00570                 rrset->rrs = rrs->next;
00571             }
00572             rrs->next = NULL;
00573             ldns_dnssec_rrs_deep_free(rrs);
00574             rrs = NULL;
00575 
00576             rrset->rr_count -= 1;
00577             rrset->del_count -= 1;
00578             log_rr(rr, "-RR", 6);
00579             return ODS_STATUS_OK;
00580         }
00581 
00582         /* keep looking */
00583         prev_rrs = rrs;
00584         rrs = rrs->next;
00585     }
00586 
00587     ods_log_warning("[%s] unable to commit del RR: no such RR", rrset_str);
00588     log_rr(rr, "-RR", 2);
00589     return ODS_STATUS_UNCHANGED;
00590 }
00591 
00592 
00597 static ods_status
00598 rrset_commit_add(rrset_type* rrset, ldns_rr* rr)
00599 {
00600     ldns_status status = LDNS_STATUS_OK;
00601 
00602     if (!rr) {
00603         ods_log_error("[%s] unable to commit add RR: no RR", rrset_str);
00604         return ODS_STATUS_ASSERT_ERR;
00605     }
00606     ods_log_assert(rr);
00607     if (!rrset) {
00608         ods_log_error("[%s] unable to commit add RR: no storage", rrset_str);
00609         return ODS_STATUS_ASSERT_ERR;
00610     }
00611     ods_log_assert(rrset);
00612 
00613     if (!rrset->rrs) {
00614         rrset->rrs = ldns_dnssec_rrs_new();
00615     }
00616 
00617     if (!rrset->rrs->rr) {
00618         rrset->rrs->rr = rr;
00619         rrset->rr_count += 1;
00620         rrset->add_count -= 1;
00621         log_rr(rr, "+RR", 6);
00622         return ODS_STATUS_OK;
00623     } else {
00624         status = util_dnssec_rrs_add_rr(rrset->rrs, rr);
00625         if (status != LDNS_STATUS_OK) {
00626             if (status == LDNS_STATUS_NO_DATA) {
00627                 ods_log_warning("[%s] unable to commit add RR: duplicate",
00628                     rrset_str);
00629                 log_rr(rr, "+RR", 2);
00630                 return ODS_STATUS_UNCHANGED;
00631             } else {
00632                 ods_log_error("[%s] unable to commit add RR: %s",
00633                     rrset_str, ldns_get_errorstr_by_id(status));
00634                 log_rr(rr, "+RR", 1);
00635                 return ODS_STATUS_ERR;
00636             }
00637         }
00638         log_rr(rr, "+RR", 6);
00639         rrset->rr_count += 1;
00640         rrset->add_count -= 1;
00641         return ODS_STATUS_OK;
00642     }
00643     /* not reached */
00644     return ODS_STATUS_ERR;
00645 }
00646 
00647 
00652 ods_status
00653 rrset_commit(rrset_type* rrset)
00654 {
00655     ldns_dnssec_rrs* rrs = NULL;
00656     ods_status status = ODS_STATUS_OK;
00657 
00658     if (!rrset) {
00659         return ODS_STATUS_ASSERT_ERR;
00660     }
00661     ods_log_assert(rrset);
00662 
00663     if (rrset->del_count || rrset->add_count) {
00664         rrset->needs_signing = 1;
00665     }
00666 
00667     /* delete RRs */
00668     rrs = rrset->del;
00669     while (rrs) {
00670         status = rrset_commit_del(rrset, rrs->rr);
00671         if (status != ODS_STATUS_OK) {
00672             ods_log_alert("[%s] commit RRset (%i) failed: %s", rrset_str,
00673                 rrset->rr_type, ods_status2str(status));
00674             return status;
00675         }
00676         rrs = rrs->next;
00677     }
00678     ldns_dnssec_rrs_deep_free(rrset->del);
00679     rrset->del = NULL;
00680     rrset->del_count = 0;
00681 
00682     /* add RRs */
00683     rrs = rrset->add;
00684     while (rrs) {
00685         status = rrset_commit_add(rrset, rrs->rr);
00686         if (status != ODS_STATUS_OK) {
00687             ods_log_alert("[%s] commit RRset (%i) failed: %s", rrset_str,
00688                 rrset->rr_type, ods_status2str(status));
00689             return status;
00690         }
00691         rrs = rrs->next;
00692     }
00693     ldns_dnssec_rrs_free(rrset->add);
00694     rrset->add = NULL;
00695     rrset->add_count = 0;
00696 
00697     /* update serial */
00698 
00699     return ODS_STATUS_OK;
00700 }
00701 
00702 
00707 void
00708 rrset_rollback(rrset_type* rrset)
00709 {
00710     if (!rrset) {
00711         return;
00712     }
00713 
00714     if (rrset->add) {
00715         ldns_dnssec_rrs_deep_free(rrset->add);
00716         rrset->add = NULL;
00717         rrset->add_count = 0;
00718     }
00719     if (rrset->del) {
00720         ldns_dnssec_rrs_deep_free(rrset->del);
00721         rrset->del = NULL;
00722         rrset->del_count = 0;
00723     }
00724     return;
00725 }
00726 
00727 
00732 static uint32_t
00733 rrset_recycle(rrset_type* rrset, signconf_type* sc, time_t signtime)
00734 {
00735     rrsigs_type* rrsigs = NULL;
00736     rrsigs_type* prev_rrsigs = NULL;
00737     rrsigs_type* next_rrsigs = NULL;
00738     uint32_t refresh = 0;
00739     uint32_t expiration = 0;
00740     uint32_t inception = 0;
00741     uint32_t reusedsigs = 0;
00742     int drop_sig = 0;
00743     key_type* key = NULL;
00744 
00745     /* Calculate the Refresh Window = Signing time + Refresh */
00746     if (sc && sc->sig_refresh_interval) {
00747         refresh = (uint32_t) (signtime +
00748             duration2time(sc->sig_refresh_interval));
00749     }
00750 
00751     /* 1. If the RRset has changed, drop all signatures */
00752     /* 2. If Refresh is disabled, drop all signatures */
00753     if (rrset->needs_signing || refresh <= (uint32_t) signtime) {
00754         ods_log_debug("[%s] drop signatures for RRset[%i]", rrset_str,
00755             rrset->rr_type);
00756         if (rrset->rrsigs) {
00757             rrsigs_cleanup(rrset->rrsigs);
00758             rrset->rrsigs = NULL;
00759         }
00760         rrset->rrsig_count = 0;
00761         rrset->needs_signing = 0;
00762         return 0;
00763     }
00764 
00765     /* 3. Check every signature if it matches the recycling logic. */
00766     rrsigs = rrset->rrsigs;
00767     while (rrsigs) {
00768         if (!rrsigs->rr) {
00769             ods_log_debug("[%s] signature set has no RRSIG record: "
00770                 "drop signatures for RRset[%i]", rrset_str, rrset->rr_type);
00771             rrsigs_cleanup(rrset->rrsigs);
00772             rrset->rrsigs = NULL;
00773             rrset->rrsig_count = 0;
00774             rrset->needs_signing = 0;
00775             return 0;
00776         }
00777 
00778         expiration = ldns_rdf2native_int32(
00779             ldns_rr_rrsig_expiration(rrsigs->rr));
00780         inception = ldns_rdf2native_int32(
00781             ldns_rr_rrsig_inception(rrsigs->rr));
00782 
00783         if (expiration < refresh) {
00784             /* 3a. Expiration - Refresh has passed */
00785             drop_sig = 1;
00786             ods_log_deeebug("[%s] refresh signature for RRset[%i]: "
00787                 "expiration minus refresh has passed: %u - %u < (signtime)",
00788                 rrset_str, rrset->rr_type, expiration, refresh,
00789                 (uint32_t) signtime);
00790         } else if (inception > (uint32_t) signtime) {
00791             /* 3b. Inception has not yet passed */
00792             drop_sig = 1;
00793             ods_log_deeebug("[%s] refresh signature for RRset[%i]: "
00794                 "inception has not passed: %u < %u (signtime)", rrset_str,
00795                 rrset->rr_type, inception, (uint32_t) signtime);
00796         } else {
00797             /* 3c. Corresponding key is dead (key is locator+flags) */
00798             key = keylist_lookup(sc->keys, rrsigs->key_locator);
00799             if (!key) {
00800                 drop_sig = 1;
00801                 ods_log_deeebug("[%s] refresh signature for RRset[%i]: "
00802                 "key %s %u is dead", rrset_str,
00803                 rrset->rr_type, rrsigs->key_locator, rrsigs->key_flags);
00804             } else if (key->flags != rrsigs->key_flags) {
00805                 drop_sig = 1;
00806                 ods_log_deeebug("[%s] refresh signature for RRset[%i]: "
00807                 "key %s %u flags mismatch", rrset_str,
00808                 rrset->rr_type, rrsigs->key_locator, rrsigs->key_flags);
00809             }
00810         }
00811 
00812         next_rrsigs = rrsigs->next;
00813         if (drop_sig) {
00814             /* A rule mismatched, refresh signature */
00815             if (prev_rrsigs) {
00816                 prev_rrsigs->next = rrsigs->next;
00817             } else {
00818                 rrset->rrsigs = rrsigs->next;
00819             }
00820             log_rr(rrsigs->rr, "-RRSIG", 6);
00821             rrset->rrsig_count -= 1;
00822             rrsigs->next = NULL;
00823             rrsigs_cleanup(rrsigs);
00824         } else {
00825             /* All rules ok, recycle signature */
00826             ods_log_deeebug("[%s] recycle signature for RRset[%i] "
00827                 "(refresh=%u, signtime=%u, inception=%u, expiration=%u)",
00828                 rrset_str, rrset->rr_type, refresh, (uint32_t) signtime,
00829                 inception, expiration);
00830             log_rr(rrsigs->rr, "*RRSIG", 7);
00831             reusedsigs += 1;
00832             prev_rrsigs = rrsigs;
00833         }
00834         drop_sig = 0;
00835         rrsigs = next_rrsigs;
00836     }
00837     return reusedsigs;
00838 }
00839 
00840 
00845 static int
00846 rrset_signed_with_algorithm(rrset_type* rrset, uint8_t algorithm)
00847 {
00848     rrsigs_type* rrsigs = NULL;
00849 
00850     if (!rrset || !algorithm) {
00851         return 0;
00852     }
00853 
00854     rrsigs = rrset->rrsigs;
00855     while (rrsigs) {
00856         if (rrsigs->rr && algorithm ==
00857             ldns_rdf2native_int8(ldns_rr_rrsig_algorithm(rrsigs->rr))) {
00858             return 1;
00859         }
00860         rrsigs = rrsigs->next;
00861     }
00862 
00863     return 0;
00864 }
00865 
00866 
00871 static ldns_rr_list*
00872 rrset2rrlist(rrset_type* rrset)
00873 {
00874     ldns_dnssec_rrs* rrs = NULL;
00875     ldns_rr_list* rr_list = NULL;
00876     int error = 0;
00877 
00878     rr_list = ldns_rr_list_new();
00879     rrs = rrset->rrs;
00880     while (rrs && rrs->rr) {
00881         error = (int) ldns_rr_list_push_rr(rr_list, rrs->rr);
00882         if (!error) {
00883             ldns_rr_list_free(rr_list);
00884             return NULL;
00885         }
00886         if (rrset->rr_type == LDNS_RR_TYPE_CNAME ||
00887             rrset->rr_type == LDNS_RR_TYPE_DNAME) {
00888             /* singleton types */
00889             return rr_list;
00890         }
00891         rrs = rrs->next;
00892     }
00893     return rr_list;
00894 }
00895 
00896 
00901 static void
00902 rrset_sigvalid_period(signconf_type* sc, ldns_rr_type rrtype, time_t signtime,
00903     time_t* inception, time_t* expiration)
00904 {
00905     time_t jitter = 0;
00906     time_t offset = 0;
00907     time_t validity = 0;
00908     time_t random_jitter = 0;
00909 
00910     if (!sc || !rrtype || !signtime) {
00911         return;
00912     }
00913 
00914     jitter = duration2time(sc->sig_jitter);
00915     if (jitter) {
00916         random_jitter = ods_rand(jitter*2);
00917     }
00918     offset = duration2time(sc->sig_inception_offset);
00919     if (rrtype == LDNS_RR_TYPE_NSEC || rrtype == LDNS_RR_TYPE_NSEC3) {
00920         validity = duration2time(sc->sig_validity_denial);
00921     } else {
00922         validity = duration2time(sc->sig_validity_default);
00923     }
00924 
00928     if (((validity + offset + random_jitter) - jitter) <
00929         ((validity + offset) - jitter) ) {
00930         ods_log_error("[%s] signature validity %u too low, should be at "
00931             "least %u", rrset_str,
00932             ((validity + offset + random_jitter) - jitter),
00933             ((validity + offset) - jitter));
00934     } else if (((validity + offset + random_jitter) - jitter) >
00935                ((validity + offset) + jitter) ) {
00936         ods_log_error("[%s] signature validity %u too high, should be at "
00937             "most %u", rrset_str,
00938             ((validity + offset + random_jitter) - jitter),
00939             ((validity + offset) + jitter));
00940     } else {
00941         ods_log_debug("[%s] signature validity %u in range [%u - %u]",
00942             rrset_str, ((validity + offset + random_jitter) - jitter),
00943             ((validity + offset) - jitter),
00944             ((validity + offset) + jitter));
00945     }
00946     *inception = signtime - offset;
00947     *expiration = (signtime + validity + random_jitter) - jitter;
00948     return;
00949 }
00950 
00951 
00956 ods_status
00957 rrset_sign(hsm_ctx_t* ctx, rrset_type* rrset, ldns_rdf* owner,
00958     signconf_type* sc, time_t signtime, stats_type* stats)
00959 {
00960     ods_status status = ODS_STATUS_OK;
00961     uint32_t newsigs = 0;
00962     uint32_t reusedsigs = 0;
00963     ldns_rr* rrsig = NULL;
00964     ldns_rr_list* rr_list = NULL;
00965     rrsigs_type* new_rrsigs = NULL;
00966     rrsigs_type* walk_rrsigs = NULL;
00967     key_type* key = NULL;
00968     time_t inception = 0;
00969     time_t expiration = 0;
00970 
00971     if (!rrset) {
00972         ods_log_error("[%s] unable to sign RRset: no RRset", rrset_str);
00973         return ODS_STATUS_ASSERT_ERR;
00974     }
00975     ods_log_assert(rrset);
00976 
00977     if (!owner) {
00978         ods_log_error("[%s] unable to sign RRset: no owner", rrset_str);
00979         return ODS_STATUS_ASSERT_ERR;
00980     }
00981     ods_log_assert(owner);
00982 
00983     if (!sc) {
00984         ods_log_error("[%s] unable to sign RRset: no signconf", rrset_str);
00985         return ODS_STATUS_ASSERT_ERR;
00986     }
00987     ods_log_assert(sc);
00988 
00989     /* recycle signatures */
00990     reusedsigs = rrset_recycle(rrset, sc, signtime);
00991 
00992     /* transmogrify the RRset */
00993     rr_list = rrset2rrlist(rrset);
00994     if (!rr_list) {
00995         ods_log_error("[%s] unable to sign RRset[%i]: to RRlist failed",
00996             rrset_str, rrset->rr_type);
00997         return ODS_STATUS_ERR;
00998     }
00999     if (ldns_rr_list_rr_count(rr_list) <= 0) {
01000         /* empty RRset, no signatures needed */
01001         ldns_rr_list_free(rr_list);
01002         return ODS_STATUS_OK;
01003     }
01004 
01005     /* prepare for signing */
01006     new_rrsigs = rrsigs_create();
01007     if (!rrset->rrsigs) {
01008         rrset->rrsigs = rrsigs_create();
01009     }
01010     rrset_sigvalid_period(sc, rrset->rr_type, signtime,
01011          &inception, &expiration);
01012 
01013     key = sc->keys->first_key;
01014     while (key) {
01015         /* ksk or zsk ? */
01016         if (!key->zsk && rrset->rr_type != LDNS_RR_TYPE_DNSKEY) {
01017             ods_log_deeebug("[%s] skipping key %s for signing RRset[%i]: no "
01018                 "active ZSK", rrset_str, key->locator, rrset->rr_type);
01019             key = key->next;
01020             continue;
01021         }
01022         if (!key->ksk && rrset->rr_type == LDNS_RR_TYPE_DNSKEY) {
01023             ods_log_deeebug("[%s] skipping key %s for signing RRset[%i]: no "
01024                 "active KSK", rrset_str, key->locator, rrset->rr_type);
01025             key = key->next;
01026             continue;
01027         }
01028 
01029         /* is there a signature with this algorithm already? */
01030         if (rrset_signed_with_algorithm(rrset, key->algorithm)) {
01031             ods_log_deeebug("[%s] skipping key %s for signing: RRset[%i] "
01032                 "already has signature with same algorithm", rrset_str,
01033                 key->locator, rrset->rr_type);
01034             key = key->next;
01035             continue;
01036         }
01037 
01043         /* sign the RRset with current key */
01044         ods_log_deeebug("[%s] signing RRset[%i] with key %s", rrset_str,
01045             rrset->rr_type, key->locator);
01046         rrsig = lhsm_sign(ctx, rr_list, key, owner, inception, expiration);
01047         if (!rrsig) {
01048             ods_log_error("[%s] unable to sign RRset[%i]: error creating "
01049                 "RRSIG RR", rrset_str, rrset->rr_type);
01050             ldns_rr_list_free(rr_list);
01051             rrsigs_cleanup(new_rrsigs);
01052             return ODS_STATUS_ERR;
01053         }
01054         /* add the signature to the set of new signatures */
01055         ods_log_deeebug("[%s] new signature created for RRset[%i]", rrset_str,
01056             rrset->rr_type);
01057         log_rr(rrsig, "+rrsig", 7);
01058         status = rrsigs_add_sig(new_rrsigs, rrsig, key->locator, key->flags);
01059         if (status == ODS_STATUS_UNCHANGED) {
01060             ods_log_warning("[%s] unable to add duplicate RRSIG: skipping",
01061                 rrset_str);
01062             log_rr(rrsig, "~RRSIG", 2);
01063             status = ODS_STATUS_OK;
01064             ldns_rr_free(rrsig);
01065             rrsig = NULL;
01066         } else if (status != ODS_STATUS_OK) {
01067             ods_log_error("[%s] unable to sign RRset[%i]: error adding RRSIG",
01068                 rrset_str, rrset->rr_type);
01069                 log_rr(rrsig, "+RRSIG", 1);
01070                 ldns_rr_list_free(rr_list);
01071                 rrsigs_cleanup(new_rrsigs);
01072             return status;
01073         }
01074         /* next key */
01075         key = key->next;
01076     }
01077 
01078     /* signing completed, add the signatures to the right RRset */
01079     walk_rrsigs = new_rrsigs;
01080     while (walk_rrsigs) {
01081         if (walk_rrsigs->rr) {
01082             ods_log_deeebug("[%s] adding signature to RRset[%i]", rrset_str,
01083                     rrset->rr_type);
01084             status = rrsigs_add_sig(rrset->rrsigs,
01085                 ldns_rr_clone(walk_rrsigs->rr),
01086                 walk_rrsigs->key_locator, walk_rrsigs->key_flags);
01087             if (status == ODS_STATUS_UNCHANGED) {
01088                 ods_log_warning("[%s] unable to add duplicate RRSIG to "
01089                     "RRset[%i]: skipping", rrset_str, rrset->rr_type);
01090                 log_rr(walk_rrsigs->rr, "~RRSIG", 2);
01091                 status = ODS_STATUS_OK;
01092             } else if (status != ODS_STATUS_OK) {
01093                 ods_log_error("[%s] unable to sign RRset[%i]: error adding "
01094                     "RRSIG to RRset[%i]", rrset_str, rrset->rr_type,
01095                     rrset->rr_type);
01096                 log_rr(walk_rrsigs->rr, "+RRSIG", 1);
01097                 ldns_rr_list_free(rr_list);
01098                 rrsigs_cleanup(new_rrsigs);
01099                 return status;
01100             }
01101             rrset->rrsig_count += 1;
01102             newsigs++;
01103             log_rr(walk_rrsigs->rr, "+RRSIG", 6);
01104         }
01105         walk_rrsigs = walk_rrsigs->next;
01106     }
01107 
01108     /* clean up */
01109     rrsigs_cleanup(new_rrsigs);
01110     ldns_rr_list_free(rr_list);
01111 
01112     lock_basic_lock(&stats->stats_lock);
01113     if (rrset->rr_type == LDNS_RR_TYPE_SOA) {
01114         stats->sig_soa_count += newsigs;
01115     }
01116     stats->sig_count += newsigs;
01117     stats->sig_reuse += reusedsigs;
01118     lock_basic_unlock(&stats->stats_lock);
01119     return ODS_STATUS_OK;
01120 }
01121 
01122 
01127 ods_status
01128 rrset_queue(rrset_type* rrset, fifoq_type* q, worker_type* worker)
01129 {
01130     ods_status status = ODS_STATUS_UNCHANGED;
01131     int tries = 0;
01132 
01133     if (!rrset) {
01134         ods_log_error("[%s] unable to queue RRset: no RRset", rrset_str);
01135         return ODS_STATUS_ASSERT_ERR;
01136     }
01137     ods_log_assert(rrset);
01138     if (!worker) {
01139         ods_log_error("[%s] unable to queue RRset: no worker", rrset_str);
01140         return ODS_STATUS_ASSERT_ERR;
01141     }
01142     ods_log_assert(worker);
01143     if (!q) {
01144         ods_log_error("[%s] unable to queue RRset: no queue", rrset_str);
01145         return ODS_STATUS_ASSERT_ERR;
01146     }
01147     ods_log_assert(q);
01148 
01149     while (status == ODS_STATUS_UNCHANGED && !worker->need_to_exit) {
01150         tries++;
01151         lock_basic_lock(&q->q_lock);
01152         status = fifoq_push(q, (void*) rrset, worker, &tries);
01157         if (status == ODS_STATUS_UNCHANGED) {
01158             worker_wait_timeout_locked(&q->q_lock, &q->q_nonfull, 60);
01159         }
01160         lock_basic_unlock(&q->q_lock);
01161     }
01162     if (status == ODS_STATUS_OK) {
01163         lock_basic_lock(&worker->worker_lock);
01164         /* [LOCK] worker */
01165         worker->jobs_appointed += 1;
01166         /* [UNLOCK] worker */
01167         lock_basic_unlock(&worker->worker_lock);
01168     }
01169     return status;
01170 }
01171 
01172 
01177 void
01178 rrset_cleanup(rrset_type* rrset)
01179 {
01180     allocator_type* allocator;
01181 
01182     if (!rrset) {
01183         return;
01184     }
01185     allocator = rrset->allocator;
01186 
01187     if (rrset->rrs) {
01188         ldns_dnssec_rrs_deep_free(rrset->rrs);
01189         rrset->rrs = NULL;
01190     }
01191     if (rrset->add) {
01192         ldns_dnssec_rrs_deep_free(rrset->add);
01193         rrset->add = NULL;
01194     }
01195     if (rrset->del) {
01196         ldns_dnssec_rrs_deep_free(rrset->del);
01197         rrset->del = NULL;
01198     }
01199     if (rrset->rrsigs) {
01200         rrsigs_cleanup(rrset->rrsigs);
01201         rrset->rrsigs = NULL;
01202     }
01203 
01204     allocator_deallocate(allocator, (void*) rrset);
01205     allocator_cleanup(allocator);
01206     return;
01207 }
01208 
01209 
01214 void
01215 rrset_print(FILE* fd, rrset_type* rrset, int skip_rrsigs)
01216 {
01217     if (!rrset || !fd) {
01218         return;
01219     }
01220     ods_log_assert(fd);
01221     ods_log_assert(rrset);
01222 
01223     if (rrset->rrs) {
01224         if (rrset->rr_type == LDNS_RR_TYPE_CNAME ||
01225             rrset->rr_type == LDNS_RR_TYPE_DNAME) {
01226             /* singleton types */
01227             if (rrset->rrs->rr) {
01228                 ldns_rr_print(fd, rrset->rrs->rr);
01229             }
01230         } else {
01231             ldns_dnssec_rrs_print(fd, rrset->rrs);
01232         }
01233     }
01234     if (rrset->rrsigs && !skip_rrsigs) {
01235         rrsigs_print(fd, rrset->rrsigs, 0);
01236     }
01237     return;
01238 }
01239 
01240 
01245 void
01246 rrset_backup(FILE* fd, rrset_type* rrset)
01247 {
01248     if (!rrset || !fd) {
01249         return;
01250     }
01251     if (rrset->rrsigs) {
01252         rrsigs_print(fd, rrset->rrsigs, 1);
01253     }
01254     return;
01255 }