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 ### #######
36  *  @ingroup yadifad
37  *  @brief
38  *
39  * @{
40  */
41 
42 #include "server-config.h"
43 
44 #include "zone-signature-policy.h"
45 #include "zone_desc.h"
46 #include "confs.h"
47 
48 #include <dnscore/mutex.h>
49 #include <dnscore/ptr_set.h>
50 #include <dnscore/u32_set.h>
51 #include <dnscore/dnskey.h>
52 #include <dnscore/logger.h>
53 #include <dnscore/timems.h>
54 #include <dnscore/random.h>
55 #include <dnscore/packet_reader.h>
56 #include <dnscore/timeformat.h>
57 #include <dnscore/service.h>
58 #include <dnscore/threaded_dll_cw.h>
59 
60 #include <dnsdb/dnssec-keystore.h>
61 #include <dnsdb/zdb_icmtl.h>
62 #include <dnsdb/nsec.h>
63 #include <dnsdb/nsec3.h>
64 
65 #include "database-service-zone-resignature.h"
66 
67 #if HAS_EVENT_DYNAMIC_MODULE
68 #include "dynamic-module-handler.h"
69 #endif
70 
71 #ifndef HAS_DYNUPDATE_DIFF_ENABLED
72 #error "HAS_DYNUPDATE_DIFF_ENABLED not defined"
73 #endif
74 
75 #define MODULE_MSG_HANDLE g_dnssec_logger
76 extern logger_handle *g_dnssec_logger;
77 
78 #include "server_error.h"
79 #include "zone.h"
80 
81 #define DNSECPOL_TAG 0x4c4f504345534e44
82 #define DPOLKYST_TAG 0x5453594b4c4f5044
83 #define DPOLKEY_TAG  0x0059454b4c4f5044
84 #define DPOLDNIL_TAG 0x4c494e444c4f5044
85 #define DPOLSALT_TAG 0x544c41534c4f5044
86 #define DPOLROLL_TAG 0x4c4c4f524c4f5044
87 #define DPOLRULE_TAG 0x454c55524c4f5044
88 #define DPOLQUEU_TAG 0x554555514c4f5044
89 
90 #define KEY_POLICY_EPOCH_MATCH_MARGIN 180 // how close two epochs have to be to be considered a match
91 
92 #define DEBUG_FORCE_INSANE_SIGNATURE_MAINTENANCE_PARAMETERS 0
93 #if DEBUG_FORCE_INSANE_SIGNATURE_MAINTENANCE_PARAMETERS
94 #pragma message("WARNING: DEBUG_FORCE_INSANE_SIGNATURE_MAINTENANCE_PARAMETERS enabled !")
95 #endif
96 
97 
98 static u32_set zone_policy_rule_definition_set = U32_SET_EMPTY;
99 static group_mutex_t zone_policy_rule_definition_set_mtx = GROUP_MUTEX_INITIALIZER;
100 static volatile u32 zone_policy_rule_definition_next_index = 0;
101 
102 // local functions definitions
103 
104 ya_result zone_policy_date_init_at_next_rule(zone_policy_date *date, const zone_policy_date *from, const zone_policy_date *rule);
105 ya_result zone_policy_date_init_at_prev_rule(zone_policy_date *date, const zone_policy_date *from, const zone_policy_date *rule);
106 ya_result zone_policy_date_init_from_rule(zone_policy_date *date, const zone_policy_date *from, const zone_policy_date *rule);
107 ya_result zone_policy_date_init_from_date(zone_policy_date *date, const zone_policy_date *from, const zone_policy_date *rule);
108 static ya_result dnssec_policy_alarm_handler(void *args, bool cancel);
109 
110 //
111 
112 static ptr_set origin_to_dnssec_policy_queue_set = PTR_SET_DNSNAME_EMPTY;
113 static mutex_t origin_to_dnssec_policy_queue_mtx = MUTEX_INITIALIZER;
114 
115 //
116 
117 static ptr_set dnssec_policy_roll_set = PTR_SET_ASCIIZ_EMPTY;
118 static group_mutex_t dnssec_policy_roll_set_mtx = GROUP_MUTEX_INITIALIZER;
119 static group_mutex_t dnssec_policy_roll_mtx = GROUP_MUTEX_INITIALIZER;
120 
121 //
122 
123 static ptr_set dnssec_policy_set = PTR_SET_ASCIIZ_EMPTY;
124 static group_mutex_t dnssec_policy_set_mtx = GROUP_MUTEX_INITIALIZER;
125 static group_mutex_t dnssec_policy_mtx = GROUP_MUTEX_INITIALIZER;
126 
127 //
128 
129 static ptr_set dnssec_denial_set = PTR_SET_ASCIIZ_EMPTY;
130 static group_mutex_t dnssec_denial_set_mtx = GROUP_MUTEX_INITIALIZER;
131 static group_mutex_t dnssec_denial_mtx = GROUP_MUTEX_INITIALIZER;
132 
133 //
134 
135 static ptr_set dnssec_policy_key_set = PTR_SET_ASCIIZ_EMPTY;
136 static group_mutex_t dnssec_policy_key_set_mtx = GROUP_MUTEX_INITIALIZER;
137 static group_mutex_t dnssec_policy_key_mtx = GROUP_MUTEX_INITIALIZER;
138 
139 //
140 
141 static ptr_set dnssec_policy_key_suite_set = PTR_SET_ASCIIZ_EMPTY;
142 static group_mutex_t dnssec_policy_key_suite_set_mtx = GROUP_MUTEX_INITIALIZER;
143 static group_mutex_t dnssec_policy_key_suite_mtx = GROUP_MUTEX_INITIALIZER;
144 
145 //
146 
147 static volatile int dnssec_policy_queue_serial = 0;
148 
149 static void
zone_policy_date_format_handler_method(const void * restrict val,output_stream * os,s32 padding,char pad_char,bool left_justified,void * restrict reserved_for_method_parameters)150 zone_policy_date_format_handler_method(const void *restrict val, output_stream *os, s32 padding, char pad_char, bool left_justified, void * restrict reserved_for_method_parameters)
151 {
152     zone_policy_date *date = (zone_policy_date*)val;
153     (void)padding;
154     (void)pad_char;
155     (void)left_justified;
156     (void)reserved_for_method_parameters;
157 
158     switch(date->type.type)
159     {
160         case ZONE_POLICY_ABSOLUTE:
161         {
162             osformat(os, "%4u-%02u-%02u %02u:%02u:00U", date->absolute.year + ZONE_POLICY_DATE_YEAR_BASE, date->absolute.month + 1, date->absolute.day + 1, date->absolute.hour, date->absolute.minute);
163             break;
164         }
165         case ZONE_POLICY_RELATIVE:
166         {
167             osformat(os, "(%u)+%us", date->relative.seconds, date->relative.relativeto);
168             break;
169         }
170         case ZONE_POLICY_RULE:
171         {
172             zone_policy_rule_definition_s *def = zone_policy_rule_definition_get_from_rule(date);
173             osformat(os, "[%016x %06x %08x %02x %x %x]", def->minute, def->hour, def->day, def->month, def->weekday, def->week);
174             break;
175         }
176         default:
177         {
178             output_stream_write(os, "?", 1);
179             break;
180         }
181     }
182 }
183 
184 dnssec_policy_queue*
dnssec_policy_queue_new(const u8 * fqdn)185 dnssec_policy_queue_new(const u8 *fqdn)
186 {
187     dnssec_policy_queue *cmd;
188     ZALLOC_OBJECT_OR_DIE( cmd, dnssec_policy_queue, DPOLQUEU_TAG);
189     ZEROMEMORY(cmd, sizeof(dnssec_policy_queue));
190     cmd->origin = dnsname_zdup(fqdn); // weak
191     return cmd;
192 }
193 
194 bool
dnssec_policy_queue_equals(const dnssec_policy_queue * a,const dnssec_policy_queue * b)195 dnssec_policy_queue_equals(const dnssec_policy_queue *a, const dnssec_policy_queue *b)
196 {
197     if(a->command == b->command)
198     {
199         switch(a->command)
200         {
201             case DNSSEC_POLICY_COMMAND_INIT:
202             {
203                 return TRUE; // as time is "asap"
204             }
205             case DNSSEC_POLICY_COMMAND_GENERATE_KEY:
206             {
207                 return (a->epoch == b->epoch) && (a->parameters.generate_key.suite == b->parameters.generate_key.suite);
208             }
209             default:
210             {
211                 // not implemented
212                 log_err("dnssec_policy_queue_equals: command not implemented");
213                 abort();
214             }
215         }
216     }
217     else
218     {
219         return FALSE;
220     }
221 }
222 
223 bool
dnssec_policy_queue_has_command(dnssec_policy_queue * cmd)224 dnssec_policy_queue_has_command(dnssec_policy_queue *cmd)
225 {
226     bool ret = FALSE;
227     mutex_lock(&origin_to_dnssec_policy_queue_mtx);
228 
229     ptr_node *queue_node = ptr_set_find(&origin_to_dnssec_policy_queue_set, cmd->origin);
230     if(queue_node != NULL)
231     {
232         dnssec_policy_queue* cmdq = (dnssec_policy_queue*)queue_node->value;
233 
234         while(cmdq != NULL)
235         {
236             if(dnssec_policy_queue_equals(cmdq, cmd))
237             {
238                 ret = TRUE;
239                 break;
240             }
241 
242             cmdq = cmdq->next;
243         }
244     }
245     mutex_unlock(&origin_to_dnssec_policy_queue_mtx);
246     return ret;
247 }
248 
249 bool
dnssec_policy_queue_has_command_type(const u8 * fqdn,int command)250 dnssec_policy_queue_has_command_type(const u8 *fqdn, int command)
251 {
252     bool ret = FALSE;
253 
254     mutex_lock(&origin_to_dnssec_policy_queue_mtx);
255     ptr_node *queue_node = ptr_set_find(&origin_to_dnssec_policy_queue_set, fqdn);
256 
257     if(queue_node != NULL)
258     {
259         dnssec_policy_queue* cmdq = (dnssec_policy_queue*)queue_node->value;
260 
261         while(cmdq != NULL)
262         {
263             if(cmdq->command == command)
264             {
265                 ret = TRUE;
266                 break;
267             }
268 
269             cmdq = cmdq->next;
270         }
271     }
272 
273     mutex_unlock(&origin_to_dnssec_policy_queue_mtx);
274     return ret;
275 }
276 
277 static int
dnssec_policy_queue_add_command(dnssec_policy_queue * cmd)278 dnssec_policy_queue_add_command(dnssec_policy_queue *cmd)
279 {
280 #if DEBUG
281     log_debug("dnssec-policy: %{dnsname}: add command %p", cmd->origin, cmd);
282 #endif
283 
284     yassert(!cmd->queued);
285 
286     mutex_lock(&origin_to_dnssec_policy_queue_mtx);
287     int ret = dnssec_policy_queue_serial;
288     dnssec_policy_queue_serial += 0x100;
289     ptr_node *queue_node = ptr_set_insert(&origin_to_dnssec_policy_queue_set, cmd->origin);
290     if(queue_node->value == NULL)
291     {
292         queue_node->key = dnsname_zdup(cmd->origin);
293     }
294     dnssec_policy_queue** cmdqp = (dnssec_policy_queue**)&queue_node->value;
295     cmd->next = *cmdqp;
296     cmd->queued = TRUE;
297     *cmdqp = cmd;
298 
299     mutex_unlock(&origin_to_dnssec_policy_queue_mtx);
300     return ret;
301 }
302 
303 void
dnssec_policy_queue_add_command_at_epoch(dnssec_policy_queue * cmd,alarm_t hndl,time_t at)304 dnssec_policy_queue_add_command_at_epoch(dnssec_policy_queue *cmd, alarm_t hndl, time_t at)
305 {
306     int serial = dnssec_policy_queue_add_command(cmd) | ALARM_KEY_DNSSEC_POLICY_EVENT;
307 
308     alarm_event_node *event = alarm_event_new(
309         at,
310         serial,
311         dnssec_policy_alarm_handler,
312         cmd,
313         ALARM_DUP_REMOVE_LATEST,
314         "dnssec-policy-generate-key");
315 
316     alarm_set(hndl, event);
317 }
318 
319 void
dnssec_policy_queue_remove_command(dnssec_policy_queue * cmd)320 dnssec_policy_queue_remove_command(dnssec_policy_queue *cmd)
321 {
322     if(cmd->queued)
323     {
324 #if DEBUG
325         log_debug("dnssec-policy: %{dnsname}: remove command %p", cmd->origin, cmd);
326 #endif
327 
328         mutex_lock(&origin_to_dnssec_policy_queue_mtx);
329 
330         ptr_node *queue_node = ptr_set_insert(&origin_to_dnssec_policy_queue_set, cmd->origin);
331         dnssec_policy_queue** cmdqp = (dnssec_policy_queue**)&queue_node->value;
332 
333         while(*cmdqp != NULL)
334         {
335             if(*cmdqp == cmd)
336             {
337                 *cmdqp = cmd->next;
338                 cmd->next = NULL;
339                 cmd->queued = FALSE;
340                 break;
341             }
342             cmdqp = &(*cmdqp)->next;
343         }
344 
345         if(queue_node->value == NULL)
346         {
347             u8* key = (u8*)queue_node->key;
348             ptr_set_delete(&origin_to_dnssec_policy_queue_set, cmd->origin);
349             dnsname_zfree(key);
350         }
351 
352         mutex_unlock(&origin_to_dnssec_policy_queue_mtx);
353     }
354 #if DEBUG
355     else
356     {
357         log_debug("dnssec-policy: %{dnsname}: remove command %p: not queued", cmd->origin, cmd);
358     }
359 #endif
360 }
361 
362 void
dnssec_policy_queue_delete_command(dnssec_policy_queue * cmd)363 dnssec_policy_queue_delete_command(dnssec_policy_queue *cmd)
364 {
365 #if DEBUG
366     log_debug("dnssec-policy: %{dnsname}: delete command %p", cmd->origin, cmd);
367 #endif
368     dnssec_policy_queue_remove_command(cmd);
369 
370     switch(cmd->command)
371     {
372         case DNSSEC_POLICY_COMMAND_INIT:
373         {
374             break;
375         }
376         case DNSSEC_POLICY_COMMAND_GENERATE_KEY:
377         {
378             if(cmd->parameters.generate_key.suite != NULL)
379             {
380                 dnssec_policy_key_suite_release(cmd->parameters.generate_key.suite);
381                 zone_release(cmd->parameters.generate_key.zone_desc);
382             }
383             break;
384         }
385     }
386 
387 #if DEBUG
388     intptr cmd_address = (intptr)cmd;
389 #endif
390 
391     dnsname_zfree(cmd->origin);
392     ZFREE_OBJECT(cmd);
393 
394 #if DEBUG
395     log_debug("dnssec-policy: delete command %p: done", cmd_address); // scan-build false positive : the memory pointed by cmd is freed, but cmd's value is still valid.
396 #endif
397 }
398 
399 ya_result
dnssec_policy_queue_add_generate_key_create_at(zone_desc_s * zone_desc,struct dnssec_policy_key_suite * kr,time_t epoch)400 dnssec_policy_queue_add_generate_key_create_at(zone_desc_s *zone_desc, struct dnssec_policy_key_suite *kr, time_t epoch)
401 {
402     zone_policy_table_s tbl;
403     zone_policy_date now_date;
404     ya_result ret;
405 
406     ret = zone_policy_date_init_from_epoch(&now_date, epoch);
407 
408     if(FAIL(ret))
409     {
410         log_err("dnssec_policy_queue_add_generate_key_create_at: zone_policy_table_init_from_date returned an error: %r", ret);
411         return ret;
412     }
413 
414     ret = zone_policy_table_init_from_date(&tbl, &kr->roll->time_table, &now_date);
415 
416     if(FAIL(ret))
417     {
418         log_err("dnssec_policy_queue_add_generate_key_create_at: zone_policy_table_init_from_date returned an error: %r", ret);
419         return ret;
420     }
421 
422 #if DEBUG
423     format_writer n_fw = {zone_policy_date_format_handler_method, &now_date};
424     format_writer c_fw = {zone_policy_date_format_handler_method, &tbl.created};
425     format_writer p_fw = {zone_policy_date_format_handler_method, &tbl.publish};
426     format_writer a_fw = {zone_policy_date_format_handler_method, &tbl.activate};
427     format_writer d_fw = {zone_policy_date_format_handler_method, &tbl.inactive};
428     format_writer r_fw = {zone_policy_date_format_handler_method, &tbl.delete};
429 
430     log_debug("dnssec-policy: %{dnsname}: %s: at %T = %U = %w: queued key: create=%w, publish=%w, activate=%w, deactivate=%w, remove=%w",
431             zone_origin(zone_desc), kr->name, epoch, epoch, &n_fw,
432             &c_fw, &p_fw, &a_fw, &d_fw, &r_fw);
433 #endif
434 
435 #if 1
436     yassert(tbl.created.type.type == ZONE_POLICY_ABSOLUTE);
437 
438     time_t alarm_epoch;
439 
440     if(FAIL(ret = zone_policy_date_get_epoch(&tbl.created, &alarm_epoch))) // note: created should be of type ZONE_POLICY_ABSOLUTE
441     {
442         log_err("dnssec_policy_queue_add_generate_key_create_at: zone_policy_date_get_epoch returned an error: %r", ret);
443         return ret;
444     }
445 
446 #if DEBUG
447     log_debug("dnssec-policy: %{dnsname}: %s: alarm set to %T", zone_origin(zone_desc), kr->name, alarm_epoch);
448     logger_flush();
449 #endif
450 
451     dnssec_policy_queue *cmd = dnssec_policy_queue_new(zone_origin(zone_desc));
452     cmd->epoch = epoch;
453     cmd->command = DNSSEC_POLICY_COMMAND_GENERATE_KEY;
454     dnssec_policy_key_suite_acquire(kr);
455     cmd->parameters.generate_key.suite = kr; // must be done else the dnssec_policy_queue_has_command will fail
456     cmd->parameters.generate_key.zone_desc = zone_desc;
457     zone_acquire(zone_desc);
458 
459     if(!dnssec_policy_queue_has_command(cmd))
460     {
461         log_debug("dnssec-policy: %{dnsname}: %s: at %T will generate a key with time parameter: %T", zone_origin(zone_desc), kr->name, alarm_epoch, epoch);
462 
463         // add the command
464 
465         zone_policy_key_suite_mark_processed(zone_desc, kr);
466 
467         dnssec_policy_queue_add_command_at_epoch(cmd, zone_desc->loaded_zone->alarm_handle, alarm_epoch);
468     }
469     else
470     {
471         // note: kr is part of cmd, so it cannot be use dafter cmd has been deleted
472         log_debug("dnssec-policy: %{dnsname}: %s: key generation for policy already set", zone_origin(zone_desc), kr->name);
473 
474         dnssec_policy_queue_delete_command(cmd);
475     }
476 #else
477     time_t created_epoch;
478     time_t publish_epoch;
479     time_t activate_epoch;
480     time_t deactivate_epoch;
481     time_t unpublish_epoch;
482 
483     if(FAIL(ret = zone_policy_date_get_epoch(&tbl.created, &created_epoch))) // note: created should be of type ZONE_POLICY_ABSOLUTE
484     {
485         log_err("dnssec_policy_queue_add_generate_key_create_at: zone_policy_date_get_epoch (created_epoch) returned an error: %r", ret);
486         return ret;
487     }
488 
489     if(FAIL(ret = zone_policy_date_get_epoch(&tbl.publish, &publish_epoch))) // note: publish should be of type ZONE_POLICY_ABSOLUTE
490     {
491         log_err("dnssec_policy_queue_add_generate_key_create_at: zone_policy_date_get_epoch (publish_epoch) returned an error: %r", ret);
492         return ret;
493     }
494 
495     if(FAIL(ret = zone_policy_date_get_epoch(&tbl.activate, &activate_epoch))) // note: activate should be of type ZONE_POLICY_ABSOLUTE
496     {
497         log_err("dnssec_policy_queue_add_generate_key_create_at: zone_policy_date_get_epoch (activate_epoch) returned an error: %r", ret);
498         return ret;
499     }
500 
501     if(FAIL(ret = zone_policy_date_get_epoch(&tbl.inactive, &deactivate_epoch))) // note: deactivate should be of type ZONE_POLICY_ABSOLUTE
502     {
503         log_err("dnssec_policy_queue_add_generate_key_create_at: zone_policy_date_get_epoch (deactivate_epoch) returned an error: %r", ret);
504         return ret;
505     }
506 
507     if(FAIL(ret = zone_policy_date_get_epoch(&tbl.delete, &unpublish_epoch))) // note: unpublish should be of type ZONE_POLICY_ABSOLUTE
508     {
509         log_err("dnssec_policy_queue_add_generate_key_create_at: zone_policy_date_get_epoch (unpublish_epoch) returned an error: %r", ret);
510         return ret;
511     }
512 
513     keyroll_generate_dnskey_ex(keyroll, kr->key->size, kr->key->algorithm, ONE_SECOND_US * created_epoch, ONE_SECOND_US * publish_epoch, ONE_SECOND_US * activate_epoch,
514                                ONE_SECOND_US * deactivate_epoch, ONE_SECOND_US * unpublish_epoch, (kr->key->flags == DNSKEY_FLAGS_KSK));
515 
516     yassert(tbl.created.type.type == ZONE_POLICY_ABSOLUTE);
517 
518     time_t alarm_epoch;
519 
520     if(FAIL(ret = zone_policy_date_get_epoch(&tbl.created, &alarm_epoch))) // note: created should be of type ZONE_POLICY_ABSOLUTE
521     {
522         log_err("dnssec_policy_queue_add_generate_key_create_at: zone_policy_date_get_epoch returned an error: %r", ret);
523         return ret;
524     }
525 
526 #if DEBUG
527     log_debug("dnssec-policy: %{dnsname}: %s: key created set at %T", zone_origin(zone_desc), kr->name, alarm_epoch);
528 #endif
529 
530 #endif // #if 0 #else
531 
532     return SUCCESS;
533 }
534 
535 /**
536  * Works only with RULEs (cron) key suites
537  *
538  * @param zone_desc
539  * @param kr
540  * @param active_at
541  * @param will_be_inactive_at a pointer that'll receive the inactive epoch (can be NULL)
542  */
543 
544 ya_result
dnssec_policy_queue_add_generate_key_active_at(zone_desc_s * zone_desc,struct dnssec_policy_key_suite * kr,time_t active_at,time_t * will_be_inactive_at)545 dnssec_policy_queue_add_generate_key_active_at(zone_desc_s *zone_desc, struct dnssec_policy_key_suite *kr, time_t active_at, time_t *will_be_inactive_at)
546 {
547     zone_policy_date creation_date;
548     zone_policy_date publish_date;
549     zone_policy_date activate_date;
550     zone_policy_date inactive_date;
551     zone_policy_date unpublish_date;
552     zone_policy_date now_date;
553 
554     ya_result ret;
555 
556     if(FAIL(ret = zone_policy_date_init_from_epoch(&now_date, active_at)))
557     {
558         return ret;
559     }
560 
561     if(FAIL(ret = zone_policy_date_init_at_prev_rule(&activate_date, &now_date, &kr->roll->time_table.activate)))
562     {
563         return ret;
564     }
565 
566     if(FAIL(ret = zone_policy_date_init_at_prev_rule(&publish_date, &activate_date, &kr->roll->time_table.publish)))
567     {
568         return ret;
569     }
570 
571     if(FAIL(ret = zone_policy_date_init_at_prev_rule(&creation_date, &publish_date, &kr->roll->time_table.created)))
572     {
573         return ret;
574     }
575 
576     time_t creation_epoch = 60;
577     time_t activate_epoch = 60;
578 
579     if(FAIL(ret = zone_policy_date_get_epoch(&creation_date, &creation_epoch)))
580     {
581         return ret;
582     }
583 
584     if(FAIL(ret = zone_policy_date_get_epoch(&activate_date, &activate_epoch)))
585     {
586         return ret;
587     }
588 
589 #if DEBUG
590     format_writer c_fw = {zone_policy_date_format_handler_method, &creation_date};
591 
592     {
593         format_writer a_fw0 = {zone_policy_date_format_handler_method, &activate_date};
594         format_writer p_fw0 = {zone_policy_date_format_handler_method, &publish_date};
595 
596         log_debug1("dnssec-policy: %{dnsname}: %s: base %w <= %w <= %w : %T", zone_origin(zone_desc), kr->name, &c_fw, &p_fw0, &a_fw0, creation_epoch);
597     }
598 #endif
599 
600     if(FAIL(ret = zone_policy_date_init_at_next_rule(&publish_date, &creation_date, &kr->roll->time_table.publish)))
601     {
602         return ret;
603     }
604 
605     if(FAIL(ret = zone_policy_date_init_at_next_rule(&activate_date, &publish_date, &kr->roll->time_table.activate)))
606     {
607         return ret;
608     }
609 
610 #if DEBUG
611     format_writer p_fw = {zone_policy_date_format_handler_method, &publish_date};
612     format_writer a_fw = {zone_policy_date_format_handler_method, &activate_date};
613     {
614         log_debug1("dnssec-policy: %{dnsname}: %s: base %w => %w => %w : %T (after forward correction)", zone_origin(zone_desc), kr->name, &c_fw, &p_fw, &a_fw, creation_epoch);
615     }
616 #endif
617 
618     // compute the future key timings to ensure there will be no period without a signature
619 
620     zone_policy_date next_creation_date;
621     zone_policy_date next_publish_date;
622     zone_policy_date next_activate_date;
623 
624     if(FAIL(ret = zone_policy_date_init_at_next_rule(&next_creation_date, &activate_date, &kr->roll->time_table.created)))
625     {
626         return ret;
627     }
628 
629     if(FAIL(ret = zone_policy_date_init_at_next_rule(&next_publish_date, &next_creation_date, &kr->roll->time_table.publish)))
630     {
631         return ret;
632     }
633 
634     if(FAIL(ret = zone_policy_date_init_at_next_rule(&next_activate_date, &next_publish_date, &kr->roll->time_table.activate)))
635     {
636         return ret;
637     }
638 
639 #if DEBUG
640     {
641         format_writer na_fw = {zone_policy_date_format_handler_method, &next_activate_date};
642         format_writer np_fw = {zone_policy_date_format_handler_method, &next_publish_date};
643         format_writer nc_fw = {zone_policy_date_format_handler_method, &next_creation_date};
644 
645         log_debug1("dnssec-policy: %{dnsname}: %s: next %w => %w => %w", zone_origin(zone_desc), kr->name, &nc_fw, &np_fw, &na_fw);
646     }
647 #endif
648 
649     // and use this next_activate as a base for the current deactivate
650 
651     if(FAIL(ret = zone_policy_date_init_at_next_rule(&inactive_date, &next_activate_date, &kr->roll->time_table.inactive)))
652     {
653         return ret;
654     }
655 
656     if(FAIL(ret = zone_policy_date_init_at_next_rule(&unpublish_date, &inactive_date, &kr->roll->time_table.delete)))
657     {
658         return ret;
659     }
660 
661     time_t inactive_epoch = 0;
662 
663     if(FAIL(ret = zone_policy_date_get_epoch(&inactive_date, &inactive_epoch)))
664     {
665         return ret;
666     }
667 
668     if(inactive_epoch - activate_epoch < DNSSEC_POLICY_MINIMUM_ACTIVATED_TIME_SUGGESTION_SECONDS)
669     {
670         double d = inactive_epoch - activate_epoch;
671         d /= 86400.0;
672         double c = DNSSEC_POLICY_MINIMUM_ACTIVATED_TIME_SUGGESTION_SECONDS;
673         c /= 86400.0;
674         log_warn("dnssec-policy: %{dnsname}: %s: the key will only be activated for %.3f days, consider increasing this value to at least %.3f days", zone_origin(zone_desc), kr->name, d, c);
675     }
676 
677     if(inactive_epoch < active_at)
678     {
679         log_err("dnssec-policy: %{dnsname}: %s: computing timings to be in the current activated time window produces an already expired key", zone_origin(zone_desc), kr->name );
680 
681         return INVALID_STATE_ERROR;
682     }
683 
684     if(will_be_inactive_at != NULL)
685     {
686         *will_be_inactive_at = inactive_epoch;
687     }
688 
689 #if DEBUG
690     format_writer d_fw = {zone_policy_date_format_handler_method, &inactive_date};
691     zone_policy_date remove_date;
692     ret = zone_policy_date_init_at_next_rule(&remove_date, &inactive_date, &kr->roll->time_table.delete);
693     (void)ret;
694     format_writer r_fw = {zone_policy_date_format_handler_method, &unpublish_date};
695 
696     log_debug("dnssec-policy: %{dnsname}: %s: rule key: create=%w, publish=%w, activate=%w, deactivate=%w, remove=%w",
697             zone_origin(zone_desc), kr->name,
698             &c_fw, &p_fw, &a_fw, &d_fw, &r_fw);
699 #endif
700 
701     log_debug("dnssec-policy: %{dnsname}: %s: will generate a key at %T (rule new) to be active at %T", zone_origin(zone_desc), kr->name, creation_epoch, active_at);
702 
703 #if DEBUG
704     logger_flush();
705 #endif
706 
707     // add the command
708 
709     ret = dnssec_policy_queue_add_generate_key_create_at(zone_desc, kr, creation_epoch);
710 
711     return ret;
712 }
713 
714 ya_result
dnssec_policy_roll_test_at(struct dnssec_policy_roll * kr,time_t active_at,time_t * will_be_inactive_at,bool print_text,bool log_text)715 dnssec_policy_roll_test_at(struct dnssec_policy_roll *kr, time_t active_at, time_t *will_be_inactive_at, bool print_text, bool log_text)
716 {
717     zone_policy_date creation_date;
718     zone_policy_date publish_date;
719     zone_policy_date activate_date;
720     zone_policy_date inactive_date;
721     zone_policy_date unpublish_date;
722     zone_policy_date now_date;
723 
724     ya_result ret;
725 
726     if(FAIL(ret = zone_policy_date_init_from_epoch(&now_date, active_at)))
727     {
728         return ret;
729     }
730 
731     if(FAIL(ret = zone_policy_date_init_at_prev_rule(&activate_date, &now_date, &kr->time_table.activate)))
732     {
733         return ret;
734     }
735 
736     if(FAIL(ret = zone_policy_date_init_at_prev_rule(&publish_date, &activate_date, &kr->time_table.publish)))
737     {
738         return ret;
739     }
740 
741     if(FAIL(ret = zone_policy_date_init_at_prev_rule(&creation_date, &publish_date, &kr->time_table.created)))
742     {
743         return ret;
744     }
745 
746     time_t creation_epoch = 60;
747     time_t activate_epoch = 60;
748 
749     if(FAIL(ret = zone_policy_date_get_epoch(&creation_date, &creation_epoch)))
750     {
751         return ret;
752     }
753 
754     if(FAIL(ret = zone_policy_date_get_epoch(&activate_date, &activate_epoch)))
755     {
756         return ret;
757     }
758 
759 #if DEBUG
760     format_writer c_fw = {zone_policy_date_format_handler_method, &creation_date};
761 
762     {
763         format_writer a_fw0 = {zone_policy_date_format_handler_method, &activate_date};
764         format_writer p_fw0 = {zone_policy_date_format_handler_method, &publish_date};
765 
766         log_debug1("key-roll: %s: base %w <= %w <= %w : %T", kr->name, &c_fw, &p_fw0, &a_fw0, creation_epoch);
767     }
768 #endif
769 
770     if(FAIL(ret = zone_policy_date_init_at_next_rule(&publish_date, &creation_date, &kr->time_table.publish)))
771     {
772         return ret;
773     }
774 
775     if(FAIL(ret = zone_policy_date_init_at_next_rule(&activate_date, &publish_date, &kr->time_table.activate)))
776     {
777         return ret;
778     }
779 
780 #if DEBUG
781     format_writer p_fw = {zone_policy_date_format_handler_method, &publish_date};
782     format_writer a_fw = {zone_policy_date_format_handler_method, &activate_date};
783     {
784         log_debug1("key-roll: %s: base %w => %w => %w : %T (after forward correction)", kr->name, &c_fw, &p_fw, &a_fw, creation_epoch);
785     }
786 #endif
787 
788     // compute the future key timings to ensure there will be no period without a signature
789 
790     zone_policy_date next_creation_date;
791     zone_policy_date next_publish_date;
792     zone_policy_date next_activate_date;
793 
794     if(FAIL(ret = zone_policy_date_init_at_next_rule(&next_creation_date, &activate_date, &kr->time_table.created)))
795     {
796         return ret;
797     }
798 
799     if(FAIL(ret = zone_policy_date_init_at_next_rule(&next_publish_date, &next_creation_date, &kr->time_table.publish)))
800     {
801         return ret;
802     }
803 
804     if(FAIL(ret = zone_policy_date_init_at_next_rule(&next_activate_date, &next_publish_date, &kr->time_table.activate)))
805     {
806         return ret;
807     }
808 
809 #if DEBUG
810     {
811         format_writer na_fw = {zone_policy_date_format_handler_method, &next_activate_date};
812         format_writer np_fw = {zone_policy_date_format_handler_method, &next_publish_date};
813         format_writer nc_fw = {zone_policy_date_format_handler_method, &next_creation_date};
814 
815         log_debug1("key-roll: %s: next %w => %w => %w", kr->name, &nc_fw, &np_fw, &na_fw);
816     }
817 #endif
818 
819     // and use this next_activate as a base for the current deactivate
820 
821     if(FAIL(ret = zone_policy_date_init_at_next_rule(&inactive_date, &next_activate_date, &kr->time_table.inactive)))
822     {
823         return ret;
824     }
825 
826     if(FAIL(ret = zone_policy_date_init_at_next_rule(&unpublish_date, &inactive_date, &kr->time_table.delete)))
827     {
828         return ret;
829     }
830 
831     time_t inactive_epoch = 0;
832 
833     if(FAIL(ret = zone_policy_date_get_epoch(&inactive_date, &inactive_epoch)))
834     {
835         return ret;
836     }
837 
838     if(inactive_epoch - activate_epoch < DNSSEC_POLICY_MINIMUM_ACTIVATED_TIME_SUGGESTION_SECONDS)
839     {
840         double d = inactive_epoch - activate_epoch;
841         d /= 86400.0;
842         double c = DNSSEC_POLICY_MINIMUM_ACTIVATED_TIME_SUGGESTION_SECONDS;
843         c /= 86400.0;
844         if(log_text)
845         {
846             log_warn("key-roll: %s: the key will only be activated for %.3f days, consider increasing this value to at least %.3f days", kr->name, d, c);
847         }
848         if(print_text)
849         {
850             formatln("key-roll: %s: the key will only be activated for %.3f days, consider increasing this value to at least %.3f days", kr->name, d, c);
851         }
852     }
853 
854     if(inactive_epoch < active_at)
855     {
856         if(log_text)
857         {
858             log_err("key-roll: %s: computing timings to be in the current activated time window produces an already expired key", kr->name);
859         }
860         if(print_text)
861         {
862             formatln("key-roll: %s: computing timings to be in the current activated time window produces an already expired key", kr->name);
863         }
864 
865         return INVALID_STATE_ERROR;
866     }
867 
868     if(will_be_inactive_at != NULL)
869     {
870         *will_be_inactive_at = inactive_epoch;
871     }
872 
873 #if DEBUG
874     format_writer d_fw = {zone_policy_date_format_handler_method, &inactive_date};
875     zone_policy_date remove_date;
876     ret = zone_policy_date_init_at_next_rule(&remove_date, &inactive_date, &kr->time_table.delete);
877     (void)ret;
878     format_writer r_fw = {zone_policy_date_format_handler_method, &unpublish_date};
879 
880     log_debug("key-roll: %s: rule key: create=%w, publish=%w, activate=%w, deactivate=%w, remove=%w",
881               kr->name,
882               &c_fw, &p_fw, &a_fw, &d_fw, &r_fw);
883 #endif
884 
885     log_debug("key-roll: %s: will generate a key at %T (rule new) to be active at %T", kr->name, creation_epoch, active_at);
886 
887     if(log_text || print_text)
888     {
889         format_writer c_fw0 = {zone_policy_date_format_handler_method, &creation_date};
890         format_writer p_fw0 = {zone_policy_date_format_handler_method, &publish_date};
891         format_writer a_fw0 = {zone_policy_date_format_handler_method, &activate_date};
892         format_writer i_fw0 = {zone_policy_date_format_handler_method, &inactive_date};
893         format_writer u_fw0 = {zone_policy_date_format_handler_method, &unpublish_date};
894         u32 delta_seconds = inactive_epoch - activate_epoch;
895         float delta_value;
896         const char *delta_units;
897 
898         if(delta_seconds > 2592000)
899         {
900             delta_value = 1.0f * delta_seconds / 2592000.f;
901             delta_units = "months";
902         }
903         else if(delta_seconds > 604800)
904         {
905             delta_value = 1.f * delta_seconds / 604800.f;
906             delta_units = "weeks";
907         }
908         else if(delta_seconds > 86400)
909         {
910             delta_value = 1.f * delta_seconds / 86400.f;
911             delta_units = "days";
912         }
913         else if(delta_seconds > 3600)
914         {
915             delta_value = 1.f * delta_seconds / 3600.f;
916             delta_units = "hours";
917         }
918         else if(delta_seconds > 60)
919         {
920             delta_value = 1.f * delta_seconds / 60.f;
921             delta_units = "minutes";
922         }
923         else
924         {
925             delta_value = 1.f * delta_seconds;
926             delta_units = "seconds";
927         }
928 
929         if(log_text)
930         {
931             log_info("key-roll: %s: creation at %w, publication at %w, activation at %w, deactivation at %w, removal at %w, %6.1f %s",
932                      kr->name, &c_fw0, &p_fw0, &a_fw0, &i_fw0, &u_fw0, delta_value, delta_units);
933         }
934 
935         if(print_text)
936         {
937             formatln("key-roll: %s: creation at %w, publication at %w, activation at %w, deactivation at %w, removal at %w, %6.1f %s",
938                      kr->name, &c_fw0, &p_fw0, &a_fw0, &i_fw0, &u_fw0, delta_value, delta_units);
939         }
940     }
941 
942 #if DEBUG
943     logger_flush();
944 #endif
945 
946     return ret;
947 }
948 
949 ya_result
dnssec_policy_roll_test(struct dnssec_policy_roll * kr,time_t active_at,u32 duration_seconds,bool print_text,bool log_text)950 dnssec_policy_roll_test(struct dnssec_policy_roll *kr, time_t active_at, u32 duration_seconds, bool print_text, bool log_text)
951 {
952     ya_result ret;
953     time_t end_at =  active_at + duration_seconds;
954     time_t inactive_at = 0;
955 
956     if(print_text)
957     {
958         formatln("key-roll: %s: testing policy sets of dates from %T to %T", kr->name, active_at, end_at);
959     }
960 
961     if(log_text)
962     {
963         formatln("key-roll: %s: testing policy sets of dates from %T to %T", kr->name, active_at, end_at);
964     }
965 
966     while(active_at < end_at)
967     {
968         if(FAIL(ret = dnssec_policy_roll_test_at(kr, active_at, &inactive_at, print_text, log_text)))
969         {
970             if(log_text)
971             {
972                 log_info("key-roll: %s: could not find a matching set of dates from %T", kr->name, active_at);
973             }
974             if(print_text)
975             {
976                 formatln("key-roll: %s: could not find a matching set of dates from %T", kr->name, active_at);
977             }
978             return ret;
979         }
980 
981         active_at = inactive_at;
982     }
983 
984     if(print_text)
985     {
986         formatln("key-roll: %s: policy sets of dates from %T to %T computed", kr->name, active_at, end_at);
987     }
988 
989     if(log_text)
990     {
991         formatln("key-roll: %s: policy sets of dates from %T to %T computed", kr->name, active_at, end_at);
992     }
993 
994     return SUCCESS;
995 }
996 
997 /**
998  * Compare two dates together.
999  * Absolute with Absolute
1000  * Relative with Relative
1001  *
1002  * Any other combination will return -1
1003  *
1004  * @param d1 first date
1005  * @param d2 second date
1006  * @return <0,0,>0 if d1 is less than, equal to, or greater than d2
1007  */
1008 
1009 int
zone_policy_date_compare(const zone_policy_date * d1,const zone_policy_date * d2)1010 zone_policy_date_compare(const zone_policy_date *d1, const zone_policy_date *d2)
1011 {
1012     int ret;
1013 
1014     if(d1->type.type == ZONE_POLICY_ABSOLUTE && d2->type.type == ZONE_POLICY_ABSOLUTE)
1015     {
1016         ret = d1->absolute.year;
1017         ret -= d2->absolute.year;
1018 
1019         if(ret == 0)
1020         {
1021             ret = d1->absolute.month;
1022             ret -= d2->absolute.month;
1023 
1024             if(ret == 0)
1025             {
1026                 ret = d1->absolute.day;
1027                 ret -= d2->absolute.day;
1028 
1029                 if(ret == 0)
1030                 {
1031                     ret = d1->absolute.hour;
1032                     ret -= d2->absolute.hour;
1033 
1034                     if(ret == 0)
1035                     {
1036                         ret = d1->absolute.minute;
1037                         ret -= d2->absolute.minute;
1038                     }
1039                 }
1040             }
1041         }
1042 
1043         return ret;
1044     }
1045     else if(d1->type.type == ZONE_POLICY_RELATIVE && d2->type.type == ZONE_POLICY_RELATIVE)
1046     {
1047         ret = d1->relative.seconds;
1048         ret -= d2->relative.seconds;
1049         return ret;
1050     }
1051 
1052     return POLICY_ILLEGAL_DATE_COMPARE;
1053 }
1054 
1055 /**
1056  * Retrieves the first day of the month.
1057  *
1058  * 0 is Sunday
1059  *
1060  * @param year 0-based
1061  * @param month 0-based
1062  * @param week 0 to 4, week of the day
1063  * @param wday 0 to 6, day of the week, 0 for Sunday
1064  * @return the number of the day of the month or an error code
1065  */
1066 
1067 ya_result
zone_policy_get_mday_from_year_month_week_wday(int year,int month,int week,int wday)1068 zone_policy_get_mday_from_year_month_week_wday(int year, int month, int week, int wday)
1069 {
1070     int mday1 = time_first_day_of_month(year, month);
1071 
1072     if(mday1 >= 0)
1073     {
1074         /**
1075          * @note this can obviously  be simplified (++week) but I think it's clearer this way (for now)
1076          */
1077 
1078         if(wday < mday1)
1079         {
1080             // 0 1 2 3 4 5 6
1081             //
1082             // X Y Z 1 2 3 4
1083             // 4[6]7 8 9 ...
1084 
1085             return wday - mday1 + 7 * (week + 1);
1086         }
1087         else
1088         {
1089             // 0 1 2 3 4 5 6
1090             //
1091             // X Y Z 1 2 3 4
1092             // 4 6 7 8[9]...
1093 
1094             return wday - mday1 + 7 * week;
1095         }
1096     }
1097     else
1098     {
1099         return POLICY_ILLEGAL_DATE;
1100     }
1101 }
1102 
1103 /**
1104  * Initialises an absolute date from a year, month, week and week-day
1105  *
1106  * ie: 2nd Wednesday of January 2001
1107  *
1108  * 0 is Sunday
1109  *
1110  * @param date the date to initialise
1111  * @param year 0-based
1112  * @param month 0-based
1113  * @param week 0 to 4, week of the day
1114  * @param wday 0 to 6, day of the week, 0 for Sunday
1115  * @return an error code
1116  */
1117 
1118 ya_result
zone_policy_date_init_from_year_month_week_wday(zone_policy_date * date,int year,int month,int week,int wday)1119 zone_policy_date_init_from_year_month_week_wday(zone_policy_date *date, int year, int month, int week, int wday)
1120 {
1121     struct tm tm;
1122     ZEROMEMORY(&tm, sizeof(struct tm));
1123     tm.tm_mday = 1;
1124     tm.tm_mon = month;
1125     tm.tm_year = year - 1900;
1126     time_t t = mkgmtime(&tm);
1127     if(t >= 0)
1128     {
1129         if(tm.tm_wday >= 0)
1130         {
1131             /**
1132              * @note this can obviously  be simplified (++week) but I think it's clearer this way (for now)
1133              *
1134              * tm_wday is the first week-day of the month
1135              */
1136 
1137             if(wday < tm.tm_wday) // [0 .. 7] < [1 .. 31] ?
1138             {
1139                 // 0 1 2 3 4 5 6
1140                 //
1141                 // X Y Z 1 2 3 4
1142                 // 4[6]7 8 9 ...
1143 
1144                 tm.tm_mday = wday - tm.tm_wday + 7 * (week + 1) + 1;
1145             }
1146             else
1147             {
1148                 // 0 1 2 3 4 5 6
1149                 //
1150                 // X Y Z 1 2 3 4
1151                 // 4 6 7 8[9]...
1152 
1153                 tm.tm_mday = wday - tm.tm_wday + 7 * week + 1;
1154             }
1155 
1156             t = mkgmtime(&tm);
1157 
1158             if(t >= 0)
1159             {
1160                 if(tm.tm_year < 228)
1161                 {
1162                     date->type.type = ZONE_POLICY_ABSOLUTE;
1163                     date->absolute.year = tm.tm_year - (ZONE_POLICY_DATE_YEAR_BASE - 1900); // 1900 based to 2000 based
1164                     date->absolute.month = tm.tm_mon;
1165                     date->absolute.day = tm.tm_mday - 1; // 1 based to 0 based
1166                     date->absolute.hour = tm.tm_hour;
1167                     date->absolute.minute = tm.tm_min;
1168 
1169                     return SUCCESS;
1170                  }
1171             }
1172         }
1173     }
1174 
1175     return POLICY_ILLEGAL_DATE_PARAMETERS;
1176 }
1177 
1178 /**
1179  * Initialises an absolute date from a UNIX epoch
1180  *
1181  * @param date
1182  * @param epoch
1183  * @return an error code
1184  */
1185 
1186 ya_result
zone_policy_date_init_from_epoch(zone_policy_date * date,time_t epoch)1187 zone_policy_date_init_from_epoch(zone_policy_date *date, time_t epoch)
1188 {
1189     time_t t = epoch;
1190     struct tm d;
1191 
1192     // if it worked and there was no overflow ...
1193 
1194     if((gmtime_r(&t, &d) != NULL) && (d.tm_year < 228))
1195     {
1196         date->type.type = ZONE_POLICY_ABSOLUTE;
1197         date->absolute.year = d.tm_year - (ZONE_POLICY_DATE_YEAR_BASE - 1900); // 1900 based to 2000 based
1198         date->absolute.month = d.tm_mon;
1199         date->absolute.day = d.tm_mday - 1; // 1 based to 0 based
1200         date->absolute.hour = d.tm_hour;
1201         date->absolute.minute = d.tm_min;
1202 
1203         return SUCCESS;
1204     }
1205 
1206     return POLICY_ILLEGAL_DATE_PARAMETERS;
1207 }
1208 
1209 /**
1210  * Gets the UNIX epoch from an absolute date
1211  *
1212  * @param date
1213  * @param epoch a pointer to hold the result
1214  * @return an error code
1215  */
1216 
1217 ya_result
zone_policy_date_get_epoch(const zone_policy_date * date,time_t * epoch)1218 zone_policy_date_get_epoch(const zone_policy_date *date, time_t *epoch)
1219 {
1220     time_t t;
1221     struct tm d;
1222 
1223     yassert(epoch != NULL);
1224 
1225     if(date->type.type != ZONE_POLICY_ABSOLUTE) // only works with absolute dates
1226     {
1227         return POLICY_ILLEGAL_DATE_TYPE;
1228     }
1229 
1230     ZEROMEMORY(&d, sizeof(struct tm));
1231 
1232     d.tm_year = date->absolute.year + (ZONE_POLICY_DATE_YEAR_BASE - 1900);  // 2000 based to 1900 based
1233     d.tm_mon = date->absolute.month;
1234     d.tm_mday = date->absolute.day + 1;     // 0 based to 1 based
1235     d.tm_hour = date->absolute.hour;
1236     d.tm_min = date->absolute.minute;
1237     d.tm_sec = 0;
1238 
1239     t = mkgmtime(&d);
1240 
1241     if(t != -1)
1242     {
1243         *epoch = t;
1244         return SUCCESS;
1245     }
1246     else
1247     {
1248         return MAKE_ERRNO_ERROR(EOVERFLOW);
1249     }
1250 }
1251 
1252 /**
1253  * Initialises the absolute date with an epoch plus time in seconds.
1254  *
1255  * @param date
1256  * @param epoch an epoch to add the seconds to
1257  * @param seconds
1258  * @return an error code
1259  */
1260 
1261 ya_result
zone_policy_date_init_after_epoch(zone_policy_date * date,time_t epoch,u32 seconds)1262 zone_policy_date_init_after_epoch(zone_policy_date *date, time_t epoch, u32 seconds)
1263 {
1264     ya_result ret = zone_policy_date_init_from_epoch(date, epoch + seconds);
1265     return ret;
1266 }
1267 
1268 /**
1269  * Initialises the absolute date with an absolute date plus time in seconds.
1270  *
1271  * @param date
1272  * @param from an absolute date to add the seconds to
1273  * @param seconds
1274  * @return an error code
1275  */
1276 
1277 ya_result
zone_policy_date_init_after_date(zone_policy_date * date,const zone_policy_date * from,u32 seconds)1278 zone_policy_date_init_after_date(zone_policy_date *date, const zone_policy_date *from, u32 seconds)
1279 {
1280     ya_result ret;
1281     time_t epoch;
1282     if(ISOK(ret = zone_policy_date_get_epoch(from, &epoch)))
1283     {
1284         ret = zone_policy_date_init_from_epoch(date, epoch + seconds);
1285     }
1286     return ret;
1287 }
1288 
1289 /**
1290  * Initialises a date using a rule applied on an epoch
1291  *
1292  * @param result_date
1293  * @param rule_date
1294  * @param after_epoch
1295  * @return
1296  */
1297 
1298 ya_result
zone_policy_date_init_from_rule_applied_with_epoch(zone_policy_date * result_date,const zone_policy_date * rule_date,time_t after_epoch)1299 zone_policy_date_init_from_rule_applied_with_epoch(zone_policy_date *result_date, const zone_policy_date *rule_date, time_t after_epoch)
1300 {
1301     zone_policy_date after_date;
1302     ya_result ret;
1303     if(ISOK(ret = zone_policy_date_init_from_epoch(&after_date, after_epoch)))
1304     {
1305         ret = zone_policy_date_init_at_next_date(result_date, &after_date, rule_date);
1306     }
1307 
1308     return ret;
1309 }
1310 
1311 /**
1312  * Initialises an epoch from a rule applied on an epoch
1313  *
1314  * @param rule_date
1315  * @param after_epoch
1316  * @param result_epoch
1317  * @return
1318  */
1319 
1320 ya_result
zone_policy_get_epoch_from_rule_applied_with_epoch(const zone_policy_date * rule_date,time_t after_epoch,time_t * result_epoch)1321 zone_policy_get_epoch_from_rule_applied_with_epoch(const zone_policy_date *rule_date, time_t after_epoch, time_t *result_epoch)
1322 {
1323     zone_policy_date result_date;
1324     ya_result ret;
1325     if(ISOK(ret = zone_policy_date_init_from_rule_applied_with_epoch(&result_date, rule_date, after_epoch)))
1326     {
1327         ret = zone_policy_date_get_epoch(&result_date, result_epoch);
1328     }
1329     return ret;
1330 }
1331 
1332 zone_policy_rule_definition_s*
zone_policy_rule_definition_get_from_index(u32 index)1333 zone_policy_rule_definition_get_from_index(u32 index)
1334 {
1335     zone_policy_rule_definition_s *ret = NULL;
1336     group_mutex_read_lock(&zone_policy_rule_definition_set_mtx);
1337     u32_node *node = u32_set_find(&zone_policy_rule_definition_set, index);
1338     if(node != NULL)
1339     {
1340         ret = (zone_policy_rule_definition_s*)node->value;
1341     }
1342     group_mutex_read_unlock(&zone_policy_rule_definition_set_mtx);
1343     return ret;
1344 }
1345 
1346 zone_policy_rule_definition_s*
zone_policy_rule_definition_get_from_rule(const zone_policy_date * rule)1347 zone_policy_rule_definition_get_from_rule(const zone_policy_date *rule)
1348 {
1349     zone_policy_rule_definition_s *ret = NULL;
1350     if(rule->type.type == ZONE_POLICY_RULE)
1351     {
1352         ret = zone_policy_rule_definition_get_from_index(rule->rule.index);
1353     }
1354     return ret;
1355 }
1356 
1357 void
zone_policy_rule_init(zone_policy_rule_s * rule,const zone_policy_rule_definition_s * rule_definition)1358 zone_policy_rule_init(zone_policy_rule_s *rule, const zone_policy_rule_definition_s *rule_definition)
1359 {
1360     group_mutex_write_lock(&zone_policy_rule_definition_set_mtx);
1361     yassert(zone_policy_rule_definition_next_index < 0x40000000);
1362 
1363     for(;;)
1364     {
1365         ++zone_policy_rule_definition_next_index;
1366         if(zone_policy_rule_definition_next_index == 0x40000000)
1367         {
1368             zone_policy_rule_definition_next_index = 0;
1369         }
1370 
1371         u32_node *node = u32_set_insert(&zone_policy_rule_definition_set, zone_policy_rule_definition_next_index);
1372 
1373         if(node->value == NULL)
1374         {
1375             rule->index = zone_policy_rule_definition_next_index;
1376             rule->type = ZONE_POLICY_RULE;
1377 
1378             zone_policy_rule_definition_s *new_rule_definition;
1379             ZALLOC_OBJECT_OR_DIE( new_rule_definition, zone_policy_rule_definition_s, DPOLRULE_TAG);
1380             memcpy(new_rule_definition, rule_definition, sizeof(zone_policy_rule_definition_s));
1381             node->value = new_rule_definition;
1382             break;
1383         }
1384     }
1385 
1386     group_mutex_write_unlock(&zone_policy_rule_definition_set_mtx);
1387 }
1388 
1389 void
zone_policy_rule_finalize(zone_policy_rule_s * rule)1390 zone_policy_rule_finalize(zone_policy_rule_s *rule)
1391 {
1392     group_mutex_write_lock(&zone_policy_rule_definition_set_mtx);
1393     u32_node *node = u32_set_find(&zone_policy_rule_definition_set, rule->index);
1394     if(node != NULL)
1395     {
1396         if(node->value != NULL)
1397         {
1398             ZFREE(node->value, zone_policy_rule_definition_s);
1399         }
1400 
1401         u32_set_delete(&zone_policy_rule_definition_set, rule->index);
1402     }
1403     group_mutex_write_unlock(&zone_policy_rule_definition_set_mtx);
1404 }
1405 
1406 void
zone_policy_date_init_from_rule_definition(zone_policy_date * date,const zone_policy_rule_definition_s * rule_definition)1407 zone_policy_date_init_from_rule_definition(zone_policy_date *date, const zone_policy_rule_definition_s *rule_definition)
1408 {
1409 
1410     date->type.type = ZONE_POLICY_RULE;
1411     zone_policy_rule_init(&date->rule, rule_definition);
1412 }
1413 
1414 /**
1415  * Initialises a date with the earliest matching of the rule starting after 'from'
1416  *
1417  * @param date
1418  * @param from
1419  * @param rule
1420  *
1421  * @return an error code
1422  */
1423 ya_result
zone_policy_date_init_at_next_date(zone_policy_date * date,const zone_policy_date * from,const zone_policy_date * rule)1424 zone_policy_date_init_at_next_date(zone_policy_date *date, const zone_policy_date *from, const zone_policy_date *rule)
1425 {
1426     ya_result ret;
1427 
1428     if((((intptr)date) == 0) | (((intptr)from) == 0) | (((intptr)rule) == 0))
1429     {
1430         return UNEXPECTED_NULL_ARGUMENT_ERROR;
1431     }
1432 
1433 #if DEBUG
1434     format_writer from_fw = {zone_policy_date_format_handler_method, from};
1435     format_writer rule_fw = {zone_policy_date_format_handler_method, rule};
1436     format_writer date_fw = {zone_policy_date_format_handler_method, date};
1437 #endif
1438 
1439     if(from->type.type != ZONE_POLICY_ABSOLUTE)
1440     {
1441 #if DEBUG
1442         log_debug1("zone_policy_date_init_at_next_date(%p, %w, %w): can only work from an absolute time", date, &from_fw, &rule_fw);
1443 #endif
1444         return POLICY_ILLEGAL_DATE_TYPE;
1445     }
1446 
1447     switch(rule->type.type)
1448     {
1449         case ZONE_POLICY_RELATIVE:
1450         {
1451             memcpy(date, from, sizeof(zone_policy_date));
1452 #if DEBUG
1453             log_debug1("zone_policy_date_init_at_next_date(%p, %w, %w): initialising relative time", date, &from_fw, &rule_fw);
1454 #endif
1455             ret = zone_policy_date_init_after_date(date, from, rule->relative.seconds); // +60 because it must be after and because of minute granularity
1456 #if DEBUG
1457             log_debug1("zone_policy_date_init_at_next_date: %w = %w + %w", &date_fw, &from_fw, &rule_fw);
1458 #endif
1459             return ret;
1460         }
1461         case ZONE_POLICY_RULE:
1462         {
1463 #if DEBUG
1464             log_debug1("zone_policy_date_init_at_next_date(%p, %w, %w): initialising rule-based time", date, &from_fw, &rule_fw);
1465 #endif
1466             ret = zone_policy_date_init_at_next_rule(date, from, rule);
1467 #if DEBUG
1468             log_debug1("zone_policy_date_init_at_next_date: %w = %w + %w", &date_fw, &from_fw, &rule_fw);
1469 #endif
1470             return ret;
1471         }
1472         default:
1473         {
1474 #if DEBUG
1475             log_debug1("zone_policy_date_init_at_next_date(%p, %w, %w): unexpected type", date, &from_fw, &rule_fw);
1476 #endif
1477             return POLICY_ILLEGAL_DATE_TYPE;
1478         }
1479     }
1480 }
1481 
1482 static zone_policy_date*
zone_policy_table_get_date_by_index(zone_policy_table_s * tbl,int index)1483 zone_policy_table_get_date_by_index(zone_policy_table_s *tbl, int index)
1484 {
1485     switch(index)
1486     {
1487         case ZONE_POLICY_RELATIVE_TO_GENERATE:
1488             return &tbl->created;
1489         case ZONE_POLICY_RELATIVE_TO_PUBLISH:
1490             return &tbl->publish;
1491         case ZONE_POLICY_RELATIVE_TO_ACTIVATE:
1492             return &tbl->activate;
1493         case ZONE_POLICY_RELATIVE_TO_INACTIVE:
1494             return &tbl->inactive;
1495         case ZONE_POLICY_RELATIVE_TO_REMOVE:
1496             return &tbl->delete;
1497 #if HAS_DS_PUBLICATION_SUPPORT
1498         case ZONE_POLICY_RELATIVE_TO_DS_PUBLISH:
1499             return &tbl->ds_publish;
1500         case ZONE_POLICY_RELATIVE_TO_DS_REMOVE:
1501             return &tbl->ds_remove;
1502 #endif
1503         default:
1504             log_err("zone_policy_table_get_date_by_index(%p, %i): index out of range [%i, %i]", tbl, index, ZONE_POLICY_RELATIVE_TO_GENERATE, ZONE_POLICY_RELATIVE_TO_REMOVE);
1505             return NULL;
1506     }
1507 }
1508 
1509 /**
1510  * This initialises a date with the earliest matching of the rule starting from 'from'
1511  *
1512  * @param date
1513  * @param from
1514  * @param rule
1515  *
1516  * @return an error code
1517  */
1518 ya_result
zone_policy_date_init_from_date(zone_policy_date * date,const zone_policy_date * from,const zone_policy_date * rule)1519 zone_policy_date_init_from_date(zone_policy_date *date, const zone_policy_date *from, const zone_policy_date *rule)
1520 {
1521     ya_result ret;
1522 
1523 #if DEBUG
1524     format_writer from_fw = {zone_policy_date_format_handler_method, from};
1525     format_writer rule_fw = {zone_policy_date_format_handler_method, rule};
1526     format_writer date_fw = {zone_policy_date_format_handler_method, date};
1527 #endif
1528 
1529     if(from->type.type != ZONE_POLICY_ABSOLUTE)
1530     {
1531 #if DEBUG
1532         log_debug1("zone_policy_date_init_from_date(%p, %w, %w): can only work from an absolute time", date, &from_fw, &rule_fw);
1533 #endif
1534         return POLICY_ILLEGAL_DATE_TYPE;
1535     }
1536 
1537     switch(rule->type.type)
1538     {
1539         case ZONE_POLICY_RELATIVE:
1540         {
1541             memcpy(date, from, sizeof(zone_policy_date));
1542 #if DEBUG
1543             log_debug1("zone_policy_date_init_from_date(%p, %w, %w): initialising relative time", date, &from_fw, &rule_fw);
1544 #endif
1545             ret = zone_policy_date_init_after_date(date, from, rule->relative.seconds);
1546 #if DEBUG
1547             log_debug1("zone_policy_date_init_from_date: %w = %w + %w", &date_fw, &from_fw, &rule_fw);
1548 #endif
1549             return ret;
1550         }
1551         case ZONE_POLICY_RULE:
1552         {
1553 #if DEBUG
1554             log_debug1("zone_policy_date_init_from_date(%p, %w, %w): initialising rule-based time", date, &from_fw, &rule_fw);
1555 #endif
1556             ret = zone_policy_date_init_from_rule(date, from, rule);
1557 #if DEBUG
1558             log_debug1("zone_policy_date_init_from_date: %w = %w + %w", &date_fw, &from_fw, &rule_fw);
1559 #endif
1560             return ret;
1561         }
1562         default:
1563         {
1564 #if DEBUG
1565             log_debug1("zone_policy_date_init_from_date(%p, %w, %w): unexpected type", date, &from_fw, &rule_fw);
1566 #endif
1567             return POLICY_ILLEGAL_DATE_TYPE;
1568         }
1569     }
1570 }
1571 
1572 ya_result
zone_policy_table_init_from_date(zone_policy_table_s * tbl,zone_policy_table_s * with,zone_policy_date * from)1573 zone_policy_table_init_from_date(zone_policy_table_s *tbl, zone_policy_table_s *with, zone_policy_date *from)
1574 {
1575     ya_result ret;
1576 
1577     if(with->created.type.type == ZONE_POLICY_RULE)
1578     {
1579         if(ISOK(ret = zone_policy_date_init_from_date(&tbl->created, from, &with->created)))
1580         {
1581             if(ISOK(ret = zone_policy_date_init_at_next_date(&tbl->publish, &tbl->created, &with->publish)))
1582             {
1583                 if(ISOK(ret = zone_policy_date_init_at_next_date(&tbl->activate, &tbl->publish, &with->activate)))
1584                 {
1585 #if DEBUG
1586                     format_writer c_fw = {zone_policy_date_format_handler_method, &tbl->created};
1587                     format_writer p_fw = {zone_policy_date_format_handler_method, &tbl->publish};
1588                     format_writer a_fw = {zone_policy_date_format_handler_method, &tbl->activate};
1589 
1590                     log_debug("zone_policy_table_init: base c:%w => p:%w => a:%w", &c_fw, &p_fw, &a_fw);
1591 #endif
1592                     // compute the future key timings to ensure there will be no period without a signature
1593 
1594                     zone_policy_date next_creation_date;
1595                     zone_policy_date next_publish_date;
1596                     zone_policy_date next_activate_date;
1597 
1598                     if(ISOK(ret = zone_policy_date_init_at_next_date(&next_creation_date, &tbl->activate, &with->created)))
1599                     {
1600                         if(ISOK(ret = zone_policy_date_init_at_next_date(&next_publish_date, &next_creation_date, &with->publish)))
1601                         {
1602                             if(ISOK(ret = zone_policy_date_init_at_next_date(&next_activate_date, &next_publish_date, &with->activate)))
1603                             {
1604 #if DEBUG
1605                                 format_writer na_fw = {zone_policy_date_format_handler_method, &next_activate_date};
1606                                 format_writer np_fw = {zone_policy_date_format_handler_method, &next_publish_date};
1607                                 format_writer nc_fw = {zone_policy_date_format_handler_method, &next_creation_date};
1608 
1609                                 log_debug("zone_policy_table_init: next c:%w => p:%w => a:%w", &nc_fw, &np_fw, &na_fw);
1610 #endif
1611                                 if(ISOK(ret = zone_policy_date_init_from_date(&tbl->inactive, &next_activate_date, &with->inactive)))
1612                                 {
1613 #if HAS_DS_PUBLICATION_SUPPORT
1614                                     if(ISOK(ret = zone_policy_date_init_at_next_date(&tbl->delete, &tbl->inactive, &with->delete)))
1615                                     {
1616                                         if(ISOK(ret = zone_policy_date_init_at_next_date(&tbl->ds_add, &tbl->created, &with->ds_add)))
1617                                         {
1618                                             ret = zone_policy_date_init_at_next_date(&tbl->ds_del, &tbl->ds_add, &with->ds_del);
1619                                         }
1620                                     }
1621 #else
1622                                     ret = zone_policy_date_init_at_next_date(&tbl->delete, &tbl->inactive, &with->delete);
1623 #if DEBUG
1624                                     format_writer i_fw = {zone_policy_date_format_handler_method, &tbl->inactive};
1625                                     format_writer d_fw = {zone_policy_date_format_handler_method, &tbl->delete};
1626 
1627                                     log_debug("zone_policy_table_init_from_date: base i:%w => d:%w", &i_fw, &d_fw);
1628 #endif
1629 #endif
1630                                 }
1631                             }
1632                         }
1633                     }
1634                 }
1635             }
1636         }
1637     }
1638     else if(with->created.type.type == ZONE_POLICY_RELATIVE)
1639     {
1640         if(ISOK(ret = zone_policy_date_init_at_next_date(&tbl->created, from, &with->created))) // here !
1641         {
1642             if(ISOK(ret = zone_policy_date_init_at_next_date(&tbl->publish, &tbl->created, &with->publish)))
1643             {
1644                 if(ISOK(ret = zone_policy_date_init_at_next_date(&tbl->activate, zone_policy_table_get_date_by_index(tbl, with->activate.relative.relativeto), &with->activate)))
1645                 {
1646                     if(ISOK(ret = zone_policy_date_init_at_next_date(&tbl->inactive, zone_policy_table_get_date_by_index(tbl, with->inactive.relative.relativeto), &with->inactive)))
1647                     {
1648                         if(ISOK(ret = zone_policy_date_init_at_next_date(&tbl->delete, zone_policy_table_get_date_by_index(tbl, with->delete.relative.relativeto), &with->delete)))
1649                         {
1650                         }
1651                     }
1652                 }
1653             }
1654         }
1655     }
1656     else
1657     {
1658         ret = POLICY_ILLEGAL_DATE_TYPE;
1659     }
1660 
1661     return ret;
1662 }
1663 
1664 ya_result
zone_policy_table_init_from_created_epoch(zone_policy_table_s * tbl,zone_policy_table_s * with,time_t created_epoch)1665 zone_policy_table_init_from_created_epoch(zone_policy_table_s *tbl, zone_policy_table_s *with, time_t created_epoch)
1666 {
1667     ya_result ret;
1668 
1669     if(FAIL(ret = zone_policy_date_init_from_epoch(&tbl->created, created_epoch)))
1670     {
1671         return ret;
1672     }
1673 
1674     if(with->created.type.type == ZONE_POLICY_RULE)
1675     {
1676         if(ISOK(ret = zone_policy_date_init_at_next_date(&tbl->publish, &tbl->created, &with->publish)))
1677         {
1678             if(ISOK(ret = zone_policy_date_init_at_next_date(&tbl->activate, &tbl->publish, &with->activate)))
1679             {
1680 #if DEBUG
1681                 format_writer c_fw = {zone_policy_date_format_handler_method, &tbl->created};
1682                 format_writer p_fw = {zone_policy_date_format_handler_method, &tbl->publish};
1683                 format_writer a_fw = {zone_policy_date_format_handler_method, &tbl->activate};
1684 
1685                 log_debug("zone_policy_table_init: base %w => %w => %w", &c_fw, &p_fw, &a_fw);
1686 #endif
1687                 // compute the future key timings to ensure there will be no period without a signature
1688 
1689                 zone_policy_date next_creation_date;
1690                 zone_policy_date next_publish_date;
1691                 zone_policy_date next_activate_date;
1692 
1693                 if(ISOK(ret = zone_policy_date_init_at_next_date(&next_creation_date, &tbl->activate, &with->created)))
1694                 {
1695                     if(ISOK(ret = zone_policy_date_init_at_next_date(&next_publish_date, &next_creation_date, &with->publish)))
1696                     {
1697                         if(ISOK(ret = zone_policy_date_init_at_next_date(&next_activate_date, &next_publish_date, &with->activate)))
1698                         {
1699 #if DEBUG
1700                             format_writer na_fw = {zone_policy_date_format_handler_method, &next_activate_date};
1701                             format_writer np_fw = {zone_policy_date_format_handler_method, &next_publish_date};
1702                             format_writer nc_fw = {zone_policy_date_format_handler_method, &next_creation_date};
1703 
1704                             log_debug("zone_policy_table_init: next %w => %w => %w", &nc_fw, &np_fw, &na_fw);
1705 #endif
1706                             if(ISOK(ret = zone_policy_date_init_from_date(&tbl->inactive, &next_activate_date, &with->inactive)))
1707                             {
1708 #if HAS_DS_PUBLICATION_SUPPORT
1709                                 if(ISOK(ret = zone_policy_date_init_at_next_date(&tbl->delete, &tbl->inactive, &with->delete)))
1710                                 {
1711                                     if(ISOK(ret = zone_policy_date_init_at_next_date(&tbl->ds_add, &tbl->created, &with->ds_add)))
1712                                     {
1713                                         ret = zone_policy_date_init_at_next_date(&tbl->ds_del, &tbl->ds_add, &with->ds_del);
1714                                     }
1715                                 }
1716 #else
1717                                 ret = zone_policy_date_init_at_next_date(&tbl->delete, &tbl->inactive, &with->delete);
1718 #endif
1719                             }
1720                         }
1721                     }
1722                 }
1723             }
1724         }
1725     }
1726     else if(with->created.type.type == ZONE_POLICY_RELATIVE)
1727     {
1728         if(ISOK(ret = zone_policy_date_init_at_next_date(&tbl->publish, &tbl->created, &with->publish)))
1729         {
1730             if(ISOK(ret = zone_policy_date_init_at_next_date(&tbl->activate, zone_policy_table_get_date_by_index(tbl, with->activate.relative.relativeto), &with->activate)))
1731             {
1732                 if(ISOK(ret = zone_policy_date_init_at_next_date(&tbl->inactive, zone_policy_table_get_date_by_index(tbl, with->inactive.relative.relativeto), &with->inactive)))
1733                 {
1734                     if(ISOK(ret = zone_policy_date_init_at_next_date(&tbl->delete, zone_policy_table_get_date_by_index(tbl, with->delete.relative.relativeto), &with->delete)))
1735                     {
1736                     }
1737                 }
1738             }
1739         }
1740     }
1741     else
1742     {
1743         ret = POLICY_ILLEGAL_DATE_TYPE;
1744     }
1745 
1746     return ret;
1747 }
1748 
1749 ya_result
zone_policy_table_init_from_epoch(zone_policy_table_s * tbl,zone_policy_table_s * with,time_t created_epoch)1750 zone_policy_table_init_from_epoch(zone_policy_table_s *tbl, zone_policy_table_s *with, time_t created_epoch)
1751 {
1752     ya_result ret;
1753 
1754     zone_policy_date epoch_date;
1755     zone_policy_date_init_from_epoch(&epoch_date, created_epoch);
1756     ret = zone_policy_table_init_from_date(tbl, with, &epoch_date);
1757 
1758     return ret;
1759 }
1760 
1761 static bool
zone_policy_key_roll_matches(const struct dnssec_policy_key_suite * kr,const dnssec_key * key)1762 zone_policy_key_roll_matches(const struct dnssec_policy_key_suite *kr, const dnssec_key *key)
1763 {
1764     yassert((kr->key->flags == DNSKEY_FLAGS_KSK) || (kr->key->flags == DNSKEY_FLAGS_ZSK));
1765 
1766     if(dnskey_get_algorithm(key) == kr->key->algorithm)
1767     {
1768         // matches flags
1769 
1770         if((dnskey_get_flags(key) & DNSKEY_FLAGS_KSK) == kr->key->flags)
1771         {
1772             int key_size = dnskey_get_size(key);
1773 
1774             if((key_size - kr->key->size) < 48)
1775             {
1776                 // algorithm, flags and size are matching
1777                 // now what about the times
1778 
1779                 if((key->epoch_created != 0) &&
1780                    (key->epoch_publish != 0) &&
1781                    (key->epoch_activate != 0) &&
1782                    (key->epoch_inactive != 0) &&
1783                    (key->epoch_delete != 0))
1784                 {
1785                     log_debug1("dnssec-policy: %s: %s: key %05d/%d timings: %T %T %T %T %T",
1786                             key->origin,
1787                             kr->name,
1788                             dnskey_get_tag_const(key), ntohs(key->flags),
1789                             key->epoch_created, key->epoch_publish, key->epoch_activate, key->epoch_inactive, key->epoch_delete);
1790 
1791                     zone_policy_table_s key_tbl;
1792                     if(ISOK(zone_policy_table_init_from_created_epoch(&key_tbl, &kr->roll->time_table, key->epoch_created)))
1793                     {
1794                         time_t key_created = 0, key_publish = 0, key_activate = 0, key_inactive = 0, key_delete = 0;
1795                         zone_policy_date_get_epoch(&key_tbl.created, &key_created);
1796                         zone_policy_date_get_epoch(&key_tbl.publish, &key_publish);
1797                         zone_policy_date_get_epoch(&key_tbl.activate, &key_activate);
1798                         zone_policy_date_get_epoch(&key_tbl.inactive, &key_inactive);
1799                         zone_policy_date_get_epoch(&key_tbl.delete, &key_delete);
1800 
1801                         s64 pait = key_inactive - key_activate;
1802                         s64 kait = key->epoch_inactive - key->epoch_activate;
1803                         s64 dait = labs(pait - kait);
1804 
1805                         s64 pidt = key_delete - key_inactive;
1806                         s64 kidt = key->epoch_delete - key->epoch_inactive;
1807                         s64 didt = labs(pidt - kidt);
1808 
1809                         s64 dc = labs(key_created - key->epoch_created);
1810                         s64 dp = labs(key_publish - key->epoch_publish);
1811                         s64 da = labs(key_activate - key->epoch_activate);
1812                         s64 di = labs(key_inactive - key->epoch_inactive);
1813                         s64 dd = labs(key_delete - key->epoch_delete);
1814 
1815                         //bool match = (/*dc < KEY_POLICY_EPOCH_MATCH_MARGIN &&*/ dp < KEY_POLICY_EPOCH_MATCH_MARGIN && da < KEY_POLICY_EPOCH_MATCH_MARGIN && di < KEY_POLICY_EPOCH_MATCH_MARGIN && dd < KEY_POLICY_EPOCH_MATCH_MARGIN);
1816 
1817                         // This checks if the key matches were it counts.  We already know flags & size are a match, now if it lives long enough and is deleted in time, then it is a match.
1818                         // The next key generation will have to align to these timings to find when will be the next one.
1819 
1820                         bool match = (dait < KEY_POLICY_EPOCH_MATCH_MARGIN) && (didt < KEY_POLICY_EPOCH_MATCH_MARGIN);
1821 
1822                         log_debug2("dnssec-policy: %s: %s: key %05d/%d pkd: ai=%lli id=%lli, with a margin of %lli",
1823                                    key->origin,
1824                                    kr->name,
1825                                    dnskey_get_tag_const(key), ntohs(key->flags), dait, didt, KEY_POLICY_EPOCH_MATCH_MARGIN);
1826 
1827                         log_debug2("dnssec-policy: %s: %s: key %05d/%d deltas: (%lli) %lli %lli %lli %lli, with a margin of %lli",
1828                                    key->origin,
1829                                    kr->name,
1830                                    dnskey_get_tag_const(key), ntohs(key->flags), dc, dp, da, di, dd, KEY_POLICY_EPOCH_MATCH_MARGIN);
1831 
1832                         log_debug1("dnssec-policy: %s: %s: key %05d/%d expects: %T %T %T %T %T : %s",
1833                                 key->origin,
1834                                 kr->name,
1835                                 dnskey_get_tag_const(key), ntohs(key->flags),
1836                                 key_created, key_publish, key_activate, key_inactive, key_delete,
1837                                 ((match)?"MATCH":"DIFFERS"));
1838 
1839                         return match;
1840                     } // else zone_policy_table_init_from_created_epoch failed and something is wrong => false
1841                     else
1842                     {
1843                         log_err("dnssec-policy: %s: %s: key %05d/%d matching triggered an error in zone_policy_table_init_from_created_epoch",
1844                                    key->origin,
1845                                    kr->name,
1846                                    dnskey_get_tag_const(key), ntohs(key->flags));
1847                     }
1848                 }
1849                 else
1850                 {
1851                     log_debug1("dnssec-policy: %s: %s: key %05d/%d is not a match as it has no time table (skipping)",
1852                             key->origin,
1853                             kr->name,
1854                             dnskey_get_tag_const(key), ntohs(key->flags));
1855                 }
1856             }
1857             else
1858             {
1859                 log_debug1("dnssec-policy: %s: %s: key %05d/%d of size %i is not a match as the expected size is %i (skipping for this key roll)",
1860                             key->origin,
1861                             kr->name,
1862                             dnskey_get_tag_const(key), ntohs(key->flags), key_size, kr->key->size);
1863             }
1864         }
1865         else
1866         {
1867             log_debug1("dnssec-policy: %s: %s: key %05d/%d is not a match as the expected flags is %i (skipping for this key roll)",
1868                             key->origin,
1869                             kr->name,
1870                             dnskey_get_tag_const(key), ntohs(key->flags), ntohs(kr->key->flags));
1871         }
1872     }
1873     else
1874     {
1875         log_debug1("dnssec-policy: %s: %s: key %05d/%d is not a match as the expected algorithm is %i (skipping for this key roll)",
1876                             key->origin,
1877                             kr->name,
1878                             dnskey_get_tag_const(key), ntohs(key->flags), kr->key->algorithm);
1879     }
1880 
1881     return FALSE;
1882 }
1883 
1884 /**
1885  * Compares keys by activation time, inactivation time and tag.
1886  * Handles 0 epoch as "never" (as expected)
1887  *
1888  * @param a_
1889  * @param b_
1890  * @return
1891  */
1892 
zone_policy_dnssec_key_ptr_vector_qsort_by_activation_time_callback(const void * a_,const void * b_)1893 static int zone_policy_dnssec_key_ptr_vector_qsort_by_activation_time_callback(const void *a_, const void *b_)
1894 {
1895     const dnssec_key *a = (const dnssec_key*)a_;
1896     const dnssec_key *b = (const dnssec_key*)b_;
1897 
1898     s64 a_a = a->epoch_activate;
1899     if(a_a == 0)
1900     {
1901         a_a = MAX_S64;
1902     }
1903 
1904     s64 b_a = b->epoch_activate;
1905     if(b_a == 0)
1906     {
1907         b_a = MAX_S64;
1908     }
1909 
1910     s64 r = a_a - b_a;
1911 
1912     if(r == 0)
1913     {
1914         s64 a_i = a->epoch_inactive;
1915         if(a_i == 0)
1916         {
1917             a_i = MAX_S64;
1918         }
1919 
1920         s64 b_i = b->epoch_inactive;
1921         if(b_i == 0)
1922         {
1923             b_i = MAX_S64;
1924         }
1925 
1926         r = a_i - b_i;
1927 
1928         if(r == 0)
1929         {
1930             r = dnskey_get_tag_const(a) - dnskey_get_tag_const(b);
1931         }
1932     }
1933 
1934     return r;
1935 }
1936 
1937 static void
zone_policy_log_debug_key(const char * prefix,const dnssec_key * key)1938 zone_policy_log_debug_key(const char *prefix, const dnssec_key *key)
1939 {
1940     EPOCHZ_DEF2(created, key->epoch_created);
1941     EPOCHZ_DEF2(publish, key->epoch_publish);
1942     EPOCHZ_DEF2(activate, key->epoch_activate);
1943     EPOCHZ_DEF2(inactive, key->epoch_inactive);
1944     EPOCHZ_DEF2(delete, key->epoch_delete);
1945 #if 0 /* fix */
1946 #else
1947     log_debug("%sK%{dnsname}+%03d+%05d/%d created=%1w publish=%1w activate=%1w inactive=%1w delete=%1w",
1948             prefix,
1949             key->owner_name,
1950             key->algorithm,
1951             dnskey_get_tag_const(key),
1952             ntohs(key->flags),
1953             EPOCHZ_REF(created),
1954             EPOCHZ_REF(publish),
1955             EPOCHZ_REF(activate),
1956             EPOCHZ_REF(inactive),
1957             EPOCHZ_REF(delete));
1958 #endif
1959 }
1960 
1961 static struct service_s dnssec_policy_command_service_handler = UNINITIALIZED_SERVICE;
1962 static threaded_dll_cw dnssec_policy_command_service_handler_queue;
1963 static bool dnssec_policy_command_service_handler_initialised = FALSE;
1964 
1965 static ya_result dnssec_policy_alarm_command_generate_key(dnssec_policy_queue *cmd);
1966 void dnssec_policy_queue_delete_command(dnssec_policy_queue *cmd);
1967 
dnssec_policy_command_service(struct service_worker_s * worker)1968 static int dnssec_policy_command_service(struct service_worker_s *worker)
1969 {
1970     log_info("dnssec-policy: command execution service started");
1971 
1972     while(service_should_run(worker))
1973     {
1974         dnssec_policy_queue *cmd = (dnssec_policy_queue*)threaded_dll_cw_dequeue(&dnssec_policy_command_service_handler_queue);
1975 
1976         if(cmd == NULL)
1977         {
1978             break;
1979         }
1980 
1981         switch(cmd->command)
1982         {
1983             case DNSSEC_POLICY_COMMAND_INIT:
1984             {
1985 #if DEBUG
1986                 log_debug("dnssec-policy: init command");
1987 #endif
1988                 dnssec_policy_queue_delete_command(cmd);
1989                 break;
1990             }
1991             case DNSSEC_POLICY_COMMAND_GENERATE_KEY:
1992             {
1993 #if DEBUG
1994                 log_debug("dnssec-policy: generate key command");
1995 #endif
1996                 dnssec_policy_alarm_command_generate_key(cmd); // deletes the command
1997                 break;
1998             }
1999             default:
2000             {
2001                 log_err("dnssec-policy: unknown command %i", cmd->command);
2002                 dnssec_policy_queue_delete_command(cmd);
2003                 break;
2004             }
2005         }
2006 
2007     }
2008 
2009     log_info("dnssec-policy: command execution service stopped");
2010 
2011     return SUCCESS;
2012 }
2013 
2014 void
dnssec_policy_command_service_start()2015 dnssec_policy_command_service_start()
2016 {
2017     ya_result ret;
2018     if(!dnssec_policy_command_service_handler_initialised)
2019     {
2020         if(ISOK(ret = service_init_ex(&dnssec_policy_command_service_handler, dnssec_policy_command_service, "dpcmd", 8)))
2021         {
2022             threaded_dll_cw_init(&dnssec_policy_command_service_handler_queue, 1000000);
2023             dnssec_policy_command_service_handler_initialised = TRUE;
2024         }
2025 
2026         service_start(&dnssec_policy_command_service_handler);
2027     }
2028 }
2029 
2030 void
dnssec_policy_command_service_stop()2031 dnssec_policy_command_service_stop()
2032 {
2033     threaded_dll_cw_finalize(&dnssec_policy_command_service_handler_queue);
2034 }
2035 
2036 void
dnssec_policy_command_queue(dnssec_policy_queue * cmd)2037 dnssec_policy_command_queue(dnssec_policy_queue *cmd)
2038 {
2039     threaded_dll_cw_enqueue(&dnssec_policy_command_service_handler_queue, cmd);
2040 }
2041 
2042 static ya_result
dnssec_policy_alarm_command_generate_key(dnssec_policy_queue * cmd)2043 dnssec_policy_alarm_command_generate_key(dnssec_policy_queue *cmd)
2044 {
2045     zone_policy_table_s tbl;
2046     zone_policy_date from;
2047     const char *algorithm_name = dns_encryption_algorithm_get_name(cmd->parameters.generate_key.suite->key->algorithm);
2048     char domain[MAX_DOMAIN_LENGTH];
2049     // from ... the time to take as a base for generation, which is the previous
2050 
2051 
2052     log_info("dnssec-policy: %{dnsname}: generating %s key of size %hu with time parameter %T",
2053              cmd->origin,
2054              algorithm_name,
2055              cmd->parameters.generate_key.suite->key->size,
2056              cmd->epoch);
2057 
2058     dnsname_to_cstr(domain, cmd->origin);
2059 
2060     ya_result ret;
2061 
2062     if(FAIL(ret = zone_policy_date_init_from_epoch(&from, cmd->epoch)))
2063     {
2064         log_err("dnssec-policy: %{dnsname}: failed to generate %s key of size %hu with time parameter %T: %r",
2065                 cmd->origin,
2066                 algorithm_name,
2067                 cmd->parameters.generate_key.suite->key->size,
2068                 cmd->epoch,
2069                 ret);
2070 
2071         zone_policy_key_suite_unmark_processed(cmd->parameters.generate_key.zone_desc, cmd->parameters.generate_key.suite);
2072 
2073         dnssec_policy_key_suite_release(cmd->parameters.generate_key.suite);
2074         cmd->parameters.generate_key.suite = NULL;
2075 
2076         dnssec_policy_queue_delete_command(cmd);
2077 
2078         return ret;
2079     }
2080 
2081     if(FAIL(ret = zone_policy_table_init_from_date(&tbl, &cmd->parameters.generate_key.suite->roll->time_table, &from)))
2082     {
2083         log_err("dnssec-policy: %{dnsname}: failed to generate time-table for %s key of size %hu with time parameter %T: %r",
2084                 cmd->origin,
2085                 algorithm_name,
2086                 cmd->parameters.generate_key.suite->key->size,
2087                 cmd->epoch,
2088                 ret);
2089 
2090         zone_policy_key_suite_unmark_processed(cmd->parameters.generate_key.zone_desc, cmd->parameters.generate_key.suite);
2091         dnssec_policy_key_suite_release(cmd->parameters.generate_key.suite);
2092         cmd->parameters.generate_key.suite = NULL;
2093         dnssec_policy_queue_delete_command(cmd);
2094 
2095         return ret;
2096     }
2097 
2098     log_debug("dnssec-policy: %{dnsname}: time-table for %s key of size %hu with time parameter %T generated",
2099               cmd->origin,
2100               algorithm_name,
2101               cmd->parameters.generate_key.suite->key->size,
2102               cmd->epoch);
2103 
2104     time_t created_epoch;
2105     time_t publish_epoch;
2106     time_t activate_epoch;
2107     time_t deactivate_epoch;
2108     time_t unpublish_epoch;
2109 
2110     if(FAIL(ret = zone_policy_date_get_epoch(&tbl.created, &created_epoch))) // note: created should be of type ZONE_POLICY_ABSOLUTE
2111     {
2112         log_err("dnssec_policy_queue_add_generate_key_create_at: zone_policy_date_get_epoch (created_epoch) returned an error: %r", ret);
2113         zone_policy_key_suite_unmark_processed(cmd->parameters.generate_key.zone_desc, cmd->parameters.generate_key.suite);
2114         dnssec_policy_key_suite_release(cmd->parameters.generate_key.suite);
2115         cmd->parameters.generate_key.suite = NULL;
2116         dnssec_policy_queue_delete_command(cmd);
2117         return ret;
2118     }
2119 
2120     if(FAIL(ret = zone_policy_date_get_epoch(&tbl.publish, &publish_epoch))) // note: publish should be of type ZONE_POLICY_ABSOLUTE
2121     {
2122         log_err("dnssec_policy_queue_add_generate_key_create_at: zone_policy_date_get_epoch (publish_epoch) returned an error: %r", ret);
2123         zone_policy_key_suite_unmark_processed(cmd->parameters.generate_key.zone_desc, cmd->parameters.generate_key.suite);
2124         dnssec_policy_key_suite_release(cmd->parameters.generate_key.suite);
2125         cmd->parameters.generate_key.suite = NULL;
2126         dnssec_policy_queue_delete_command(cmd);
2127         return ret;
2128     }
2129 
2130     if(FAIL(ret = zone_policy_date_get_epoch(&tbl.activate, &activate_epoch))) // note: activate should be of type ZONE_POLICY_ABSOLUTE
2131     {
2132         log_err("dnssec_policy_queue_add_generate_key_create_at: zone_policy_date_get_epoch (activate_epoch) returned an error: %r", ret);
2133         zone_policy_key_suite_unmark_processed(cmd->parameters.generate_key.zone_desc, cmd->parameters.generate_key.suite);
2134         dnssec_policy_key_suite_release(cmd->parameters.generate_key.suite);
2135         cmd->parameters.generate_key.suite = NULL;
2136         dnssec_policy_queue_delete_command(cmd);
2137         return ret;
2138     }
2139 
2140     if(FAIL(ret = zone_policy_date_get_epoch(&tbl.inactive, &deactivate_epoch))) // note: deactivate should be of type ZONE_POLICY_ABSOLUTE
2141     {
2142         log_err("dnssec_policy_queue_add_generate_key_create_at: zone_policy_date_get_epoch (deactivate_epoch) returned an error: %r", ret);
2143         zone_policy_key_suite_unmark_processed(cmd->parameters.generate_key.zone_desc, cmd->parameters.generate_key.suite);
2144         dnssec_policy_key_suite_release(cmd->parameters.generate_key.suite);
2145         cmd->parameters.generate_key.suite = NULL;
2146         dnssec_policy_queue_delete_command(cmd);
2147         return ret;
2148     }
2149 
2150     if(FAIL(ret = zone_policy_date_get_epoch(&tbl.delete, &unpublish_epoch))) // note: unpublish should be of type ZONE_POLICY_ABSOLUTE
2151     {
2152         log_err("dnssec_policy_queue_add_generate_key_create_at: zone_policy_date_get_epoch (unpublish_epoch) returned an error: %r", ret);
2153         zone_policy_key_suite_unmark_processed(cmd->parameters.generate_key.zone_desc, cmd->parameters.generate_key.suite);
2154         dnssec_policy_key_suite_release(cmd->parameters.generate_key.suite);
2155         cmd->parameters.generate_key.suite = NULL;
2156         dnssec_policy_queue_delete_command(cmd);
2157         return ret;
2158     }
2159 
2160     dnssec_key *key;
2161     ret = dnssec_keystore_new_key(cmd->parameters.generate_key.suite->key->algorithm,
2162                                   cmd->parameters.generate_key.suite->key->size,
2163                                   cmd->parameters.generate_key.suite->key->flags|DNSKEY_FLAGS_ZSK,
2164                                   domain,
2165                                   &key);
2166 
2167     if(ISOK(ret))
2168     {
2169         key->epoch_created = created_epoch;
2170         key->epoch_publish = publish_epoch;
2171         key->epoch_activate = activate_epoch;
2172         key->epoch_inactive = deactivate_epoch;
2173         key->epoch_delete = unpublish_epoch;
2174 
2175         key->status |= DNSKEY_KEY_HAS_SMART_FIELD_CREATED|DNSKEY_KEY_HAS_SMART_FIELD_PUBLISH|DNSKEY_KEY_HAS_SMART_FIELD_DELETE|DNSKEY_KEY_HAS_SMART_FIELD_ACTIVATE|DNSKEY_KEY_HAS_SMART_FIELD_INACTIVE;
2176 
2177         dnssec_keystore_store_private_key(key);
2178         dnssec_keystore_store_public_key(key);
2179 
2180         log_info("dnssec-policy: %{dnsname}: key K%{dnsname}+%03d+%05d/%d generated from %T: created at %T, publish at %T, activate at %T, inactive at %T, delete at %T",
2181                  cmd->origin, cmd->origin, key->algorithm, dnskey_get_tag(key), ntohs(key->flags), cmd->epoch,
2182                  key->epoch_created, key->epoch_publish, key->epoch_activate, key->epoch_inactive, key->epoch_delete
2183         );
2184 
2185 #if HAS_EVENT_DYNAMIC_MODULE
2186         if(dynamic_module_dnskey_interface_chain_available())
2187         {
2188             dynamic_module_on_dnskey_created(key);
2189         }
2190 #endif
2191         zdb_zone* zone = zdb_acquire_zone_read_from_fqdn(g_config->database, cmd->origin);
2192         if(zone != NULL)
2193         {
2194             database_service_zone_dnskey_set_alarms(zone);
2195             zdb_zone_release(zone);
2196         }
2197 
2198         zone_desc_s *zone_desc = cmd->parameters.generate_key.zone_desc;
2199         dnssec_policy_key_suite *kr = cmd->parameters.generate_key.suite;
2200 
2201         if(kr->roll->time_table.created.type.type == ZONE_POLICY_RELATIVE)
2202         {
2203             if(FAIL(ret = dnssec_policy_queue_add_generate_key_create_at(zone_desc, kr, key->epoch_created)))
2204             {
2205                 log_err("dnssec-policy: %{dnsname}: %s: failed to setup key generation from previous key: %r", zone_origin(zone_desc), kr->name, ret);
2206             }
2207         }
2208         else if(kr->roll->time_table.created.type.type == ZONE_POLICY_RULE)
2209         {
2210             if(FAIL(ret = dnssec_policy_queue_add_generate_key_active_at(zone_desc, kr, key->epoch_inactive, NULL)))
2211             {
2212                 log_err("dnssec-policy: %{dnsname}: %s: failed to setup key generation from previous end period: %r", zone_origin(zone_desc), kr->name, ret);
2213             }
2214         }
2215 
2216         dnskey_release(key);
2217     }
2218     else
2219     {
2220         log_err("dnssec-policy: %{dnsname}: failed to generate key: %r This is likely to break the policy maintenance state for the zone.", cmd->origin, ret);
2221     }
2222 
2223     zone_policy_key_suite_unmark_processed(cmd->parameters.generate_key.zone_desc, cmd->parameters.generate_key.suite);
2224 
2225     dnssec_policy_key_suite_release(cmd->parameters.generate_key.suite);
2226     cmd->parameters.generate_key.suite = NULL;
2227 
2228     dnssec_policy_queue_delete_command(cmd);
2229 
2230     return ret;
2231 }
2232 
2233 static ya_result
dnssec_policy_alarm_handler(void * args,bool cancel)2234 dnssec_policy_alarm_handler(void *args, bool cancel)
2235 {
2236     dnssec_policy_queue *cmd = (dnssec_policy_queue*)args;
2237 
2238 #if DEBUG
2239     log_debug("dnssec-policy: alarm(%p,%i)", cmd, cancel);
2240 #endif
2241 
2242     if(cancel)
2243     {
2244         dnssec_policy_queue_remove_command(cmd);
2245         dnssec_policy_queue_delete_command(cmd);
2246         return SUCCESS;
2247     }
2248 
2249     dnssec_policy_command_queue(cmd);
2250 
2251     return SUCCESS;
2252 }
2253 
2254 static void
zone_policy_nsec_enable(zdb_zone * zone)2255 zone_policy_nsec_enable(zdb_zone *zone)
2256 {
2257     //zdb_zone_double_lock();
2258     zdb_zone_double_lock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_DYNUPDATE);
2259     zdb_rr_label_flag_or(zone->apex, ZDB_RR_LABEL_NSEC);
2260     if(zdb_rr_label_has_rrset(zone->apex, TYPE_DNSKEY))
2261     {
2262         nsec_zone_set_status(zone, ZDB_ZONE_MUTEX_DYNUPDATE, NSEC_ZONE_ENABLED|NSEC_ZONE_GENERATING);
2263     }
2264     zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_DYNUPDATE);
2265 }
2266 
2267 static void
zone_policy_nsec3_enable(zdb_zone * zone,dnssec_denial * denial)2268 zone_policy_nsec3_enable(zdb_zone *zone, dnssec_denial *denial)
2269 {
2270     u8 *salt;
2271     u8 salt_len;
2272     u8 salt_buffer[256];
2273 
2274     if(denial->salt != NULL)
2275     {
2276         salt = denial->salt;
2277         salt_len = denial->salt_length;
2278     }
2279     else
2280     {
2281         random_ctx rnd = random_init_auto();
2282 
2283         salt = &salt_buffer[0];
2284         salt_len = denial->salt_length;
2285         for(int i = 0; i < salt_len; ++i)
2286         {
2287             salt[i] = random_next(rnd);
2288         }
2289 
2290         random_finalize(rnd);
2291     }
2292 
2293     u8 flags = (denial->optout)?1:0;
2294     u8 current_status = 0;
2295 
2296     zdb_zone_lock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER);
2297 
2298     if(zdb_rr_label_has_rrset(zone->apex, TYPE_DNSKEY))
2299     {
2300         ya_result got_status = nsec3_zone_get_status(zone, denial->algorithm, flags, denial->iterations, salt, salt_len, &current_status);
2301         zdb_zone_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER);
2302         if(got_status == 1)
2303         {
2304             if(current_status & NSEC3_ZONE_ENABLED)
2305             {
2306                 return;
2307             }
2308         }
2309         zdb_zone_double_lock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_DYNUPDATE);
2310         nsec3_zone_set_status(zone, ZDB_ZONE_MUTEX_DYNUPDATE, denial->algorithm, flags, denial->iterations, salt, salt_len, NSEC3_ZONE_ENABLED|NSEC3_ZONE_GENERATING);
2311         zdb_zone_double_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER, ZDB_ZONE_MUTEX_DYNUPDATE);
2312     }
2313     else
2314     {
2315         zdb_zone_unlock(zone, ZDB_ZONE_MUTEX_SIMPLEREADER);
2316     }
2317 }
2318 
2319 ya_result
zone_policy_roll_create_from_rules(const char * id,const zone_policy_rule_definition_s * generate,const zone_policy_rule_definition_s * publish,const zone_policy_rule_definition_s * activate,const zone_policy_rule_definition_s * inactive,const zone_policy_rule_definition_s * remove,const zone_policy_rule_definition_s * ds_publish,const zone_policy_rule_definition_s * ds_remove)2320 zone_policy_roll_create_from_rules(const char *id,
2321                                    const zone_policy_rule_definition_s *generate,
2322                                    const zone_policy_rule_definition_s *publish,
2323                                    const zone_policy_rule_definition_s *activate,
2324                                    const zone_policy_rule_definition_s *inactive,
2325                                    const zone_policy_rule_definition_s *remove,
2326                                    const zone_policy_rule_definition_s *ds_publish,
2327                                    const zone_policy_rule_definition_s *ds_remove)
2328 {
2329     log_debug("dnssec-policy-roll: %s: (rules stuff)", id);
2330 
2331     dnssec_policy_roll *dpr;
2332     ZALLOC_OBJECT_OR_DIE( dpr, dnssec_policy_roll, DPOLROLL_TAG);
2333     dpr->name = strdup(id);
2334 
2335     group_mutex_write_lock(&dnssec_policy_roll_set_mtx);
2336     ptr_node *node = ptr_set_insert(&dnssec_policy_roll_set, dpr->name);
2337 
2338     if(node->value != NULL)
2339     {
2340         dnssec_policy_roll_release((dnssec_policy_roll*)node->value);
2341         node->key = dpr->name;
2342     }
2343 
2344     zone_policy_rule_init(&dpr->time_table.created.rule, generate);
2345     zone_policy_rule_init(&dpr->time_table.publish.rule, publish);
2346     zone_policy_rule_init(&dpr->time_table.activate.rule, activate);
2347     zone_policy_rule_init(&dpr->time_table.inactive.rule, inactive);
2348     zone_policy_rule_init(&dpr->time_table.delete.rule, remove);
2349 #if HAS_DS_PUBLICATION_SUPPORT
2350     zone_policy_rule_init(&dpr->time_table.ds_add.rule, ds_publish);
2351     zone_policy_rule_init(&dpr->time_table.ds_del.rule, ds_remove);
2352 #else
2353     (void)ds_publish;
2354     (void)ds_remove;
2355 #endif
2356     dpr->rc = 1;
2357     node->value = dpr;
2358 
2359     group_mutex_write_unlock(&dnssec_policy_roll_set_mtx);
2360     return 0;
2361 }
2362 
2363 ya_result
zone_policy_roll_create_from_relatives(const char * id,const zone_policy_relative_s * generate,u8 generate_from,const zone_policy_relative_s * publish,u8 publish_from,const zone_policy_relative_s * activate,u8 activate_from,const zone_policy_relative_s * inactive,u8 inactive_from,const zone_policy_relative_s * remove,u8 remove_from,const zone_policy_relative_s * ds_publish,u8 ds_publish_from,const zone_policy_relative_s * ds_remove,u8 ds_remove_from)2364 zone_policy_roll_create_from_relatives(const char *id,
2365                                        const zone_policy_relative_s *generate,
2366                                        u8 generate_from,
2367                                        const zone_policy_relative_s *publish,
2368                                        u8 publish_from,
2369                                        const zone_policy_relative_s *activate,
2370                                        u8 activate_from,
2371                                        const zone_policy_relative_s *inactive,
2372                                        u8 inactive_from,
2373                                        const zone_policy_relative_s *remove,
2374                                        u8 remove_from
2375 #if HAS_DS_PUBLICATION_SUPPORT
2376                                        ,
2377                                        const zone_policy_relative_s *ds_publish,
2378                                        u8 ds_publish_from,
2379                                        const zone_policy_relative_s *ds_remove,
2380                                        u8 ds_remove_from
2381 #endif
2382                                        )
2383 {
2384     log_debug("dnssec-policy-roll: %s: (relative stuff)", id);
2385 
2386     if(generate->seconds < 60)
2387     {
2388         log_err("dnssec-policy: %s: generate parameter cannot be less than one minute", id);
2389         return POLICY_ILLEGAL_DATE_PARAMETERS;
2390     }
2391 
2392     if(inactive->seconds - activate->seconds < 60)
2393     {
2394         log_err("dnssec-policy: %s: key appears to not be activated for even one minute", id);
2395         return POLICY_ILLEGAL_DATE_PARAMETERS;
2396     }
2397 
2398     if(generate->seconds < 3600)
2399     {
2400         log_warn("dnssec-policy: %s: key is generated every %i seconds.  Keys are expected to be generated every few weeks, months or years.", id, generate->seconds);
2401     }
2402 
2403     if(inactive->seconds - activate->seconds < generate->seconds)
2404     {
2405         log_warn("dnssec-policy: %s: key appears to not be activated for less time than the generation period", id);
2406     }
2407 
2408     dnssec_policy_roll *dpr;
2409     ZALLOC_OBJECT_OR_DIE( dpr, dnssec_policy_roll, DPOLROLL_TAG);
2410     dpr->name = strdup(id);
2411 
2412     group_mutex_write_lock(&dnssec_policy_roll_set_mtx);
2413     ptr_node *node = ptr_set_insert(&dnssec_policy_roll_set, dpr->name);
2414 
2415     if(node->value != NULL)
2416     {
2417         dnssec_policy_roll_release((dnssec_policy_roll*)node->value);
2418         node->value = NULL;
2419     }
2420 
2421     dpr->time_table.created.relative = *generate;
2422     dpr->time_table.publish.relative = *publish;
2423     dpr->time_table.activate.relative = *activate;
2424     dpr->time_table.inactive.relative = *inactive;
2425     dpr->time_table.delete.relative = *remove;
2426 
2427     dpr->time_table.created.relative.seconds += 59;
2428     dpr->time_table.created.relative.seconds -= (dpr->time_table.created.relative.seconds % 60);
2429 
2430     dpr->time_table.publish.relative.seconds += 59;
2431     dpr->time_table.publish.relative.seconds -= (dpr->time_table.publish.relative.seconds % 60);
2432 
2433     dpr->time_table.activate.relative.seconds += 59;
2434     dpr->time_table.activate.relative.seconds -= (dpr->time_table.activate.relative.seconds % 60);
2435 
2436     dpr->time_table.inactive.relative.seconds += 59;
2437     dpr->time_table.inactive.relative.seconds -= (dpr->time_table.inactive.relative.seconds % 60);
2438 
2439     dpr->time_table.delete.relative.seconds += 59;
2440     dpr->time_table.delete.relative.seconds -= (dpr->time_table.delete.relative.seconds % 60);
2441 
2442 #if HAS_DS_PUBLICATION_SUPPORT
2443     dpr->time_table.ds_add.relative = *ds_publish;
2444     dpr->time_table.ds_del.relative = *ds_remove;
2445 #endif
2446 
2447     yassert(publish_from <= ZONE_POLICY_RELATIVE_TO_GENERATE);
2448     yassert(activate_from <= ZONE_POLICY_RELATIVE_TO_PUBLISH);
2449     yassert(inactive_from <= ZONE_POLICY_RELATIVE_TO_INACTIVE);
2450     yassert(remove_from <= ZONE_POLICY_RELATIVE_TO_REMOVE);
2451 #if HAS_DS_PUBLICATION_SUPPORT
2452     yassert(ds_publish_from <= ZONE_POLICY_RELATIVE_TO_DS_PUBLISH);
2453     yassert(ds_remove_from <= ZONE_POLICY_RELATIVE_TO_DS_REMOVE);
2454 #endif
2455 
2456     dpr->time_table.created.relative.relativeto = generate_from;
2457     dpr->time_table.publish.relative.relativeto = publish_from;
2458     dpr->time_table.activate.relative.relativeto = activate_from;
2459     dpr->time_table.inactive.relative.relativeto = inactive_from;
2460     dpr->time_table.delete.relative.relativeto = remove_from;
2461 #if HAS_DS_PUBLICATION_SUPPORT
2462     dpr->time_table.ds_add.relative.relativeto = ds_publish_from;
2463     dpr->time_table.ds_del.relative.relativeto = ds_remove_from;
2464 #endif
2465 
2466     dpr->rc = 1;
2467     node->key = dpr->name;
2468     node->value = dpr;
2469 
2470     group_mutex_write_unlock(&dnssec_policy_roll_set_mtx);
2471 
2472     return 0;
2473 }
2474 
2475 dnssec_policy_roll *
dnssec_policy_roll_acquire_from_name(const char * id)2476 dnssec_policy_roll_acquire_from_name(const char *id)
2477 {
2478     dnssec_policy_roll *dpr = NULL;
2479 
2480     group_mutex_read_lock(&dnssec_policy_roll_set_mtx);
2481 
2482     ptr_node *node = ptr_set_find(&dnssec_policy_roll_set, id);
2483     if(node != NULL)
2484     {
2485         dpr = (dnssec_policy_roll*)node->value;
2486         group_mutex_write_lock(&dnssec_policy_roll_mtx);
2487         ++dpr->rc;
2488         group_mutex_write_unlock(&dnssec_policy_roll_mtx);
2489     }
2490 
2491     group_mutex_read_unlock(&dnssec_policy_roll_set_mtx);
2492 
2493     return dpr;
2494 }
2495 
2496 ya_result
dnssec_policy_roll_test_all(time_t active_at,u32 duration_seconds,bool print_text,bool log_text)2497 dnssec_policy_roll_test_all(time_t active_at, u32 duration_seconds, bool print_text, bool log_text)
2498 {
2499     ya_result ret = SUCCESS;
2500 
2501     group_mutex_read_lock(&dnssec_policy_roll_set_mtx);
2502 
2503     ptr_set_iterator iter;
2504     ptr_set_iterator_init(&dnssec_policy_roll_set, &iter);
2505     while(ptr_set_iterator_hasnext(&iter))
2506     {
2507         ptr_node *node = ptr_set_iterator_next_node(&iter);
2508         if(node->value != NULL)
2509         {
2510             dnssec_policy_roll *dpr = (dnssec_policy_roll*)node->value;
2511             if(FAIL(ret = dnssec_policy_roll_test(dpr, active_at, duration_seconds, print_text, log_text)))
2512             {
2513                 break;
2514             }
2515         }
2516     }
2517 
2518     group_mutex_read_unlock(&dnssec_policy_roll_set_mtx);
2519 
2520     return ret;
2521 }
2522 
2523 dnssec_policy_roll *
dnssec_policy_roll_acquire_from_index(int index)2524 dnssec_policy_roll_acquire_from_index(int index)
2525 {
2526     dnssec_policy_roll *dpr = NULL;
2527 
2528     if(index >= 0)
2529     {
2530         group_mutex_read_lock(&dnssec_policy_roll_set_mtx);
2531 
2532         ptr_set_iterator iter;
2533         ptr_set_iterator_init(&dnssec_policy_roll_set, &iter);
2534         while(ptr_set_iterator_hasnext(&iter))
2535         {
2536             ptr_node *node = ptr_set_iterator_next_node(&iter);
2537             if(index == 0)
2538             {
2539                 if(node->value != NULL)
2540                 {
2541                     dpr = (dnssec_policy_roll*)node->value;
2542                     group_mutex_write_lock(&dnssec_policy_roll_mtx);
2543                     ++dpr->rc;
2544                     group_mutex_write_unlock(&dnssec_policy_roll_mtx);
2545                 }
2546 
2547                 break;
2548             }
2549 
2550             --index;
2551         }
2552 
2553         group_mutex_read_unlock(&dnssec_policy_roll_set_mtx);
2554     }
2555 
2556     return dpr;
2557 }
2558 
2559 
2560 void
dnssec_policy_roll_release(dnssec_policy_roll * dpr)2561 dnssec_policy_roll_release(dnssec_policy_roll *dpr)
2562 {
2563     group_mutex_write_lock(&dnssec_policy_roll_mtx);
2564     if(--dpr->rc == 0)
2565     {
2566         // destroy the table
2567         if(dpr->time_table.created.type.type == ZONE_POLICY_RULE)
2568         {
2569             zone_policy_rule_finalize(&dpr->time_table.created.rule);
2570         }
2571         if(dpr->time_table.publish.type.type == ZONE_POLICY_RULE)
2572         {
2573             zone_policy_rule_finalize(&dpr->time_table.publish.rule);
2574         }
2575         if(dpr->time_table.activate.type.type == ZONE_POLICY_RULE)
2576         {
2577             zone_policy_rule_finalize(&dpr->time_table.activate.rule);
2578         }
2579         if(dpr->time_table.inactive.type.type == ZONE_POLICY_RULE)
2580         {
2581             zone_policy_rule_finalize(&dpr->time_table.inactive.rule);
2582         }
2583         if(dpr->time_table.delete.type.type == ZONE_POLICY_RULE)
2584         {
2585             zone_policy_rule_finalize(&dpr->time_table.delete.rule);
2586         }
2587 #if HAS_DS_PUBLICATION_SUPPORT
2588         if(dpr->time_table.ds_add.type.type == ZONE_POLICY_RULE)
2589         {
2590             zone_policy_rule_finalize(&dpr->time_table.ds_add.rule);
2591         }
2592         if(dpr->time_table.ds_del.type.type == ZONE_POLICY_RULE)
2593         {
2594             zone_policy_rule_finalize(&dpr->time_table.ds_del.rule);
2595         }
2596 #endif
2597         free(dpr->name);
2598         ZFREE_OBJECT(dpr);
2599     }
2600     group_mutex_write_unlock(&dnssec_policy_roll_mtx);
2601 }
2602 
2603 dnssec_denial *
dnssec_policy_denial_create(const char * id,u8 algorithm,u16 iterations,const u8 * salt,u8 salt_length,u32 resalting,bool optout)2604 dnssec_policy_denial_create(const char *id, u8 algorithm, u16 iterations, const u8 *salt, u8 salt_length, u32 resalting, bool optout)
2605 {
2606     log_debug("dnssec-policy-denial: %s: algorithm=%hhu, iterations=%hu, salt@%p, salt_length=%hhu, resalting=%u",
2607             id, algorithm, iterations, salt, salt_length, resalting);
2608 
2609     dnssec_denial *dd = NULL;
2610     ZALLOC_OBJECT_OR_DIE( dd, dnssec_denial, DPOLDNIL_TAG);
2611     dd->name = strdup(id);
2612     if(salt != NULL && salt_length > 0)
2613     {
2614         ZALLOC_ARRAY_OR_DIE(u8*, dd->salt, salt_length, DPOLSALT_TAG);
2615         memcpy(dd->salt, salt, salt_length);
2616     }
2617     else
2618     {
2619         dd->salt = NULL;
2620     }
2621 
2622     dd->resalting = resalting;
2623     dd->iterations = iterations;
2624     dd->algorithm = algorithm;
2625     dd->salt_length = salt_length;
2626     dd->optout = optout;
2627     dd->rc = 1;
2628 
2629     group_mutex_write_lock(&dnssec_denial_set_mtx);
2630     ptr_node *node = ptr_set_insert(&dnssec_denial_set, dd->name);
2631     if(node->value != NULL)
2632     {
2633         dnssec_policy_denial_release((dnssec_denial*)node->value);
2634     }
2635     node->key = dd->name;
2636     node->value = dd;
2637     group_mutex_write_unlock(&dnssec_denial_set_mtx);
2638 
2639     return dd;
2640 }
2641 
2642 
2643 dnssec_denial *
dnssec_policy_denial_acquire(const char * id)2644 dnssec_policy_denial_acquire(const char *id)
2645 {
2646     dnssec_denial *dd = NULL;
2647     group_mutex_read_lock(&dnssec_denial_set_mtx);
2648     ptr_node *node = ptr_set_find(&dnssec_denial_set, id);
2649     if(node != NULL && node->value != NULL)
2650     {
2651         dd = (dnssec_denial*)node->value;
2652         group_mutex_write_lock(&dnssec_denial_mtx);
2653         ++dd->rc;
2654         group_mutex_write_unlock(&dnssec_denial_mtx);
2655     }
2656     group_mutex_read_unlock(&dnssec_denial_set_mtx);
2657 
2658     return dd;
2659 }
2660 
2661 void
dnssec_policy_denial_release(dnssec_denial * dd)2662 dnssec_policy_denial_release(dnssec_denial *dd)
2663 {
2664     if(dd == NULL) return;
2665 
2666     group_mutex_write_lock(&dnssec_denial_mtx);
2667     if(--dd->rc == 0)
2668     {
2669         if(dd->salt != NULL)
2670         {
2671             ZFREE_ARRAY(dd->salt, dd->salt_length);
2672         }
2673         free(dd->name);
2674         ZFREE_OBJECT(dd);
2675     }
2676     group_mutex_write_unlock(&dnssec_denial_mtx);
2677 }
2678 
2679 dnssec_policy_key *
dnssec_policy_key_create(const char * id,u8 algorithm,u16 size,bool ksk,char * engine)2680 dnssec_policy_key_create(const char *id, u8 algorithm, u16 size, bool ksk, char* engine)
2681 {
2682     log_debug("dnssec-policy-key: %s: algorithm=%hhu, size=%hu, ksk=%i, engine=%s",
2683             id, algorithm, size, ksk, STRNULL(engine));
2684 
2685     (void)engine;
2686     dnssec_policy_key *dpk = NULL;
2687 
2688     ZALLOC_OBJECT_OR_DIE( dpk, dnssec_policy_key, DPOLKEY_TAG);
2689     dpk->name = strdup(id);
2690 
2691     dpk->flags = (ksk)?DNSKEY_FLAGS_KSK:DNSKEY_FLAGS_ZSK;
2692     dpk->size = size;
2693     dpk->algorithm = algorithm;
2694     dpk->rc = 1;
2695 
2696     group_mutex_write_lock(&dnssec_policy_key_set_mtx);
2697     ptr_node *node = ptr_set_insert(&dnssec_policy_key_set, dpk->name);
2698     if(node->value != NULL)
2699     {
2700         dnssec_policy_key_release((dnssec_policy_key*)node->value);
2701         node->key = dpk->name;
2702     }
2703     node->value = dpk;
2704     group_mutex_write_unlock(&dnssec_policy_key_set_mtx);
2705 
2706     return dpk;
2707 }
2708 
2709 dnssec_policy_key *
dnssec_policy_key_acquire_from_name(const char * id)2710 dnssec_policy_key_acquire_from_name(const char *id)
2711 {
2712     dnssec_policy_key *dpk = NULL;
2713 
2714     group_mutex_read_lock(&dnssec_policy_key_set_mtx);
2715     ptr_node *node = ptr_set_find(&dnssec_policy_key_set, id);
2716     if(node != NULL && node->value != NULL)
2717     {
2718         dpk = (dnssec_policy_key*)node->value;
2719         group_mutex_write_lock(&dnssec_policy_key_mtx);
2720         ++dpk->rc;
2721         group_mutex_write_unlock(&dnssec_policy_key_mtx);
2722     }
2723     group_mutex_read_unlock(&dnssec_policy_key_set_mtx);
2724     return dpk;
2725 }
2726 
2727 void
dnssec_policy_key_release(dnssec_policy_key * dpk)2728 dnssec_policy_key_release(dnssec_policy_key *dpk)
2729 {
2730     group_mutex_write_lock(&dnssec_policy_key_mtx);
2731     if(--dpk->rc == 0)
2732     {
2733         free(dpk->name);
2734         ZFREE_OBJECT(dpk);
2735     }
2736     group_mutex_write_unlock(&dnssec_policy_key_mtx);
2737 }
2738 
2739 dnssec_policy_key_suite *
dnssec_policy_key_suite_create(const char * id,dnssec_policy_key * dpk,dnssec_policy_roll * dpr)2740 dnssec_policy_key_suite_create(const char *id, dnssec_policy_key *dpk, dnssec_policy_roll *dpr)
2741 {
2742     log_debug("dnssec-policy-key-suite: %s: policy-key=%s, policy-roll=%s", id, dpk->name, dpr->name);
2743 
2744     dnssec_policy_key_suite *dpks = NULL;
2745 
2746     ZALLOC_OBJECT_OR_DIE( dpks, dnssec_policy_key_suite, DPOLKYST_TAG);
2747     dpks->name = strdup(id);
2748     dpks->key = dnssec_policy_key_acquire_from_name(dpk->name);
2749     dpks->roll = dnssec_policy_roll_acquire_from_name(dpr->name);
2750     dpks->rc = 1;
2751 
2752     group_mutex_write_lock(&dnssec_policy_key_suite_set_mtx);
2753     ptr_node *node = ptr_set_insert(&dnssec_policy_key_suite_set, dpks->name);
2754     if(node->value != NULL)
2755     {
2756         dnssec_policy_key_suite_release((dnssec_policy_key_suite*)node->value);
2757     }
2758     node->key = dpks->name;
2759     node->value = dpks;
2760     group_mutex_write_unlock(&dnssec_policy_key_suite_set_mtx);
2761 
2762     return dpks;
2763 }
2764 
2765 dnssec_policy_key_suite *
dnssec_policy_key_suite_acquire_from_name(const char * id)2766 dnssec_policy_key_suite_acquire_from_name(const char *id)
2767 {
2768     dnssec_policy_key_suite *dpks = NULL;
2769 
2770     group_mutex_read_lock(&dnssec_policy_key_suite_set_mtx);
2771     ptr_node *node = ptr_set_find(&dnssec_policy_key_suite_set, id);
2772     if(node != NULL && node->value != NULL)
2773     {
2774         dpks = (dnssec_policy_key_suite*)node->value;
2775         group_mutex_write_lock(&dnssec_policy_key_suite_mtx);
2776         ++dpks->rc;
2777         group_mutex_write_unlock(&dnssec_policy_key_suite_mtx);
2778     }
2779     group_mutex_read_unlock(&dnssec_policy_key_suite_set_mtx);
2780     return dpks;
2781 }
2782 
2783 void
dnssec_policy_key_suite_acquire(dnssec_policy_key_suite * dpks)2784 dnssec_policy_key_suite_acquire(dnssec_policy_key_suite *dpks)
2785 {
2786     group_mutex_write_lock(&dnssec_policy_key_suite_mtx);
2787     ++dpks->rc;
2788     group_mutex_write_unlock(&dnssec_policy_key_suite_mtx);
2789 }
2790 
2791 
2792 void
dnssec_policy_key_suite_release(dnssec_policy_key_suite * dpks)2793 dnssec_policy_key_suite_release(dnssec_policy_key_suite *dpks)
2794 {
2795     group_mutex_write_lock(&dnssec_policy_key_suite_mtx);
2796     if(--dpks->rc == 0)
2797     {
2798         free(dpks->name);
2799         dnssec_policy_key_release(dpks->key);
2800         dnssec_policy_roll_release(dpks->roll);
2801         ZFREE_OBJECT(dpks);
2802     }
2803     group_mutex_write_unlock(&dnssec_policy_key_suite_mtx);
2804 }
2805 
2806 dnssec_policy *
dnssec_policy_create(char * name,dnssec_denial * dd,ptr_vector * key_suite)2807 dnssec_policy_create(char *name, dnssec_denial *dd, ptr_vector *key_suite)
2808 {
2809     dnssec_policy *dp = NULL;
2810 
2811     log_debug("dnssec-policy: %s: denial=%s", name, (dd!=NULL)?dd->name:"nsec");
2812     bool has_zsk = FALSE;
2813     ZALLOC_OBJECT_OR_DIE( dp, dnssec_policy, DNSECPOL_TAG);
2814     dp->name = strdup(name);
2815     dp->denial= (dd!=NULL)?dnssec_policy_denial_acquire(dd->name):NULL;
2816     ptr_vector_init_ex(&dp->key_suite, ptr_vector_size(key_suite));
2817     for(int i = 0; i <= ptr_vector_last_index(key_suite); ++i)
2818     {
2819         dnssec_policy_key_suite *dpks = (dnssec_policy_key_suite*)ptr_vector_get(key_suite, i);
2820         if((dpks->key->flags & DNSKEY_FLAGS_KSK) != DNSKEY_FLAGS_KSK)
2821         {
2822             has_zsk = TRUE;
2823         }
2824 
2825         dnssec_policy_key_suite *dpks_a = dnssec_policy_key_suite_acquire_from_name(dpks->name);
2826 
2827         for(int j = 0; j <= ptr_vector_last_index(&dp->key_suite); ++j)
2828         {
2829             dnssec_policy_key_suite* dpks_b = (dnssec_policy_key_suite*)ptr_vector_get(&dp->key_suite, j);
2830             if(dpks_a == dpks_b)
2831             {
2832                 // dup
2833                 log_warn("dnssec-policy: %s: key-suite %s is a duplicate entry", name, dpks->name);
2834                 dnssec_policy_key_suite_release(dpks_a);
2835                 dpks_a = NULL;
2836                 break;
2837             }
2838         }
2839 
2840         if(dpks_a != NULL)
2841         {
2842             ptr_vector_append(&dp->key_suite, dpks_a);
2843             log_debug("dnssec-policy: %s: key-suite %s added", name, dpks->name);
2844         }
2845     }
2846     dp->rc = 1;
2847 
2848     if(has_zsk)
2849     {
2850         log_warn("dnssec-policy: %s: no key-signing-key in the key-suite", name);
2851     }
2852 
2853     group_mutex_write_lock(&dnssec_policy_set_mtx);
2854     ptr_node *node = ptr_set_insert(&dnssec_policy_set, dp->name);
2855     if(node->value != NULL)
2856     {
2857         dnssec_policy_release((dnssec_policy*)node->value);
2858         node->key = dp->name;
2859     }
2860     node->value = dp;
2861     group_mutex_write_unlock(&dnssec_policy_set_mtx);
2862 
2863     return dp;
2864 }
2865 
2866 dnssec_policy *
dnssec_policy_acquire_from_name(const char * id)2867 dnssec_policy_acquire_from_name(const char *id)
2868 {
2869     dnssec_policy *dp = NULL;
2870 
2871     group_mutex_read_lock(&dnssec_policy_set_mtx);
2872     ptr_node *node = ptr_set_find(&dnssec_policy_set, id);
2873     if(node != NULL && node->value != NULL)
2874     {
2875         dp = (dnssec_policy*)node->value;
2876         group_mutex_write_lock(&dnssec_policy_mtx);
2877         ++dp->rc;
2878         group_mutex_write_unlock(&dnssec_policy_mtx);
2879     }
2880     group_mutex_read_unlock(&dnssec_policy_set_mtx);
2881     return dp;
2882 }
2883 
2884 void
dnssec_policy_acquire(dnssec_policy * dp)2885 dnssec_policy_acquire(dnssec_policy *dp)
2886 {
2887     group_mutex_write_lock(&dnssec_policy_mtx);
2888     ++dp->rc;
2889     group_mutex_write_unlock(&dnssec_policy_mtx);
2890 }
2891 
2892 void
dnssec_policy_release(dnssec_policy * dp)2893 dnssec_policy_release(dnssec_policy *dp)
2894 {
2895     group_mutex_write_lock(&dnssec_policy_mtx);
2896     if(--dp->rc == 0)
2897     {
2898         free(dp->name);
2899         dnssec_policy_denial_release(dp->denial);
2900         for(int i = 0; i <= ptr_vector_last_index(&dp->key_suite); ++i)
2901         {
2902             dnssec_policy_key_suite *dpks = (dnssec_policy_key_suite*)ptr_vector_get(&dp->key_suite, i);
2903             dnssec_policy_key_suite_release(dpks);
2904         }
2905         ptr_vector_destroy(&dp->key_suite);
2906         ZFREE_OBJECT(dp);
2907     }
2908     group_mutex_write_unlock(&dnssec_policy_mtx);
2909 }
2910 
2911 ya_result
dnssec_policy_zone_desc_config(const char * value,void * dest,anytype sizeoftarget)2912 dnssec_policy_zone_desc_config(const char *value, void *dest, anytype sizeoftarget)
2913 {
2914     (void)sizeoftarget;
2915     dnssec_policy **dp = (dnssec_policy**)dest;
2916     if(*dp != NULL)
2917     {
2918         dnssec_policy_release(*dp);
2919     }
2920     if(value != NULL)
2921     {
2922         *dp = dnssec_policy_acquire_from_name(value);
2923         return (*dp != NULL)?SUCCESS:POLICY_UNDEFINED;
2924     }
2925     else
2926     {
2927         return POLICY_NULL_REQUESTED;
2928     }
2929 }
2930 
2931 static void
zone_policy_process_release_keys_cb(void * ptr)2932 zone_policy_process_release_keys_cb(void *ptr)
2933 {
2934     dnssec_key *key = (dnssec_key*)ptr;
2935     if(key != NULL)
2936     {
2937         dnskey_release(key);
2938     }
2939 }
2940 
2941 ////////////////////////////////////////////////////////////////////////////////////////////////
2942 //
2943 // This is where yadifad and the keyroll fundamentally differs
2944 //
2945 ////////////////////////////////////////////////////////////////////////////////////////////////
2946 
2947 /**
2948  * Sets the DNSSEC mode of the zone using the policy.
2949  */
2950 
2951 ya_result
zone_policy_process_dnssec_chain(zone_desc_s * zone_desc)2952 zone_policy_process_dnssec_chain(zone_desc_s *zone_desc)
2953 {
2954     zdb_zone *zone = zone_desc->loaded_zone;
2955 
2956     if(zone == NULL)
2957     {
2958         return INVALID_STATE_ERROR;
2959     }
2960 
2961     const dnssec_policy *policy = zone_desc->dnssec_policy;
2962 
2963     if(policy == NULL)
2964     {
2965         return SUCCESS; // nothing to do
2966     }
2967 
2968     u8 zone_dnssec_type = zone_policy_guess_dnssec_type(zone);
2969 
2970     if(policy->denial == NULL)
2971     {
2972         // zone is expected to be NSEC
2973 
2974         zone_set_maintain_mode(zone, ZDB_ZONE_MAINTAIN_NSEC);
2975 
2976         switch(zone_dnssec_type)
2977         {
2978             case ZONE_DNSSEC_FL_NOSEC:
2979             {
2980                 // generate NSEC now
2981                 log_info("dnssec-policy: %{dnsname}: zone will be secured with NSEC", zone_origin(zone_desc));
2982                 zone_policy_nsec_enable(zone);
2983                 break;
2984             }
2985             case ZONE_DNSSEC_FL_NSEC:
2986             {
2987                 // do nothing
2988                 if((zone->nsec.nsec->children.lr.right == NULL) && (zone->nsec.nsec->children.lr.left == NULL))
2989                 {
2990                     log_info("dnssec-policy: %{dnsname}: zone is NSEC, chain is probably incomplete", zone_origin(zone_desc));
2991                     zone_policy_nsec_enable(zone);
2992                 }
2993                 else
2994                 {
2995                     log_info("dnssec-policy: %{dnsname}: zone is NSEC", zone_origin(zone_desc));
2996                 }
2997                 break;
2998             }
2999             case ZONE_DNSSEC_FL_NSEC3:
3000             case ZONE_DNSSEC_FL_NSEC3_OPTOUT:
3001             {
3002                 log_warn("dnssec-policy: %{dnsname}: zone is secured by NSEC3 but policy is made for NSEC", zone_origin(zone_desc));
3003                 break;
3004             }
3005         }
3006     }
3007     else
3008     {
3009         if(policy->denial->optout)
3010         {
3011             zone_set_maintain_mode(zone, ZDB_ZONE_MAINTAIN_NSEC3_OPTOUT);
3012         }
3013         else
3014         {
3015             zone_set_maintain_mode(zone, ZDB_ZONE_MAINTAIN_NSEC3);
3016         }
3017 
3018         // zone is expected to be NSEC3
3019         switch(zone_dnssec_type)
3020         {
3021             case ZONE_DNSSEC_FL_NOSEC:
3022             {
3023                 // generate NSEC now
3024                 log_info("dnssec-policy: %{dnsname}: zone will be secured with NSEC3", zone_origin(zone_desc));
3025 
3026                 zone_policy_nsec3_enable(zone, policy->denial);
3027 
3028                 break;
3029             }
3030             case ZONE_DNSSEC_FL_NSEC:
3031             {
3032                 // do nothing
3033                 log_warn("dnssec-policy: %{dnsname}: zone is an NSEC type but policy is made for NSEC3", zone_origin(zone_desc));
3034                 break;
3035             }
3036             case ZONE_DNSSEC_FL_NSEC3:
3037             case ZONE_DNSSEC_FL_NSEC3_OPTOUT:
3038             {
3039                 if((zone->nsec.nsec3->items->children.lr.left == NULL) && (zone->nsec.nsec3->items->children.lr.right == NULL))
3040                 {
3041                     log_info("dnssec-policy: %{dnsname}: zone is NSEC3, chain is probably incomplete", zone_origin(zone_desc));
3042                     zone_policy_nsec3_enable(zone, policy->denial);
3043                 }
3044                 else
3045                 {
3046                     log_info("dnssec-policy: %{dnsname}: zone is NSEC3", zone_origin(zone_desc));
3047                 }
3048                 break;
3049             }
3050         }
3051     }
3052 
3053     return SUCCESS;
3054 }
3055 
3056 ya_result
zone_policy_process(zone_desc_s * zone_desc)3057 zone_policy_process(zone_desc_s *zone_desc)
3058 {
3059     // the policy is referenced by the zone desc
3060     // and the zone desc by the parent
3061     // no need to acquire anything here
3062 
3063     ya_result final_ret = SUCCESS;
3064     ya_result ret;
3065 
3066     dnssec_policy_initialise();
3067 
3068     log_debug("dnssec-policy: %{dnsname} process", zone_origin(zone_desc));
3069 
3070     if(zone_desc->type != ZT_MASTER)
3071     {
3072         log_debug("dnssec-policy: %{dnsname} is not a master zone", zone_origin(zone_desc));
3073 
3074         return INVALID_STATE_ERROR;   // not a master zone
3075     }
3076 
3077     const dnssec_policy *policy = zone_desc->dnssec_policy;
3078 
3079     if(policy == NULL)
3080     {
3081         log_debug("dnssec-policy: %{dnsname} has no policy", zone_origin(zone_desc));
3082 
3083         zone_lock(zone_desc, ZONE_LOCK_READONLY);
3084         zdb_zone *zone = zone_desc->loaded_zone;
3085         if(zone != NULL)
3086         {
3087             zdb_zone_acquire(zone);
3088 
3089             if(zdb_zone_isvalid(zone))
3090             {
3091                 /*
3092                 if(zone_desc->dnssec_mode != 0)
3093                 {
3094                     zdb_zone_set_maintained(zone, TRUE);
3095                     //zone_desc_dnssec_mode = zone_desc->dnssec_mode << ZDB_ZONE_DNSSEC_SHIFT;
3096                 }
3097                 */
3098             }
3099             zdb_zone_release(zone);
3100         }
3101 
3102         zone_unlock(zone_desc, ZONE_LOCK_READONLY);
3103 
3104         return SUCCESS;
3105     }
3106 
3107     // Look in the commands for a full init.  If one is present then nothing more can be done.
3108 
3109     if(dnssec_policy_queue_has_command_type(zone_origin(zone_desc), DNSSEC_POLICY_COMMAND_INIT))
3110     {
3111         log_debug("dnssec-policy: %{dnsname} is already marked for full generation", zone_origin(zone_desc));
3112         return SUCCESS;
3113     }
3114 
3115     const char *denial_name = (policy->denial == NULL)?"nsec":policy->denial->name;
3116 
3117     log_debug("dnssec-policy: %{dnsname} has policy %s/%s with %i keys", zone_origin(zone_desc), policy->name, denial_name, ptr_vector_size(&policy->key_suite));
3118 
3119     // get the current DNSSEC status of the zone
3120 
3121     zone_lock(zone_desc, ZONE_LOCK_READONLY);
3122     zdb_zone *zone = zone_desc->loaded_zone;
3123     if(zone != NULL)
3124     {
3125         zdb_zone_acquire(zone);
3126         zone_unlock(zone_desc, ZONE_LOCK_READONLY);
3127     }
3128     else
3129     {
3130         log_warn("dnssec-policy: %{dnsname}: settings are not linked to a loaded zone", zone_origin(zone_desc));
3131         zone_unlock(zone_desc, ZONE_LOCK_READONLY);
3132         return POLICY_ZONE_NOT_READY;
3133     }
3134 
3135     log_debug("dnssec-policy: %{dnsname} zone acquired", zone->origin);
3136 
3137     if(zdb_zone_isvalid(zone))
3138     {
3139         zone->sig_validity_regeneration_seconds = zone_desc->signature.sig_validity_regeneration * SIGNATURE_VALIDITY_REGENERATION_S;
3140         zone->sig_validity_interval_seconds = zone_desc->signature.sig_validity_interval * SIGNATURE_VALIDITY_INTERVAL_S;
3141         zone->sig_validity_jitter_seconds = zone_desc->signature.sig_validity_jitter * SIGNATURE_VALIDITY_JITTER_S;
3142 
3143 #if DEBUG_FORCE_INSANE_SIGNATURE_MAINTENANCE_PARAMETERS
3144         zone->sig_validity_regeneration_seconds = 90;
3145         zone->sig_validity_interval_seconds = 180;
3146         zone->sig_validity_jitter_seconds = 5;
3147 #endif
3148 
3149         zdb_zone_set_maintained(zone, TRUE);
3150 
3151         // set DNSSEC mode using the policy
3152 
3153         zone_policy_process_dnssec_chain(zone_desc);
3154     }
3155     else // zone is not valid
3156     {
3157         log_err("dnssec-policy: %{dnsname}: unable to manage DNSSEC status of invalid zone", zone_origin(zone_desc));
3158         log_debug("dnssec-policy: %{dnsname} released", zone->origin);
3159         zdb_zone_release(zone);
3160         return INVALID_STATE_ERROR;
3161     }
3162 
3163     // enumerate the available keys and if they are in the zone and being used and so on.
3164 
3165     // KEEP, IGNORE, REMOVE
3166 
3167     ptr_vector key_roll_keys[DNSSEC_POLICY_KEY_ROLL_COUNT_MAXIMUM];
3168 
3169     for(int i = 0; i < DNSSEC_POLICY_KEY_ROLL_COUNT_MAXIMUM; ++i)
3170     {
3171         ptr_vector_init_ex(&key_roll_keys[i], 0); // with an initial capacity set to 0, no allocation is made until at least one item is added
3172     }
3173 
3174     yassert(ptr_vector_size(&policy->key_suite) <= 8);
3175 
3176     for(int i = 0; ; ++i)
3177     {
3178         dnssec_key *key = dnssec_keystore_acquire_key_from_fqdn_at_index(zone_origin(zone_desc), i);
3179 
3180         if(key == NULL)
3181         {
3182             break;
3183         }
3184 
3185         zone_policy_log_debug_key("dnssec-policy: found ", key);
3186 
3187         /*
3188          * @note 20160425 edf -- care must be taken here, keys may be generated in an another thread.
3189          *                       also, a key can only effectively be found after its generation (which discards the idea of virtual key)
3190          *                       so whatever is done here, pending key creation tasks should be taken into account (other operations are "real time")
3191          *
3192          * If the key is expired,
3193          *      ignore it (it should be handled by the smart signing).
3194          * If the key is out of the expected parameters (size/alg) and it is not acceptable,
3195          *      edit the times of the keys and remember the smart signing should be triggered.
3196          * If the key is valid, keep it on the side.
3197          *
3198          */
3199 
3200         if(dnskey_is_expired_now(key) ||
3201 
3202            (key->epoch_publish == 0) ||
3203            (key->epoch_inactive == 0))
3204         {
3205             zone_policy_log_debug_key("dnssec-policy: ignore ", key);
3206             // this key is irrelevant. It will be released after this control block.
3207         }
3208 
3209         else
3210         {
3211             // for all key suite, if the key matches the suite, add the key to the suite array
3212             for(int j = 0; j <= ptr_vector_last_index(&policy->key_suite); ++j)
3213             {
3214                 const struct dnssec_policy_key_suite *kr = (const struct dnssec_policy_key_suite*)ptr_vector_get(&policy->key_suite, j);
3215 
3216                 if(zone_policy_key_suite_is_marked_processed(zone_desc, kr))
3217                 {
3218                     continue;
3219                 }
3220 
3221                 if(zone_policy_key_roll_matches(kr, key))
3222                 {
3223                     char tmp[512];
3224                     snformat(tmp,sizeof(tmp), "dnssec-policy: matches %s", policy->name);
3225                     zone_policy_log_debug_key(tmp, key);
3226 
3227                     dnskey_acquire(key);
3228                     ptr_vector_append(&key_roll_keys[j], key);
3229                 }
3230             }
3231         }
3232 
3233         dnskey_release(key);
3234     }
3235 
3236     /*
3237      * For all key suites ...
3238      *
3239      * sort-out the remaining keys
3240      * trigger the generation of keys
3241      *
3242      * keys of the array are matching the policy
3243      */
3244     for(int ksi = 0; ksi <= ptr_vector_last_index(&policy->key_suite); ++ksi)
3245     {
3246         struct dnssec_policy_key_suite *kr = (struct dnssec_policy_key_suite*)ptr_vector_get(&policy->key_suite, ksi);
3247 
3248         if(zone_policy_key_suite_is_marked_processed(zone_desc, kr))
3249         {
3250             log_debug("dnssec-policy: %{dnsname}: %s: key suite is already being processed", zone_origin(zone_desc), kr->name);
3251             continue;
3252         }
3253 
3254         log_debug("dnssec-policy: %{dnsname}: %s: key suite has %i matching keys", zone_origin(zone_desc), kr->name, ptr_vector_size(&key_roll_keys[ksi]));
3255 
3256         if(ptr_vector_size(&key_roll_keys[ksi]) > 0)
3257         {
3258             // sort array by time
3259 
3260             if(ptr_vector_size(&key_roll_keys[ksi]) > 1) // avoids the call but ptr_vector_qsort already checks this
3261             {
3262                 ptr_vector_qsort(&key_roll_keys[ksi], zone_policy_dnssec_key_ptr_vector_qsort_by_activation_time_callback);
3263             }
3264 
3265             // ensure we have continuity
3266             // start with a base period
3267 
3268             dnssec_key *previous_key = NULL;
3269             s64 previous_begin_period;
3270             s64 previous_next_period;
3271             s64 previous_end_period;
3272 
3273             {
3274                 previous_key = (dnssec_key*)ptr_vector_get(&key_roll_keys[ksi], 0);
3275 
3276 #if DEBUG
3277                 log_debug("dnssec-policy: %s: %s: key %05d/%d timings: %T %T %T %T %T [0]",
3278                           previous_key->origin,
3279                           kr->name,
3280                           dnskey_get_tag_const(previous_key), ntohs(previous_key->flags),
3281                           previous_key->epoch_created, previous_key->epoch_publish, previous_key->epoch_activate, previous_key->epoch_inactive, previous_key->epoch_delete);
3282 #endif
3283 
3284                 database_service_zone_dnskey_set_alarms_for_key(zone, previous_key);
3285 
3286                 previous_begin_period = previous_key->epoch_activate;
3287                 previous_next_period = previous_begin_period;
3288                 previous_end_period = previous_key->epoch_inactive;
3289             }
3290 
3291             log_debug("dnssec-policy: %{dnsname}: %s: first key will be inactive at %T", zone_origin(zone_desc), kr->name, previous_end_period);
3292 
3293             for(int i = 1; i <= ptr_vector_last_index(&key_roll_keys[ksi]); ++i)
3294             {
3295                 dnssec_key *key = (dnssec_key*)ptr_vector_get(&key_roll_keys[ksi], i);
3296 #if DEBUG
3297                 log_debug("dnssec-policy: %s: %s: key %05d/%d timings: %T %T %T %T %T [%i]",
3298                           key->origin,
3299                           kr->name,
3300                           dnskey_get_tag_const(key), ntohs(key->flags),
3301                           key->epoch_created, key->epoch_publish, key->epoch_activate, key->epoch_inactive, key->epoch_delete, i);
3302 #endif
3303                 previous_next_period = key->epoch_activate;
3304 
3305                 // ensure the key chains with this interval
3306                 if(key->epoch_activate > previous_end_period /*|| key->epoch_inactive < begin_period irrelevant because of the sort */)
3307                 {
3308                     // bad
3309                     log_warn("dnssec-policy: timeline hole of %d seconds from %d to %d", key->epoch_activate - previous_end_period , previous_end_period, key->epoch_activate);
3310                     zone_policy_log_debug_key("dnssec-policy: unchained ", key);
3311 
3312                     /*
3313                      * This case happens if there is at least one key K with timings in the future but the last key L of the valid chain is made inactive
3314                      * before K is being made active.
3315                      *
3316                      * _ Create key(s) for the gap ?
3317                      * _ Only create one key to fill that gap <- probably the best solution
3318                      */
3319                     break;
3320                 }
3321                 else // the key chains fine
3322                 {
3323                     // if the previous key ends before this one we keep it
3324 
3325                     if(previous_end_period < key->epoch_inactive)
3326                     {
3327                         database_service_zone_dnskey_set_alarms_for_key(zone, key);
3328 
3329                         previous_key = key;
3330                         previous_end_period = key->epoch_inactive;
3331                     }
3332                     else
3333                     {
3334                         // else the key is irrelevant for the chain
3335                     }
3336                 }
3337             }
3338 
3339             log_debug("dnssec-policy: %{dnsname}: %s: covered from %T to %T, last key activates at %T", zone_origin(zone_desc), kr->name, previous_begin_period, previous_end_period, previous_next_period);
3340 
3341             time_t now = time(NULL);
3342 
3343             if(previous_key->epoch_created <= now)
3344             {
3345                 if(kr->roll->time_table.created.type.type == ZONE_POLICY_RELATIVE)
3346                 {
3347                     if(FAIL(ret = dnssec_policy_queue_add_generate_key_create_at(zone_desc, kr, previous_key->epoch_created)))
3348                     {
3349                         log_err("dnssec-policy: %{dnsname}: %s: failed to setup key generation from previous key: %r", zone_origin(zone_desc), kr->name, ret);
3350                         final_ret = ret;
3351                     }
3352                 }
3353                 else if(kr->roll->time_table.created.type.type == ZONE_POLICY_RULE)
3354                 {
3355                     if(FAIL(ret = dnssec_policy_queue_add_generate_key_active_at(zone_desc, kr, previous_end_period, NULL)))
3356                     {
3357                         log_err("dnssec-policy: %{dnsname}: %s: failed to setup key generation from previous end period: %r", zone_origin(zone_desc), kr->name, ret);
3358                         final_ret = ret;
3359                     }
3360                 }
3361                 else
3362                 {
3363                     log_err("dnssec-policy: %{dnsname}: %s: is not supported by this version of the policies", zone_origin(zone_desc), kr->name);
3364                 }
3365             }
3366             ptr_vector_callback_and_destroy(&key_roll_keys[ksi], zone_policy_process_release_keys_cb);
3367         }
3368         else
3369         {
3370             // no key at all ? do a full init (with (re)signature)
3371 
3372             log_info("dnssec-policy: %{dnsname}: %s: will be completely initialised", zone_origin(zone_desc), kr->name);
3373 
3374             // for relative rules: do it now
3375             // for cron rules: generate it back-dated
3376 
3377             if(kr->roll->time_table.created.type.type == ZONE_POLICY_RELATIVE)
3378             {
3379                 // now
3380 
3381                 time_t now = time(NULL);
3382 
3383                 // add the command, aim to be active "now"
3384 
3385                 s64 delta = kr->roll->time_table.created.relative.seconds + // from the previous created key ...
3386                             kr->roll->time_table.publish.relative.seconds +
3387                             kr->roll->time_table.activate.relative.seconds ;
3388 
3389                 if(delta > (s64)now)
3390                 {
3391                     delta = (s64)now;   //
3392                 }
3393 
3394                 time_t first_key_create = now - (s32)delta;
3395 
3396                 if(ISOK(ret = dnssec_policy_queue_add_generate_key_create_at(zone_desc, kr, first_key_create))) // works on any kind of dates
3397                 {
3398                     log_debug("dnssec-policy: %{dnsname}: %s: will generate a first key at %T minus %i = %T", zone_origin(zone_desc), kr->name, now, (s32)delta, first_key_create);
3399 
3400                     // scan-build false-positive : kr isn't freed here (scan-build missed the acquire before the release)
3401 
3402                 }
3403                 else
3404                 {
3405                     log_err("dnssec-policy: %{dnsname}: %s: failed to setup key generation before now: %r", zone_origin(zone_desc), kr->name, ret);
3406                     final_ret = ret;
3407                 }
3408             }
3409             else if(kr->roll->time_table.created.type.type == ZONE_POLICY_RULE)
3410             {
3411                 // compute the back-dated epoch
3412 
3413                 time_t now = time(NULL);
3414                 time_t will_be_inactive_at = 0;
3415                 if(ISOK(ret = dnssec_policy_queue_add_generate_key_active_at(zone_desc, kr, now, &will_be_inactive_at))) // @note : only works on rules
3416                 {
3417                     log_debug("dnssec-policy: %{dnsname}: %s: will generate a first key that'll be inactive at %T", zone_origin(zone_desc), kr->name, will_be_inactive_at);
3418 
3419                     // scan-build false-positive : kr isn't freed here (scan-build missed the acquire before the release)
3420 
3421                 }
3422                 else
3423                 {
3424                     log_err("dnssec-policy: %{dnsname}: %s: failed to setup key generation from now: %r", zone_origin(zone_desc), kr->name, ret);
3425                     final_ret = ret;
3426                 }
3427             }
3428             else
3429             {
3430                 log_err("dnssec-policy: %{dnsname}: %s: don't know how to proceed", zone_origin(zone_desc), kr->name);
3431             }
3432         }
3433     } // for all key suites
3434 
3435     zdb_zone_release(zone);
3436 
3437     log_debug("dnssec-policy: %{dnsname} released", zone_origin(zone_desc));
3438 
3439     for(int i = 0; i < DNSSEC_POLICY_KEY_ROLL_COUNT_MAXIMUM; ++i)
3440     {
3441         ptr_vector_callback_and_destroy(&key_roll_keys[i], zone_policy_process_release_keys_cb);
3442     }
3443 
3444     // decide what to do
3445 
3446     return final_ret;   // returns success or the last error from the key generation part
3447 }
3448 
3449 void
dnssec_policy_initialise()3450 dnssec_policy_initialise()
3451 {
3452     dnssec_policy_command_service_start();
3453 }
3454 
3455 void
dnssec_policy_finalize()3456 dnssec_policy_finalize()
3457 {
3458     ptr_set_iterator iter;
3459 
3460     //
3461 
3462     group_mutex_write_lock(&dnssec_policy_set_mtx);
3463     ptr_set_iterator_init(&dnssec_policy_set, &iter);
3464     while(ptr_set_iterator_hasnext(&iter))
3465     {
3466         ptr_node *node = ptr_set_iterator_next_node(&iter);
3467         dnssec_policy *dp = (dnssec_policy*)node->value;
3468         group_mutex_write_lock(&dnssec_policy_mtx);
3469         int rc = dp->rc;
3470         group_mutex_write_unlock(&dnssec_policy_mtx);
3471         if(rc == 1)
3472         {
3473             // destroy it
3474             log_debug("dnssec-policy: %s: policy released", dp->name);
3475             dnssec_policy_release(dp);
3476         }
3477         else
3478         {
3479             log_warn("dnssec-policy: %s: policy is still referenced %i times", dp->name, rc);
3480         }
3481     }
3482 
3483     ptr_set_destroy(&dnssec_policy_set);
3484 
3485     group_mutex_write_unlock(&dnssec_policy_set_mtx);
3486 
3487     //
3488 
3489     group_mutex_write_lock(&dnssec_policy_key_suite_set_mtx);
3490     ptr_set_iterator_init(&dnssec_policy_key_suite_set, &iter);
3491     while(ptr_set_iterator_hasnext(&iter))
3492     {
3493         ptr_node *node = ptr_set_iterator_next_node(&iter);
3494         dnssec_policy_key_suite *dpks = (dnssec_policy_key_suite*)node->value;
3495         group_mutex_write_lock(&dnssec_policy_key_suite_mtx);
3496         int rc = dpks->rc;
3497         group_mutex_write_unlock(&dnssec_policy_key_suite_mtx);
3498         if(rc == 1)
3499         {
3500             // destroy it
3501             log_debug("dnssec-policy: %s: key suite released", dpks->name);
3502             dnssec_policy_key_suite_release(dpks);
3503         }
3504         else
3505         {
3506             log_warn("dnssec-policy: %s: key suite is still referenced %i times", dpks->name, rc);
3507         }
3508     }
3509 
3510     ptr_set_destroy(&dnssec_policy_key_suite_set);
3511 
3512     group_mutex_write_unlock(&dnssec_policy_key_suite_set_mtx);
3513 
3514     //
3515 
3516     group_mutex_write_lock(&dnssec_policy_key_set_mtx);
3517     ptr_set_iterator_init(&dnssec_policy_key_set, &iter);
3518     while(ptr_set_iterator_hasnext(&iter))
3519     {
3520         ptr_node *node = ptr_set_iterator_next_node(&iter);
3521         dnssec_policy_key *dpk = (dnssec_policy_key*)node->value;
3522         group_mutex_write_lock(&dnssec_policy_key_mtx);
3523         int rc = dpk->rc;
3524         group_mutex_write_unlock(&dnssec_policy_key_mtx);
3525         if(rc == 1)
3526         {
3527             // destroy it
3528             log_debug("dnssec-policy: %s: key released", dpk->name);
3529             dnssec_policy_key_release(dpk);
3530         }
3531         else
3532         {
3533             log_warn("dnssec-policy: %s: key is still referenced %i times", dpk->name, rc);
3534         }
3535     }
3536 
3537     ptr_set_destroy(&dnssec_policy_key_set);
3538 
3539     group_mutex_write_unlock(&dnssec_policy_key_set_mtx);
3540 
3541     //
3542 
3543     group_mutex_write_lock(&dnssec_policy_roll_set_mtx);
3544     ptr_set_iterator_init(&dnssec_policy_roll_set, &iter);
3545     while(ptr_set_iterator_hasnext(&iter))
3546     {
3547         ptr_node *node = ptr_set_iterator_next_node(&iter);
3548         dnssec_policy_roll *dpr = (dnssec_policy_roll*)node->value;
3549         group_mutex_write_lock(&dnssec_policy_roll_mtx);
3550         int rc = dpr->rc;
3551         group_mutex_write_unlock(&dnssec_policy_roll_mtx);
3552         if(rc == 1)
3553         {
3554             // destroy it
3555             log_debug("dnssec-policy: %s: roll released", dpr->name);
3556             dnssec_policy_roll_release(dpr);
3557         }
3558         else
3559         {
3560             log_warn("dnssec-policy: %s: roll is still referenced %i times", dpr->name, rc);
3561         }
3562     }
3563 
3564     ptr_set_destroy(&dnssec_policy_roll_set);
3565 
3566     group_mutex_write_unlock(&dnssec_policy_roll_set_mtx);
3567     //
3568 
3569     group_mutex_write_lock(&dnssec_denial_set_mtx);
3570     ptr_set_iterator_init(&dnssec_denial_set, &iter);
3571     while(ptr_set_iterator_hasnext(&iter))
3572     {
3573         ptr_node *node = ptr_set_iterator_next_node(&iter);
3574         dnssec_denial *dd = (dnssec_denial*)node->value;
3575         group_mutex_write_lock(&dnssec_denial_mtx);
3576         int rc = dd->rc;
3577         group_mutex_write_unlock(&dnssec_denial_mtx);
3578         if(rc == 1)
3579         {
3580             // destroy it
3581             log_debug("dnssec-policy: %s: denial released", dd->name);
3582             dnssec_policy_denial_release(dd);
3583         }
3584         else
3585         {
3586             log_warn("dnssec-policy: %s: denial is still referenced %i times", dd->name, rc);
3587         }
3588     }
3589 
3590     ptr_set_destroy(&dnssec_denial_set);
3591 
3592     mutex_lock(&origin_to_dnssec_policy_queue_mtx);
3593     ptr_set_iterator_init(&origin_to_dnssec_policy_queue_set, &iter);
3594     while(ptr_set_iterator_hasnext(&iter))
3595     {
3596         ptr_node *node = ptr_set_iterator_next_node(&iter);
3597         dnsname_zfree(node->key);
3598         dnssec_policy_queue* cmd = (dnssec_policy_queue*)node->value;
3599         while(cmd != NULL)
3600         {
3601             dnssec_policy_queue *tmp = cmd;
3602             dnsname_zfree(cmd->origin);
3603             cmd = cmd->next;
3604             ZFREE_OBJECT(tmp);
3605         }
3606     }
3607     ptr_set_destroy(&origin_to_dnssec_policy_queue_set);
3608     mutex_unlock(&origin_to_dnssec_policy_queue_mtx);
3609 
3610     group_mutex_write_unlock(&dnssec_denial_set_mtx);
3611 }
3612 
3613 
3614 
3615 /**
3616  * @}
3617  */
3618