OpenDNSSEC-signer 1.2.1

/build/buildd-opendnssec_1.2.1.dfsg-1-mips-p9AT07/opendnssec-1.2.1.dfsg/signer/src/signer/rrset.c

Go to the documentation of this file.
00001 /*
00002  * $Id: rrset.c 4521 2011-03-01 14:56:15Z 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 "signer/hsm.h"
00036 #include "signer/rrset.h"
00037 #include "util/duration.h"
00038 #include "util/log.h"
00039 #include "util/se_malloc.h"
00040 #include "util/util.h"
00041 
00042 #include <ldns/ldns.h> /* ldns_rr_*(), ldns_dnssec_*() */
00043 
00044 
00049 rrset_type*
00050 rrset_create(ldns_rr_type rrtype)
00051 {
00052     rrset_type* rrset = (rrset_type*) se_calloc(1, sizeof(rrset_type));
00053     se_log_assert(rrtype);
00054     rrset->rr_type = rrtype;
00055     rrset->rr_count = 0;
00056     rrset->rrsig_count = 0;
00057     rrset->add_count = 0;
00058     rrset->del_count = 0;
00059     rrset->internal_serial = 0;
00060     rrset->initialized = 0;
00061     rrset->rrs = ldns_dnssec_rrs_new();
00062     rrset->add = NULL;
00063     rrset->del = NULL;
00064     rrset->rrsigs = NULL;
00065     rrset->drop_signatures = 0;
00066     return rrset;
00067 }
00068 
00069 
00074 rrset_type*
00075 rrset_create_frm_rr(ldns_rr* rr)
00076 {
00077     rrset_type* rrset = (rrset_type*) se_calloc(1, sizeof(rrset_type));
00078     se_log_assert(rr);
00079     rrset->rr_type = ldns_rr_get_type(rr);
00080     rrset->rr_count = 1;
00081     rrset->add_count = 0;
00082     rrset->del_count = 0;
00083     rrset->rrsig_count = 0;
00084     rrset->internal_serial = 0;
00085     rrset->initialized = 0;
00086     rrset->rrs = ldns_dnssec_rrs_new();
00087     rrset->rrs->rr = rr;
00088     rrset->add = NULL;
00089     rrset->del = NULL;
00090     rrset->rrsigs = NULL;
00091     rrset->drop_signatures = 0;
00092     return rrset;
00093 }
00094 
00099 int
00100 rrset_compare_rrs(ldns_dnssec_rrs* rrs1, ldns_dnssec_rrs* rrs2)
00101 {
00102     int cmp = 0;
00103     ldns_status status = LDNS_STATUS_OK;
00104 
00105     if (!rrs1 || !rrs2) {
00106         return 1;
00107     }
00108     while (rrs1 && rrs2) {
00109         if (rrs1->rr && rrs2->rr) {
00110             status = util_dnssec_rrs_compare(rrs1->rr, rrs2->rr, &cmp);
00111             if (status != LDNS_STATUS_OK || cmp != 0) {
00112                 return cmp;
00113             }
00114             /* check ttl */
00115             if (ldns_rr_ttl(rrs1->rr) != ldns_rr_ttl(rrs2->rr)) {
00116                 return ldns_rr_ttl(rrs1->rr) - ldns_rr_ttl(rrs2->rr);
00117             }
00118 
00119             /* the same */
00120         } else {
00121             return 1;
00122         }
00123         rrs1 = rrs1->next;
00124         rrs2 = rrs2->next;
00125     }
00126 
00127     if (!rrs1 && !rrs2) {
00128         return 0;
00129     }
00130     return 1;
00131 }
00132 
00133 
00138 static int
00139 rrs_examine_ns_rdata(ldns_dnssec_rrs* rrs, ldns_rdf* nsdname)
00140 {
00141     ldns_dnssec_rrs* walk = NULL;
00142 
00143     if (!rrs || !nsdname) {
00144         return 1;
00145     }
00146     walk = rrs;
00147     while (walk) {
00148         if (walk->rr &&
00149             ldns_dname_compare(ldns_rr_rdf(walk->rr, 0), nsdname) == 0) {
00150             return 0;
00151         }
00152         walk = walk->next;
00153     }
00154     return 1;
00155 }
00156 
00157 
00162 int
00163 rrset_examine_ns_rdata(rrset_type* rrset, ldns_rdf* nsdname)
00164 {
00165     if (!rrset || !nsdname || rrset->rr_type != LDNS_RR_TYPE_NS) {
00166         return 1;
00167     }
00168 
00169     if (rrs_examine_ns_rdata(rrset->add, nsdname) == 0) {
00170         return 0;
00171     }
00172     if (rrs_examine_ns_rdata(rrset->del, nsdname) == 0) {
00173         return 1;
00174     }
00175     if (rrs_examine_ns_rdata(rrset->rrs, nsdname) == 0) {
00176         return 0;
00177     }
00178     return 1;
00179 }
00180 
00181 
00186 void
00187 log_rr(ldns_rr* rr, const char* pre, int level)
00188 {
00189     char* str = NULL;
00190 
00191     str = ldns_rr2str(rr);
00192     if (str) {
00193         str[(strlen(str))-1] = '\0';
00194     }
00195     if (level == 1) {
00196         se_log_error("%s %s", pre?pre:"", str?str:"(null)");
00197     } else if (level == 2) {
00198         se_log_warning("%s %s", pre?pre:"", str?str:"(null)");
00199     } else if (level == 3) {
00200         se_log_info("%s %s", pre?pre:"", str?str:"(null)");
00201     } else if (level == 4) {
00202         se_log_verbose("%s %s", pre?pre:"", str?str:"(null)");
00203     } else if (level == 5) {
00204         se_log_debug("%s %s", pre?pre:"", str?str:"(null)");
00205     } else {
00206         se_log_deeebug("%s %s", pre?pre:"", str?str:"(null)");
00207     }
00208     se_free((void*)str);
00209     return;
00210 }
00211 
00212 
00217 static ldns_status
00218 rrset_add_pending_rr(rrset_type* rrset, ldns_rr* rr)
00219 {
00220     ldns_status status = LDNS_STATUS_OK;
00221 
00222     if (!rrset->rrs) {
00223         rrset->rrs = ldns_dnssec_rrs_new();
00224     }
00225 
00226     if (!rrset->rrs->rr) {
00227         rrset->rrs->rr = rr;
00228         rrset->rr_count += 1;
00229         rrset->add_count -= 1;
00230         log_rr(rr, "+RR", 6);
00231         return LDNS_STATUS_OK;
00232     } else {
00233         status = util_dnssec_rrs_add_rr(rrset->rrs, rr);
00234         if (status != LDNS_STATUS_OK) {
00235             if (status == LDNS_STATUS_NO_DATA) {
00236                 se_log_warning("error adding RR to RRset (%i): duplicate",
00237                     rrset->rr_type);
00238                 log_rr(rr, "+RR", 2);
00239                 return LDNS_STATUS_OK;
00240             } else {
00241                 se_log_error("error adding RR to RRset (%i): %s",
00242                     rrset->rr_type, ldns_get_errorstr_by_id(status));
00243                 log_rr(rr, "+RR", 1);
00244                 return status;
00245             }
00246         }
00247         log_rr(rr, "+RR", 6);
00248         rrset->rr_count += 1;
00249         rrset->add_count -= 1;
00250         return LDNS_STATUS_OK;
00251     }
00252     /* not reached */
00253     return LDNS_STATUS_ERR;
00254 }
00255 
00256 
00261 static void
00262 rrset_del_pending_rr(rrset_type* rrset, ldns_rr* rr)
00263 {
00264     ldns_dnssec_rrs* rrs = NULL;
00265     ldns_dnssec_rrs* prev_rrs = NULL;
00266 
00267     rrs = rrset->rrs;
00268     while (rrs) {
00269         if (util_soa_compare(rrs->rr, rr) == 0 ||
00270             ldns_rr_compare(rrs->rr, rr) == 0) {
00271             /* this is it */
00272             if (prev_rrs) {
00273                 prev_rrs->next = rrs->next;
00274             } else {
00275                 rrset->rrs = rrs->next;
00276             }
00277             ldns_rr_free(rrs->rr);
00278             se_free((void*)rrs);
00279             rrset->rr_count -= 1;
00280             rrset->del_count -= 1;
00281             log_rr(rr, "-RR", 6);
00282             return;
00283         }
00284         prev_rrs = rrs;
00285         rrs = rrs->next;
00286     }
00287     se_log_warning("error deleting RR from RRset (%i): does not exist",
00288         rrset->rr_type);
00289     log_rr(rr, "-RR", 2);
00290     return;
00291 }
00292 
00293 
00298 int
00299 rrset_recover_rr_from_backup(rrset_type* rrset, ldns_rr* rr)
00300 {
00301     return !(rrset_add_pending_rr(rrset, rr) == LDNS_STATUS_OK);
00302 }
00303 
00304 
00309 int
00310 rrset_recover_rrsig_from_backup(rrset_type* rrset, ldns_rr* rrsig,
00311     const char* locator, uint32_t flags)
00312 {
00313     int error = 0;
00314 
00315     se_log_assert(rrset);
00316     se_log_assert(rrsig);
00317 
00318     if (!rrset->rrsigs) {
00319         rrset->rrsigs = rrsigs_create();
00320     }
00321 
00322     error = rrsigs_add_sig(rrset->rrsigs, rrsig, locator, flags);
00323     if (!error) {
00324         rrset->rrsig_count += 1;
00325     } else {
00326         switch (error) {
00327             case 2:
00328                 se_log_warning("error adding RRSIG to RRset (%i): duplicate",
00329                     rrset->rr_type);
00330                 log_rr(rrsig, "+RR", 2);
00331                 break;
00332             case 1:
00333                 se_log_error("error adding RRSIG to RRset (%i): compare failed",
00334                     rrset->rr_type);
00335                 log_rr(rrsig, "+RR", 2);
00336                 break;
00337             default:
00338                 se_log_error("error adding RRSIG to RRset (%i): unknown error",
00339                     rrset->rr_type);
00340                 log_rr(rrsig, "+RR", 2);
00341                 break;
00342         }
00343     }
00344     return error;
00345 }
00346 
00347 
00352 int
00353 rrset_update(rrset_type* rrset, uint32_t serial)
00354 {
00355     ldns_dnssec_rrs* rrs = NULL;
00356     ldns_status status = LDNS_STATUS_OK;
00357 
00358     se_log_assert(rrset);
00359 
00360     if (!rrset->initialized || DNS_SERIAL_GT(serial, rrset->internal_serial)) {
00361         /* compare del and add */
00362         if (rrset_compare_rrs(rrset->del, rrset->add) != 0) {
00363             rrset->drop_signatures = 1;
00364         }
00365 
00366         /* delete RRs */
00367         rrs = rrset->del;
00368         while (rrs) {
00369             if (rrs->rr) {
00370                 rrset_del_pending_rr(rrset, rrs->rr);
00371             }
00372             rrs = rrs->next;
00373         }
00374         ldns_dnssec_rrs_deep_free(rrset->del);
00375         rrset->del = NULL;
00376         rrset->del_count = 0;
00377 
00378         /* add RRs */
00379         rrs = rrset->add;
00380         while (rrs) {
00381             if (rrs->rr) {
00382                 status = rrset_add_pending_rr(rrset, rrs->rr);
00383                 if (status != LDNS_STATUS_OK) {
00384                     se_log_alert("update RRset[%i] to serial %u failed",
00385                         rrset->rr_type, serial);
00386                     return 1;
00387                 }
00388             }
00389             rrs = rrs->next;
00390         }
00391         ldns_dnssec_rrs_free(rrset->add);
00392         rrset->add = NULL;
00393         rrset->add_count = 0;
00394 
00395         /* update serial */
00396         rrset->internal_serial = serial;
00397         rrset->initialized = 1;
00398     }
00399     return 0;
00400 }
00401 
00406 void
00407 rrset_cancel_update(rrset_type* rrset)
00408 {
00409     if (rrset->add) {
00410         ldns_dnssec_rrs_deep_free(rrset->add);
00411         rrset->add = NULL;
00412         rrset->add_count = 0;
00413     }
00414     if (rrset->del) {
00415         ldns_dnssec_rrs_deep_free(rrset->del);
00416         rrset->del = NULL;
00417         rrset->del_count = 0;
00418     }
00419     return;
00420 }
00421 
00426 int
00427 rrset_count_rr(rrset_type* rrset)
00428 {
00429     se_log_assert(rrset);
00430     return rrset->rr_count;
00431 }
00432 
00433 
00438 int
00439 rrset_count_add(rrset_type* rrset)
00440 {
00441     se_log_assert(rrset);
00442     return rrset->add_count;
00443 }
00444 
00445 
00450 int
00451 rrset_count_del(rrset_type* rrset)
00452 {
00453     se_log_assert(rrset);
00454     return rrset->del_count;
00455 }
00456 
00457 
00462 int
00463 rrset_count_RR(rrset_type* rrset)
00464 {
00465     se_log_assert(rrset);
00466     return ((rrset->rr_count + rrset->add_count) - rrset->del_count);
00467 }
00468 
00469 
00474 int
00475 rrset_add_rr(rrset_type* rrset, ldns_rr* rr)
00476 {
00477     ldns_status status = LDNS_STATUS_OK;
00478 
00479     se_log_assert(rr);
00480     se_log_assert(rrset);
00481     se_log_assert(ldns_rr_get_type(rr) == rrset->rr_type);
00482 
00483     if (!rrset->add) {
00484         rrset->add = ldns_dnssec_rrs_new();
00485     }
00486 
00487     if (!rrset->add->rr) {
00488         rrset->add->rr = rr;
00489         rrset->add_count = 1;
00490         log_rr(rr, "+rr", 6);
00491     } else {
00492         status = util_dnssec_rrs_add_rr(rrset->add, rr);
00493         if (status != LDNS_STATUS_OK) {
00494             if (status == LDNS_STATUS_NO_DATA) {
00495                 se_log_warning("error adding RR to pending add RRset (%i): "
00496                     "duplicate", rrset->rr_type);
00497                 log_rr(rr, "+rr", 2);
00498                 return 0;
00499             } else {
00500                 se_log_error("error adding RR to pending add RRset (%i): %s",
00501                     rrset->rr_type, ldns_get_errorstr_by_id(status));
00502                 log_rr(rr, "+rr", 1);
00503                 ldns_dnssec_rrs_deep_free(rrset->add);
00504                 rrset->add = NULL;
00505                 rrset->add_count = 0;
00506                 return 1;
00507             }
00508         }
00509         rrset->add_count += 1;
00510         log_rr(rr, "+rr", 6);
00511     }
00512     return 0;
00513 }
00514 
00515 
00520 int
00521 rrset_del_rr(rrset_type* rrset, ldns_rr* rr)
00522 {
00523     ldns_status status = LDNS_STATUS_OK;
00524 
00525     se_log_assert(rr);
00526     se_log_assert(rrset);
00527     se_log_assert(ldns_rr_get_type(rr) == rrset->rr_type);
00528 
00529     if (!rrset->del) {
00530         rrset->del = ldns_dnssec_rrs_new();
00531     }
00532 
00533     if (!rrset->del->rr) {
00534         rrset->del->rr = rr;
00535         rrset->del_count = 1;
00536         log_rr(rr, "-rr", 6);
00537     } else {
00538         status = util_dnssec_rrs_add_rr(rrset->del, rr);
00539         if (status != LDNS_STATUS_OK) {
00540             if (status == LDNS_STATUS_NO_DATA) {
00541                 se_log_warning("error adding RR to pending del RRset (%i): "
00542                     "duplicate", rrset->rr_type);
00543                 log_rr(rr, "-rr", 2);
00544                 return 0;
00545             } else {
00546                 se_log_error("error adding RR to pending del RRset (%i): %s",
00547                    rrset->rr_type, ldns_get_errorstr_by_id(status));
00548                 log_rr(rr, "-rr", 1);
00549                 ldns_dnssec_rrs_deep_free(rrset->del);
00550                 rrset->del = NULL;
00551                 rrset->del_count = 0;
00552                 return 1;
00553             }
00554         }
00555         rrset->del_count += 1;
00556         log_rr(rr, "-rr", 6);
00557     }
00558     return 0;
00559 }
00560 
00561 
00566 static int
00567 rrset_recycle_rrsigs(rrset_type* rrset, signconf_type* sc, time_t signtime,
00568     uint32_t* reusedsigs)
00569 {
00570     rrsigs_type* rrsigs = NULL;
00571     rrsigs_type* prev_rrsigs = NULL;
00572     rrsigs_type* next_rrsigs = NULL;
00573     uint32_t refresh = 0;
00574     uint32_t expiration = 0;
00575     uint32_t inception = 0;
00576     int drop_sig = 0;
00577     key_type* key = NULL;
00578 
00579     if (sc && sc->sig_refresh_interval) {
00580         refresh = (uint32_t) (signtime +
00581             duration2time(sc->sig_refresh_interval));
00582     }
00583 
00584     /* 1. If the RRset has changed, drop all signatures */
00585     /* 2. If Refresh is disabled, drop all signatures */
00586     if (rrset->drop_signatures || !refresh) {
00587         se_log_debug("drop signatures for RRset[%i]", rrset->rr_type);
00588         if (rrset->rrsigs) {
00589             rrsigs_cleanup(rrset->rrsigs);
00590             rrset->rrsigs = NULL;
00591         }
00592         rrset->rrsig_count = 0;
00593         rrset->drop_signatures = 0;
00594         return 0;
00595     }
00596 
00597     /* 3. Check every signature if it matches the recycling logic. */
00598     rrsigs = rrset->rrsigs;
00599     while (rrsigs) {
00600         if (!rrsigs->rr) {
00601             se_log_warning("signature set has no RRSIG record: "
00602                 "drop signatures for RRset[%i]", rrset->rr_type);
00603             rrsigs_cleanup(rrset->rrsigs);
00604             rrset->rrsigs = NULL;
00605             rrset->rrsig_count = 0;
00606             rrset->drop_signatures = 0;
00607             return 0;
00608         }
00609 
00610         expiration = ldns_rdf2native_int32(
00611             ldns_rr_rrsig_expiration(rrsigs->rr));
00612         inception = ldns_rdf2native_int32(
00613             ldns_rr_rrsig_inception(rrsigs->rr));
00614 
00615         if (expiration < refresh) {
00616             /* 3a. Expiration - Refresh has passed */
00617             drop_sig = 1;
00618             se_log_deeebug("refresh signature for RRset[%i]: expiration minus "
00619                 "refresh has passed: %u - %u < (signtime)",
00620                 rrset->rr_type, expiration, refresh, (uint32_t) signtime);
00621         } else if (inception > (uint32_t) signtime) {
00622             /* 3b. Inception has not yet passed */
00623             drop_sig = 1;
00624             se_log_deeebug("refresh signature for RRset[%i]: inception has "
00625                 "not passed: %u < %u (signtime)",
00626                 rrset->rr_type, inception, (uint32_t) signtime);
00627         } else {
00628             /* 3c. Corresponding key is dead */
00629             key = keylist_lookup(sc->keys, rrsigs->key_locator);
00630             if (!key) {
00631                 drop_sig = 1;
00632                 se_log_deeebug("refresh signature for RRset[%i]: key %s %u "
00633                 "is dead",
00634                 rrset->rr_type, rrsigs->key_locator, rrsigs->key_flags);
00635             } else if (key->flags != rrsigs->key_flags) {
00636                 drop_sig = 1;
00637                 se_log_deeebug("refresh signature for RRset[%i]: key %s %u "
00638                 "flags mismatch",
00639                 rrset->rr_type, rrsigs->key_locator, rrsigs->key_flags);
00640             }
00641         }
00642 
00643         next_rrsigs = rrsigs->next;
00644         if (drop_sig) {
00645             /* A rule mismatched, refresh signature */
00646             if (prev_rrsigs) {
00647                 prev_rrsigs->next = rrsigs->next;
00648             } else {
00649                 rrset->rrsigs = rrsigs->next;
00650             }
00651             log_rr(rrsigs->rr, "-RRSIG", 6);
00652             rrset->rrsig_count -= 1;
00653             rrsigs->next = NULL;
00654             rrsigs_cleanup(rrsigs);
00655         } else {
00656             /* All rules ok, recycle signature */
00657             se_log_deeebug("recycle signature for RRset[%i] (refresh=%u, "
00658                 "signtime=%u, inception=%u, expiration=%u)", rrset->rr_type,
00659                 refresh, (uint32_t) signtime, inception, expiration);
00660             log_rr(rrsigs->rr, "*RRSIG", 6);
00661             *reusedsigs += 1;
00662             prev_rrsigs = rrsigs;
00663         }
00664         rrsigs = next_rrsigs;
00665     }
00666     return 0;
00667 }
00668 
00669 
00674 static void
00675 rrset_sign_set_timers(signconf_type* sc, ldns_rr_type rrtype, time_t signtime,
00676     time_t* inception, time_t* expiration)
00677 {
00678     time_t jitter = 0;
00679     time_t offset = 0;
00680     time_t validity = 0;
00681     time_t random_jitter = 0;
00682 
00683     se_log_assert(sc);
00684     se_log_assert(rrtype);
00685     se_log_assert(signtime);
00686 
00687     jitter = duration2time(sc->sig_jitter);
00688     if (jitter) {
00689         random_jitter = se_rand(jitter*2);
00690     }
00691     offset = duration2time(sc->sig_inception_offset);
00692     if (rrtype == LDNS_RR_TYPE_NSEC || rrtype == LDNS_RR_TYPE_NSEC3) {
00693         validity = duration2time(sc->sig_validity_denial);
00694     } else {
00695         validity = duration2time(sc->sig_validity_default);
00696     }
00697 
00701     if (((validity + offset + random_jitter) - jitter) <
00702         ((validity + offset) - jitter) ) {
00703         se_log_error("signature validity %u too low, should be at least %u",
00704             ((validity + offset + random_jitter) - jitter),
00705             ((validity + offset) - jitter));
00706     } else if (((validity + offset + random_jitter) - jitter) >
00707                ((validity + offset) + jitter) ) {
00708         se_log_error("signature validity %u too high, should be at most %u",
00709             ((validity + offset + random_jitter) - jitter),
00710             ((validity + offset) + jitter));
00711     } else {
00712         se_log_debug("signature validity %u in range [%u - %u]",
00713             ((validity + offset + random_jitter) - jitter),
00714             ((validity + offset) - jitter),
00715             ((validity + offset) + jitter));
00716     }
00717 
00718     *inception = signtime - offset;
00719     *expiration = (signtime + validity + random_jitter) - jitter;
00720     return;
00721 }
00722 
00723 
00728 static int
00729 rrset_signed_with_algorithm(rrset_type* rrset, uint8_t algorithm)
00730 {
00731     rrsigs_type* rrsigs = NULL;
00732 
00733     if (!rrset || !algorithm) {
00734         return 0;
00735     }
00736 
00737     rrsigs = rrset->rrsigs;
00738     while (rrsigs) {
00739         if (rrsigs->rr && algorithm ==
00740             ldns_rdf2native_int8(ldns_rr_rrsig_algorithm(rrsigs->rr))) {
00741             return 1;
00742         }
00743         rrsigs = rrsigs->next;
00744     }
00745 
00746     return 0;
00747 }
00748 
00753 static ldns_rr_list*
00754 rrset2rrlist(rrset_type* rrset)
00755 {
00756     ldns_dnssec_rrs* rrs = NULL;
00757     ldns_rr_list* rr_list = NULL;
00758     int error = 0;
00759 
00760     rr_list = ldns_rr_list_new();
00761     rrs = rrset->rrs;
00762     while (rrs && rrs->rr) {
00763         error = (int) ldns_rr_list_push_rr(rr_list, rrs->rr);
00764         if (!error) {
00765             ldns_rr_list_free(rr_list);
00766             return NULL;
00767         }
00768         if (rrset->rr_type == LDNS_RR_TYPE_CNAME ||
00769             rrset->rr_type == LDNS_RR_TYPE_DNAME) {
00770             /* singleton types */
00771             return rr_list;
00772         }
00773 
00774         rrs = rrs->next;
00775     }
00776     return rr_list;
00777 }
00778 
00779 
00784 int
00785 rrset_sign(hsm_ctx_t* ctx, rrset_type* rrset, ldns_rdf* owner,
00786     signconf_type* sc, time_t signtime, stats_type* stats)
00787 {
00788     int error = 0;
00789     uint32_t newsigs = 0;
00790     uint32_t reusedsigs = 0;
00791     ldns_rr* rrsig = NULL;
00792     ldns_rr_list* rr_list = NULL;
00793     rrsigs_type* new_rrsigs = NULL;
00794     rrsigs_type* walk_rrsigs = NULL;
00795     key_type* key = NULL;
00796     time_t inception = 0;
00797     time_t expiration = 0;
00798 
00799     se_log_assert(rrset);
00800     se_log_assert(sc);
00801     se_log_assert(stats);
00802 
00803         /* drop unrecyclable signatures */
00804         error = rrset_recycle_rrsigs(rrset, sc, signtime, &reusedsigs);
00805 
00806         /* convert the RRset */
00807         rr_list = rrset2rrlist(rrset);
00808         if (!rr_list) {
00809             se_log_error("error signing RRset[%i], cannot convert to rr "
00810                 "list", rrset->rr_type);
00811             return 1;
00812         }
00813         if (ldns_rr_list_rr_count(rr_list) <= 0) {
00814             /* empty RRset, no signatures needed */
00815             ldns_rr_list_free(rr_list);
00816             return 0;
00817         }
00818 
00819         /* prepare for signing */
00820         new_rrsigs = rrsigs_create();
00821         if (!rrset->rrsigs) {
00822             rrset->rrsigs = rrsigs_create();
00823         }
00824         rrset_sign_set_timers(sc, rrset->rr_type, signtime,
00825              &inception, &expiration);
00826 
00827         key = sc->keys->first_key;
00828         while (key) {
00829             /* ksk or zsk ? */
00830             if (!key->zsk && rrset->rr_type != LDNS_RR_TYPE_DNSKEY) {
00831                 se_log_deeebug("skipping key %s for signing RRset[%i]: no "
00832                     "active ZSK", key->locator, rrset->rr_type);
00833                 key = key->next;
00834                 continue;
00835             }
00836 
00837             if (!key->ksk && rrset->rr_type == LDNS_RR_TYPE_DNSKEY) {
00838                 se_log_deeebug("skipping key %s for signing RRset[DNSKEY]: no "
00839                     "active KSK", key->locator);
00840                 key = key->next;
00841                 continue;
00842             }
00843 
00844             /* is there a signature with this algorithm already? */
00845             if (rrset_signed_with_algorithm(rrset, key->algorithm)) {
00846                 se_log_deeebug("skipping key %s for signing: RRset[%i] "
00847                     "already has signature with same algorithm", key->locator);
00848                 key = key->next;
00849                 continue;
00850             }
00851 
00857             /* sign the RRset with current key */
00858             se_log_deeebug("signing RRset[%i] with key %s",
00859                 rrset->rr_type, key->locator);
00860             rrsig = hsm_sign_rrset_with_key(ctx, owner, key, rr_list,
00861                  inception, expiration);
00862             if (!rrsig) {
00863                 se_log_error("error creating RRSIG for rrset[%i]",
00864                     rrset->rr_type);
00865                 ldns_rr_list_free(rr_list);
00866                 rrsigs_cleanup(new_rrsigs);
00867                 return 1;
00868             }
00869             /* add the signature to the set of new signatures */
00870             se_log_deeebug("new signature created for RRset[%i]",
00871                 rrset->rr_type);
00872             log_rr(rrsig, "+RRSIG", 6);
00873             error = rrsigs_add_sig(new_rrsigs, rrsig, key->locator,
00874                 key->flags);
00875             if (error) {
00876                 se_log_error("error adding RRSIG to list of signatures");
00877                 log_rr(rrsig, "+RRSIG", 1);
00878                 ldns_rr_list_free(rr_list);
00879                 rrsigs_cleanup(new_rrsigs);
00880                 return 1;
00881             }
00882 
00883             /* next key */
00884             key = key->next;
00885         }
00886 
00887         /* now add the signatures to the RRset */
00888         walk_rrsigs = new_rrsigs;
00889         while (walk_rrsigs) {
00890             if (walk_rrsigs->rr) {
00891                 se_log_deeebug("adding signature to RRset[%i]",
00892                     rrset->rr_type);
00893                 log_rr(rrsig, "+RRSIG", 6);
00894                 error = rrsigs_add_sig(rrset->rrsigs,
00895                     ldns_rr_clone(walk_rrsigs->rr),
00896                     walk_rrsigs->key_locator, walk_rrsigs->key_flags);
00897                 if (error) {
00898                     se_log_error("error adding RRSIG to RRset[%i]",
00899                         rrset->rr_type);
00900                     log_rr(walk_rrsigs->rr, "+RRSIG", 1);
00901                     ldns_rr_list_free(rr_list);
00902                     rrsigs_cleanup(new_rrsigs);
00903                     return 1;
00904                 }
00905                 rrset->rrsig_count += 1;
00906                 log_rr(walk_rrsigs->rr, "+RRSIG", 6);
00907                 newsigs++;
00908             }
00909             walk_rrsigs = walk_rrsigs->next;
00910         }
00911 
00912         /* clean up */
00913         rrsigs_cleanup(new_rrsigs);
00914         ldns_rr_list_free(rr_list);
00915 
00916     if (rrset->rr_type == LDNS_RR_TYPE_SOA) {
00917         stats->sig_soa_count += newsigs;
00918     }
00919     stats->sig_count += newsigs;
00920     stats->sig_reuse += reusedsigs;
00921     return 0;
00922 }
00923 
00924 
00929 int
00930 rrset_del_rrs(rrset_type* rrset)
00931 {
00932     ldns_dnssec_rrs* rrs = NULL;
00933     ldns_rr* rr = NULL;
00934 
00935     se_log_assert(rrset);
00936     if (!rrset->rrs) {
00937         return 0;
00938     }
00939     if (!rrset->del) {
00940         rrset->del = ldns_dnssec_rrs_new();
00941     }
00942     rrs = rrset->rrs;
00943     while (rrs) {
00944         if (rrs->rr) {
00945             rr = ldns_rr_clone(rrs->rr);
00946             if (rrset_del_rr(rrset, rr) != 0) {
00947                 return 1;
00948             }
00949         }
00950         rrs = rrs->next;
00951     }
00952     return 0;
00953 }
00954 
00955 
00960 void
00961 rrset_cleanup(rrset_type* rrset)
00962 {
00963     if (rrset) {
00964         if (rrset->rrs) {
00965             ldns_dnssec_rrs_deep_free(rrset->rrs);
00966             rrset->rrs = NULL;
00967         }
00968         if (rrset->add) {
00969             ldns_dnssec_rrs_deep_free(rrset->add);
00970             rrset->add = NULL;
00971         }
00972         if (rrset->del) {
00973             ldns_dnssec_rrs_deep_free(rrset->del);
00974             rrset->del = NULL;
00975         }
00976         if (rrset->rrsigs) {
00977             rrsigs_cleanup(rrset->rrsigs);
00978             rrset->rrsigs = NULL;
00979         }
00980         se_free((void*) rrset);
00981     } else {
00982         se_log_warning("cleanup empty rrset");
00983     }
00984     return;
00985 }
00986 
00987 
00992 void
00993 rrset_print(FILE* fd, rrset_type* rrset, int skip_rrsigs)
00994 {
00995     se_log_assert(fd);
00996     se_log_assert(rrset);
00997 
00998     if (rrset->rrs) {
00999         if (rrset->rr_type == LDNS_RR_TYPE_CNAME ||
01000             rrset->rr_type == LDNS_RR_TYPE_DNAME) {
01001             /* singleton types */
01002             if (rrset->rrs->rr) {
01003                 ldns_rr_print(fd, rrset->rrs->rr);
01004             }
01005         } else {
01006             ldns_dnssec_rrs_print(fd, rrset->rrs);
01007         }
01008     }
01009     if (rrset->rrsigs && !skip_rrsigs) {
01010         rrsigs_print(fd, rrset->rrsigs, 0);
01011     }
01012     return;
01013 }
01014 
01015 
01020 void
01021 rrset_print_rrsig(FILE* fd, rrset_type* rrset)
01022 {
01023     se_log_assert(fd);
01024     se_log_assert(rrset);
01025 
01026     if (rrset->rrsigs) {
01027         rrsigs_print(fd, rrset->rrsigs, 1);
01028     }
01029     return;
01030 }