1 /*
2  * Copyright (c) 2009 NLNet Labs. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
19  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
21  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
22  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
23  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  */
26 
27 /**
28  * RRset.
29  *
30  */
31 
32 #include "config.h"
33 #include "file.h"
34 #include "hsm.h"
35 #include "log.h"
36 #include "util.h"
37 #include "compat.h"
38 #include "signer/rrset.h"
39 #include "signer/zone.h"
40 
41 static const char* rrset_str = "rrset";
42 
43 /**
44  * Log RR.
45  *
46  */
47 void
log_rr(ldns_rr * rr,const char * pre,int level)48 log_rr(ldns_rr* rr, const char* pre, int level)
49 {
50     char* str = NULL;
51     size_t i = 0;
52 
53     if (ods_log_get_level() < level) {
54         return;
55     }
56     str = ldns_rr2str(rr);
57     if (!str) {
58         ods_log_error("[%s] %s: Error converting RR to string", rrset_str,
59             pre?pre:"");
60         return;
61     }
62     str[(strlen(str))-1] = '\0';
63     /* replace tabs with white space */
64     for (i=0; i < strlen(str); i++) {
65         if (str[i] == '\t') {
66             str[i] = ' ';
67         }
68     }
69     if (level == LOG_EMERG) {
70         ods_fatal_exit("[%s] %s: %s", rrset_str, pre?pre:"", str);
71     } else if (level == LOG_ALERT) {
72         ods_log_alert("[%s] %s: %s", rrset_str, pre?pre:"", str);
73     } else if (level == LOG_CRIT) {
74         ods_log_crit("[%s] %s: %s", rrset_str, pre?pre:"", str);
75     } else if (level == LOG_ERR) {
76         ods_log_error("[%s] %s: %s", rrset_str, pre?pre:"", str);
77     } else if (level == LOG_WARNING) {
78         ods_log_warning("[%s] %s: %s", rrset_str, pre?pre:"", str);
79     } else if (level == LOG_NOTICE) {
80         ods_log_info("[%s] %s: %s", rrset_str, pre?pre:"", str);
81     } else if (level == LOG_INFO) {
82         ods_log_verbose("[%s] %s: %s", rrset_str, pre?pre:"", str);
83     } else if (level == LOG_DEBUG) {
84         ods_log_debug("[%s] %s: %s", rrset_str, pre?pre:"", str);
85     } else if (level == LOG_DEEEBUG) {
86         ods_log_deeebug("[%s] %s: %s", rrset_str, pre?pre:"", str);
87     } else {
88         ods_log_deeebug("[%s] %s: %s", rrset_str, pre?pre:"", str);
89     }
90     free((void*)str);
91 }
92 
93 
94 /**
95  * Log RRset.
96  *
97  */
98 void
log_rrset(ldns_rdf * dname,ldns_rr_type type,const char * pre,int level)99 log_rrset(ldns_rdf* dname, ldns_rr_type type, const char* pre, int level)
100 {
101     char* str = NULL;
102     size_t i = 0;
103 
104     if (ods_log_get_level() < level) {
105         return;
106     }
107     str = ldns_rdf2str(dname);
108     if (!str) {
109         return;
110     }
111     str[(strlen(str))-1] = '\0';
112     /* replace tabs with white space */
113     for (i=0; i < strlen(str); i++) {
114         if (str[i] == '\t') {
115             str[i] = ' ';
116         }
117     }
118     if (level == LOG_EMERG) {
119         ods_fatal_exit("[%s] %s: <%s,%s>", rrset_str, pre?pre:"", str,
120             rrset_type2str(type));
121     } else if (level == LOG_ALERT) {
122         ods_log_alert("[%s] %s: <%s,%s>", rrset_str, pre?pre:"", str,
123             rrset_type2str(type));
124     } else if (level == LOG_CRIT) {
125         ods_log_crit("[%s] %s: <%s,%s>", rrset_str, pre?pre:"", str,
126             rrset_type2str(type));
127     } else if (level == LOG_ERR) {
128         ods_log_error("[%s] %s: <%s,%s>", rrset_str, pre?pre:"", str,
129             rrset_type2str(type));
130     } else if (level == LOG_WARNING) {
131         ods_log_warning("[%s] %s: <%s,%s>", rrset_str, pre?pre:"", str,
132             rrset_type2str(type));
133     } else if (level == LOG_NOTICE) {
134         ods_log_info("[%s] %s: <%s,%s>", rrset_str, pre?pre:"", str,
135             rrset_type2str(type));
136     } else if (level == LOG_INFO) {
137         ods_log_verbose("[%s] %s: <%s,%s>", rrset_str, pre?pre:"", str,
138             rrset_type2str(type));
139     } else if (level == LOG_DEBUG) {
140         ods_log_debug("[%s] %s: <%s,%s>", rrset_str, pre?pre:"", str,
141             rrset_type2str(type));
142     } else if (level == LOG_DEEEBUG) {
143         ods_log_deeebug("[%s] %s: <%s,%s>", rrset_str, pre?pre:"", str,
144             rrset_type2str(type));
145     } else {
146         ods_log_deeebug("[%s] %s: <%s,%s>", rrset_str, pre?pre:"", str,
147             rrset_type2str(type));
148     }
149     free((void*)str);
150 }
151 
152 
153 /**
154  * Get the string-format of RRtype.
155  *
156  */
157 const char*
rrset_type2str(ldns_rr_type type)158 rrset_type2str(ldns_rr_type type)
159 {
160     if (type == LDNS_RR_TYPE_IXFR) {
161         return "IXFR";
162     } else if (type == LDNS_RR_TYPE_AXFR) {
163         return "AXFR";
164     } else if (type == LDNS_RR_TYPE_MAILB) {
165         return "MAILB";
166     } else if (type == LDNS_RR_TYPE_MAILA) {
167         return "MAILA";
168     } else if (type == LDNS_RR_TYPE_ANY) {
169         return "ANY";
170     } else {
171         const ldns_rr_descriptor* descriptor = ldns_rr_descript(type);
172         if (descriptor && descriptor->_name) {
173             return descriptor->_name;
174         }
175     }
176     return "TYPE???";
177 }
178 
179 static int
memberdestroy(void * dummy,void * member)180 memberdestroy(void* dummy, void* member)
181 {
182     rrsig_type* sig = (rrsig_type*) member;
183     (void)dummy;
184     free((void*) sig->key_locator);
185     sig->key_locator = NULL;
186     /* The rrs may still be in use by IXFRs so cannot do ldns_rr_free(sig->rr); */
187     ldns_rr_free(sig->rr);
188     sig->owner = NULL;
189     sig->rr = NULL;
190     return 0;
191 }
192 
193 
194 /**
195  * Create RRset.
196  *
197  */
198 rrset_type*
rrset_create(zone_type * zone,ldns_rr_type type)199 rrset_create(zone_type* zone, ldns_rr_type type)
200 {
201     rrset_type* rrset = NULL;
202     if (!type || !zone) {
203         return NULL;
204     }
205     CHECKALLOC(rrset = (rrset_type*) malloc(sizeof(rrset_type)));
206     if (!rrset) {
207         ods_log_error("[%s] unable to create RRset %u: allocator_alloc() "
208             "failed", rrset_str, (unsigned) type);
209         return NULL;
210     }
211     rrset->next = NULL;
212     rrset->rrs = NULL;
213     rrset->domain = NULL;
214     rrset->zone = zone;
215     rrset->rrtype = type;
216     rrset->rr_count = 0;
217     collection_create_array(&rrset->rrsigs, sizeof(rrsig_type), rrset->zone->rrstore);
218     rrset->needs_signing = 0;
219     return rrset;
220 }
221 
222 collection_class
rrset_store_initialize()223 rrset_store_initialize()
224 {
225     collection_class klass;
226     collection_class_allocated(&klass, NULL, memberdestroy);
227     return klass;
228 }
229 
230 
231 /**
232  * Lookup RR in RRset.
233  *
234  */
235 rr_type*
rrset_lookup_rr(rrset_type * rrset,ldns_rr * rr)236 rrset_lookup_rr(rrset_type* rrset, ldns_rr* rr)
237 {
238     ldns_status lstatus = LDNS_STATUS_OK;
239     int cmp = 0;
240     size_t i = 0;
241 
242     if (!rrset || !rr || rrset->rr_count <= 0) {
243        return NULL;
244     }
245     for (i=0; i < rrset->rr_count; i++) {
246         lstatus = util_dnssec_rrs_compare(rrset->rrs[i].rr, rr, &cmp);
247         if (lstatus != LDNS_STATUS_OK) {
248             ods_log_error("[%s] unable to lookup RR: compare failed (%s)",
249                 rrset_str, ldns_get_errorstr_by_id(lstatus));
250             return NULL;
251         }
252         if (!cmp) { /* equal */
253             return &rrset->rrs[i];
254         }
255     }
256     return NULL;
257 }
258 
259 /**
260  * What TTL should new RR's in this RRS get?
261  */
262 uint32_t
rrset_lookup_ttl(rrset_type * rrset,uint32_t default_ttl)263 rrset_lookup_ttl(rrset_type* rrset, uint32_t default_ttl)
264 {
265     for (int i = 0; i < rrset->rr_count; i++) {
266         if (!rrset->rrs[i].is_added) continue;
267         return ldns_rr_ttl(rrset->rrs[i].rr);
268     }
269     return default_ttl;
270 }
271 
272 
273 /**
274  * Count the number of RRs in this RRset that have is_added.
275  *
276  */
277 size_t
rrset_count_rr_is_added(rrset_type * rrset)278 rrset_count_rr_is_added(rrset_type* rrset)
279 {
280     size_t i = 0;
281     size_t count = 0;
282     if (!rrset) {
283         return 0;
284     }
285     for (i=0; i < rrset->rr_count; i++) {
286         if (rrset->rrs[i].is_added) {
287             count++;
288         }
289     }
290     return count;
291 }
292 
293 
294 /**
295  * Add RR to RRset.
296  *
297  */
298 rr_type*
rrset_add_rr(rrset_type * rrset,ldns_rr * rr)299 rrset_add_rr(rrset_type* rrset, ldns_rr* rr)
300 {
301     rr_type* rrs_old = NULL;
302 
303     ods_log_assert(rrset);
304     ods_log_assert(rr);
305     ods_log_assert(rrset->rrtype == ldns_rr_get_type(rr));
306 
307     rrs_old = rrset->rrs;
308     CHECKALLOC(rrset->rrs = (rr_type*) malloc((rrset->rr_count + 1) * sizeof(rr_type)));
309     if (!rrset->rrs) {
310         ods_fatal_exit("[%s] fatal unable to add RR: allocator_alloc() failed",
311             rrset_str);
312     }
313     if (rrs_old) {
314         memcpy(rrset->rrs, rrs_old, (rrset->rr_count) * sizeof(rr_type));
315     }
316     free(rrs_old);
317     rrset->rr_count++;
318     rrset->rrs[rrset->rr_count - 1].owner = rrset->domain;
319     rrset->rrs[rrset->rr_count - 1].rr = rr;
320     rrset->rrs[rrset->rr_count - 1].exists = 0;
321     rrset->rrs[rrset->rr_count - 1].is_added = 1;
322     rrset->rrs[rrset->rr_count - 1].is_removed = 0;
323     rrset->needs_signing = 1;
324     log_rr(rr, "+RR", LOG_DEEEBUG);
325     return &rrset->rrs[rrset->rr_count -1];
326 }
327 
328 
329 /**
330  * Delete RR from RRset.
331  *
332  */
333 void
rrset_del_rr(rrset_type * rrset,uint16_t rrnum)334 rrset_del_rr(rrset_type* rrset, uint16_t rrnum)
335 {
336     rr_type* rrs_orig = NULL;
337 
338     ods_log_assert(rrset);
339     ods_log_assert(rrnum < rrset->rr_count);
340 
341     log_rr(rrset->rrs[rrnum].rr, "-RR", LOG_DEEEBUG);
342     rrset->rrs[rrnum].owner = NULL; /* who owns owner? */
343     ldns_rr_free(rrset->rrs[rrnum].rr);
344     while (rrnum < rrset->rr_count-1) {
345         rrset->rrs[rrnum] = rrset->rrs[rrnum+1];
346         rrnum++;
347     }
348     memset(&rrset->rrs[rrset->rr_count-1], 0, sizeof(rr_type));
349     rrs_orig = rrset->rrs;
350     CHECKALLOC(rrset->rrs = (rr_type*) malloc((rrset->rr_count - 1) * sizeof(rr_type)));
351     if(!rrset->rrs) {
352         ods_fatal_exit("[%s] fatal unable to delete RR: allocator_alloc() failed",
353             rrset_str);
354     }
355     memcpy(rrset->rrs, rrs_orig, (rrset->rr_count -1) * sizeof(rr_type));
356     free(rrs_orig);
357     rrset->rr_count--;
358     rrset->needs_signing = 1;
359 }
360 
361 /**
362  * Apply differences at RRset.
363  *
364  */
365 void
rrset_diff(rrset_type * rrset,unsigned is_ixfr,unsigned more_coming)366 rrset_diff(rrset_type* rrset, unsigned is_ixfr, unsigned more_coming)
367 {
368     zone_type* zone = NULL;
369     uint16_t i = 0;
370     uint8_t del_sigs = 0;
371     if (!rrset) {
372         return;
373     }
374     zone = (zone_type*) rrset->zone;
375     /* CAUTION: both iterator and condition (implicit) are changed
376      * within the loop. */
377     for (i=0; i < rrset->rr_count; i++) {
378         if (rrset->rrs[i].is_added) {
379             if (!rrset->rrs[i].exists) {
380                 /* ixfr +RR */
381                 if (zone->db->is_initialized) {
382                     pthread_mutex_lock(&zone->ixfr->ixfr_lock);
383                     ixfr_add_rr(zone->ixfr, rrset->rrs[i].rr);
384                     pthread_mutex_unlock(&zone->ixfr->ixfr_lock);
385                 }
386                 del_sigs = 1;
387             }
388             rrset->rrs[i].exists = 1;
389             if ((rrset->rrtype == LDNS_RR_TYPE_DNSKEY) && more_coming) {
390                 continue;
391             }
392             rrset->rrs[i].is_added = 0;
393         } else if (!is_ixfr || rrset->rrs[i].is_removed) {
394             if (rrset->rrs[i].exists && zone->db->is_initialized) {
395                 /* ixfr -RR */
396                 pthread_mutex_lock(&zone->ixfr->ixfr_lock);
397                 ixfr_del_rr(zone->ixfr, rrset->rrs[i].rr);
398                 pthread_mutex_unlock(&zone->ixfr->ixfr_lock);
399             }
400             rrset->rrs[i].exists = 0;
401             rrset_del_rr(rrset, i);
402             del_sigs = 1;
403             i--;
404         }
405     }
406     if (del_sigs) {
407         rrset_drop_rrsigs(zone, rrset);
408     }
409 }
410 
411 /**
412  * Remove signatures, deallocate storage and add then to the outgoing IFXR for that zone.
413  *
414  */
415 void
rrset_drop_rrsigs(zone_type * zone,rrset_type * rrset)416 rrset_drop_rrsigs(zone_type* zone, rrset_type* rrset)
417 {
418     rrsig_type* rrsig;
419     while((rrsig = collection_iterator(rrset->rrsigs))) {
420         /* ixfr -RRSIG */
421         if (zone->db->is_initialized) {
422             pthread_mutex_lock(&zone->ixfr->ixfr_lock);
423             ixfr_del_rr(zone->ixfr, rrsig->rr);
424             pthread_mutex_unlock(&zone->ixfr->ixfr_lock);
425         }
426         collection_del_cursor(rrset->rrsigs);
427     }
428 }
429 
430 /**
431  * Add RRSIG to RRset.
432  *
433  */
434 void
rrset_add_rrsig(rrset_type * rrset,ldns_rr * rr,const char * locator,uint32_t flags)435 rrset_add_rrsig(rrset_type* rrset, ldns_rr* rr,
436     const char* locator, uint32_t flags)
437 {
438     rrsig_type rrsig;
439     ods_log_assert(rrset);
440     ods_log_assert(rr);
441     ods_log_assert(ldns_rr_get_type(rr) == LDNS_RR_TYPE_RRSIG);
442     rrsig.owner = rrset->domain;
443     rrsig.rr = rr;
444     rrsig.key_locator = locator;
445     rrsig.key_flags = flags;
446     collection_add(rrset->rrsigs, &rrsig);
447 }
448 
449 /**
450  * Transmogrify the RRset to a RRlist.
451  *
452  */
453 static ldns_rr_list*
rrset2rrlist(rrset_type * rrset)454 rrset2rrlist(rrset_type* rrset)
455 {
456     ldns_rr_list* rr_list = NULL;
457     int ret = 0;
458     size_t i = 0;
459     rr_list = ldns_rr_list_new();
460     for (i=0; i < rrset->rr_count; i++) {
461         if (!rrset->rrs[i].exists) {
462             log_rr(rrset->rrs[i].rr, "RR does not exist", LOG_WARNING);
463             continue;
464         }
465         ret = (int) ldns_rr_list_push_rr(rr_list, rrset->rrs[i].rr);
466         if (!ret) {
467             ldns_rr_list_free(rr_list);
468             return NULL;
469         }
470         if (rrset->rrtype == LDNS_RR_TYPE_CNAME ||
471             rrset->rrtype == LDNS_RR_TYPE_DNAME) {
472             /* singleton types */
473             return rr_list;
474         }
475     }
476     ldns_rr_list_sort(rr_list);
477     return rr_list;
478 }
479 
480 
481 /**
482  * Calculate the signature validation period.
483  *
484  */
485 static void
rrset_sigvalid_period(signconf_type * sc,ldns_rr_type rrtype,time_t signtime,time_t * inception,time_t * expiration)486 rrset_sigvalid_period(signconf_type* sc, ldns_rr_type rrtype, time_t signtime,
487     time_t* inception, time_t* expiration)
488 {
489     time_t jitter = 0;
490     time_t offset = 0;
491     time_t validity = 0;
492     time_t random_jitter = 0;
493     if (!sc || !rrtype || !signtime) {
494         return;
495     }
496     jitter = duration2time(sc->sig_jitter);
497     if (jitter) {
498         random_jitter = ods_rand(jitter*2);
499     }
500     offset = duration2time(sc->sig_inception_offset);
501     switch (rrtype) {
502         case LDNS_RR_TYPE_NSEC:
503         case LDNS_RR_TYPE_NSEC3:
504             validity = duration2time(sc->sig_validity_denial);
505             break;
506         case LDNS_RR_TYPE_DNSKEY:
507             if (sc->sig_validity_keyset != NULL && duration2time(sc->sig_validity_keyset) > 0) {
508                 validity = duration2time(sc->sig_validity_keyset);
509             } else {
510                 validity = duration2time(sc->sig_validity_default);
511             }
512             break;
513         default:
514             validity = duration2time(sc->sig_validity_default);
515     }
516     *inception = signtime - offset;
517     *expiration = (signtime + validity + random_jitter) - jitter;
518 }
519 
520 
521 struct rrsigkeymatching {
522     rrsig_type* signature;
523     key_type* key;
524 };
525 
526 static int
rrsigkeyismatching(rrsig_type * rrsig,key_type * key)527 rrsigkeyismatching(rrsig_type* rrsig, key_type* key)
528 {
529     if(rrsig->key_flags == key->flags && !strcmp(rrsig->key_locator,key->locator)) {
530         return 1;
531     } else {
532         return 0;
533     }
534 }
535 
536 static void
rrsigkeymatching(signconf_type * signconf,int nrrsigs,rrsig_type ** rrsigs,struct rrsigkeymatching ** rrsigkeymatchingptr,int * nrrsigkeymatchingptr)537 rrsigkeymatching(signconf_type* signconf, int nrrsigs, rrsig_type** rrsigs, struct rrsigkeymatching** rrsigkeymatchingptr, int* nrrsigkeymatchingptr)
538 {
539     int nmatches = 0;
540     struct rrsigkeymatching* matches = malloc(sizeof(struct rrsigkeymatching) * (signconf->keys->count + nrrsigs));
541     for(int i=0; i<nrrsigs; i++) {
542         matches[nmatches].signature = rrsigs[i];
543         matches[nmatches].key = NULL;
544         ++nmatches;
545     }
546     for(int keyidx=0; keyidx<signconf->keys->count; keyidx++) {
547         int matchidx;
548         for(matchidx=0; matchidx<nmatches; matchidx++) {
549             if(matches[matchidx].signature && rrsigkeyismatching(matches[matchidx].signature, &signconf->keys->keys[keyidx])) {
550                 matches[matchidx].key = &signconf->keys->keys[keyidx];
551                 break;
552             }
553         }
554         if(matchidx==nmatches) {
555             matches[nmatches].signature = NULL;
556             matches[nmatches].key = &signconf->keys->keys[keyidx];
557             ++nmatches;
558         }
559     }
560     *rrsigkeymatchingptr = matches;
561     *nrrsigkeymatchingptr = nmatches;
562 }
563 
564 
565 /**
566  * Sign RRset.
567  *
568  */
569 ods_status
rrset_sign(hsm_ctx_t * ctx,rrset_type * rrset,time_t signtime)570 rrset_sign(hsm_ctx_t* ctx, rrset_type* rrset, time_t signtime)
571 {
572     ods_status status;
573     zone_type* zone = NULL;
574     uint32_t newsigs = 0;
575     uint32_t reusedsigs = 0;
576     ldns_rr* rrsig = NULL;
577     rrsig_type* signature;
578     ldns_rr_list* rr_list = NULL;
579     ldns_rr_list* rr_list_clone = NULL;
580     const char* locator = NULL;
581     time_t inception = 0;
582     time_t expiration = 0;
583     size_t i = 0, j;
584     domain_type* domain = NULL;
585     ldns_rr_type dstatus = LDNS_RR_TYPE_FIRST;
586     ldns_rr_type delegpt = LDNS_RR_TYPE_FIRST;
587     uint8_t algorithm = 0;
588 
589     ods_log_assert(ctx);
590     ods_log_assert(rrset);
591     zone = (zone_type*) rrset->zone;
592     ods_log_assert(zone);
593     ods_log_assert(zone->signconf);
594     /* Recycle signatures */
595     if (rrset->rrtype == LDNS_RR_TYPE_NSEC ||
596         rrset->rrtype == LDNS_RR_TYPE_NSEC3) {
597         dstatus = LDNS_RR_TYPE_SOA;
598         delegpt = LDNS_RR_TYPE_SOA;
599     } else {
600         domain = (domain_type*) rrset->domain;
601         dstatus = domain_is_occluded(domain);
602         delegpt = domain_is_delegpt(domain);
603     }
604 
605     int nrrsigs;
606     for(nrrsigs=0; (signature = collection_iterator(rrset->rrsigs)); nrrsigs++)
607         ;
608     rrsig_type** rrsigs = malloc(sizeof(rrsig_type*) * nrrsigs);
609     for(i=0; (signature = collection_iterator(rrset->rrsigs)); i++) {
610         assert(signature);
611         rrsigs[i] = signature;
612     }
613     struct rrsigkeymatching* matchedsignatures = NULL;
614     int nmatchedsignatures;
615     rrsigkeymatching(zone->signconf, nrrsigs, rrsigs, &matchedsignatures, &nmatchedsignatures);
616 
617     rrset->needs_signing = 0;
618 
619     ods_log_assert(rrset->rrs);
620     ods_log_assert(rrset->rrs[0].rr);
621 
622     /* Skip delegation, glue and occluded RRsets */
623     if (dstatus != LDNS_RR_TYPE_SOA) {
624         log_rrset(ldns_rr_owner(rrset->rrs[0].rr), rrset->rrtype,
625             "skip signing occluded RRset", LOG_DEEEBUG);
626         free(rrsigs);
627         free(matchedsignatures);
628         return ODS_STATUS_OK;
629     }
630     if (delegpt != LDNS_RR_TYPE_SOA && rrset->rrtype != LDNS_RR_TYPE_DS) {
631         log_rrset(ldns_rr_owner(rrset->rrs[0].rr), rrset->rrtype,
632             "skip signing delegation RRset", LOG_DEEEBUG);
633         free(rrsigs);
634         free(matchedsignatures);
635         return ODS_STATUS_OK;
636     }
637 
638     log_rrset(ldns_rr_owner(rrset->rrs[0].rr), rrset->rrtype,
639         "sign RRset", LOG_DEEEBUG);
640     ods_log_assert(dstatus == LDNS_RR_TYPE_SOA ||
641         (delegpt == LDNS_RR_TYPE_SOA || rrset->rrtype == LDNS_RR_TYPE_DS));
642     /* Transmogrify rrset */
643     rr_list = rrset2rrlist(rrset);
644     if (ldns_rr_list_rr_count(rr_list) <= 0) {
645         /* Empty RRset, no signatures needed */
646         ldns_rr_list_free(rr_list);
647         free(rrsigs);
648         free(matchedsignatures);
649         return ODS_STATUS_OK;
650     }
651     /* Use rr_list_clone for signing, keep the original rr_list untouched for case preservation */
652     rr_list_clone = ldns_rr_list_clone(rr_list);
653 
654     /* Further in the code the ORIG_TTL field for the signature will be set
655      * to the TTL of the first RR in the list. We must make sure all RR's
656      * have the same TTL when signing. We do not need to publish these TTLs.
657      * We find the smallest TTL as other software seems to do this.
658      **/
659     uint32_t min_ttl = ldns_rr_ttl(ldns_rr_list_rr(rr_list_clone, 0));
660     for (i = 1; i < ldns_rr_list_rr_count(rr_list_clone); i++) {
661         uint32_t rr_ttl = ldns_rr_ttl(ldns_rr_list_rr(rr_list_clone, i));
662         if (rr_ttl < min_ttl) min_ttl = rr_ttl;
663     }
664     for (i = 0; i < ldns_rr_list_rr_count(rr_list_clone); i++) {
665         ldns_rr_set_ttl(ldns_rr_list_rr(rr_list_clone, i), min_ttl);
666     }
667 
668     assert(zone->signconf);
669     /* Calculate signature validity */
670     rrset_sigvalid_period(zone->signconf, rrset->rrtype, signtime,
671          &inception, &expiration);
672     uint32_t refresh = 0;
673     if (zone->signconf && zone->signconf->sig_refresh_interval) {
674         refresh = (uint32_t) (signtime + duration2time(zone->signconf->sig_refresh_interval));
675     }
676 
677     /* for each signature-key pair, determine whether the signature is valid and/or the key
678      * should produce a signature.
679      */
680     for (int i = 0; i < nmatchedsignatures; i++) {
681         if (matchedsignatures[i].signature) {
682             assert(matchedsignatures[i].signature->rr);
683             expiration = ldns_rdf2native_int32(ldns_rr_rrsig_expiration(matchedsignatures[i].signature->rr));
684             inception = ldns_rdf2native_int32(ldns_rr_rrsig_inception(matchedsignatures[i].signature->rr));
685         }
686         if (matchedsignatures[i].key && matchedsignatures[i].key->ksk && !matchedsignatures[i].key->zsk && rrset->rrtype != LDNS_RR_TYPE_DNSKEY) {
687             /* If KSK (not CSK) don't sign non-DNSKEY RRsets */
688             matchedsignatures[i].key = NULL;
689             matchedsignatures[i].signature = NULL;
690         } else if (matchedsignatures[i].key && !matchedsignatures[i].key->ksk && !matchedsignatures[i].key->zsk && rrset->rrtype != LDNS_RR_TYPE_DNSKEY && !matchedsignatures[i].signature) {
691             /* Drop keys that aren't ZSK or KSK and still have signatures */
692             matchedsignatures[i].key = NULL;
693         } else if (matchedsignatures[i].key && !matchedsignatures[i].key->ksk && !matchedsignatures[i].key->zsk && rrset->rrtype != LDNS_RR_TYPE_DNSKEY && !matchedsignatures[i].key->publish) {
694             matchedsignatures[i].key = NULL;
695             matchedsignatures[i].signature = NULL;
696         } else if (matchedsignatures[i].key && !matchedsignatures[i].key->ksk && !matchedsignatures[i].key->zsk && rrset->rrtype == LDNS_RR_TYPE_DNSKEY) {
697             matchedsignatures[i].key = NULL;
698             matchedsignatures[i].signature = NULL;
699         } else if (matchedsignatures[i].key && !matchedsignatures[i].key->ksk && matchedsignatures[i].key->zsk && rrset->rrtype == LDNS_RR_TYPE_DNSKEY) {
700             /* If ZSK (not CSK) don't sign DNSKEY RRset */
701             matchedsignatures[i].key = NULL;
702             matchedsignatures[i].signature = NULL;
703         } else if (matchedsignatures[i].key && matchedsignatures[i].key->ksk && matchedsignatures[i].key->locator == NULL) {
704             /* If key has no locator, and should be pre-signed dnskey RR, skip */
705             matchedsignatures[i].key = NULL;
706         } else if (refresh <= (uint32_t) signtime) {
707             /* If Refresh is disabled, drop all signatures */
708             matchedsignatures[i].signature = NULL;
709         } else if (matchedsignatures[i].signature && expiration < refresh && matchedsignatures[i].key && !matchedsignatures[i].key->ksk && !matchedsignatures[i].key->zsk) {
710             /* Signature has expired but key not used for signing anymore */
711             matchedsignatures[i].signature = NULL;
712             matchedsignatures[i].key = NULL;
713         } else if (matchedsignatures[i].signature && expiration < refresh) {
714             /* Expiration - Refresh has passed */
715             matchedsignatures[i].signature = NULL;
716         } else if (matchedsignatures[i].signature && inception > (uint32_t) signtime) {
717             /* Inception has not yet passed */
718             matchedsignatures[i].signature = NULL;
719         } else if (matchedsignatures[i].signature && !matchedsignatures[i].key) {
720             /* Orphaned signatures */
721             matchedsignatures[i].signature = NULL;
722         } else if (dstatus != LDNS_RR_TYPE_SOA || (delegpt != LDNS_RR_TYPE_SOA && rrset->rrtype != LDNS_RR_TYPE_DS)) {
723             /* Skip delegation, glue and occluded RRsets */
724             matchedsignatures[i].key = NULL;
725             matchedsignatures[i].signature = NULL;
726         } else {
727             ods_log_assert(dstatus == LDNS_RR_TYPE_SOA || (delegpt == LDNS_RR_TYPE_SOA || rrset->rrtype == LDNS_RR_TYPE_DS));
728         }
729     }
730     /* At this time, each signature, key pair is valid, if there is a signature and a key, it is valid, if there is
731      * no key, there should be no signature, if there is no key, there should be no signature.  However for DNS
732      * optimization, there needs to be no signature, if there is a signature for another key with the same algorithm
733      * that is still valid.
734      */
735     for (int i = 0; i < nmatchedsignatures; i++) {
736         if (!matchedsignatures[i].signature && matchedsignatures[i].key) {
737             /* We now know this key doesn't sign the set, we will only
738              * sign when there isn't already an active key for that algorithm
739              */
740             int j;
741             for (j = 0; j < nmatchedsignatures; j++) {
742                 if (j != i) {
743                     if (matchedsignatures[j].key && matchedsignatures[j].key->publish && matchedsignatures[j].signature && matchedsignatures[j].key->algorithm == matchedsignatures[i].key->algorithm) {
744                         break;
745                     }
746                 }
747             }
748             if (j < nmatchedsignatures) {
749                 matchedsignatures[i].key = NULL;
750                 matchedsignatures[i].signature = NULL;
751             }
752         }
753     }
754 
755     /* For each of the existing signatures, if they are no longer present in the output, delete them
756      * The rrsigs array is guaranteed to line up with the mathcedsignatures array
757      */
758     if (zone->db->is_initialized) {
759         pthread_mutex_lock(&zone->ixfr->ixfr_lock);
760         for(i=0; i<nrrsigs; i++) {
761             if(matchedsignatures[i].signature == NULL) {
762                 if (rrsigs[i] != NULL) {
763                     ixfr_del_rr(zone->ixfr, rrsigs[i]->rr);
764                 }
765             }
766         }
767         pthread_mutex_unlock(&zone->ixfr->ixfr_lock);
768     }
769     for(i=0; i<nrrsigs; i++) {
770         if(matchedsignatures[i].signature == NULL) {
771             if (rrsigs[i] != NULL) {
772                 while((signature = collection_iterator(rrset->rrsigs))) {
773                     if(signature == rrsigs[i]) {
774                         collection_del_cursor(rrset->rrsigs);
775                     }
776                 }
777             }
778         } else
779            ++reusedsigs;
780     }
781     /* only at this time we have no need for the list anymore (just the list) */
782     free(rrsigs);
783 
784     /* Calculate signature validity for new signatures */
785     rrset_sigvalid_period(zone->signconf, rrset->rrtype, signtime, &inception, &expiration);
786     /* for each missing signature (no signature, but with key in the tuplie list) produce a signature */
787     for (int i = 0; i < nmatchedsignatures; i++) {
788         if (!matchedsignatures[i].signature && matchedsignatures[i].key) {
789             /* Sign the RRset with this key */
790             ods_log_deeebug("[%s] signing RRset[%i] with key %s", rrset_str,
791                 rrset->rrtype, zone->signconf->keys->keys[i].locator);
792             rrsig = lhsm_sign(ctx, rr_list_clone, matchedsignatures[i].key,
793                 zone->apex, inception, expiration);
794             if (!rrsig) {
795                 ods_log_crit("[%s] unable to sign RRset[%i]: lhsm_sign() failed",
796                         rrset_str, rrset->rrtype);
797                 free(matchedsignatures);
798                 ldns_rr_list_free(rr_list);
799                 ldns_rr_list_free(rr_list_clone);
800                 return ODS_STATUS_HSM_ERR;
801             }
802             /* Add signature */
803             locator = strdup(matchedsignatures[i].key->locator);
804             rrset_add_rrsig(rrset, rrsig, locator, matchedsignatures[i].key->flags);
805             newsigs++;
806             /* ixfr +RRSIG */
807             if (zone->db->is_initialized) {
808                 pthread_mutex_lock(&zone->ixfr->ixfr_lock);
809                 ixfr_add_rr(zone->ixfr, rrsig);
810                 pthread_mutex_unlock(&zone->ixfr->ixfr_lock);
811             }
812         }
813     }
814     /* Add signatures for DNSKEY if have been configured to be added explicitjy */
815     if(rrset->rrtype == LDNS_RR_TYPE_DNSKEY && zone->signconf->dnskey_signature) {
816         for(i=0; zone->signconf->dnskey_signature[i]; i++) {
817             rrsig = NULL;
818             if ((status = rrset_getliteralrr(&rrsig, zone->signconf->dnskey_signature[i], duration2time(zone->signconf->dnskey_ttl), zone->apex)) != ODS_STATUS_OK) {
819                     ods_log_error("[%s] unable to publish dnskeys for zone %s: "
820                             "error decoding literal dnskey", rrset_str, zone->name);
821                     ldns_rr_list_deep_free(rr_list_clone);
822                     return status;
823             }
824             /* Add signature */
825             rrset_add_rrsig(rrset, rrsig, NULL, 0);
826             newsigs++;
827             /* ixfr +RRSIG */
828             if (zone->db->is_initialized) {
829                 pthread_mutex_lock(&zone->ixfr->ixfr_lock);
830                 ixfr_add_rr(zone->ixfr, rrsig);
831                 pthread_mutex_unlock(&zone->ixfr->ixfr_lock);
832             }
833         }
834     }
835 
836     /* RRset signing completed */
837     free(matchedsignatures);
838     ldns_rr_list_free(rr_list);
839     ldns_rr_list_deep_free(rr_list_clone);
840     pthread_mutex_lock(&zone->stats->stats_lock);
841     if (rrset->rrtype == LDNS_RR_TYPE_SOA) {
842         zone->stats->sig_soa_count += newsigs;
843     }
844     zone->stats->sig_count += newsigs;
845     zone->stats->sig_reuse += reusedsigs;
846     pthread_mutex_unlock(&zone->stats->stats_lock);
847     return ODS_STATUS_OK;
848 }
849 
850 ods_status
rrset_getliteralrr(ldns_rr ** dnskey,const char * resourcerecord,uint32_t ttl,ldns_rdf * apex)851 rrset_getliteralrr(ldns_rr** dnskey, const char *resourcerecord, uint32_t ttl, ldns_rdf* apex)
852 {
853     uint8_t dnskeystring[4096];
854     ldns_status ldnsstatus;
855     int len;
856     if ((len = b64_pton(resourcerecord, dnskeystring, sizeof (dnskeystring) - 2)) < 0) {
857         return ODS_STATUS_PARSE_ERR;
858     }
859     dnskeystring[len] = '\0';
860     if ((ldnsstatus = ldns_rr_new_frm_str(dnskey, (const char*) dnskeystring, ttl, apex, NULL)) != LDNS_STATUS_OK) {
861         return ODS_STATUS_PARSE_ERR;
862     }
863     return ODS_STATUS_OK;
864 }
865 
866 /**
867  * Print RRset.
868  *
869  */
870 void
rrset_print(FILE * fd,rrset_type * rrset,int skip_rrsigs,ods_status * status)871 rrset_print(FILE* fd, rrset_type* rrset, int skip_rrsigs,
872     ods_status* status)
873 {
874     rrsig_type* rrsig;
875     uint16_t i = 0;
876     ods_status result = ODS_STATUS_OK;
877 
878     if (!rrset || !fd) {
879         ods_log_crit("[%s] unable to print RRset: rrset or fd missing",
880             rrset_str);
881         if (status) {
882             *status = ODS_STATUS_ASSERT_ERR;
883         }
884     } else {
885         for (i=0; i < rrset->rr_count; i++) {
886             if (rrset->rrs[i].exists) {
887                 result = util_rr_print(fd, rrset->rrs[i].rr);
888                 if (rrset->rrtype == LDNS_RR_TYPE_CNAME ||
889                     rrset->rrtype == LDNS_RR_TYPE_DNAME) {
890                     /* singleton types */
891                     break;
892                 }
893                 if (result != ODS_STATUS_OK) {
894                     zone_type* zone = (zone_type*) rrset->zone;
895                     log_rrset(ldns_rr_owner(rrset->rrs[i].rr), rrset->rrtype,
896                         "error printing RRset", LOG_CRIT);
897                     zone->adoutbound->error = 1;
898                     break;
899                 }
900             }
901         }
902         if (! skip_rrsigs) {
903             result = ODS_STATUS_OK;
904             while((rrsig = collection_iterator(rrset->rrsigs))) {
905                 if (result == ODS_STATUS_OK) {
906                     result = util_rr_print(fd, rrsig->rr);
907                     if (result != ODS_STATUS_OK) {
908                         zone_type* zone = rrset->zone;
909                         log_rrset(ldns_rr_owner(rrset->rrs[i].rr), rrset->rrtype,
910                             "error printing RRset", LOG_CRIT);
911                         zone->adoutbound->error = 1;
912                     }
913                 }
914             }
915         }
916         if (status) {
917             *status = result;
918         }
919     }
920 }
921 
922 
923 /**
924  * Clean up RRset.
925  *
926  */
927 void
rrset_cleanup(rrset_type * rrset)928 rrset_cleanup(rrset_type* rrset)
929 {
930     uint16_t i = 0;
931     if (!rrset) {
932        return;
933     }
934     rrset_cleanup(rrset->next);
935     rrset->next = NULL;
936     rrset->domain = NULL;
937     for (i=0; i < rrset->rr_count; i++) {
938         ldns_rr_free(rrset->rrs[i].rr);
939         rrset->rrs[i].owner = NULL;
940     }
941     collection_destroy(&rrset->rrsigs);
942     free(rrset->rrs);
943     free(rrset);
944 }
945 
946 /**
947  * Backup RRset.
948  *
949  */
950 void
rrset_backup2(FILE * fd,rrset_type * rrset)951 rrset_backup2(FILE* fd, rrset_type* rrset)
952 {
953     rrsig_type* rrsig;
954     char* str = NULL;
955     if (!rrset || !fd) {
956         return;
957     }
958     while((rrsig = collection_iterator(rrset->rrsigs))) {
959         if ((str = ldns_rr2str(rrsig->rr))) {
960             fprintf(fd, "%.*s; {locator %s flags %u}\n", (int)strlen(str)-1, str,
961                     rrsig->key_locator, rrsig->key_flags);
962             free(str);
963         }
964     }
965 }
966