No empty .Rs/.Re
[netbsd-mini2440.git] / external / bsd / bind / dist / contrib / zkt / rollover.c
blob10579e866e7f97029dcc67e5919a1a18d5101c4b
1 /* $NetBSD$ */
3 /*****************************************************************
4 **
5 ** @(#) rollover.c -- The key rollover functions
6 **
7 ** Copyright (c) Jan 2005 - May 2008, Holger Zuleger HZnet. All rights reserved.
8 **
9 ** This software is open source.
11 ** Redistribution and use in source and binary forms, with or without
12 ** modification, are permitted provided that the following conditions
13 ** are met:
15 ** Redistributions of source code must retain the above copyright notice,
16 ** this list of conditions and the following disclaimer.
18 ** Redistributions in binary form must reproduce the above copyright notice,
19 ** this list of conditions and the following disclaimer in the documentation
20 ** and/or other materials provided with the distribution.
22 ** Neither the name of Holger Zuleger HZnet nor the names of its contributors may
23 ** be used to endorse or promote products derived from this software without
24 ** specific prior written permission.
26 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 ** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 ** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
30 ** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 ** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 ** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 ** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 ** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 ** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 ** POSSIBILITY OF SUCH DAMAGE.
38 *****************************************************************/
39 # include <stdio.h>
40 # include <string.h>
41 # include <stdlib.h>
42 # include <ctype.h>
43 # include <time.h>
44 # include <assert.h>
45 # include <dirent.h>
46 # include <errno.h>
47 # include <unistd.h>
48 #ifdef HAVE_CONFIG_H
49 # include <config.h>
50 #endif
51 # include "config_zkt.h"
52 # include "zconf.h"
53 # include "debug.h"
55 # include "misc.h"
56 # include "zone.h"
57 # include "dki.h"
58 # include "log.h"
59 #define extern
60 # include "rollover.h"
61 #undef extern
63 /*****************************************************************
64 ** local function definition
65 *****************************************************************/
67 static dki_t *genkey (dki_t **listp, const char *dir, const char *domain, int ksk, const zconf_t *conf, int status)
69 dki_t *dkp;
71 if ( listp == NULL || domain == NULL )
72 return NULL;
74 if ( ksk )
75 dkp = dki_new (dir, domain, DKI_KSK, conf->k_algo, conf->k_bits, conf->k_random, conf->k_life / DAYSEC);
76 else
77 dkp = dki_new (dir, domain, DKI_ZSK, conf->k_algo, conf->z_bits, conf->z_random, conf->z_life / DAYSEC);
78 dki_add (listp, dkp);
79 dki_setstatus (dkp, status);
81 return dkp;
84 static dki_t *genkey2 (dki_t **listp, const char *dir, const char *domain, int ksk, const zconf_t *conf, int status)
86 dki_t *dkp;
88 if ( listp == NULL || domain == NULL )
89 return NULL;
91 if ( ksk )
92 dkp = dki_new (dir, domain, DKI_KSK, conf->k2_algo, conf->k_bits, conf->k_random, conf->k_life / DAYSEC);
93 else
94 dkp = dki_new (dir, domain, DKI_ZSK, conf->k2_algo, conf->z_bits, conf->z_random, conf->z_life / DAYSEC);
95 dki_add (listp, dkp);
96 dki_setstatus (dkp, status);
98 return dkp;
101 static time_t get_exptime (dki_t *key, const zconf_t *z)
103 time_t exptime;
105 exptime = dki_exptime (key);
106 if ( exptime == 0L )
108 if ( dki_lifetime (key) )
109 exptime = dki_time (key) + dki_lifetime (key);
110 else
111 exptime = dki_time (key) + z->k_life;
114 return exptime;
117 /*****************************************************************
118 ** is_parentdirsigned (name)
119 ** Check if the parent directory of the zone specified by zp
120 ** is a directory with a signed zone
121 ** Returns 0 | 1
122 *****************************************************************/
123 static int is_parentdirsigned (const zone_t *zonelist, const zone_t *zp)
125 char path[MAX_PATHSIZE+1];
126 const char *ext;
127 #if 0
128 const zconf_t *conf;
130 /* check if there is a local config file to get the name of the zone file */
131 snprintf (path, sizeof (path), "%s/../%s", zp->dir, LOCALCONF_FILE);
132 if ( fileexist (path) ) /* parent dir has local config file ? */
133 conf = loadconfig (path, NULL);
134 else
135 conf = zp->conf;
137 /* build the path of the .signed zone file */
138 snprintf (path, sizeof (path), "%s/../%s.signed", conf->dir, conf->zonefile);
139 if ( conf != zp->conf ) /* if we read in a local config file.. */
140 free (conf); /* ..free the memory used */
142 #else
143 /* currently we use the signed zone file name of the
144 * current directory for checking if the file exist.
145 * TODO: Instead we have to use the name of the zone file
146 * used in the parent dir (see above)
149 ext = strrchr (zp->sfile, '.');
150 if ( ext && strcmp (zp->sfile, ".dsigned") == 0 ) /* is the current zone a dynamic one ? */
151 /* hack: we are using the standard zone file name for a static zone here */
152 snprintf (path, sizeof (path), "%s/../%s", zp->dir, "zone.db.signed");
153 else
155 # if 1
156 const zone_t *parent;
157 const char *parentname;
159 /* find out name of parent */
160 parentname = strchr (zp->zone, '.'); /* find first dot in zone name */
161 if ( parentname == NULL ) /* no parent found! */
162 return 0;
163 parentname += 1; /* skip '.' */
165 /* try to find parent zone in zonelist */
166 if ( (parent = zone_search (zonelist, parentname)) == NULL )
167 return 0;
168 snprintf (path, sizeof (path), "%s/%s", parent->dir, parent->sfile);
169 # else
170 snprintf (path, sizeof (path), "%s/../%s", zp->dir, zp->sfile);
171 # endif
173 #endif
174 lg_mesg (LG_DEBUG, "%s: is_parentdirsigned = %d fileexist (%s)\n", zp->zone, fileexist (path), path);
175 return fileexist (path); /* parent dir has zone.db.signed file ? */
178 /*****************************************************************
179 ** create_parent_file ()
180 *****************************************************************/
181 static int create_parent_file (const char *fname, int phase, int ttl, const dki_t *dkp)
183 FILE *fp;
185 assert ( fname != NULL );
187 if ( dkp == NULL || (phase != 1 && phase != 2) )
188 return 0;
190 if ( (fp = fopen (fname, "w")) == NULL )
191 fatal ("can\'t create new parentfile \"%s\"\n", fname);
193 if ( phase == 1 )
194 fprintf (fp, "; KSK rollover phase1 (new key generated but this is alread the old one)\n");
195 else
196 fprintf (fp, "; KSK rollover phase2 (this is the new key)\n");
198 dki_prt_dnskeyttl (dkp, fp, ttl);
199 fclose (fp);
201 return phase;
204 /*****************************************************************
205 ** get_parent_phase ()
206 *****************************************************************/
207 static int get_parent_phase (const char *file)
209 FILE *fp;
210 int phase;
212 if ( (fp = fopen (file, "r")) == NULL )
213 return -1;
215 phase = 0;
216 if ( fscanf (fp, "; KSK rollover phase%d", &phase) != 1 )
217 phase = 0;
219 fclose (fp);
220 return phase;
223 /*****************************************************************
224 ** kskrollover ()
225 *****************************************************************/
226 static int kskrollover (dki_t *ksk, zone_t *zonelist, zone_t *zp)
228 char path[MAX_PATHSIZE+1];
229 const zconf_t *z;
230 time_t lifetime;
231 time_t currtime;
232 time_t age;
233 int currphase;
234 int parfile_age;
235 int parent_propagation;
236 int parent_resign;
237 int parent_keyttl;
240 assert ( ksk != NULL );
241 assert ( zp != NULL );
243 z = zp->conf;
244 /* check ksk lifetime */
245 if ( (lifetime = dki_lifetime (ksk)) == 0 ) /* if lifetime of key is not set.. */
246 lifetime = z->k_life; /* ..use global configured lifetime */
248 currtime = time (NULL);
249 age = dki_age (ksk, currtime);
251 /* build path of parent-file */
252 pathname (path, sizeof (path), zp->dir, "parent-", zp->zone);
254 /* check if we have to change the ksk ? */
255 if ( lifetime > 0 && age > lifetime && !fileexist (path) ) /* lifetime is over and no kskrollover in progress */
257 /* we are in hierachical mode and the parent directory contains a signed zone ? */
258 if ( z->keysetdir && strcmp (z->keysetdir, "..") == 0 && is_parentdirsigned (zonelist, zp) )
260 verbmesg (2, z, "\t\tkskrollover: create new key signing key\n");
261 /* create a new key: this is phase one of a double signing key rollover */
262 ksk = genkey (&zp->keys, zp->dir, zp->zone, DKI_KSK, z, DKI_ACTIVE);
263 if ( ksk == NULL )
265 lg_mesg (LG_ERROR, "\"%s\": unable to generate new ksk for double signing rollover", zp->zone);
266 return 0;
268 lg_mesg (LG_INFO, "\"%s\": kskrollover phase1: New key %d generated", zp->zone, ksk->tag);
270 /* find the oldest active ksk to create the parent file */
271 if ( (ksk = (dki_t *)dki_findalgo (zp->keys, DKI_KSK, zp->conf->k_algo, 'a', 1)) == NULL )
272 lg_mesg (LG_ERROR, "kskrollover phase1: Couldn't find the old active key\n");
273 if ( !create_parent_file (path, 1, z->key_ttl, ksk) )
274 lg_mesg (LG_ERROR, "Couldn't create parentfile %s\n", path);
277 else /* print out a warning only */
279 logmesg ("\t\tWarning: Lifetime of Key Signing Key %d exceeded: %s\n",
280 ksk->tag, str_delspace (age2str (age)));
281 lg_mesg (LG_WARNING, "\"%s\": lifetime of key signing key %d exceeded since %s",
282 zp->zone, ksk->tag, str_delspace (age2str (age - lifetime)));
284 return 1;
287 /* now check if there is an ongoing key rollover */
289 /* check if parent-file already exist */
290 if ( !fileexist (path) ) /* no parent-<zone> file found ? */
291 return 0; /* ok, that's it */
293 /* check the ksk rollover phase we are in */
294 currphase = get_parent_phase (path); /* this is the actual state we are in */
295 parfile_age = file_age (path);
297 /* TODO: Set these values to the one found in the parent dnssec.conf file */
298 parent_propagation = PARENT_PROPAGATION;
299 parent_resign = z->resign;
300 parent_keyttl = z->key_ttl;
302 switch ( currphase )
304 case 1: /* we are currently in state one (new ksk already generated) */
305 if ( parfile_age > z->proptime + z->key_ttl ) /* can we go to phase 2 ? */
307 verbmesg (2, z, "\t\tkskrollover: save new ksk in parent file\n");
308 ksk = ksk->next; /* set ksk to new ksk */
309 if ( !create_parent_file (path, currphase+1, z->key_ttl, ksk) )
310 lg_mesg (LG_ERROR, "Couldn't create parentfile %s\n", path);
311 lg_mesg (LG_INFO, "\"%s\": kskrollover phase2: send new key %d to the parent zone", zp->zone, ksk->tag);
312 return 1;
314 else
315 verbmesg (2, z, "\t\tkskrollover: we are in state 1 and waiting for propagation of the new key (parentfile %dsec < prop %dsec + keyttl %dsec\n", parfile_age, z->proptime, z->key_ttl);
316 break;
317 case 2: /* we are currently in state two (propagation of new key to the parent) */
318 #if 0
319 if ( parfile_age >= parent_propagation + parent_resign + parent_keyttl ) /* can we go to phase 3 ? */
320 #else
321 if ( parfile_age >= parent_propagation + parent_keyttl ) /* can we go to phase 3 ? */
322 #endif
324 /* remove the parentfile */
325 unlink (path);
327 /* remove oldest key from list and mark file as removed */
328 zp->keys = dki_remove (ksk);
330 // verbmesg (2, z, "kskrollover: remove parentfile and rename old key to k<zone>+<algo>+<tag>.key\n");
331 verbmesg (2, z, "\t\tkskrollover: remove parentfile and rename old key to k%s+%03d+%05d.key\n",
332 ksk->name, ksk->algo, ksk->tag);
333 lg_mesg (LG_INFO, "\"%s\": kskrollover phase3: Remove old key %d", zp->zone, ksk->tag);
334 return 1;
336 else
337 #if 0
338 verbmesg (2, z, "\t\tkskrollover: we are in state 2 and waiting for parent propagation (parentfile %d < parentprop %d + parentresig %d + parentkeyttl %d\n", parfile_age, parent_propagation, parent_resign, parent_keyttl);
339 #else
340 verbmesg (2, z, "\t\tkskrollover: we are in state 2 and waiting for parent propagation (parentfile %dsec < parentprop %dsec + parentkeyttl %dsec\n", parfile_age, parent_propagation, parent_keyttl);
341 #endif
342 break;
343 default:
344 assert ( currphase == 1 || currphase == 2 );
345 /* NOTREACHED */
348 return 0;
351 /*****************************************************************
352 ** global function definition
353 *****************************************************************/
355 /*****************************************************************
356 ** ksk5011status ()
357 ** Check if the list of zone keys containing a revoked or a
358 ** standby key.
359 ** Remove the revoked key if it is older than 30 days.
360 ** If the lifetime of the active key is reached, do a rfc5011
361 ** keyrollover.
362 ** Returns an int with the rightmost bit set if a resigning
363 ** is required. The second rightmost bit is set, if it is an
364 ** rfc5011 zone.
365 *****************************************************************/
366 int ksk5011status (dki_t **listp, const char *dir, const char *domain, const zconf_t *z)
368 dki_t *standbykey;
369 dki_t *activekey;
370 dki_t *dkp;
371 dki_t *prev;
372 time_t currtime;
373 time_t exptime;
374 int ret;
376 assert ( listp != NULL );
377 assert ( z != NULL );
379 if ( z->k_life == 0 )
380 return 0;
382 verbmesg (1, z, "\tCheck RFC5011 status\n");
384 ret = 0;
385 currtime = time (NULL);
387 /* go through the list of key signing keys, */
388 /* remove revoked keys and set a pointer to standby and active key */
389 standbykey = activekey = NULL;
390 prev = NULL;
391 for ( dkp = *listp; dkp && dki_isksk (dkp); dkp = dkp->next )
393 exptime = get_exptime (dkp, z);
394 if ( dki_isrevoked (dkp) )
395 lg_mesg (LG_DEBUG, "zone \"%s\": found revoked key (id=%d exptime=%s); waiting for remove hold down time",
396 domain, dkp->tag, time2str (exptime, 's'));
398 /* revoked key is older than 30 days? */
399 if ( dki_isrevoked (dkp) && currtime > exptime + REMOVE_HOLD_DOWN )
401 verbmesg (1, z, "\tRemove revoked key %d which is older than 30 days\n", dkp->tag);
402 lg_mesg (LG_NOTICE, "zone \"%s\": removing revoked key %d", domain, dkp->tag);
404 /* remove key from list and mark file as removed */
405 if ( prev == NULL ) /* at the beginning of the list ? */
406 *listp = dki_remove (dkp);
407 else /* anywhere in the middle of the list */
408 prev->next = dki_remove (dkp);
410 ret |= 01; /* from now on a resigning is necessary */
413 /* remember oldest standby and active key */
414 if ( dki_status (dkp) == DKI_PUBLISHED )
415 standbykey = dkp;
416 if ( dki_status (dkp) == DKI_ACTIVE )
417 activekey = dkp;
419 /* no activekey or no standby key and also no revoked key found ? */
420 if ( activekey == NULL || (standbykey == NULL && ret == 0) )
421 return ret; /* Seems that this is a non rfc5011 zone! */
423 ret |= 02; /* Zone looks like a rfc5011 zone */
425 exptime = get_exptime (activekey, z);
426 #if 0
427 lg_mesg (LG_DEBUG, "Act Exptime: %s", time2str (exptime, 's'));
428 lg_mesg (LG_DEBUG, "Stb time: %s", time2str (dki_time (standbykey), 's'));
429 lg_mesg (LG_DEBUG, "Stb time+wait: %s", time2str (dki_time (standbykey) + min (DAYSEC * 30, z->key_ttl), 's'));
430 #endif
431 /* At the first time we introduce a standby key, the lifetime of the current KSK shouldn't be expired, */
432 /* otherwise we run into an (nearly) immediate key rollover! */
433 if ( currtime > exptime && currtime > dki_time (standbykey) + min (ADD_HOLD_DOWN, z->key_ttl) )
435 lg_mesg (LG_NOTICE, "\"%s\": starting rfc5011 rollover", domain);
436 verbmesg (1, z, "\tLifetime of Key Signing Key %d exceeded (%s): Starting rfc5011 rollover!\n",
437 activekey->tag, str_delspace (age2str (dki_age (activekey, currtime))));
438 verbmesg (2, z, "\t\t=>Generating new standby key signing key\n");
439 dkp = genkey (listp, dir, domain, DKI_KSK, z, DKI_PUBLISHED); /* gentime == now; lifetime = z->k_life; exp = 0 */
440 if ( !dkp )
442 error ("\tcould not generate new standby KSK\n");
443 lg_mesg (LG_ERROR, "\%s\": can't generate new standby KSK", domain);
445 else
446 lg_mesg (LG_NOTICE, "\"%s\": generated new standby KSK %d", domain, dkp->tag);
448 /* standby key gets active */
449 verbmesg (2, z, "\t\t=>Activating old standby key %d \n", standbykey->tag);
450 dki_setstatus (standbykey, DKI_ACT);
452 /* active key should be revoked */
453 verbmesg (2, z, "\t\t=>Revoking old active key %d \n", activekey->tag);
454 dki_setstatus (activekey, DKI_REVOKED);
455 dki_setexptime (activekey, currtime); /* now the key is expired */
457 ret |= 01; /* resigning necessary */
460 return ret;
463 /*****************************************************************
464 ** kskstatus ()
465 ** Check the ksk status of a zone if a ksk lifetime is set.
466 ** If there is no key signing key present create a new one.
467 ** Prints out a warning message if the lifetime of the current
468 ** key signing key is over.
469 ** Returns 1 if a resigning of the zone is necessary, otherwise
470 ** the function returns 0.
471 *****************************************************************/
472 int kskstatus (zone_t *zonelist, zone_t *zp)
474 dki_t *akey;
475 const zconf_t *z;
477 assert ( zp != NULL );
479 z = zp->conf;
480 if ( z->k_life == 0 )
481 return 0;
483 verbmesg (1, z, "\tCheck KSK status\n");
484 /* check if a key signing key exist ? */
485 akey = (dki_t *)dki_findalgo (zp->keys, DKI_KSK, z->k_algo, 'a', 1);
486 if ( akey == NULL )
488 verbmesg (1, z, "\tNo active KSK found: generate new one\n");
489 akey = genkey (&zp->keys, zp->dir, zp->zone, DKI_KSK, z, DKI_ACTIVE);
490 if ( !akey )
492 error ("\tcould not generate new KSK\n");
493 lg_mesg (LG_ERROR, "\"%s\": can't generate new KSK: \"%s\"",
494 zp->zone, dki_geterrstr());
496 else
497 lg_mesg (LG_INFO, "\"%s\": generated new KSK %d", zp->zone, akey->tag);
498 return akey != NULL; /* return value of 1 forces a resigning of the zone */
500 else /* try to start a full automated ksk rollover */
501 kskrollover (akey, zonelist, zp);
503 /* is a second algorithm requested ? (since 0.99) */
504 if ( z->k2_algo && z->k2_algo != z->k_algo )
506 /* check for ksk supporting the additional algorithm */
507 akey = (dki_t *)dki_findalgo (zp->keys, DKI_KSK, z->k2_algo, 'a', 1);
508 if ( akey == NULL )
510 verbmesg (1, z, "\tNo active KSK for second algorithm found: generate new one\n");
511 akey = genkey2 (&zp->keys, zp->dir, zp->zone, DKI_KSK, z, DKI_ACTIVE);
512 if ( !akey )
514 error ("\tcould not generate new KSK for 2nd algorithm\n");
515 lg_mesg (LG_ERROR, "\"%s\": can't generate new KSK for 2nd algorithm: \"%s\"",
516 zp->zone, dki_geterrstr());
518 else
519 lg_mesg (LG_INFO, "\"%s\": generated new KSK %d for 2nd algorithm",
520 zp->zone, akey->tag);
521 return 1; /* return value of 1 forces a resigning of the zone */
525 return 0;
528 /*****************************************************************
529 ** zskstatus ()
530 ** Check the zsk status of a zone.
531 ** Returns 1 if a resigning of the zone is necessary, otherwise
532 ** the function returns 0.
533 *****************************************************************/
534 int zskstatus (dki_t **listp, const char *dir, const char *domain, const zconf_t *z)
536 dki_t *akey;
537 dki_t *nextkey;
538 dki_t *dkp, *last;
539 int keychange;
540 time_t lifetime;
541 time_t age;
542 time_t currtime;
544 assert ( listp != NULL );
545 /* dir can be NULL */
546 assert ( domain != NULL );
547 assert ( z != NULL );
549 currtime = time (NULL);
551 verbmesg (1, z, "\tCheck ZSK status\n");
552 dbg_val("zskstatus for %s \n", domain);
553 keychange = 0;
554 /* Is the depreciated key expired ? */
555 /* As mentioned by olaf, this is the max_ttl of all the rr in the zone */
556 lifetime = z->max_ttl + z->proptime; /* draft kolkman/gieben */
557 last = NULL;
558 dkp = *listp;
559 while ( dkp )
560 if ( !dki_isksk (dkp) &&
561 dki_status (dkp) == DKI_DEPRECIATED &&
562 dki_age (dkp, currtime) > lifetime )
564 keychange = 1;
565 verbmesg (1, z, "\tLifetime(%d sec) of depreciated key %d exceeded (%d sec)\n",
566 lifetime, dkp->tag, dki_age (dkp, currtime));
567 lg_mesg (LG_INFO, "\"%s\": old ZSK %d removed", domain, dkp->tag);
568 dkp = dki_destroy (dkp); /* delete the keyfiles */
569 dbg_msg("zskstatus: depreciated key removed ");
570 if ( last )
571 last->next = dkp;
572 else
573 *listp = dkp;
574 verbmesg (1, z, "\t\t->remove it\n");
576 else
578 last = dkp;
579 dkp = dkp->next;
582 /* check status of active key */
583 dbg_msg("zskstatus check status of active key ");
584 lifetime = z->z_life; /* global configured lifetime for zsk */
585 akey = (dki_t *)dki_findalgo (*listp, DKI_ZSK, z->k_algo, 'a', 1);
586 if ( akey == NULL && lifetime > 0 ) /* no active key found */
588 verbmesg (1, z, "\tNo active ZSK found: generate new one\n");
589 akey = genkey (listp, dir, domain, DKI_ZSK, z, DKI_ACTIVE);
590 lg_mesg (LG_INFO, "\"%s\": generated new ZSK %d", domain, akey->tag);
592 else /* active key exist */
594 if ( dki_lifetime (akey) )
595 lifetime = dki_lifetime (akey); /* set lifetime to lt of active key */
597 /* lifetime of active key is expired and published key exist ? */
598 age = dki_age (akey, currtime);
599 if ( lifetime > 0 && age > lifetime - (OFFSET) )
601 verbmesg (1, z, "\tLifetime(%d +/-%d sec) of active key %d exceeded (%d sec)\n",
602 lifetime, (OFFSET) , akey->tag, dki_age (akey, currtime) );
604 /* depreciate the key only if there is another active or published key */
605 if ( (nextkey = (dki_t *)dki_findalgo (*listp, DKI_ZSK, z->k_algo, 'a', 2)) == NULL ||
606 nextkey == akey )
607 nextkey = (dki_t *)dki_findalgo (*listp, DKI_ZSK, z->k_algo, 'p', 1);
609 /* Is the published key sufficient long in the zone ? */
610 /* As mentioned by Olaf, this should be the ttl of the DNSKEY RR ! */
611 if ( nextkey && dki_age (nextkey, currtime) > z->key_ttl + z->proptime )
613 keychange = 1;
614 verbmesg (1, z, "\t\t->depreciate it\n");
615 dki_setstatus (akey, 'd'); /* depreciate the active key */
616 verbmesg (1, z, "\t\t->activate published key %d\n", nextkey->tag);
617 dki_setstatus (nextkey, 'a'); /* activate published key */
618 lg_mesg (LG_NOTICE, "\"%s\": lifetime of zone signing key %d exceeded: ZSK rollover done", domain, akey->tag);
619 akey = nextkey;
620 nextkey = NULL;
621 lifetime = dki_lifetime (akey); /* set lifetime to lt of the new active key (F. Behrens) */
623 else
625 verbmesg (1, z, "\t\t->waiting for published key\n");
626 lg_mesg (LG_NOTICE, "\"%s\": lifetime of zone signing key %d exceeded since %s: ZSK rollover deferred: waiting for published key",
627 domain, akey->tag, str_delspace (age2str (age - lifetime)));
631 /* Should we add a new publish key? This is necessary if the active
632 * key will be expired at the next re-signing interval (The published
633 * time will be checked just before the active key will be removed.
634 * See above).
636 nextkey = (dki_t *)dki_findalgo (*listp, DKI_ZSK, z->k_algo, 'p', 1);
637 if ( nextkey == NULL && lifetime > 0 && (akey == NULL ||
638 dki_age (akey, currtime + z->resign) > lifetime - (OFFSET)) )
640 keychange = 1;
641 verbmesg (1, z, "\tNew key for publishing needed\n");
642 nextkey = genkey (listp, dir, domain, DKI_ZSK, z, DKI_PUB);
644 if ( nextkey )
646 verbmesg (1, z, "\t\t->creating new key %d\n", nextkey->tag);
647 lg_mesg (LG_INFO, "\"%s\": new key %d generated for publishing", domain, nextkey->tag);
649 else
651 error ("\tcould not generate new ZSK: \"%s\"\n", dki_geterrstr());
652 lg_mesg (LG_ERROR, "\"%s\": can't generate new ZSK: \"%s\"",
653 domain, dki_geterrstr());
657 /* is a second algorithm requested ? (since 0.99) */
658 if ( z->k2_algo && z->k2_algo != z->k_algo )
660 /* check for zsk supporting the additional algorithm */
661 akey = (dki_t *)dki_findalgo (*listp, DKI_ZSK, z->k2_algo, 'a', 1);
662 if ( akey == NULL )
664 verbmesg (1, z, "\tNo active ZSK for second algorithm found: generate new one\n");
665 akey = genkey2 (listp, dir, domain, DKI_ZSK, z, DKI_ACTIVE);
666 if ( !akey )
668 error ("\tcould not generate new ZSK for 2nd algorithm\n");
669 lg_mesg (LG_ERROR, "\"%s\": can't generate new ZSK for 2nd algorithm: \"%s\"",
670 domain, dki_geterrstr());
672 else
673 lg_mesg (LG_INFO, "\"%s\": generated new ZSK %d for 2nd algorithm",
674 domain, akey->tag);
675 return 1; /* return value of 1 forces a resigning of the zone */
679 return keychange;