etc/services - sync with NetBSD-8
[minix.git] / external / bsd / bind / dist / contrib / zkt-1.1.3 / rollover.c
blobfc55d24909a420a8edc76d64f82e21a44fe1617b
1 /* $NetBSD: rollover.c,v 1.1.1.1 2015/07/08 15:37:48 christos Exp $ */
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 (int addkey, dki_t **listp, const char *dir, const char *domain, int ksk, const zconf_t *conf, int status);
69 /* generate the first (or primary) key (algorithm k_algo) */
70 static dki_t *genfirstkey (dki_t **listp, const char *dir, const char *domain, int ksk, const zconf_t *conf, int status)
72 return genkey (0, listp, dir, domain, ksk, conf, status);
75 /* generate the additional (or second) key (algorithm k2_algo) */
76 static dki_t *genaddkey (dki_t **listp, const char *dir, const char *domain, int ksk, const zconf_t *conf, int status)
78 return genkey (1, listp, dir, domain, ksk, conf, status);
82 /* generate a DNSKEY key */
83 static dki_t *genkey (int addkey, dki_t **listp, const char *dir, const char *domain, int ksk, const zconf_t *conf, int status)
85 dki_t *dkp;
86 int confalgo;
87 int algo;
89 #if 0
90 if ( listp == NULL || domain == NULL )
91 return NULL;
92 #else
93 assert ( listp != NULL );
94 assert ( domain != NULL );
95 #endif
97 if ( addkey ) /* generating an additional key ? */
98 confalgo = conf->k2_algo;
99 else
100 confalgo = conf->k_algo;
102 algo = confalgo;
103 if ( conf->nsec3 != NSEC3_OFF ) /* is nsec3 turned on ? */
105 if ( confalgo == DK_ALGO_RSASHA1 )
106 algo = DK_ALGO_NSEC3RSASHA1;
107 else if ( confalgo == DK_ALGO_DSA )
108 algo = DK_ALGO_NSEC3DSA;
111 if ( ksk )
112 dkp = dki_new (dir, domain, DKI_KSK, algo, conf->k_bits, conf->k_random, conf->k_life / DAYSEC);
113 else
114 dkp = dki_new (dir, domain, DKI_ZSK, algo, conf->z_bits, conf->z_random, conf->z_life / DAYSEC);
115 dki_add (listp, dkp);
116 dki_setstatus (dkp, status);
118 return dkp;
121 /* get expiration time */
122 static time_t get_exptime (dki_t *key, const zconf_t *z)
124 time_t exptime;
126 exptime = dki_exptime (key);
127 if ( exptime == 0L )
129 if ( dki_lifetime (key) )
130 exptime = dki_time (key) + dki_lifetime (key);
131 else
132 exptime = dki_time (key) + z->k_life;
135 return exptime;
138 /*****************************************************************
139 ** is_parentdirsigned (name)
140 ** Check if the parent directory of the zone specified by zp
141 ** is a directory with a signed zone
142 ** Returns 0 | 1
143 *****************************************************************/
144 static int is_parentdirsigned (const zone_t *zonelist, const zone_t *zp)
146 char path[MAX_PATHSIZE+1];
147 const char *ext;
148 #if 0
149 const zconf_t *conf;
151 /* check if there is a local config file to get the name of the zone file */
152 snprintf (path, sizeof (path), "%s/../%s", zp->dir, LOCALCONF_FILE);
153 if ( fileexist (path) ) /* parent dir has local config file ? */
154 conf = loadconfig (path, NULL);
155 else
156 conf = zp->conf;
158 /* build the path of the .signed zone file */
159 snprintf (path, sizeof (path), "%s/../%s.signed", conf->dir, conf->zonefile);
160 if ( conf != zp->conf ) /* if we read in a local config file.. */
161 free (conf); /* ..free the memory used */
163 #else
164 /* currently we use the signed zone file name of the
165 * current directory for checking if the file exist.
166 * TODO: Instead we have to use the name of the zone file
167 * used in the parent dir (see above)
170 ext = strrchr (zp->sfile, '.');
171 if ( ext && strcmp (zp->sfile, ".dsigned") == 0 ) /* is the current zone a dynamic one ? */
172 /* hack: we are using the standard zone file name for a static zone here */
173 snprintf (path, sizeof (path), "%s/../%s", zp->dir, "zone.db.signed");
174 else
176 # if 1
177 const zone_t *parent;
178 const char *parentname;
180 /* find out name of parent */
181 parentname = strchr (zp->zone, '.'); /* find first dot in zone name */
182 if ( parentname == NULL ) /* no parent found! */
183 return 0;
184 parentname += 1; /* skip '.' */
186 /* try to find parent zone in zonelist */
187 if ( (parent = zone_search (zonelist, parentname)) == NULL )
188 return 0;
189 snprintf (path, sizeof (path), "%s/%s", parent->dir, parent->sfile);
190 # else
191 snprintf (path, sizeof (path), "%s/../%s", zp->dir, zp->sfile);
192 # endif
194 #endif
195 lg_mesg (LG_DEBUG, "%s: is_parentdirsigned = %d fileexist (%s)\n", zp->zone, fileexist (path), path);
196 return fileexist (path); /* parent dir has zone.db.signed file ? */
199 /*****************************************************************
200 ** create_parent_file ()
201 *****************************************************************/
202 static int create_parent_file (const char *fname, int phase, int ttl, const dki_t *dkp)
204 FILE *fp;
206 assert ( fname != NULL );
208 if ( dkp == NULL || (phase != 1 && phase != 2) )
209 return 0;
211 if ( (fp = fopen (fname, "w")) == NULL )
212 fatal ("can\'t create new parentfile \"%s\"\n", fname);
214 if ( phase == 1 )
215 fprintf (fp, "; KSK rollover phase1 (new key generated but this is alread the old one)\n");
216 else
217 fprintf (fp, "; KSK rollover phase2 (this is the new key)\n");
219 dki_prt_dnskeyttl (dkp, fp, ttl);
220 fclose (fp);
222 return phase;
225 /*****************************************************************
226 ** get_parent_phase ()
227 *****************************************************************/
228 static int get_parent_phase (const char *file)
230 FILE *fp;
231 int phase;
233 if ( (fp = fopen (file, "r")) == NULL )
234 return -1;
236 phase = 0;
237 if ( fscanf (fp, "; KSK rollover phase%d", &phase) != 1 )
238 phase = 0;
240 fclose (fp);
241 return phase;
244 /*****************************************************************
245 ** kskrollover ()
246 *****************************************************************/
247 static int kskrollover (dki_t *ksk, zone_t *zonelist, zone_t *zp)
249 char path[MAX_PATHSIZE+1];
250 const zconf_t *z;
251 time_t lifetime;
252 time_t currtime;
253 time_t age;
254 int currphase;
255 int parfile_age;
256 int parent_propagation;
257 int parent_resign;
258 int parent_keyttl;
261 assert ( ksk != NULL );
262 assert ( zp != NULL );
264 z = zp->conf;
265 /* check ksk lifetime */
266 if ( (lifetime = dki_lifetime (ksk)) == 0 ) /* if lifetime of key is not set.. */
267 lifetime = z->k_life; /* ..use global configured lifetime */
269 currtime = time (NULL);
270 age = dki_age (ksk, currtime);
272 /* build path of parent-file */
273 pathname (path, sizeof (path), zp->dir, "parent-", zp->zone);
275 /* check if we have to change the ksk ? */
276 if ( lifetime > 0 && age > lifetime && !fileexist (path) ) /* lifetime is over and no kskrollover in progress */
278 /* we are in hierachical mode and the parent directory contains a signed zone ? */
279 if ( z->keysetdir && strcmp (z->keysetdir, "..") == 0 && is_parentdirsigned (zonelist, zp) )
281 verbmesg (2, z, "\t\tkskrollover: create new key signing key\n");
282 /* create a new key: this is phase one of a double signing key rollover */
283 ksk = genfirstkey (&zp->keys, zp->dir, zp->zone, DKI_KSK, z, DKI_ACTIVE);
284 if ( ksk == NULL )
286 lg_mesg (LG_ERROR, "\"%s\": unable to generate new ksk for double signing rollover", zp->zone);
287 return 0;
289 lg_mesg (LG_INFO, "\"%s\": kskrollover phase1: New key %d generated", zp->zone, ksk->tag);
291 /* find the oldest active ksk to create the parent file */
292 if ( (ksk = (dki_t *)dki_findalgo (zp->keys, DKI_KSK, zp->conf->k_algo, 'a', 1)) == NULL )
293 lg_mesg (LG_ERROR, "kskrollover phase1: Couldn't find the old active key\n");
294 if ( !create_parent_file (path, 1, z->key_ttl, ksk) )
295 lg_mesg (LG_ERROR, "Couldn't create parentfile %s\n", path);
298 else /* print out a warning only */
300 logmesg ("\t\tWarning: Lifetime of Key Signing Key %d exceeded: %s\n",
301 ksk->tag, str_delspace (age2str (age)));
302 lg_mesg (LG_WARNING, "\"%s\": lifetime of key signing key %d exceeded since %s",
303 zp->zone, ksk->tag, str_delspace (age2str (age - lifetime)));
305 return 1;
308 /* now check if there is an ongoing key rollover */
310 /* check if parent-file already exist */
311 if ( !fileexist (path) ) /* no parent-<zone> file found ? */
312 return 0; /* ok, that's it */
314 /* check the ksk rollover phase we are in */
315 currphase = get_parent_phase (path); /* this is the actual state we are in */
316 parfile_age = file_age (path);
318 /* TODO: Set these values to the one found in the parent dnssec.conf file */
319 parent_propagation = PARENT_PROPAGATION;
320 parent_resign = z->resign;
321 parent_keyttl = z->key_ttl;
323 switch ( currphase )
325 case 1: /* we are currently in state one (new ksk already generated) */
326 if ( parfile_age > z->proptime + z->key_ttl ) /* can we go to phase 2 ? */
328 verbmesg (2, z, "\t\tkskrollover: save new ksk in parent file\n");
329 ksk = ksk->next; /* set ksk to new ksk */
330 if ( !create_parent_file (path, currphase+1, z->key_ttl, ksk) )
331 lg_mesg (LG_ERROR, "Couldn't create parentfile %s\n", path);
332 lg_mesg (LG_INFO, "\"%s\": kskrollover phase2: send new key %d to the parent zone", zp->zone, ksk->tag);
333 return 1;
335 else
336 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);
337 break;
338 case 2: /* we are currently in state two (propagation of new key to the parent) */
339 #if 0
340 if ( parfile_age >= parent_propagation + parent_resign + parent_keyttl ) /* can we go to phase 3 ? */
341 #else
342 if ( parfile_age >= parent_propagation + parent_keyttl ) /* can we go to phase 3 ? */
343 #endif
345 /* remove the parentfile */
346 unlink (path);
348 /* remove oldest key from list and mark file as removed */
349 zp->keys = dki_remove (ksk);
351 // verbmesg (2, z, "kskrollover: remove parentfile and rename old key to k<zone>+<algo>+<tag>.key\n");
352 verbmesg (2, z, "\t\tkskrollover: remove parentfile and rename old key to k%s+%03d+%05d.key\n",
353 ksk->name, ksk->algo, ksk->tag);
354 lg_mesg (LG_INFO, "\"%s\": kskrollover phase3: Remove old key %d", zp->zone, ksk->tag);
355 return 1;
357 else
358 #if 0
359 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);
360 #else
361 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);
362 #endif
363 break;
364 default:
365 assert ( currphase == 1 || currphase == 2 );
366 /* NOTREACHED */
369 return 0;
372 /*****************************************************************
373 ** global function definition
374 *****************************************************************/
376 /*****************************************************************
377 ** ksk5011status ()
378 ** Check if the list of zone keys containing a revoked or a
379 ** standby key.
380 ** Remove the revoked key if it is older than 30 days.
381 ** If the lifetime of the active key is reached, do a rfc5011
382 ** keyrollover.
383 ** Returns an int with the rightmost bit set if a resigning
384 ** is required. The second rightmost bit is set, if it is an
385 ** rfc5011 zone.
386 *****************************************************************/
387 int ksk5011status (dki_t **listp, const char *dir, const char *domain, const zconf_t *z)
389 dki_t *standbykey;
390 dki_t *activekey;
391 dki_t *dkp;
392 dki_t *prev;
393 time_t currtime;
394 time_t exptime;
395 int ret;
397 assert ( listp != NULL );
398 assert ( z != NULL );
400 if ( z->k_life == 0 )
401 return 0;
403 verbmesg (1, z, "\tCheck RFC5011 status\n");
405 ret = 0;
406 currtime = time (NULL);
408 /* go through the list of key signing keys, */
409 /* remove revoked keys and set a pointer to standby and active key */
410 standbykey = activekey = NULL;
411 prev = NULL;
412 for ( dkp = *listp; dkp && dki_isksk (dkp); dkp = dkp->next )
414 exptime = get_exptime (dkp, z);
415 if ( dki_isrevoked (dkp) )
416 lg_mesg (LG_DEBUG, "zone \"%s\": found revoked key (id=%d exptime=%s); waiting for remove hold down time",
417 domain, dkp->tag, time2str (exptime, 's'));
419 /* revoked key is older than 30 days? */
420 if ( dki_isrevoked (dkp) && currtime > exptime + REMOVE_HOLD_DOWN )
422 verbmesg (1, z, "\tRemove revoked key %d which is older than 30 days\n", dkp->tag);
423 lg_mesg (LG_NOTICE, "zone \"%s\": removing revoked key %d", domain, dkp->tag);
425 /* remove key from list and mark file as removed */
426 if ( prev == NULL ) /* at the beginning of the list ? */
427 *listp = dki_remove (dkp);
428 else /* anywhere in the middle of the list */
429 prev->next = dki_remove (dkp);
431 ret |= 01; /* from now on a resigning is necessary */
434 /* remember oldest standby and active key */
435 if ( dki_status (dkp) == DKI_PUBLISHED )
436 standbykey = dkp;
437 if ( dki_status (dkp) == DKI_ACTIVE )
438 activekey = dkp;
440 /* no activekey or no standby key and also no revoked key found ? */
441 if ( activekey == NULL || (standbykey == NULL && ret == 0) )
442 return ret; /* Seems that this is a non rfc5011 zone! */
444 ret |= 02; /* Zone looks like a rfc5011 zone */
446 exptime = get_exptime (activekey, z);
447 #if 0
448 lg_mesg (LG_DEBUG, "Act Exptime: %s", time2str (exptime, 's'));
449 lg_mesg (LG_DEBUG, "Stb time: %s", time2str (dki_time (standbykey), 's'));
450 lg_mesg (LG_DEBUG, "Stb time+wait: %s", time2str (dki_time (standbykey) + min (DAYSEC * 30, z->key_ttl), 's'));
451 #endif
452 /* At the first time we introduce a standby key, the lifetime of the current KSK shouldn't be expired, */
453 /* otherwise we run into an (nearly) immediate key rollover! */
454 if ( currtime > exptime && currtime > dki_time (standbykey) + min (ADD_HOLD_DOWN, z->key_ttl) )
456 lg_mesg (LG_NOTICE, "\"%s\": starting rfc5011 rollover", domain);
457 verbmesg (1, z, "\tLifetime of Key Signing Key %d exceeded (%s): Starting rfc5011 rollover!\n",
458 activekey->tag, str_delspace (age2str (dki_age (activekey, currtime))));
459 verbmesg (2, z, "\t\t=>Generating new standby key signing key\n");
460 dkp = genfirstkey (listp, dir, domain, DKI_KSK, z, DKI_PUBLISHED); /* gentime == now; lifetime = z->k_life; exp = 0 */
461 if ( !dkp )
463 error ("\tcould not generate new standby KSK\n");
464 lg_mesg (LG_ERROR, "\%s\": can't generate new standby KSK", domain);
466 else
467 lg_mesg (LG_NOTICE, "\"%s\": generated new standby KSK %d", domain, dkp->tag);
469 /* standby key gets active */
470 verbmesg (2, z, "\t\t=>Activating old standby key %d \n", standbykey->tag);
471 dki_setstatus (standbykey, DKI_ACT);
473 /* active key should be revoked */
474 verbmesg (2, z, "\t\t=>Revoking old active key %d \n", activekey->tag);
475 dki_setstatus (activekey, DKI_REVOKED);
476 dki_setexptime (activekey, currtime); /* now the key is expired */
478 ret |= 01; /* resigning necessary */
481 return ret;
484 /*****************************************************************
485 ** kskstatus ()
486 ** Check the ksk status of a zone if a ksk lifetime is set.
487 ** If there is no key signing key present create a new one.
488 ** Prints out a warning message if the lifetime of the current
489 ** key signing key is over.
490 ** Returns 1 if a resigning of the zone is necessary, otherwise
491 ** the function returns 0.
492 *****************************************************************/
493 int kskstatus (zone_t *zonelist, zone_t *zp)
495 dki_t *akey;
496 const zconf_t *z;
498 assert ( zp != NULL );
500 z = zp->conf;
501 if ( z->k_life == 0 )
502 return 0;
504 verbmesg (1, z, "\tCheck KSK status\n");
505 /* check if a key signing key exist ? */
506 akey = (dki_t *)dki_findalgo (zp->keys, DKI_KSK, z->k_algo, 'a', 1);
507 if ( akey == NULL )
509 verbmesg (1, z, "\tNo active KSK found: generate new one\n");
510 akey = genfirstkey (&zp->keys, zp->dir, zp->zone, DKI_KSK, z, DKI_ACTIVE);
511 if ( !akey )
513 error ("\tcould not generate new KSK\n");
514 lg_mesg (LG_ERROR, "\"%s\": can't generate new KSK: \"%s\"",
515 zp->zone, dki_geterrstr());
517 else
518 lg_mesg (LG_INFO, "\"%s\": generated new KSK %d", zp->zone, akey->tag);
519 return akey != NULL; /* return value of 1 forces a resigning of the zone */
521 else /* try to start a full automated ksk rollover */
522 kskrollover (akey, zonelist, zp);
524 /* is a second algorithm requested ? (since 0.99) */
525 if ( z->k2_algo && z->k2_algo != z->k_algo )
527 /* check for ksk supporting the additional algorithm */
528 akey = (dki_t *)dki_findalgo (zp->keys, DKI_KSK, z->k2_algo, 'a', 1);
529 if ( akey == NULL )
531 verbmesg (1, z, "\tNo active KSK for additional algorithm found: generate new one\n");
532 akey = genaddkey (&zp->keys, zp->dir, zp->zone, DKI_KSK, z, DKI_ACTIVE);
533 if ( !akey )
535 error ("\tcould not generate new KSK for additional algorithm\n");
536 lg_mesg (LG_ERROR, "\"%s\": can't generate new KSK for 2nd algorithm: \"%s\"",
537 zp->zone, dki_geterrstr());
539 else
540 lg_mesg (LG_INFO, "\"%s\": generated new KSK %d for additional algorithm",
541 zp->zone, akey->tag);
542 return 1; /* return value of 1 forces a resigning of the zone */
546 return 0;
549 /*****************************************************************
550 ** zskstatus ()
551 ** Check the zsk status of a zone.
552 ** Returns 1 if a resigning of the zone is necessary, otherwise
553 ** the function returns 0.
554 *****************************************************************/
555 int zskstatus (dki_t **listp, const char *dir, const char *domain, const zconf_t *z)
557 dki_t *akey;
558 dki_t *nextkey;
559 dki_t *dkp, *last;
560 int keychange;
561 time_t lifetime;
562 time_t age;
563 time_t currtime;
565 assert ( listp != NULL );
566 /* dir can be NULL */
567 assert ( domain != NULL );
568 assert ( z != NULL );
570 currtime = time (NULL);
572 verbmesg (1, z, "\tCheck ZSK status\n");
573 dbg_val("zskstatus for %s \n", domain);
574 keychange = 0;
575 /* Is the depreciated key expired ? */
576 /* As mentioned by olaf, this is the max_ttl of all the rr in the zone */
577 lifetime = z->max_ttl + z->proptime; /* draft kolkman/gieben */
578 last = NULL;
579 dkp = *listp;
580 while ( dkp )
581 if ( !dki_isksk (dkp) &&
582 dki_status (dkp) == DKI_DEPRECIATED &&
583 dki_age (dkp, currtime) > lifetime )
585 keychange = 1;
586 verbmesg (1, z, "\tLifetime(%d sec) of depreciated key %d exceeded (%d sec)\n",
587 lifetime, dkp->tag, dki_age (dkp, currtime));
588 lg_mesg (LG_INFO, "\"%s\": old ZSK %d removed", domain, dkp->tag);
589 dkp = dki_destroy (dkp); /* delete the keyfiles */
590 dbg_msg("zskstatus: depreciated key removed ");
591 if ( last )
592 last->next = dkp;
593 else
594 *listp = dkp;
595 verbmesg (1, z, "\t\t->remove it\n");
597 else
599 last = dkp;
600 dkp = dkp->next;
603 /* check status of active key */
604 dbg_msg("zskstatus check status of active key ");
605 lifetime = z->z_life; /* global configured lifetime for zsk */
606 akey = (dki_t *)dki_findalgo (*listp, DKI_ZSK, z->k_algo, 'a', 1);
607 if ( akey == NULL && lifetime > 0 ) /* no active key found */
609 verbmesg (1, z, "\tNo active ZSK found: generate new one\n");
610 akey = genfirstkey (listp, dir, domain, DKI_ZSK, z, DKI_ACTIVE);
611 if ( !akey )
613 error ("\tcould not generate new ZSK\n");
614 lg_mesg (LG_ERROR, "\%s\": can't generate new ZSK", domain);
616 else
617 lg_mesg (LG_INFO, "\"%s\": generated new ZSK %d", domain, akey->tag);
619 else /* active key exist */
621 if ( dki_lifetime (akey) )
622 lifetime = dki_lifetime (akey); /* set lifetime to lt of active key */
624 /* lifetime of active key is expired and published key exist ? */
625 age = dki_age (akey, currtime);
626 if ( lifetime > 0 && age > lifetime - (OFFSET) )
628 verbmesg (1, z, "\tLifetime(%d +/-%d sec) of active key %d exceeded (%d sec)\n",
629 lifetime, (OFFSET) , akey->tag, dki_age (akey, currtime) );
631 /* depreciate the key only if there is another active or published key */
632 if ( (nextkey = (dki_t *)dki_findalgo (*listp, DKI_ZSK, z->k_algo, 'a', 2)) == NULL ||
633 nextkey == akey )
634 nextkey = (dki_t *)dki_findalgo (*listp, DKI_ZSK, z->k_algo, 'p', 1);
636 /* Is the published key sufficient long in the zone ? */
637 /* As mentioned by Olaf, this should be the ttl of the DNSKEY RR ! */
638 if ( nextkey && dki_age (nextkey, currtime) > z->key_ttl + z->proptime )
640 keychange = 1;
641 verbmesg (1, z, "\t\t->depreciate it\n");
642 dki_setstatus (akey, 'd'); /* depreciate the active key */
643 verbmesg (1, z, "\t\t->activate published key %d\n", nextkey->tag);
644 dki_setstatus (nextkey, 'a'); /* activate published key */
645 lg_mesg (LG_NOTICE, "\"%s\": lifetime of zone signing key %d exceeded: ZSK rollover done", domain, akey->tag);
646 akey = nextkey;
647 nextkey = NULL;
648 lifetime = dki_lifetime (akey); /* set lifetime to lt of the new active key (F. Behrens) */
650 else
652 verbmesg (1, z, "\t\t->waiting for published key\n");
653 lg_mesg (LG_NOTICE, "\"%s\": lifetime of zone signing key %d exceeded since %s: ZSK rollover deferred: waiting for published key",
654 domain, akey->tag, str_delspace (age2str (age - lifetime)));
659 /* Should we add a new publish key? */
660 nextkey = (dki_t *)dki_findalgo (*listp, DKI_ZSK, z->k_algo, 'p', 1); /* is there a published ZSK? */
661 #if defined(ALLOW_ALWAYS_PREPUBLISH_ZSK) && ALLOW_ALWAYS_PREPUBLISH_ZSK
662 if ( z->z_always ) /* always add a pre-publish ZSK (patch from Hrant Dadivanyan) */
664 if ( nextkey == NULL )
666 verbmesg (1, z, "\tNew key for pre-publishing needed\n");
667 nextkey = genfirstkey (listp, dir, domain, DKI_ZSK, z, DKI_PUB);
668 if ( nextkey )
670 keychange = 1;
671 verbmesg (1, z, "\t\t->creating new key %d\n", nextkey->tag);
672 lg_mesg (LG_INFO, "\"%s\": new key %d generated for pre-publishing", domain, nextkey->tag);
674 else
676 error ("\tcould not generate new ZSK: \"%s\"\n", dki_geterrstr());
677 lg_mesg (LG_ERROR, "\"%s\": can't generate new ZSK: \"%s\"",
678 domain, dki_geterrstr());
682 else /* do we need a new ZSK ? */
683 #endif
685 /* This is necessary if the active key will be expired at the
686 * next re-signing interval (The published time will be checked
687 * just before the active key will be removed. See above).
689 if ( nextkey == NULL && lifetime > 0 && (akey == NULL ||
690 dki_age (akey, currtime + z->resign) > lifetime - (OFFSET)) )
692 verbmesg (1, z, "\tNew ZSK for publishing needed\n");
693 nextkey = genfirstkey (listp, dir, domain, DKI_ZSK, z, DKI_PUB);
694 if ( nextkey )
696 keychange = 1;
697 verbmesg (1, z, "\t\t->creating new key %d\n", nextkey->tag);
698 lg_mesg (LG_INFO, "\"%s\": new zone signing key %d generated for publishing", domain, nextkey->tag);
700 else
702 error ("\tcould not generate new ZSK: \"%s\"\n", dki_geterrstr());
703 lg_mesg (LG_ERROR, "\"%s\": can't generate new ZSK: \"%s\"",
704 domain, dki_geterrstr());
709 /* is a second algorithm requested ? (since 0.99) */
710 if ( z->k2_algo && z->k2_algo != z->k_algo )
712 /* check for zsk supporting the additional algorithm */
713 akey = (dki_t *)dki_findalgo (*listp, DKI_ZSK, z->k2_algo, 'a', 1);
714 if ( akey == NULL )
716 verbmesg (1, z, "\tNo active ZSK for second algorithm found: generate new one\n");
717 akey = genaddkey (listp, dir, domain, DKI_ZSK, z, DKI_ACTIVE);
718 if ( !akey )
720 error ("\tcould not generate new ZSK for 2nd algorithm\n");
721 lg_mesg (LG_ERROR, "\"%s\": can't generate new ZSK for 2nd algorithm: \"%s\"",
722 domain, dki_geterrstr());
724 else
725 lg_mesg (LG_INFO, "\"%s\": generated new ZSK %d for 2nd algorithm",
726 domain, akey->tag);
727 return 1; /* return value of 1 forces a resigning of the zone */
731 return keychange;