1 /*------------------------------------------------------------------------------
2  *
3  * Copyright (c) 2011-2021, EURid vzw. All rights reserved.
4  * The YADIFA TM software product is provided under the BSD 3-clause license:
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  *        * Redistributions of source code must retain the above copyright
11  *          notice, this list of conditions and the following disclaimer.
12  *        * Redistributions in binary form must reproduce the above copyright
13  *          notice, this list of conditions and the following disclaimer in the
14  *          documentation and/or other materials provided with the distribution.
15  *        * Neither the name of EURid nor the names of its contributors may be
16  *          used to endorse or promote products derived from this software
17  *          without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  *
31  *------------------------------------------------------------------------------
32  *
33  */
34 
35 /** @defgroup dnskey DNSSEC keys functions
36  *  @ingroup dnsdbdnssec
37  *  @brief
38  *
39  * @{
40  */
41 /*------------------------------------------------------------------------------
42  *
43  * USE INCLUDES */
44 #include "dnsdb/dnsdb-config.h"
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <limits.h>
48 #include <string.h>
49 //#include <strings.h>
50 #include <arpa/inet.h>
51 
52 #include <dnscore/thread.h>
53 
54 #include <dnscore/base64.h>
55 #include <dnscore/format.h>
56 #include <dnscore/timeformat.h>
57 #include <dnscore/zalloc.h>
58 #include <dnscore/string_set.h>
59 #include <dnscore/file_input_stream.h>
60 #include <dnscore/dnskey-keyring.h>
61 
62 #include <dnscore/ptr_set.h>
63 #include <dnscore/u32_set.h>
64 
65 #include <dnscore/fdtools.h>
66 #include <sys/stat.h>
67 
68 #include "dnsdb/zdb_error.h"
69 #include "dnsdb/zdb_record.h"
70 
71 #include "dnsdb/dnssec.h"
72 #include "dnsdb/dnssec_config.h"
73 #include "dnsdb/dnssec-keystore.h"
74 
75 #define MODULE_MSG_HANDLE g_dnssec_logger
76 extern logger_handle *g_dnssec_logger;
77 
78 #ifndef PATH_MAX
79 #define PATH_MAX 4096
80 #endif
81 
82 #define ZDB_KEYSTORE_ORIGIN_TAG 0x4e494749524f534b
83 
84 #define OAT_PRIVATE_FORMAT "K%s+%03d+%05d.private"
85 #define OAT_DNSKEY_FORMAT "K%s+%03d+%05d.key"
86 
87 // if the key is irrelevant and yadifad is self-managing, then a deactivated key can be removed after this time elapsed
88 
89 #define AUTOMATIC_DEACTIVATED_DNSKEY_UNPUBLISH_DELAY 86400
90 
91 static int dnssec_keystore_keys_node_compare(const void *, const void *);
92 
93 #define DNSSEC_KEYSTORE_EMPTY {PTR_SET_CUSTOM(ptr_set_nullable_asciizp_node_compare), PTR_SET_CUSTOM(dnssec_keystore_keys_node_compare), PTR_SET_CUSTOM(ptr_set_nullable_dnsname_node_compare)/*, NULL*/, MUTEX_INITIALIZER}
94 
95 
96 //typedef btree dnssec_keystore;
97 
98 /**
99  * After carefully weighting the advantages and disadvantages,
100  * the maintenance of the keys will go through a new keystore
101  *
102  * The keystore will contain all the paths it is supposed to scan and how many times a path has been added
103  * ie: once for the "global" setting, once for each zone it is specifically set on
104  * These paths are mandatory to avoid doing a lot of IOs when a simple scan can answer all our questions
105  *
106  * The keystore will contain all the keys by their name alg and tag.
107  * Probably something like tag + ( alg << 16 ), the idea being to use unassigned bits [9;14] of the flags
108  * Actually the name + tag should be enough.
109  *
110  * The keystore will contain a list of the keys for each zone, by their name
111  */
112 
113 #define KSDOMAIN_TAG 0x4e49414d4f44534b
114 
115 struct dnssec_keystore_domain_s
116 {
117     u8* fqdn;               // domain name
118     u64 keys_scan_epoch;    // last time the keys have been refreshed
119     const char *keys_path;  // path where to find the keys of the domain
120     dnssec_key *key_chain;  // list of keys for the domain
121 };
122 
123 typedef struct dnssec_keystore_domain_s dnssec_keystore_domain_s;
124 
125 struct dnssec_keystore
126 {
127     ptr_set paths;      // path -> count : each path of the keystore and the number of domains using it
128     ptr_set keys;       // name+alg+tag -> key
129     ptr_set domains;    // name -> dnssec_keystore_domain_s
130     //const char *default_path;
131     mutex_t lock;       // mutex
132 };
133 
134 typedef struct dnssec_keystore dnssec_keystore;
135 
136 static const char* g_keystore_path = DNSSEC_DEFAULT_KEYSTORE_PATH;
137 static dnssec_keystore g_keystore = DNSSEC_KEYSTORE_EMPTY;
138 
139 #define KEY_HASH(key) ((((hashcode)key->tag)<<16)|key->flags|(key->algorithm<<1))
140 #define TAG_FLAGS_ALGORITHM_HASH(t_,f_,a_) ((((hashcode)t_)<<16)|(f_)|((a_)<<1))
141 
142 static int
dnssec_keystore_keys_node_compare(const void * node_a,const void * node_b)143 dnssec_keystore_keys_node_compare(const void *node_a, const void *node_b)
144 {
145     dnssec_key *k_a = (dnssec_key*)node_a;
146     dnssec_key *k_b = (dnssec_key*)node_b;
147     ya_result ret;
148 
149     ret = dnskey_get_algorithm(k_a) - dnskey_get_algorithm(k_b);
150 
151     if(ret == 0)
152     {
153         ret = dnskey_get_tag(k_a) - dnskey_get_tag(k_b);
154 
155         if(ret == 0)
156         {
157             ret = dnsname_compare(dnskey_get_domain(k_a), dnskey_get_domain(k_b));
158         }
159     }
160 
161     return ret;
162 }
163 
164 /**
165  *
166  * Initialises the keystore
167  *
168  * @param ks
169  */
170 
171 void
dnssec_keystore_init()172 dnssec_keystore_init(/*dnssec_keystore *ks*/)
173 {
174     /*
175     dnssec_keystore *ks = &g_keystore;
176     ks->paths.root = NULL;
177     ks->paths.compare = ptr_set_nullable_asciizp_node_compare;
178     ks->keys.root = NULL;
179     ks->keys.compare = dnssec_keystore_keys_node_compare;
180     ks->domains.root = NULL;
181     ks->domains.compare =  ptr_set_nullable_dnsname_node_compare;
182     mutex_init(&ks->lock);
183     */
184 }
185 
186 static dnssec_keystore_domain_s*
dnssec_keystore_get_domain_nolock(dnssec_keystore * ks,const u8 * domain)187 dnssec_keystore_get_domain_nolock(dnssec_keystore *ks, const u8 *domain)
188 {
189     ptr_node *d_node = ptr_set_find(&ks->domains, domain);
190 
191     return (dnssec_keystore_domain_s*)((d_node != NULL)?d_node->value:NULL);
192 }
193 
194 static dnssec_keystore_domain_s*
dnssec_keystore_get_domain(dnssec_keystore * ks,const u8 * domain)195 dnssec_keystore_get_domain(dnssec_keystore *ks, const u8 *domain)
196 {
197     mutex_lock(&ks->lock);
198     dnssec_keystore_domain_s *ret = dnssec_keystore_get_domain_nolock(ks, domain); // locked
199     mutex_unlock(&ks->lock);
200     return ret;
201 }
202 
203 /**
204  * Adds the knowledge of domain<->path
205  * Set path to NULL to use the default value
206  *
207  * Can overwrite a previous value
208  *
209  * @param ks
210  * @param domain
211  * @param path
212  */
213 
214 static dnssec_keystore_domain_s*
dnssec_keystore_add_domain_nolock(dnssec_keystore * ks,const u8 * domain,const char * path)215 dnssec_keystore_add_domain_nolock(dnssec_keystore *ks, const u8 *domain, const char *path)
216 {
217     // insert or get the domain in the collection
218 
219     ptr_node *d_node = ptr_set_insert(&ks->domains, (u8*)domain);
220     dnssec_keystore_domain_s *d;
221 
222     if(d_node->value == NULL)
223     {
224         // insert : setup
225 
226         ZALLOC_OBJECT_OR_DIE(d, dnssec_keystore_domain_s, KSDOMAIN_TAG);
227         d->fqdn = dnsname_zdup(domain);
228         d_node->key = d->fqdn;
229         d->keys_scan_epoch = 0;
230         d->keys_path = NULL;
231         d->key_chain = NULL;
232         d_node->value = d;
233     }
234     else
235     {
236         // get : has the keys path changed ?
237 
238         d = (dnssec_keystore_domain_s*)d_node->value;
239 
240         if(d->keys_path != NULL)
241         {
242             // tests for NULL or equality
243 
244             if((path == d->keys_path) || ((path != NULL) && (strcmp(path, d->keys_path) == 0)))
245             {
246                 // it has not changed : nothing to do
247                 return d;
248             }
249 
250             // it has changed : reduce previous count
251 
252             ptr_node *node = ptr_set_find(&ks->paths, (char*)d->keys_path);
253             yassert(node != NULL);
254 
255             node->value = (void*)(((intptr)node->value) - 1);
256 
257             if(node->value == NULL)
258             {
259                 char *key = (char*)node->key;
260                 ptr_set_delete(&ks->paths, path);
261                 free(key);
262             }
263 
264             // the previous path is fully removed, the new value will be assigned, if needs to be, at the next step
265 
266             d->keys_path = NULL;
267             d->keys_scan_epoch = 0;
268         }
269     }
270 
271     if(path != NULL)
272     {
273         ptr_node *p_node = ptr_set_insert(&ks->paths, (char*)path);
274         if(p_node->value == NULL)
275         {
276             p_node->key = strdup(path);
277         }
278         p_node->value = (void*)(((intptr)p_node->value) + 1);
279 
280         d->keys_path = (const char*)p_node->key;
281         d->keys_scan_epoch = 0;
282     }
283 
284     return d;
285 }
286 
287 void
dnssec_keystore_add_domain(const u8 * domain,const char * path)288 dnssec_keystore_add_domain(/*dnssec_keystore *ks, */const u8 *domain, const char *path)
289 {
290     dnssec_keystore *ks = &g_keystore;
291     mutex_lock(&ks->lock);
292     dnssec_keystore_add_domain_nolock(ks, domain, path);
293     mutex_unlock(&ks->lock);
294 }
295 
296 /**
297  * Remove the knowledge of domain<->path
298  *
299  * @param ks
300  * @param domain
301  * @param path
302  */
303 
304 void
dnssec_keystore_remove_domain_nolock(const u8 * domain,const char * path)305 dnssec_keystore_remove_domain_nolock(/*dnssec_keystore *ks, */const u8 *domain, const char *path)
306 {
307     (void)domain;
308     dnssec_keystore *ks = &g_keystore;
309     ptr_node *node = ptr_set_find(&ks->paths, path);
310     if(node != NULL)
311     {
312         node->value = (void*)(((intptr)node->value) - 1);
313 
314         if(node->value == NULL)
315         {
316             char *key = (char*)node->key;
317             ptr_set_delete(&ks->paths, path);
318             free(key);
319         }
320     }
321 }
322 
323 void
dnssec_keystore_remove_domain(const u8 * domain,const char * path)324 dnssec_keystore_remove_domain(/*dnssec_keystore *ks, */const u8 *domain, const char *path)
325 {
326     (void)domain;
327     dnssec_keystore *ks = &g_keystore;
328     mutex_lock(&ks->lock);
329     dnssec_keystore_remove_domain_nolock(domain, path);
330     mutex_unlock(&ks->lock);
331 }
332 
333 /**
334  *
335  * Add a key to the keystore, do nothing if the key is already known
336  *
337  * RC ok
338  *
339  * @param ks
340  * @param key
341  */
342 
343 static bool
dnssec_keystore_add_key_nolock(dnssec_keystore * ks,dnssec_key * key)344 dnssec_keystore_add_key_nolock(dnssec_keystore *ks, dnssec_key *key)
345 {
346     const u8 *domain = dnskey_get_domain(key);
347     dnssec_keystore_domain_s *kd;
348 
349     kd = dnssec_keystore_get_domain_nolock(ks, domain); // caller nolock
350     if(kd == NULL)
351     {
352         kd = dnssec_keystore_add_domain_nolock(ks, domain, NULL);
353 
354         yassert(kd != NULL);
355     }
356 
357     // Add a reference in the keys collection
358 
359 
360     ptr_node *key_node = ptr_set_insert(&ks->keys, key);
361 
362 
363     if(key_node->value == NULL)
364     {
365         // new one
366         key_node->value = key;
367         dnskey_acquire(key); // RC
368 
369         // Add a reference in the domain keys collection
370         // insert, sorted by tag value
371 
372         dnskey_add_to_chain(key, &kd->key_chain); // RC
373 
374         return TRUE;
375     }
376     // else already known
377 
378     return FALSE;
379 }
380 
381 /**
382  *
383  * Replace a key from the keystore, release the replaced key
384  *
385  * RC ok
386  *
387  * @param ks
388  * @param key
389  */
390 
391 static bool
dnssec_keystore_replace_key_nolock(dnssec_keystore * ks,dnssec_key * key)392 dnssec_keystore_replace_key_nolock(dnssec_keystore *ks, dnssec_key *key)
393 {
394     const u8 *domain = dnskey_get_domain(key);
395     dnssec_keystore_domain_s *kd;
396 
397     kd = dnssec_keystore_get_domain_nolock(ks, domain); // caller nolock
398     if(kd == NULL)
399     {
400         kd = dnssec_keystore_add_domain_nolock(ks, domain, NULL);
401 
402         yassert(kd != NULL);
403     }
404 
405     // Add a reference in the keys collection
406 
407 
408     ptr_node *key_node = ptr_set_insert(&ks->keys, key);
409 
410 
411     dnssec_key *old_key = (dnssec_key*)key_node->value;
412 
413     if(old_key != key)
414     {
415         if(old_key != NULL)
416         {
417             dnskey_remove_from_chain(old_key, &kd->key_chain);
418             dnskey_release(old_key);
419         }
420 
421         dnskey_acquire(key);
422         key_node->value = key;
423 
424         // Add a reference in the domain keys collection
425         // insert, sorted by tag value
426 
427         dnskey_add_to_chain(key, &kd->key_chain); // RC
428 
429         return TRUE;
430     }
431     // else already known
432 
433     return FALSE;
434 }
435 
436 
437 /**
438  *
439  * Add a key to the keystore, do nothing if a key with the same tag and algorithm is
440  * in the keystore for that domain already
441  *
442  * RC ok
443  *
444  * @param ks
445  * @param key
446  *
447  * @return TRUE iff the key was added
448  */
449 
450 bool
dnssec_keystore_add_key(dnssec_key * key)451 dnssec_keystore_add_key(dnssec_key *key)
452 {
453     dnssec_keystore *ks = &g_keystore;
454     mutex_lock(&ks->lock);
455     bool ret = dnssec_keystore_add_key_nolock(ks, key); // RC // locked
456     mutex_unlock(&ks->lock);
457     return ret;
458 }
459 
460 /**
461  *
462  * Replace a key from the keystore, release the replaced key
463  *
464  * RC ok
465  *
466  * @param ks
467  * @param key
468  *
469  * @return TRUE iff the key was added
470  */
471 
472 bool
dnssec_keystore_replace_key(dnssec_key * key)473 dnssec_keystore_replace_key(dnssec_key *key)
474 {
475     dnssec_keystore *ks = &g_keystore;
476     mutex_lock(&ks->lock);
477     bool ret = dnssec_keystore_replace_key_nolock(ks, key); // RC // locked
478     mutex_unlock(&ks->lock);
479     return ret;
480 }
481 
482 /**
483  *
484  * Removes a key from the keystore
485  * If the key is found, it is returned acquired (still has to be released)
486  *
487  * RC ok
488  *
489  * @param ks
490  * @param key
491  * @return the instance of the key from the keystore, or NULL if the key was not found
492  */
493 
494 static dnssec_key*
dnssec_keystore_remove_key_nolock(dnssec_keystore * ks,dnssec_key * key)495 dnssec_keystore_remove_key_nolock(dnssec_keystore *ks, dnssec_key *key)
496 {
497     dnssec_key *ret_key = NULL;
498 
499     ptr_node *key_node = ptr_set_find(&ks->keys, key);
500 
501     if(key_node != NULL)
502     {
503         ret_key = (dnssec_key*)key_node->value;
504         ptr_set_delete(&ks->keys, key);
505         // no not release as it will be returned
506 
507         const u8 *domain = dnskey_get_domain(key);
508 
509         dnssec_keystore_domain_s *kd = dnssec_keystore_get_domain_nolock(ks, domain); // caller nolock
510 
511         if(kd != NULL)
512         {
513             // remove, sorted by tag value
514 
515             dnskey_remove_from_chain(key, &kd->key_chain); // RC
516         }
517     }
518     // else already known
519 
520     return ret_key;
521 }
522 
523 /**
524  *
525  * Removes a key from the keystore
526  * If the key is found, it is returned acquired (still requires release)
527  *
528  * RC ok
529  *
530  * @param ks
531  * @param key
532  *
533  * @return the instance of the key from the keystore, or NULL if the key was not found
534  */
535 
536 dnssec_key*
dnssec_keystore_remove_key(dnssec_key * key)537 dnssec_keystore_remove_key(dnssec_key *key)
538 {
539     dnssec_keystore *ks = &g_keystore;
540     mutex_lock(&ks->lock);
541     dnssec_key *ret_key = dnssec_keystore_remove_key_nolock(ks, key); // RC // locked
542     mutex_unlock(&ks->lock);
543     return ret_key;
544 }
545 
546 /**
547  * Removes a key from the keystore, if possible.
548  * Renames both key files adding suffix of the creation time plus bak
549  * Does not return any error code as it's a best effort kind of thing.
550  *
551  * @param key
552  */
553 
554 void
dnssec_keystore_delete_key(dnssec_key * key)555 dnssec_keystore_delete_key(dnssec_key *key)
556 {
557     dnssec_keystore_domain_s *domain;
558     char clean_origin[MAX_DOMAIN_LENGTH];
559 
560     const u8 *fqdn = key->owner_name;
561     const u8 algorithm = key->algorithm;
562     const u16 tag = key->tag;
563 
564     /* Load from the disk, add to the keystore */
565 
566     domain = dnssec_keystore_get_domain(&g_keystore, fqdn);
567     dnsname_to_cstr(clean_origin, fqdn);
568 
569     format_writer epoch_writer = {packedepoch_format_handler_method, (void*)(intptr)key->epoch_created};
570 
571     char path[PATH_MAX];
572     char path_new[PATH_MAX];
573 
574     // PRIVATE
575 
576     ya_result ret = SUCCESS;
577 
578     if((domain != NULL) && (domain->keys_path != NULL))
579     {
580         if(snprintf(path, PATH_MAX, "%s/" OAT_PRIVATE_FORMAT, domain->keys_path, clean_origin, algorithm, tag) >= PATH_MAX)
581         {
582             /* Path bigger than PATH_MAX */
583             ret = BIGGER_THAN_PATH_MAX;
584         }
585     }
586     else
587     {
588         if(snprintf(path, PATH_MAX, "%s/" OAT_PRIVATE_FORMAT, g_keystore_path, clean_origin, algorithm, tag) >= PATH_MAX)
589         {
590             /* Path bigger than PATH_MAX */
591             ret =  BIGGER_THAN_PATH_MAX;
592         }
593     }
594 
595     if(ISOK(ret) && (snformat(path_new, sizeof(path_new), "%s.%w.bak", path, &epoch_writer) < PATH_MAX))
596     {
597         log_debug("dnskey-keystore: %{dnsname}: delete: private key file is '%s'", fqdn, path);
598 
599         if(file_exists(path))
600         {
601             dnssec_key *key_from_file = NULL;
602 
603             ret = dnskey_new_private_key_from_file(path, &key_from_file); // RC
604 
605             if(ISOK(ret))
606             {
607                 if(dnskey_equals(key, key_from_file))
608                 {
609                     log_info("dnskey-keystore: %{dnsname}: delete: private key file content matches key: renaming file '%s' to '%s'",
610                             fqdn, path, path_new);
611 
612                     if(rename(path, path_new) < 0)
613                     {
614                         ret = ERRNO_ERROR;
615                         log_err("dnskey-keystore: %{dnsname}: delete: could not rename file '%s' to '%s': %r",
616                                 fqdn, path, path_new, ret);
617                     }
618                 }
619                 else
620                 {
621                     log_info("dnskey-keystore: %{dnsname}: delete: private key file content does not matches key: renaming file '%s' to '%s'",
622                             fqdn, path, path_new);
623                 }
624 
625                 dnskey_release(key_from_file);
626                 key_from_file = NULL;
627             }
628             else
629             {
630                 log_err("dnskey-keystore: %{dnsname}: delete: could not read key from private key file '%s': %r", fqdn, path, ret);
631             }
632         }
633         else
634         {
635             log_info("dnskey-keystore: %{dnsname}: delete: private key file '%s' does not exists", fqdn, path);
636         }
637     }
638     else
639     {
640         log_err("dnskey-keystore: %{dnsname}: delete: K%s+%03d+%05d private key file path size would be too big", fqdn, clean_origin, algorithm, tag);
641     }
642 
643     // PUBLIC
644 
645     ret = SUCCESS;
646 
647     if((domain != NULL) && (domain->keys_path != NULL))
648     {
649         if(snprintf(path, PATH_MAX, "%s/" OAT_DNSKEY_FORMAT, domain->keys_path, clean_origin, algorithm, tag) >= PATH_MAX)
650         {
651             /* Path bigger than PATH_MAX */
652             ret = BIGGER_THAN_PATH_MAX;
653         }
654     }
655     else
656     {
657         if(snprintf(path, PATH_MAX, "%s/" OAT_DNSKEY_FORMAT, g_keystore_path, clean_origin, algorithm, tag) >= PATH_MAX)
658         {
659             /* Path bigger than PATH_MAX */
660             ret = BIGGER_THAN_PATH_MAX;
661         }
662     }
663 
664     if(ISOK(ret) && (snformat(path_new, sizeof(path_new), "%s.%w.bak", path, &epoch_writer) < PATH_MAX))
665     {
666         log_debug("dnskey-keystore: %{dnsname}: delete: public key file is '%s'", fqdn, path);
667 
668         if(file_exists(path))
669         {
670             dnssec_key *key_from_file = NULL;
671 
672             ret = dnskey_new_public_key_from_file(path, &key_from_file); // RC
673 
674             if(ISOK(ret))
675             {
676                 if(dnskey_public_equals(key, key_from_file))
677                 {
678                     log_info("dnskey-keystore: %{dnsname}: delete: public key file content matches key: renaming file '%s' to '%s'", fqdn, path, path_new);
679 
680                     if(rename(path, path_new) < 0)
681                     {
682                         ret = ERRNO_ERROR;
683                         log_err("dnskey-keystore: %{dnsname}: delete: could not rename file '%s' to '%s': %r", fqdn, path, path_new, ret);
684                     }
685                 }
686                 else
687                 {
688                     log_info("dnskey-keystore: %{dnsname}: delete: public key file content does not matches key: renaming file '%s' to '%s'", fqdn, path, path_new);
689                 }
690 
691                 dnskey_release(key_from_file);
692                 key_from_file = NULL;
693             }
694             else
695             {
696                 log_err("dnskey-keystore: %{dnsname}: delete: could not read key from public key file '%s': %r", fqdn, path, ret);
697             }
698         }
699         else
700         {
701             log_info("dnskey-keystore: %{dnsname}: delete: public key file '%s' does not exists", fqdn, path);
702         }
703     }
704     else
705     {
706         log_err("dnskey-keystore: %{dnsname}: delete: K%s+%03d+%05d public key file path size would be too big", fqdn, clean_origin, algorithm, tag);
707     }
708 
709     dnssec_key *keystore_key =  dnssec_keystore_remove_key(key);
710     if(keystore_key != NULL)
711     {
712         dnskey_release(keystore_key);
713         keystore_key = NULL;
714     }
715 }
716 
717 /**
718  *
719  * Retrieves a key from the keystore
720  *
721  * RC ok
722  *
723  * @param ks
724  * @param domain
725  * @param tag
726  * @return
727  */
728 
729 static dnssec_key*
dnssec_keystore_acquire_key_from_fqdn_nolock(dnssec_keystore * ks,const u8 * domain,u16 tag)730 dnssec_keystore_acquire_key_from_fqdn_nolock(dnssec_keystore *ks, const u8 *domain, u16 tag)
731 {
732     dnssec_key *key = NULL;
733 
734     dnssec_keystore_domain_s* kd = dnssec_keystore_get_domain_nolock(ks, domain); // caller nolock
735     if(kd != NULL)
736     {
737         key = kd->key_chain;
738 
739         while(key != NULL)
740         {
741             u16 key_tag = dnskey_get_tag(key);
742             if(key_tag == tag)
743             {
744                 break;
745             }
746 
747             key = key->next;
748         }
749 
750         if(key != NULL)
751         {
752             dnskey_acquire(key);
753         }
754     }
755 
756     return key;
757 }
758 
759 /**
760  *
761  * Retrieves a key from the keystore
762  *
763  * RC ok
764  *
765  * @param ks
766  * @param domain
767  * @param tag
768  * @return
769  */
770 
771 dnssec_key*
dnssec_keystore_acquire_key_from_fqdn_with_tag(const u8 * domain,u16 tag)772 dnssec_keystore_acquire_key_from_fqdn_with_tag(const u8 *domain, u16 tag)
773 {
774     dnssec_keystore *ks = &g_keystore;
775     mutex_lock(&ks->lock);
776     dnssec_key *key = dnssec_keystore_acquire_key_from_fqdn_nolock(ks, domain, tag); // RC // locked
777     mutex_unlock(&ks->lock);
778 
779     return key;
780 }
781 
782 /**
783  *
784  * Retrieves a key from the keystore
785  *
786  * RC ok
787  *
788  * @param ks
789  * @param domain
790  * @param tag
791  * @return
792  */
793 
794 dnssec_key*
dnssec_keystore_acquire_key_from_rdata(const u8 * domain,const u8 * rdata,u16 rdata_size)795 dnssec_keystore_acquire_key_from_rdata(const u8 *domain, const u8 *rdata, u16 rdata_size)
796 {
797     dnssec_keystore *ks = &g_keystore;
798     u16 tag = dnskey_get_tag_from_rdata(rdata, rdata_size);
799     mutex_lock(&ks->lock);
800     dnssec_key *key = dnssec_keystore_acquire_key_from_fqdn_nolock(ks, domain, tag); // RC // locked
801     mutex_unlock(&ks->lock);
802 
803     return key;
804 }
805 
806 /**
807  * Returns the nth key from the domain or NULL if no such key exist
808  *
809  * RC ok
810  *
811  * @return a dnskey
812  */
813 
814 dnssec_key*
dnssec_keystore_acquire_key_from_fqdn_by_index(const u8 * domain,int idx)815 dnssec_keystore_acquire_key_from_fqdn_by_index(const u8 *domain, int idx)
816 {
817     dnssec_keystore *ks = &g_keystore;
818     dnssec_key *key = NULL;
819     mutex_lock(&ks->lock);
820     dnssec_keystore_domain_s* kd = dnssec_keystore_get_domain_nolock(ks, domain); // locked
821     if(kd != NULL)
822     {
823         key = kd->key_chain;
824 
825         while(idx > 0 && key != NULL)
826         {
827             --idx;
828             key = key->next;
829         }
830 
831         if(key != NULL)
832         {
833             dnskey_acquire(key);
834         }
835     }
836     mutex_unlock(&ks->lock);
837 
838     return key;
839 }
840 
841 dnssec_key *
dnssec_keystore_acquire_key_from_fqdn_at_index(const u8 * domain,int index)842 dnssec_keystore_acquire_key_from_fqdn_at_index(const u8 *domain, int index)
843 {
844     dnssec_key *key = NULL;
845     dnssec_keystore *ks = &g_keystore;
846     mutex_lock(&ks->lock);
847     dnssec_keystore_domain_s *ks_domain = dnssec_keystore_get_domain_nolock(ks, domain); // locked
848     if(ks_domain != NULL)
849     {
850         key = ks_domain->key_chain;
851         while(index > 0 && key != NULL)
852         {
853             key = key->next;
854             --index;
855         }
856         if(key != NULL)
857         {
858             dnskey_acquire(key);
859         }
860     }
861     mutex_unlock(&ks->lock);
862     return key;
863 }
864 
865 bool
dnssec_keystore_has_usable_ksk(const u8 * domain,time_t attime)866 dnssec_keystore_has_usable_ksk(const u8 *domain, time_t attime)
867 {
868     dnssec_keystore *ks = &g_keystore;
869     dnssec_key *key = NULL;
870     bool ret = FALSE;
871     mutex_lock(&ks->lock);
872     dnssec_keystore_domain_s* kd = dnssec_keystore_get_domain_nolock(ks, domain); // locked
873     if(kd != NULL)
874     {
875         key = kd->key_chain;
876 
877         while(key != NULL)
878         {
879             if(dnskey_get_flags(key) == (DNSKEY_FLAG_ZONEKEY | DNSKEY_FLAG_KEYSIGNINGKEY))
880             {
881                 if(dnskey_is_activated(key, attime))
882                 {
883                     ret = TRUE;
884                     break;
885                 }
886             }
887 
888             key = key->next;
889         }
890     }
891 
892     mutex_unlock(&ks->lock);
893 
894     return ret;
895 }
896 
897 
898 
899 int
dnssec_keystore_acquire_publish_delete_keys_from_fqdn_to_vectors(const u8 * domain,ptr_vector * publish_keys,ptr_vector * delete_keys)900 dnssec_keystore_acquire_publish_delete_keys_from_fqdn_to_vectors(const u8 *domain, ptr_vector *publish_keys, ptr_vector *delete_keys)
901 {
902     time_t now = time(NULL);
903 
904     for(int i = 0; ;++i)
905     {
906         dnssec_key *key = dnssec_keystore_acquire_key_from_fqdn_by_index(domain, i);
907 
908         if(key == NULL)
909         {
910             log_debug1("dnskey-keystore: acquiring activated key %{dnsname}: no other key available", domain);
911             break;
912         }
913 
914         if((key->status & DNSKEY_KEY_IS_IN_ZONE) == 0)
915         {
916             if(dnskey_has_explicit_publish_or_delete(key))
917             {
918                 if(dnskey_is_published(key, now))
919                 {
920                     if((publish_keys != NULL) && (ptr_vector_search_ptr_index(publish_keys, key) < 0))
921                     {
922                         ptr_vector_append(publish_keys, key);
923                     }
924                     else
925                     {
926                         dnskey_release(key);
927                     }
928                     continue;
929                 }
930 
931                 if(dnskey_is_unpublished(key, now))
932                 {
933                     if((delete_keys != NULL) && (ptr_vector_search_ptr_index(delete_keys, key) < 0))
934                     {
935                         ptr_vector_append(delete_keys, key);
936                     }
937                     else
938                     {
939                         dnskey_release(key);
940                     }
941                     continue;
942                 }
943             }
944             else if(dnskey_has_activate_or_deactivate(key))
945             {
946                 if(dnskey_is_activated(key, now))
947                 {
948                     if((publish_keys != NULL) && (ptr_vector_search_ptr_index(publish_keys, key) < 0))
949                     {
950                         ptr_vector_append(publish_keys, key);
951                     }
952                     else
953                     {
954                         dnskey_release(key);
955                     }
956                     continue;
957                 }
958                 if(dnskey_is_deactivated(key, MAX((s64)now - AUTOMATIC_DEACTIVATED_DNSKEY_UNPUBLISH_DELAY, 0)))
959                 {
960                     if((delete_keys != NULL) && (ptr_vector_search_ptr_index(delete_keys, key) < 0))
961                     {
962                         ptr_vector_append(delete_keys, key);
963                     }
964                     else
965                     {
966                         dnskey_release(key);
967                     }
968                     continue;
969                 }
970             }
971         }
972 
973         dnskey_release(key);
974     }
975 
976     int ret = 0;
977 
978     if(publish_keys != NULL)
979     {
980         ret += ptr_vector_size(publish_keys);
981     }
982 
983     if(delete_keys != NULL)
984     {
985         ret += ptr_vector_size(delete_keys);
986     }
987 
988     return  ret;
989 }
990 
991 /**
992  * Releases all the keys from a vector.
993  *
994  * @param keys
995  */
996 
997 void
dnssec_keystore_release_keys_from_vector(ptr_vector * keys)998 dnssec_keystore_release_keys_from_vector(ptr_vector *keys)
999 {
1000     for(int i = 0; i <= ptr_vector_last_index(keys); ++i)
1001     {
1002         dnssec_key *key = (dnssec_key*)ptr_vector_get(keys, i);
1003 
1004         log_debug("dnskey-keystore: releasing key %{dnsname}", dnskey_get_domain(key));
1005 
1006         dnskey_release(key);
1007     }
1008 }
1009 
1010 /**
1011  *
1012  * Retrieves a key from the keystore
1013  *
1014  * RC ok
1015  *
1016  * @param ks
1017  * @param domain
1018  * @param tag
1019  * @return
1020  */
1021 
1022 static dnssec_key*
dnssec_keystore_acquire_key_from_name_nolock(dnssec_keystore * ks,const char * domain,u16 tag)1023 dnssec_keystore_acquire_key_from_name_nolock(dnssec_keystore *ks, const char *domain, u16 tag)
1024 {
1025     dnssec_key *key = NULL;
1026     u8 fqdn[MAX_DOMAIN_LENGTH];
1027 
1028     if(ISOK(cstr_to_dnsname(fqdn, domain)))
1029     {
1030         key = dnssec_keystore_acquire_key_from_fqdn_nolock(ks, fqdn, tag); // RC // caller nolock
1031     }
1032 
1033     return key;
1034 }
1035 
1036 /**
1037  *
1038  * Retrieves a key from the keystore
1039  *
1040  * RC ok
1041  *
1042  * @param ks
1043  * @param domain
1044  * @param tag
1045  * @return
1046  */
1047 
1048 dnssec_key*
dnssec_keystore_acquire_key_from_name(const char * domain,u16 tag)1049 dnssec_keystore_acquire_key_from_name(const char *domain, u16 tag)
1050 {
1051     dnssec_key *key = NULL;
1052     u8 fqdn[MAX_DOMAIN_LENGTH];
1053 
1054     if(ISOK(cstr_to_dnsname(fqdn, domain)))
1055     {
1056         key = dnssec_keystore_acquire_key_from_fqdn_with_tag(fqdn, tag); // RC
1057     }
1058 
1059     return key;
1060 }
1061 
1062 /**
1063  * Returns the nth key from the domain or NULL if no such key exist
1064  *
1065  * RC ok
1066  *
1067  * @return a dnskey
1068  */
1069 
1070 dnssec_key *
dnssec_keystore_acquire_key_from_name_by_index(const char * domain,int idx)1071 dnssec_keystore_acquire_key_from_name_by_index(const char *domain, int idx)
1072 {
1073     dnssec_key *key = NULL;
1074     u8 fqdn[MAX_DOMAIN_LENGTH];
1075 
1076     if(ISOK(cstr_to_dnsname(fqdn, domain)))
1077     {
1078         key = dnssec_keystore_acquire_key_from_fqdn_by_index(fqdn, idx); // RC
1079     }
1080 
1081     return key;
1082 }
1083 
1084 struct dnssec_keystore_reload_readdir_callback_s
1085 {
1086     dnssec_keystore *ks;
1087     const char *domain;
1088     int private_update;
1089 };
1090 
1091 typedef struct dnssec_keystore_reload_readdir_callback_s dnssec_keystore_reload_readdir_callback_s;
1092 
1093 static ya_result
dnssec_keystore_reload_readdir_callback_nolock(const char * basedir,const char * filename,u8 filetype,void * args_)1094 dnssec_keystore_reload_readdir_callback_nolock(const char *basedir, const char *filename, u8 filetype, void *args_)
1095 {
1096 //#define OAT_PRIVATE_FORMAT "K%s+%03d+%05d.private"
1097 //#define OAT_DNSKEY_FORMAT "K%s+%03d+%05d.key"
1098     if((filetype == DT_REG) && (filename[0] != 'K'))
1099     {
1100         return SUCCESS;
1101     }
1102 
1103     dnssec_keystore_reload_readdir_callback_s *args = (dnssec_keystore_reload_readdir_callback_s*)args_;
1104 
1105     dnssec_keystore *ks = args->ks;
1106 
1107     int algorithm;
1108     int tag;
1109     char extension[16];
1110     char domain[256];
1111     char file[PATH_MAX + 1];
1112 
1113     size_t dlen = strlen(basedir);
1114     size_t flen = strlen(filename);
1115 
1116     if(dlen + flen >= sizeof(file))
1117     {
1118         log_err("path too long for '%s'/'%s'", basedir, filename);
1119         return INVALID_PATH;
1120     }
1121     memset(extension, 0, sizeof(extension)); // to shut-up valgrind
1122     memcpy(file, basedir, dlen);
1123     if(file[dlen - 1] != '/')
1124     {
1125         file[dlen++] = '/';
1126     }
1127     memcpy(&file[dlen], filename, flen + 1);
1128 
1129     if(sscanf(filename, "K%255[^+]+%03d+%05d.%15s", domain, &algorithm, &tag, extension) == 4)
1130     {
1131         domain[255] = '\0'; // ensure the 256th char is '\0'
1132         if((args->domain == NULL) || (strcmp(domain, args->domain) == 0))
1133         {
1134             if(memcmp(extension, "private", 8) == 0)
1135             {
1136                 log_debug("found private key file for domain '%s' with tag %i and algorithm %i", domain, tag, algorithm);
1137                 s64 ts;
1138 
1139                 if(ISOK(file_mtime(file, &ts)))
1140                 {
1141                     // get the key with that domain/tag
1142                     // @note 20150907 edf -- work in progress
1143 
1144                     dnssec_key *current_key = dnssec_keystore_acquire_key_from_name_nolock(ks, domain, tag); // RC // caller nolock
1145                     if(current_key != NULL)
1146                     {
1147                         // check if it has to be reloaded
1148                         if(current_key->timestamp >= ts)
1149                         {
1150                             // ignore this file (already got it)
1151 
1152                             dnskey_release(current_key);
1153 
1154                             return SUCCESS;
1155                         }
1156 
1157 			            log_info("DNSKEY from file '%s' was modified (expected %lT, got %lT)", filename, current_key->timestamp, ts);
1158                     }
1159 
1160                     dnssec_key *key;
1161 
1162                     // remove the key from the keystore, load the key from disk
1163 
1164                     log_debug("dnssec_keystore_reload_readdir_callback: opening file '%s'", file);
1165 
1166                     ya_result ret;
1167 
1168                     if(ISOK(ret = dnskey_new_private_key_from_file(file, &key)))
1169                     {
1170                         bool is_missing_any_smart_field = !dnskey_has_explicit_publish_and_delete(key) || !dnskey_has_explicit_activate(key) || !dnskey_has_explicit_deactivate(key);
1171                         bool has_no_smart_field = dnskey_has_explicit_publish_or_delete(key) && dnskey_has_explicit_activate(key) && dnskey_has_explicit_deactivate(key);
1172 
1173                         if(has_no_smart_field)
1174                         {
1175                             log_info("key from '%s' has no smart fields", file);
1176                         }
1177                         else if(is_missing_any_smart_field)
1178                         {
1179                             log_info("key from '%s' is missing some smart fields", file);
1180                         }
1181 #if DEBUG
1182                         log_debug1("dnssec_keystore_reload_readdir_callback: private key generated from file '%s'", file);
1183 #endif
1184                         // compare the cryptographic parts of the key (the public key is enough) and
1185                         // overwrite the timestamps iff they are the same, else ... refuse to break security
1186 
1187                         if(current_key != NULL)
1188                         {
1189                             if(dnskey_equals(current_key, key))
1190                             {
1191 #if DEBUG
1192                                 log_debug1("dnssec_keystore_reload_readdir_callback: file '%s' has already been loaded", file);
1193 #endif
1194                                 current_key->epoch_created = key->epoch_created;
1195                                 current_key->epoch_publish = key->epoch_publish;
1196                                 current_key->epoch_activate = key->epoch_activate;
1197 
1198                                 current_key->epoch_inactive = key->epoch_inactive;
1199                                 current_key->epoch_delete = key->epoch_delete;
1200                                 current_key->timestamp = key->timestamp;
1201                                 current_key->status &= ~(DNSKEY_KEY_HAS_SMART_FIELD_PUBLISH|DNSKEY_KEY_HAS_SMART_FIELD_DELETE|DNSKEY_KEY_HAS_SMART_FIELD_ACTIVATE|DNSKEY_KEY_HAS_SMART_FIELD_INACTIVE);
1202                                 current_key->status |= key->status &  (DNSKEY_KEY_HAS_SMART_FIELD_PUBLISH|DNSKEY_KEY_HAS_SMART_FIELD_DELETE|DNSKEY_KEY_HAS_SMART_FIELD_ACTIVATE|DNSKEY_KEY_HAS_SMART_FIELD_INACTIVE);
1203                             }
1204                             else
1205                             {
1206                                 // update
1207 #if DEBUG
1208                                 log_debug1("dnssec_keystore_reload_readdir_callback: file '%s' updated a key", file);
1209 #endif
1210                                 current_key->epoch_created = key->epoch_created;
1211                                 current_key->epoch_publish = key->epoch_publish;
1212                                 current_key->epoch_activate = key->epoch_activate;
1213 
1214                                 current_key->epoch_inactive = key->epoch_inactive;
1215                                 current_key->epoch_delete = key->epoch_delete;
1216                                 current_key->timestamp = key->timestamp;
1217 
1218                                 current_key->status &= ~(DNSKEY_KEY_HAS_SMART_FIELD_PUBLISH|DNSKEY_KEY_HAS_SMART_FIELD_DELETE|DNSKEY_KEY_HAS_SMART_FIELD_ACTIVATE|DNSKEY_KEY_HAS_SMART_FIELD_INACTIVE);
1219                                 current_key->status |= key->status & (DNSKEY_KEY_HAS_SMART_FIELD_PUBLISH|DNSKEY_KEY_HAS_SMART_FIELD_DELETE|DNSKEY_KEY_HAS_SMART_FIELD_ACTIVATE|DNSKEY_KEY_HAS_SMART_FIELD_INACTIVE);
1220 
1221                                 // update key re-signature scheduling
1222                             }
1223 
1224                             dnskey_release(current_key);
1225                         }
1226                         else
1227                         {
1228                             // add the new key
1229 #if DEBUG
1230                             log_debug1("dnssec_keystore_reload_readdir_callback: file '%s' generated a new key", file);
1231 #endif
1232                             dnssec_keystore_add_key_nolock(ks, key); // RC // caller nolock
1233 
1234                             // also : the key should be put in the zone and signature should be scheduled
1235                         }
1236 
1237                         dnskey_release(key);
1238                         ++args->private_update; // one key was modified (it's timings at the very least)
1239 #if DEBUG
1240                         log_debug1("dnssec_keystore_reload_readdir_callback: file '%s' successfully read", file);
1241 #endif
1242                     }
1243                     else
1244                     {
1245                         log_debug("could not read '%s': %r (missing public .key file ?)", file, ret);
1246                     }
1247                 }
1248                 else
1249                 {
1250                     log_err("could not access '%s': %r", file, ERRNO_ERROR);
1251                 }
1252             } // else this is not a private key file
1253         }
1254         else
1255         {
1256             log_debug("ignoring key file %s (%s != %s)", filename, domain, args->domain);
1257         }
1258     }
1259     else
1260     {
1261         log_debug("ignoring file %s", filename);
1262     }
1263 
1264     return SUCCESS; // invalid file name, but it's irrelevant for this
1265 }
1266 
1267 /**
1268  *
1269  * (Re)loads keys found in the paths of the keystore
1270  *
1271  * @return
1272  */
1273 
1274 ya_result
dnssec_keystore_reload()1275 dnssec_keystore_reload()
1276 {
1277     // scan all directories
1278 
1279     //   for each key found, load and propose it to the domain
1280     //     if the key has changed ...
1281     //       timings: remove the previous alarms (?)
1282     //       removed: ?
1283     //       added:   update alarms (?)
1284 
1285     dnssec_keystore *ks = &g_keystore;
1286     ya_result ret;
1287 
1288     dnssec_keystore_reload_readdir_callback_s args = {ks, NULL, 0};
1289 
1290     mutex_lock(&ks->lock);
1291 
1292     ptr_set_iterator iter;
1293     ptr_set_iterator_init(&ks->paths, &iter);
1294     while(ptr_set_iterator_hasnext(&iter))
1295     {
1296         ptr_node *path_node = ptr_set_iterator_next_node(&iter);
1297         const char *path = (const char*)path_node->key;
1298         if(FAIL(ret = readdir_forall(path, dnssec_keystore_reload_readdir_callback_nolock, &args)))
1299         {
1300             log_err("dnssec keystore reload: an error occurred reading key directory '%s': %r", path, ret);
1301         }
1302     }
1303 
1304     if(FAIL(ret = readdir_forall(g_keystore_path, dnssec_keystore_reload_readdir_callback_nolock, &args)))
1305     {
1306         log_err("dnssec keystore reload: an error occurred reading key directory '%s': %r", g_keystore_path, ret);
1307     }
1308 
1309     mutex_unlock(&ks->lock);
1310 
1311     if(ISOK(ret))
1312     {
1313         ret = args.private_update;
1314     }
1315 
1316     return ret;
1317 }
1318 
1319 /**
1320  *
1321  * (Re)loads keys found in the path of the keystore for the specified domain
1322  *
1323  * @param fqdn
1324  * @return
1325  */
1326 
1327 ya_result
dnssec_keystore_reload_domain(const u8 * fqdn)1328 dnssec_keystore_reload_domain(const u8 *fqdn)
1329 {
1330     // scan all directories
1331 
1332     //   for each key found, load and propose it to the domain
1333     //     if the key has changed ...
1334     //       timings: remove the previous alarms (?)
1335     //       removed: ?
1336     //       added:   update alarms (?)
1337 
1338     log_debug("dnskey-keystore: %{dnsname}: reload domain: scanning for keys", fqdn);
1339 
1340     dnssec_keystore *ks = &g_keystore;
1341     ya_result ret = SUCCESS;
1342 
1343     mutex_lock(&ks->lock);
1344 
1345     dnssec_keystore_domain_s *keystore_domain = dnssec_keystore_get_domain_nolock(ks, fqdn); // locked
1346 
1347     ret = DNSSEC_ERROR_NO_KEY_FOR_DOMAIN; // no key for domain
1348 
1349     if(keystore_domain != NULL)
1350     {
1351         char domain[MAX_DOMAIN_LENGTH];
1352 
1353         dnsname_to_cstr(domain, fqdn);
1354 
1355         dnssec_keystore_reload_readdir_callback_s args = {ks, domain, 0};
1356 
1357         const char *path = keystore_domain->keys_path;
1358 
1359         if(path == NULL)
1360         {
1361             path = g_keystore_path;
1362         }
1363 
1364         struct stat st;
1365         stat(path, &st);
1366 #if defined WIN32
1367         s64 mod_time = st.st_mtime;
1368 #elif IS_DARWIN_OS
1369         s64 mod_time = st.st_mtimespec.tv_sec;
1370         mod_time *= 1000000000LL;
1371         mod_time += st.st_mtimespec.tv_nsec;
1372 #else
1373         s64 mod_time = st.st_mtim.tv_sec;
1374         mod_time *= 1000000000LL;
1375         mod_time += st.st_mtim.tv_nsec;
1376 #endif
1377 
1378         if((u64)mod_time > keystore_domain->keys_scan_epoch)
1379         {
1380             if(ISOK(ret = readdir_forall(path, dnssec_keystore_reload_readdir_callback_nolock, &args)))
1381             {
1382                 ret = args.private_update;
1383 
1384                 keystore_domain->keys_scan_epoch = mod_time;
1385             }
1386             else
1387             {
1388                 log_err("dnssec keystore: %{dnsname} reload domain: an error occurred reading key directory '%s': %r", fqdn, path, ret);
1389 
1390                 if(keystore_domain->key_chain != NULL)
1391                 {
1392                     ret = 0;
1393                 }
1394             }
1395         }
1396         else
1397         {
1398             log_debug("dnssec keystore: %{dnsname} reload domain: no need to scan key directory '%s' again", fqdn, path);
1399 
1400             ret = 0;
1401         }
1402     }
1403 
1404     mutex_unlock(&ks->lock);
1405 
1406     return ret;
1407 }
1408 
1409 // sanitises an origin
1410 
1411 static void
dnssec_keystore_origin_copy_sanitize(char * target,const char * origin)1412 dnssec_keystore_origin_copy_sanitize(char* target, const char* origin)
1413 {
1414     if(origin == NULL)
1415     {
1416         target[0] = '.';
1417         target[1] = '\0';
1418         return;
1419     }
1420 
1421     int origin_len = strlen(origin);
1422 
1423     if(origin_len == 0)
1424     {
1425         target[0] = '.';
1426         target[1] = '\0';
1427         return;
1428     }
1429 
1430     if(origin[origin_len - 1] == '.')
1431     {
1432         origin_len++;
1433         MEMCOPY(target, origin, origin_len);
1434     }
1435     else
1436     {
1437         MEMCOPY(target, origin, origin_len);
1438         target[origin_len++] = '.';
1439         target[origin_len] = '\0';
1440     }
1441 }
1442 
1443 const char*
dnssec_keystore_getpath()1444 dnssec_keystore_getpath()
1445 {
1446     return g_keystore_path;
1447 }
1448 
1449 static const char* dnssec_default_keystore_path = DNSSEC_DEFAULT_KEYSTORE_PATH;
1450 
1451 void
dnssec_keystore_resetpath()1452 dnssec_keystore_resetpath()
1453 {
1454     /*
1455      * cast to void to avoid the -Wstring-compare warning
1456      */
1457 
1458     if(((void*)g_keystore_path) != ((void*)dnssec_default_keystore_path))
1459     {
1460         free((void*)g_keystore_path);
1461         g_keystore_path = dnssec_default_keystore_path;
1462     }
1463 }
1464 
1465 void
dnssec_keystore_setpath(const char * path)1466 dnssec_keystore_setpath(const char* path)
1467 {
1468     dnssec_keystore_resetpath();
1469 
1470     if(path != NULL)
1471     {
1472         g_keystore_path = strdup(path);
1473     }
1474 }
1475 /*
1476 void
1477 dnssec_keystore_destroy_paths_cb(ptr_node *node)
1478 {
1479     free(node->key);
1480 }
1481 */
1482 
1483 static void
dnssec_keystore_destroy_domains_cb(ptr_node * node)1484 dnssec_keystore_destroy_domains_cb(ptr_node *node)
1485 {
1486     dnssec_keystore_domain_s *d = (dnssec_keystore_domain_s*)node->value;
1487     dnsname_zfree(d->fqdn);
1488     d->fqdn = NULL;
1489     ZFREE_OBJECT(d);
1490     //d->keys_path is a pointer to a key in g_keystore.paths
1491     //d->key_chain should have been emptied by now
1492 }
1493 
1494 void
dnssec_keystore_destroy()1495 dnssec_keystore_destroy()
1496 {
1497     log_debug("dnskey-keystore: clearing-up");
1498 
1499     mutex_lock(&g_keystore.lock);
1500 
1501     while(!ptr_set_isempty(&g_keystore.keys))
1502     {
1503         ptr_node *key_node = g_keystore.keys.root;
1504         dnssec_key *key = (dnssec_key *)key_node->key;
1505 
1506         if(key != NULL)
1507         {
1508             log_debug("dnskey-keystore: %{dnsname} +%03d+%05d/%d status=%x rc=%i (%p)", dnskey_get_domain(key), key->algorithm, key->tag, ntohs(key->flags), key->status, key->rc, key);
1509 
1510             dnssec_key *ret_key = dnssec_keystore_remove_key_nolock(&g_keystore, key); // locked
1511             dnskey_release(ret_key);
1512         }
1513         else
1514         {
1515             break;
1516         }
1517     }
1518 
1519     ptr_set_callback_and_destroy(&g_keystore.domains, dnssec_keystore_destroy_domains_cb);
1520 
1521     mutex_unlock(&g_keystore.lock);
1522 }
1523 
1524 
1525 /** Generates a private key, store in the keystore
1526  *  The caller is supposed to create a resource record with this key and add
1527  *  it to the owner.
1528  */
1529 
1530 ya_result
dnssec_keystore_new_key(u8 algorithm,u32 size,u16 flags,const char * origin,dnssec_key ** out_key)1531 dnssec_keystore_new_key(u8 algorithm, u32 size, u16 flags, const char *origin, dnssec_key **out_key)
1532 {
1533     ya_result return_value;
1534 
1535     dnssec_key* key = NULL;
1536 
1537     char clean_origin[MAX_DOMAIN_LENGTH];
1538     u8 fqdn[MAX_DOMAIN_LENGTH];
1539 
1540     /* sanitise the origin name */
1541 
1542     dnssec_keystore_origin_copy_sanitize(clean_origin, origin);
1543     cstr_to_dnsname(fqdn, clean_origin);
1544 
1545     /**
1546      * @note if 65536 keys exist then this function will loop forever
1547      */
1548 
1549     for(;;)
1550     {
1551         switch(algorithm)
1552         {
1553             case DNSKEY_ALGORITHM_RSASHA1:
1554             case DNSKEY_ALGORITHM_RSASHA1_NSEC3:
1555             case DNSKEY_ALGORITHM_RSASHA256_NSEC3:
1556             case DNSKEY_ALGORITHM_RSASHA512_NSEC3:
1557             {
1558                 if(FAIL(return_value = dnskey_rsa_newinstance(size, algorithm, flags, clean_origin, &key)))
1559                 {
1560                     return return_value;
1561                 }
1562 
1563                 break;
1564             }
1565             case DNSKEY_ALGORITHM_DSASHA1:
1566             case DNSKEY_ALGORITHM_DSASHA1_NSEC3:
1567             {
1568                 if(FAIL(return_value = dnskey_dsa_newinstance(size, algorithm, flags, clean_origin, &key)))
1569                 {
1570                     return return_value;
1571                 }
1572 
1573                 break;
1574             }
1575 #if HAS_ECDSA_SUPPORT
1576             case DNSKEY_ALGORITHM_ECDSAP256SHA256:
1577             case DNSKEY_ALGORITHM_ECDSAP384SHA384:
1578             {
1579                 if(FAIL(return_value = dnskey_ecdsa_newinstance(size, algorithm, flags, clean_origin, &key)))
1580                 {
1581                     return return_value;
1582                 }
1583 
1584                 break;
1585             }
1586 #endif
1587 #if HAS_EDDSA_SUPPORT
1588             case DNSKEY_ALGORITHM_ED25519:
1589             case DNSKEY_ALGORITHM_ED448:
1590             {
1591                 if(FAIL(return_value = dnskey_eddsa_newinstance(size, algorithm, flags, clean_origin, &key)))
1592                 {
1593                     return return_value;
1594                 }
1595 
1596                 break;
1597             }
1598 #endif
1599 #ifdef DNSKEY_ALGORITHM_DUMMY
1600             case DNSKEY_ALGORITHM_DUMMY:
1601             {
1602                 if(FAIL(return_value = dnskey_dummy_newinstance(size, algorithm, flags, clean_origin, &key)))
1603                 {
1604                     return return_value;
1605                 }
1606             }
1607 #endif
1608             default:
1609             {
1610                 return DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM;
1611             }
1612         }
1613 
1614         dnssec_key *same_tag_key = NULL;
1615 
1616         dnskey_get_tag(key); // updates the tag field if needed
1617 
1618         if(ISOK(return_value = dnssec_keystore_load_private_key_from_parameters(algorithm, key->tag, flags, fqdn, &same_tag_key))) // key properly released
1619         {
1620             dnskey_release(same_tag_key);
1621         }
1622         else
1623         {
1624             // the key already exists
1625 
1626             dnssec_keystore_store_private_key(key);
1627             dnssec_keystore_store_public_key(key);
1628 
1629             dnssec_keystore_add_key(key);
1630             break;
1631         }
1632 
1633         dnskey_release(key);
1634     }
1635 
1636     *out_key = key;
1637 
1638     return SUCCESS;
1639 }
1640 
1641 /**
1642  * Loads a public key from the rdata, store in the keystore, then sets out_key to point to it
1643  *
1644  * RC ok
1645  *
1646  * @param rdata
1647  * @param rdata_size
1648  * @param origin
1649  * @param out_key
1650  * @return
1651  */
1652 
1653 ya_result
dnssec_keystore_load_public_key_from_rdata(const u8 * rdata,u16 rdata_size,const u8 * fqdn,dnssec_key ** out_key)1654 dnssec_keystore_load_public_key_from_rdata(const u8 *rdata, u16 rdata_size, const u8 *fqdn, dnssec_key **out_key)
1655 {
1656     //u16 flags = DNSKEY_FLAGS_FROM_RDATA(rdata);
1657     //u8 algorithm = rdata[3];
1658 
1659     u16 tag = dnskey_get_tag_from_rdata(rdata, rdata_size);
1660 
1661     ya_result ret = SUCCESS;
1662 
1663     dnssec_key *key = dnssec_keystore_acquire_key_from_fqdn_with_tag(fqdn, tag);
1664 
1665     if(key == NULL)
1666     {
1667         if(ISOK(ret = dnskey_new_from_rdata(rdata, rdata_size, fqdn, &key))) // RC
1668         {
1669             if(!dnssec_keystore_add_key(key)) // RC
1670             {
1671                 dnskey_release(key);
1672 
1673                 key = dnssec_keystore_acquire_key_from_fqdn_with_tag(fqdn, tag);
1674 
1675                 if(key == NULL) // should not happen
1676                 {
1677                     ret = ERROR;
1678                 }
1679             }
1680         }
1681     }
1682 
1683     *out_key = key; // already RCed at instantiation
1684 
1685     return ret;
1686 }
1687 
1688 /**
1689  *  Loads a private key from the disk or the keystore, then returns it.
1690  *  NOTE: If the key already existed as a public-only key, the public version is released.
1691  *
1692  * RC ok
1693  *
1694  * @param algorithm
1695  * @param tag
1696  * @param flags
1697  * @param origin
1698  * @param out_key
1699  * @return the number of keys loaded by the call (1 or 0) or an error code
1700  */
1701 
1702 ya_result
dnssec_keystore_load_private_key_from_rdata(const u8 * rdata,u16 rdata_size,const u8 * fqdn,dnssec_key ** out_key)1703 dnssec_keystore_load_private_key_from_rdata(const u8 *rdata, u16 rdata_size, const u8 *fqdn, dnssec_key **out_key)
1704 {
1705     if(rdata_size < 4)
1706     {
1707         return INVALID_ARGUMENT_ERROR;
1708     }
1709 
1710     u16 tag = dnskey_get_tag_from_rdata(rdata, rdata_size);
1711     u16 flags = GET_U16_AT_P(rdata);
1712     u8 algorithm = rdata[3];
1713 
1714     ya_result ret = dnssec_keystore_load_private_key_from_parameters(algorithm, tag, flags, fqdn, out_key);
1715 
1716     return ret;
1717 }
1718 
1719 /**
1720  *  Loads a private key from the disk or the keystore, then returns it.
1721  *  NOTE: If the key already existed as a public-only key, the public version is released.
1722  *
1723  * RC ok
1724  *
1725  * @param algorithm
1726  * @param tag
1727  * @param flags
1728  * @param origin
1729  * @param out_key
1730  * @return SUCCESS if a key is loaded, 1 if the key was already loaded, or an error code
1731  */
1732 
1733 ya_result
dnssec_keystore_load_private_key_from_parameters(u8 algorithm,u16 tag,u16 flags,const u8 * fqdn,dnssec_key ** out_key)1734 dnssec_keystore_load_private_key_from_parameters(u8 algorithm, u16 tag, u16 flags, const u8* fqdn, dnssec_key **out_key)
1735 {
1736     dnssec_key *key = dnssec_keystore_acquire_key_from_fqdn_with_tag(fqdn, tag);
1737     ya_result ret;
1738     bool has_public_key = FALSE;
1739 
1740     *out_key = NULL;
1741 
1742     if(key != NULL && !dnskey_is_private(key))
1743     {
1744         log_debug("dnssec_key_load_private: %{dnsname} +%03d+%05d/%d is not private", fqdn, algorithm, tag, ntohs(flags));
1745 
1746         has_public_key = TRUE;
1747         dnskey_release(key);
1748         key = NULL;
1749     }
1750 
1751     if(key == NULL)
1752     {
1753         // the key is not loaded already
1754 
1755         dnssec_keystore_domain_s *domain;
1756         char clean_origin[MAX_DOMAIN_LENGTH];
1757         dnsname_to_cstr(clean_origin, fqdn);
1758 
1759         /* Load from the disk, add to the keystore */
1760 
1761         domain = dnssec_keystore_get_domain(&g_keystore, fqdn);
1762 
1763         char path[PATH_MAX];
1764         path[0] = '\0';
1765 
1766         if((domain != NULL) && (domain->keys_path != NULL))
1767         {
1768             if(snprintf(path, sizeof(path), "%s/" OAT_PRIVATE_FORMAT, domain->keys_path, clean_origin, algorithm, tag) >= PATH_MAX)
1769             {
1770                 /* Path bigger than PATH_MAX */
1771                 return BIGGER_THAN_PATH_MAX;
1772             }
1773         }
1774         else
1775         {
1776             if(snprintf(path, sizeof(path), "%s/" OAT_PRIVATE_FORMAT, g_keystore_path, clean_origin, algorithm, tag) >= PATH_MAX)
1777             {
1778                 /* Path bigger than PATH_MAX */
1779                 return BIGGER_THAN_PATH_MAX;
1780             }
1781         }
1782 
1783         log_debug("dnssec_key_load_private: %{dnsname} +%03d+%05d/%d: opening file '%s'", fqdn, algorithm, tag, ntohs(flags), path);
1784 
1785         ret = dnskey_new_private_key_from_file(path, &key); // RC
1786 
1787         if(ISOK(ret))
1788         {
1789             if(has_public_key)
1790             {
1791                 /*
1792                  * remove the old (public) version
1793                  */
1794 
1795                 log_debug("dnssec_key_load_private: %{dnsname} +%03d+%05hd/%hd: replacing previous version with loaded key", fqdn, algorithm, tag, ntohs(flags));
1796 
1797                 dnssec_keystore_replace_key(key); // RC
1798             }
1799             else
1800             {
1801                 log_debug("dnssec_key_load_private: %{dnsname} +%03d+%05hd/%hd: adding loaded key", fqdn, algorithm, tag, ntohs(flags));
1802 
1803                 dnssec_keystore_add_key(key); // RC
1804             }
1805 
1806             log_info("dnssec: loaded private key: %{dnsname} +%03d+%05hd/%hd from '%s'", fqdn, algorithm, tag, ntohs(flags), path);
1807 
1808             *out_key = key;
1809             ret = 1; // newly loaded
1810         }
1811         else
1812         {
1813             log_debug("dnssec_key_load_private: %{dnsname} +%03d+%05hd/%hd: could not load the key: %r", fqdn, algorithm, tag, ntohs(flags), ret);
1814         }
1815     }
1816     else
1817     {
1818         *out_key = key;
1819         ret = 0;    // already loaded
1820     }
1821 
1822     return ret;
1823 }
1824 
1825 ya_result
dnssec_keystore_store_private_key(dnssec_key * key)1826 dnssec_keystore_store_private_key(dnssec_key* key)
1827 {
1828     char path[PATH_MAX];
1829 
1830     if(key == NULL || key->key.any == NULL || key->origin == NULL || !dnskey_is_private(key))
1831     {
1832         return DNSSEC_ERROR_INCOMPLETEKEY;
1833     }
1834 
1835     dnskey_get_tag(key); // updates the tag field if needed
1836 
1837     dnssec_keystore_domain_s *domain = dnssec_keystore_get_domain(&g_keystore, key->owner_name);
1838 
1839     if((domain != NULL) && (domain->keys_path != NULL))
1840     {
1841         if(snprintf(path, sizeof(path), "%s/" OAT_PRIVATE_FORMAT, domain->keys_path, key->origin, key->algorithm, key->tag) >= PATH_MAX)
1842         {
1843             /* Path bigger than PATH_MAX */
1844             return DNSSEC_ERROR_KEYSTOREPATHISTOOLONG;
1845         }
1846     }
1847     else
1848     {
1849         if(snprintf(path, sizeof(path), "%s/" OAT_PRIVATE_FORMAT, g_keystore_path, key->origin, key->algorithm, key->tag) >= PATH_MAX)
1850         {
1851             /* Path bigger than PATH_MAX */
1852             return DNSSEC_ERROR_KEYSTOREPATHISTOOLONG;
1853         }
1854     }
1855 
1856     switch(key->algorithm)
1857     {
1858         case DNSKEY_ALGORITHM_RSASHA1:
1859         case DNSKEY_ALGORITHM_RSASHA1_NSEC3:
1860         case DNSKEY_ALGORITHM_RSASHA256_NSEC3:
1861         case DNSKEY_ALGORITHM_RSASHA512_NSEC3:
1862         case DNSKEY_ALGORITHM_DSASHA1:
1863         case DNSKEY_ALGORITHM_DSASHA1_NSEC3:
1864         case DNSKEY_ALGORITHM_ECDSAP256SHA256:
1865         case DNSKEY_ALGORITHM_ECDSAP384SHA384:
1866         case DNSKEY_ALGORITHM_ED25519:
1867         case DNSKEY_ALGORITHM_ED448:
1868 #ifdef DNSKEY_ALGORITHM_DUMMY
1869         case DNSKEY_ALGORITHM_DUMMY:
1870 #endif
1871         {
1872             break;
1873         }
1874         default:
1875         {
1876             return DNSSEC_ERROR_UNSUPPORTEDKEYALGORITHM;
1877         }
1878     }
1879 
1880     ya_result ret = dnskey_store_private_key_to_file(key, path);
1881 
1882     return ret;
1883 }
1884 
1885 ya_result
dnssec_keystore_store_public_key(dnssec_key * key)1886 dnssec_keystore_store_public_key(dnssec_key* key)
1887 {
1888     char path[PATH_MAX];
1889 
1890     dnskey_get_tag(key); // updates the tag field if needed
1891 
1892     dnssec_keystore_domain_s *domain = dnssec_keystore_get_domain(&g_keystore, key->owner_name);
1893 
1894     if((domain != NULL) && (domain->keys_path != NULL))
1895     {
1896         if(snprintf(path, PATH_MAX, "%s/" OAT_DNSKEY_FORMAT, domain->keys_path, key->origin, key->algorithm, key->tag) >= PATH_MAX)
1897         {
1898             /* Path bigger than PATH_MAX */
1899             return DNSSEC_ERROR_KEYSTOREPATHISTOOLONG;
1900         }
1901     }
1902     else
1903     {
1904         if(snprintf(path, PATH_MAX, "%s/" OAT_DNSKEY_FORMAT, g_keystore_path, key->origin, key->algorithm, key->tag) >= PATH_MAX)
1905         {
1906             /* Path bigger than PATH_MAX */
1907             return DNSSEC_ERROR_KEYSTOREPATHISTOOLONG;
1908         }
1909     }
1910 
1911     FILE* f;
1912 
1913     if((f = fopen(path, "w+b")) == NULL)
1914     {
1915         return DNSSEC_ERROR_UNABLETOCREATEKEYFILES;
1916     }
1917 
1918     u32 lc = 1;
1919     const char* p = key->origin;
1920     char c;
1921     while((c = *p) != '\0')
1922     {
1923         if(c == '.')
1924         {
1925             lc++;
1926         }
1927         p++;
1928     }
1929 
1930     fprintf(f, "%s IN DNSKEY %u %u %u ", key->origin, ntohs(key->flags), lc, key->algorithm);
1931 
1932     u8* rdata;
1933     u32 rdata_size = key->vtbl->dnssec_key_rdatasize(key);
1934 
1935     MALLOC_OR_DIE(u8*, rdata, rdata_size, DNSKEY_RDATA_TAG);
1936 
1937     /* store the RDATA */
1938 
1939     key->vtbl->dnssec_key_writerdata(key, rdata, rdata_size);
1940 
1941     char b64[BASE64_ENCODED_SIZE(4096)];
1942 
1943     u8* ptr = rdata + 4;
1944     rdata_size -= 4;
1945     ya_result ret;
1946     u32 n = base64_encode(ptr, rdata_size, b64);
1947     if(fwrite(b64, n, 1, f) == 1)
1948     {
1949         ret = SUCCESS;
1950     }
1951     else
1952     {
1953         ret = DNSSEC_ERROR_KEYWRITEERROR;
1954     }
1955 
1956     fprintf(f, "\n");
1957 
1958     free(rdata);
1959 
1960     fclose(f);
1961 
1962     return ret;
1963 }
1964 
1965 /**
1966  * Adds all the valid keys of the domain in the keyring
1967  *
1968  * @param fqdn the domain name
1969  * @param at_time the epoch at which the test is done ie: time(NULL)
1970  * @param kr the target keyring
1971  */
1972 
1973 u32
dnssec_keystore_add_valid_keys_from_fqdn(const u8 * fqdn,time_t at_time,struct dnskey_keyring * kr)1974 dnssec_keystore_add_valid_keys_from_fqdn(const u8 *fqdn, time_t at_time, struct dnskey_keyring *kr)
1975 {
1976     dnssec_keystore *ks = &g_keystore;
1977     u32 count = 0;
1978     mutex_lock(&ks->lock);
1979     dnssec_keystore_domain_s *ks_domain = dnssec_keystore_get_domain_nolock(ks, fqdn); // locked
1980     if(ks_domain != NULL)
1981     {
1982         dnssec_key *key = ks_domain->key_chain;
1983 
1984         while(key != NULL)
1985         {
1986             time_t from = (key->epoch_activate == 0)?1:key->epoch_activate;
1987             time_t to = (key->epoch_inactive == 0)?MAX_S32:key->epoch_inactive;
1988             if(from <= at_time && to >= at_time)
1989             {
1990                 if(ISOK(dnskey_keyring_add(kr, key)))
1991                 {
1992                     ++count;
1993                 }
1994             }
1995 
1996             key = key->next;
1997         }
1998     }
1999     mutex_unlock(&ks->lock);
2000     return count;
2001 }
2002 
2003 /**
2004  * Returns all the active keys, chained in a single linked list whose nodes need to be freed,
2005  *
2006  * @param zone
2007  * @param out_keys
2008  * @param out_ksk_count
2009  * @param out_zsk_count
2010  * @return
2011  */
2012 
2013 ya_result
zdb_zone_get_active_keys(zdb_zone * zone,dnssec_key_sll ** out_keys,int * out_ksk_count,int * out_zsk_count)2014 zdb_zone_get_active_keys(zdb_zone *zone, dnssec_key_sll **out_keys, int *out_ksk_count, int *out_zsk_count)
2015 {
2016     ya_result ret = SUCCESS;
2017     int ksk_count = 0;
2018     int zsk_count = 0;
2019 
2020     zdb_packed_ttlrdata* dnskey_rrset = zdb_record_find(&zone->apex->resource_record_set, TYPE_DNSKEY); // zone is locked
2021 
2022     if(dnskey_rrset == NULL)
2023     {
2024         if(out_ksk_count != NULL)
2025         {
2026             *out_ksk_count = 0;
2027         }
2028 
2029         if(out_zsk_count != NULL)
2030         {
2031             *out_zsk_count = 0;
2032         }
2033 
2034         if(out_keys != NULL)
2035         {
2036             *out_keys = NULL;
2037         }
2038 
2039         return DNSSEC_ERROR_RRSIG_NOZONEKEYS;
2040     }
2041 
2042     dnssec_key_sll *keys = NULL;
2043 
2044     for(zdb_packed_ttlrdata* key = dnskey_rrset ;key != NULL ;key = key->next)
2045     {
2046         u8 algorithm = DNSKEY_ALGORITHM(*key);
2047         u16 tag = DNSKEY_TAG(*key);
2048         u16 flags = DNSKEY_FLAGS(*key);
2049 
2050         if((flags != DNSKEY_FLAGS_KSK) && (flags != DNSKEY_FLAGS_ZSK))
2051         {
2052             // ignore the key
2053             log_debug("rrsig: %{dnsname}: key with private key algorithm=%d tag=%05d flags=%3d is ignored (flags)", zone->origin, algorithm, tag, ntohs(flags));
2054 
2055             continue;
2056         }
2057 
2058         dnssec_key* priv_key;
2059         // from disk or from global keyring
2060         ret = dnssec_keystore_load_private_key_from_parameters(algorithm, tag, flags, zone->origin, &priv_key); // converted, key put in a collection or released
2061 
2062         if(ISOK(ret))
2063         {
2064             yassert(priv_key != NULL);
2065 
2066             if(dnskey_is_activated(priv_key, time(NULL)))
2067             {
2068                 log_debug("rrsig: %{dnsname}: private key algorithm=%d tag=%05d flags=%3d is active", zone->origin, algorithm, tag, ntohs(flags));
2069 
2070                /*
2071                 * We can sign with this key : chain it
2072                 */
2073 
2074                 if(flags == DNSKEY_FLAGS_KSK)
2075                 {
2076                     ++ksk_count;
2077                 }
2078                 else // flags == DNSKEY_FLAGS_ZSK
2079                 {
2080                     ++zsk_count;
2081                 }
2082 
2083                 if(out_keys != NULL)
2084                 {
2085                     dnssec_key_sll *key_node;
2086                     ZALLOC_OBJECT_OR_DIE(key_node, dnssec_key_sll, DNSSEC_KEY_SLL_TAG);
2087                     key_node->next = keys;
2088                     key_node->key = priv_key;
2089                     keys = key_node;
2090                 }
2091                 else
2092                 {
2093                     dnskey_release(priv_key);
2094                 }
2095             }
2096             else
2097             {
2098                 log_debug("rrsig: %{dnsname}: private key algorithm=%d tag=%05d flags=%3d is not active", zone->origin, algorithm, tag, ntohs(flags));
2099                 dnskey_release(priv_key);
2100             }
2101         }
2102         else
2103         {
2104             yassert(priv_key == NULL);
2105         }
2106     }
2107 
2108     if(out_ksk_count != NULL)
2109     {
2110         *out_ksk_count = ksk_count;
2111     }
2112 
2113     if(out_zsk_count != NULL)
2114     {
2115         *out_zsk_count = zsk_count;
2116     }
2117 
2118     if(out_keys != NULL)
2119     {
2120         *out_keys = keys;
2121     }
2122 
2123     ret = ksk_count + zsk_count;
2124 
2125     return ret;
2126 }
2127 
2128 /**
2129  *
2130  * @param keys
2131  */
2132 
2133 void
zdb_zone_release_active_keys(dnssec_key_sll * keys)2134 zdb_zone_release_active_keys(dnssec_key_sll *keys)
2135 {
2136     while(keys != NULL)
2137     {
2138         dnskey_release(keys->key);
2139         dnssec_key_sll *tmp = keys;
2140         keys = keys->next;
2141         ZFREE_OBJECT(tmp);
2142     }
2143 }
2144 
2145 /** @} */
2146