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

/build/buildd-opendnssec_1.3.2-1~bpo60+1-powerpc-mjESd6/opendnssec-1.3.2/signer/src/signer/rrset.c

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

Generated on Sat Dec 17 2011 10:26:15 for OpenDNSSEC-signer by  doxygen 1.7.1