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