summaryrefslogtreecommitdiffstats
path: root/contrib/zkt/rollover.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/zkt/rollover.c')
-rw-r--r--contrib/zkt/rollover.c615
1 files changed, 615 insertions, 0 deletions
diff --git a/contrib/zkt/rollover.c b/contrib/zkt/rollover.c
new file mode 100644
index 0000000..0c9fee0
--- /dev/null
+++ b/contrib/zkt/rollover.c
@@ -0,0 +1,615 @@
+/*****************************************************************
+**
+** @(#) rollover.c -- The key rollover functions
+**
+** Copyright (c) Jan 2005 - May 2008, Holger Zuleger HZnet. All rights reserved.
+**
+** This software is open source.
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions
+** are met:
+**
+** Redistributions of source code must retain the above copyright notice,
+** this list of conditions and the following disclaimer.
+**
+** Redistributions in binary form must reproduce the above copyright notice,
+** this list of conditions and the following disclaimer in the documentation
+** and/or other materials provided with the distribution.
+**
+** Neither the name of Holger Zuleger HZnet nor the names of its contributors may
+** be used to endorse or promote products derived from this software without
+** specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+** POSSIBILITY OF SUCH DAMAGE.
+**
+*****************************************************************/
+# include <stdio.h>
+# include <string.h>
+# include <stdlib.h>
+# include <ctype.h>
+# include <time.h>
+# include <assert.h>
+# include <dirent.h>
+# include <errno.h>
+# include <unistd.h>
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+# include "config_zkt.h"
+# include "zconf.h"
+# include "debug.h"
+
+# include "misc.h"
+# include "zone.h"
+# include "dki.h"
+# include "log.h"
+#define extern
+# include "rollover.h"
+#undef extern
+
+/*****************************************************************
+** local function definition
+*****************************************************************/
+
+static dki_t *genkey (dki_t **listp, const char *dir, const char *domain, int ksk, const zconf_t *conf, int status)
+{
+ dki_t *dkp;
+
+ if ( listp == NULL || domain == NULL )
+ return NULL;
+
+ if ( ksk )
+ dkp = dki_new (dir, domain, DKI_KSK, conf->k_algo, conf->k_bits, conf->k_random, conf->k_life / DAYSEC);
+ else
+ dkp = dki_new (dir, domain, DKI_ZSK, conf->z_algo, conf->z_bits, conf->z_random, conf->z_life / DAYSEC);
+ dki_add (listp, dkp);
+ dki_setstatus (dkp, status);
+
+ return dkp;
+}
+
+static time_t get_exptime (dki_t *key, const zconf_t *z)
+{
+ time_t exptime;
+
+ exptime = dki_exptime (key);
+ if ( exptime == 0L )
+ {
+ if ( dki_lifetime (key) )
+ exptime = dki_time (key) + dki_lifetime (key);
+ else
+ exptime = dki_time (key) + z->k_life;
+ }
+
+ return exptime;
+}
+
+/*****************************************************************
+** is_parentdirsigned (name)
+** Check if the parent directory of the zone specified by zp
+** is a directory with a signed zone
+** Returns 0 | 1
+*****************************************************************/
+static int is_parentdirsigned (const zone_t *zonelist, const zone_t *zp)
+{
+ char path[MAX_PATHSIZE+1];
+ const char *ext;
+#if 0
+ const zconf_t *conf;
+
+ /* check if there is a local config file to get the name of the zone file */
+ snprintf (path, sizeof (path), "%s/../%s", zp->dir, LOCALCONF_FILE);
+ if ( fileexist (path) ) /* parent dir has local config file ? */
+ conf = loadconfig (path, NULL);
+ else
+ conf = zp->conf;
+
+ /* build the path of the .signed zone file */
+ snprintf (path, sizeof (path), "%s/../%s.signed", conf->dir, conf->zonefile);
+ if ( conf != zp->conf ) /* if we read in a local config file.. */
+ free (conf); /* ..free the memory used */
+
+#else
+ /* currently we use the signed zone file name of the
+ * current directory for checking if the file exist.
+ * TODO: Instead we have to use the name of the zone file
+ * used in the parent dir (see above)
+ */
+
+ ext = strrchr (zp->sfile, '.');
+ if ( ext && strcmp (zp->sfile, ".dsigned") == 0 ) /* is the current zone a dynamic one ? */
+ /* hack: we are using the standard zone file name for a static zone here */
+ snprintf (path, sizeof (path), "%s/../%s", zp->dir, "zone.db.signed");
+ else
+ {
+# if 1
+ const zone_t *parent;
+ const char *parentname;
+
+ /* find out name of parent */
+ parentname = strchr (zp->zone, '.'); /* find first dot in zone name */
+ if ( parentname == NULL ) /* no parent found! */
+ return 0;
+ parentname += 1; /* skip '.' */
+
+ /* try to find parent zone in zonelist */
+ if ( (parent = zone_search (zonelist, parentname)) == NULL )
+ return 0;
+ snprintf (path, sizeof (path), "%s/%s", parent->dir, parent->sfile);
+# else
+ snprintf (path, sizeof (path), "%s/../%s", zp->dir, zp->sfile);
+# endif
+ }
+#endif
+lg_mesg (LG_DEBUG, "%s: is_parentdirsigned = %d fileexist (%s)\n", zp->zone, fileexist (path), path);
+ return fileexist (path); /* parent dir has zone.db.signed file ? */
+}
+
+/*****************************************************************
+** create_parent_file ()
+*****************************************************************/
+static int create_parent_file (const char *fname, int phase, int ttl, const dki_t *dkp)
+{
+ FILE *fp;
+
+ assert ( fname != NULL );
+
+ if ( dkp == NULL || (phase != 1 && phase != 2) )
+ return 0;
+
+ if ( (fp = fopen (fname, "w")) == NULL )
+ fatal ("can\'t create new parentfile \"%s\"\n", fname);
+
+ if ( phase == 1 )
+ fprintf (fp, "; KSK rollover phase1 (new key generated but this is alread the old one)\n");
+ else
+ fprintf (fp, "; KSK rollover phase2 (this is the new key)\n");
+
+ dki_prt_dnskeyttl (dkp, fp, ttl);
+ fclose (fp);
+
+ return phase;
+}
+
+/*****************************************************************
+** get_parent_phase ()
+*****************************************************************/
+static int get_parent_phase (const char *file)
+{
+ FILE *fp;
+ int phase;
+
+ if ( (fp = fopen (file, "r")) == NULL )
+ return -1;
+
+ phase = 0;
+ if ( fscanf (fp, "; KSK rollover phase%d", &phase) != 1 )
+ phase = 0;
+
+ fclose (fp);
+ return phase;
+}
+
+/*****************************************************************
+** kskrollover ()
+*****************************************************************/
+static int kskrollover (dki_t *ksk, zone_t *zonelist, zone_t *zp)
+{
+ char path[MAX_PATHSIZE+1];
+ const zconf_t *z;
+ time_t lifetime;
+ time_t currtime;
+ time_t age;
+ int currphase;
+ int parfile_age;
+ int parent_propagation;
+ int parent_resign;
+ int parent_keyttl;
+
+
+ assert ( ksk != NULL );
+ assert ( zp != NULL );
+
+ z = zp->conf;
+ /* check ksk lifetime */
+ if ( (lifetime = dki_lifetime (ksk)) == 0 ) /* if lifetime of key is not set.. */
+ lifetime = z->k_life; /* ..use global configured lifetime */
+
+ currtime = time (NULL);
+ age = dki_age (ksk, currtime);
+
+ /* build path of parent-file */
+ pathname (path, sizeof (path), zp->dir, "parent-", zp->zone);
+
+ /* check if we have to change the ksk ? */
+ if ( lifetime > 0 && age > lifetime && !fileexist (path) ) /* lifetime is over and no kskrollover in progress */
+ {
+ /* we are using hierachical mode and the parent directory contains a signed zone ? */
+ if ( z->keysetdir && strcmp (z->keysetdir, "..") == 0 && is_parentdirsigned (zonelist, zp) )
+ {
+ verbmesg (2, z, "\t\tkskrollover: create new key signing key\n");
+ /* create a new key: this is phase one of a double signing key rollover */
+ ksk = genkey (&zp->keys, zp->dir, zp->zone, DKI_KSK, z, DKI_ACTIVE);
+ if ( ksk == NULL )
+ {
+ lg_mesg (LG_ERROR, "\"%s\": unable to generate new ksk for double signing rollover", zp->zone);
+ return 0;
+ }
+ lg_mesg (LG_INFO, "\"%s\": kskrollover phase1: New key %d generated", zp->zone, ksk->tag);
+
+ /* find the oldest active ksk to create the parent file */
+ if ( (ksk = (dki_t *)dki_find (zp->keys, 1, 'a', 1)) == NULL )
+ lg_mesg (LG_ERROR, "kskrollover phase1: Couldn't find the old active key\n");
+ if ( !create_parent_file (path, 1, z->key_ttl, ksk) )
+ lg_mesg (LG_ERROR, "Couldn't create parentfile %s\n", path);
+
+ }
+ else /* print out a warning only */
+ {
+ logmesg ("\t\tWarning: Lifetime of Key Signing Key %d exceeded: %s\n",
+ ksk->tag, str_delspace (age2str (age)));
+ lg_mesg (LG_WARNING, "\"%s\": lifetime of key signing key %d exceeded since %s",
+ zp->zone, ksk->tag, str_delspace (age2str (age - lifetime)));
+ }
+ return 1;
+ }
+
+ /* now check if there is an ongoing key rollover */
+
+ /* check if parent-file already exist */
+ if ( !fileexist (path) ) /* no parent-<zone> file found ? */
+ return 0; /* ok, that's it */
+
+ /* check the ksk rollover phase we are in */
+ currphase = get_parent_phase (path); /* this is the actual state we are in */
+ parfile_age = file_age (path);
+
+ /* TODO: Set these values to the one found in the parent dnssec.conf file */
+ parent_propagation = 5 * MINSEC;
+ parent_resign = z->resign;
+ parent_keyttl = z->key_ttl;
+
+ switch ( currphase )
+ {
+ case 1: /* we are currently in state one (new ksk already generated) */
+ if ( parfile_age > z->proptime + z->key_ttl ) /* can we go to phase 2 ? */
+ {
+ verbmesg (2, z, "\t\tkskrollover: save new ksk in parent file\n");
+ ksk = ksk->next; /* set ksk to new ksk */
+ if ( !create_parent_file (path, currphase+1, z->key_ttl, ksk) )
+ lg_mesg (LG_ERROR, "Couldn't create parentfile %s\n", path);
+ lg_mesg (LG_INFO, "\"%s\": kskrollover phase2: send new key %d to the parent zone", zp->zone, ksk->tag);
+ return 1;
+ }
+ else
+ verbmesg (2, z, "\t\tkskrollover: we are in state 1 and waiting for propagation of the new key (parentfile %d < prop %d + keyttl %d\n", parfile_age, z->proptime, z->key_ttl);
+ break;
+ case 2: /* we are currently in state two (propagation of new key to the parent) */
+#if 0
+ if ( parfile_age >= parent_propagation + parent_resign + parent_keyttl ) /* can we go to phase 3 ? */
+#else
+ if ( parfile_age >= parent_propagation + parent_keyttl ) /* can we go to phase 3 ? */
+#endif
+ {
+ /* remove the parentfile */
+ unlink (path);
+
+ /* remove oldest key from list and mark file as removed */
+ zp->keys = dki_remove (ksk);
+
+ // verbmesg (2, z, "kskrollover: remove parentfile and rename old key to k<zone>+<algo>+<tag>.key\n");
+ verbmesg (2, z, "\t\tkskrollover: remove parentfile and rename old key to k%s+%03d+%05d.key\n",
+ ksk->name, ksk->algo, ksk->tag);
+ lg_mesg (LG_INFO, "\"%s\": kskrollover phase3: Remove old key %d", zp->zone, ksk->tag);
+ return 1;
+ }
+ else
+#if 0
+ 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);
+#else
+ verbmesg (2, z, "\t\tkskrollover: we are in state 2 and waiting for parent propagation (parentfile %d < parentprop %d + parentkeyttl %d\n", parfile_age, parent_propagation, parent_keyttl);
+#endif
+ break;
+ default:
+ assert ( currphase == 1 || currphase == 2 );
+ /* NOTREACHED */
+ }
+
+ return 0;
+}
+
+/*****************************************************************
+** global function definition
+*****************************************************************/
+
+/*****************************************************************
+** ksk5011status ()
+** Check if the list of zone keys containing a revoked or a
+** standby key.
+** Remove the revoked key if it is older than 30 days.
+** If the lifetime of the active key is reached, do a rfc5011
+** keyrollover.
+** Returns an int with the rightmost bit set if a resigning
+** is required. The second rightmost bit is set, if it is an
+** rfc5011 zone.
+*****************************************************************/
+int ksk5011status (dki_t **listp, const char *dir, const char *domain, const zconf_t *z)
+{
+ dki_t *standbykey;
+ dki_t *activekey;
+ dki_t *dkp;
+ dki_t *prev;
+ time_t currtime;
+ time_t exptime;
+ int ret;
+
+ assert ( listp != NULL );
+ assert ( z != NULL );
+
+ if ( z->k_life == 0 )
+ return 0;
+
+ verbmesg (1, z, "\tCheck RFC5011 status\n");
+
+ ret = 0;
+ currtime = time (NULL);
+
+ /* go through the list of key signing keys, */
+ /* remove revoked keys and set a pointer to standby and active key */
+ standbykey = activekey = NULL;
+ prev = NULL;
+ for ( dkp = *listp; dkp && dki_isksk (dkp); dkp = dkp->next )
+ {
+ exptime = get_exptime (dkp, z);
+ if ( dki_isrevoked (dkp) )
+ lg_mesg (LG_DEBUG, "Rev Exptime: %s", time2str (exptime, 's'));
+
+ /* revoked key is older than 30 days? */
+ if ( dki_isrevoked (dkp) && currtime > exptime + (DAYSEC * 30) )
+ {
+ verbmesg (1, z, "\tRemove revoked key %d which is older than 30 days\n", dkp->tag);
+ lg_mesg (LG_NOTICE, "zone \"%s\": removing revoked key %d", domain, dkp->tag);
+
+ /* remove key from list and mark file as removed */
+ if ( prev == NULL ) /* at the beginning of the list ? */
+ *listp = dki_remove (dkp);
+ else /* anywhere in the middle of the list */
+ prev->next = dki_remove (dkp);
+
+ ret |= 01; /* from now on a resigning is neccessary */
+ }
+
+ /* remember oldest standby and active key */
+ if ( dki_status (dkp) == DKI_PUBLISHED )
+ standbykey = dkp;
+ if ( dki_status (dkp) == DKI_ACTIVE )
+ activekey = dkp;
+ }
+
+ if ( standbykey == NULL && ret == 0 ) /* no standby key and also no revoked key found ? */
+ return ret; /* Seems that this is a non rfc5011 zone! */
+
+ ret |= 02; /* Zone looks like a rfc5011 zone */
+
+ exptime = get_exptime (activekey, z);
+#if 0
+ lg_mesg (LG_DEBUG, "Act Exptime: %s", time2str (exptime, 's'));
+ lg_mesg (LG_DEBUG, "Stb time: %s", time2str (dki_time (standbykey), 's'));
+ lg_mesg (LG_DEBUG, "Stb time+wait: %s", time2str (dki_time (standbykey) + min (DAYSEC * 30, z->key_ttl), 's'));
+#endif
+ /* At the time we first introduce a standby key, the lifetime of the current KSK should not be expired, */
+ /* otherwise we run into an (nearly) immediate key rollover! */
+ if ( currtime > exptime && currtime > dki_time (standbykey) + min (DAYSEC * 30, z->key_ttl) )
+ {
+ lg_mesg (LG_NOTICE, "\"%s\": starting rfc5011 rollover", domain);
+ verbmesg (1, z, "\tLifetime of Key Signing Key %d exceeded (%s): Starting rfc5011 rollover!\n",
+ activekey->tag, str_delspace (age2str (dki_age (activekey, currtime))));
+ verbmesg (2, z, "\t\t=>Generating new standby key signing key\n");
+ dkp = genkey (listp, dir, domain, DKI_KSK, z, DKI_PUBLISHED); /* gentime == now; lifetime = z->k_life; exp = 0 */
+ if ( !dkp )
+ {
+ error ("\tcould not generate new standby KSK\n");
+ lg_mesg (LG_ERROR, "\%s\": can't generate new standby KSK", domain);
+ }
+ else
+ lg_mesg (LG_INFO, "\"%s\": generated new standby KSK %d", domain, dkp->tag);
+
+ /* standby key gets active */
+ verbmesg (2, z, "\t\t=>Activating old standby key %d \n", standbykey->tag);
+ dki_setstatus (standbykey, DKI_ACT);
+
+ /* active key should be revoked */
+ verbmesg (2, z, "\t\t=>Revoking old active key %d \n", activekey->tag);
+ dki_setstatus (activekey, DKI_REVOKED);
+ dki_setexptime (activekey, currtime); /* now the key is expired */
+
+ ret |= 01; /* resigning neccessary */
+ }
+
+ return ret;
+}
+
+/*****************************************************************
+** kskstatus ()
+** Check the ksk status of a zone if a ksk lifetime is set.
+** If there is no key signing key present create a new one.
+** Prints out a warning message if the lifetime of the current
+** key signing key is over.
+** Returns 1 if a resigning of the zone is neccessary, otherwise
+** the function returns 0.
+*****************************************************************/
+int kskstatus (zone_t *zonelist, zone_t *zp)
+{
+ dki_t *akey;
+ const zconf_t *z;
+
+ assert ( zp != NULL );
+
+ z = zp->conf;
+ if ( z->k_life == 0 )
+ return 0;
+
+ verbmesg (1, z, "\tCheck KSK status\n");
+ /* check if a key signing key exist ? */
+ akey = (dki_t *)dki_find (zp->keys, 1, 'a', 1);
+ if ( akey == NULL )
+ {
+ verbmesg (1, z, "\tNo active KSK found: generate new one\n");
+ akey = genkey (&zp->keys, zp->dir, zp->zone, DKI_KSK, z, DKI_ACTIVE);
+ if ( !akey )
+ {
+ error ("\tcould not generate new KSK\n");
+ lg_mesg (LG_ERROR, "\"%s\": can't generate new KSK: \"%s\"",
+ zp->zone, dki_geterrstr());
+ }
+ else
+ lg_mesg (LG_INFO, "\"%s\": generated new KSK %d", zp->zone, akey->tag);
+ return akey != NULL; /* return value of 1 forces a resigning of the zone */
+ }
+ else /* try to start a full automatic ksk rollover */
+ kskrollover (akey, zonelist, zp);
+
+ return 0;
+}
+
+/*****************************************************************
+** zskstatus ()
+** Check the zsk status of a zone.
+** Returns 1 if a resigning of the zone is neccessary, otherwise
+** the function returns 0.
+*****************************************************************/
+int zskstatus (dki_t **listp, const char *dir, const char *domain, const zconf_t *z)
+{
+ dki_t *akey;
+ dki_t *nextkey;
+ dki_t *dkp, *last;
+ int keychange;
+ time_t lifetime;
+ time_t age;
+ time_t currtime;
+
+ assert ( listp != NULL );
+ /* dir can be NULL */
+ assert ( domain != NULL );
+ assert ( z != NULL );
+
+ currtime = time (NULL);
+
+ verbmesg (1, z, "\tCheck ZSK status\n");
+ dbg_val("zskstatus for %s \n", domain);
+ keychange = 0;
+ /* Is the depreciated key expired ? */
+ /* As mentioned by olaf, this is the max_ttl of all the rr in the zone */
+ lifetime = z->max_ttl + z->proptime; /* draft kolkman/gieben */
+ last = NULL;
+ dkp = *listp;
+ while ( dkp )
+ if ( !dki_isksk (dkp) &&
+ dki_status (dkp) == DKI_DEPRECIATED &&
+ dki_age (dkp, currtime) > lifetime )
+ {
+ keychange = 1;
+ verbmesg (1, z, "\tLifetime(%d sec) of depreciated key %d exceeded (%d sec)\n",
+ lifetime, dkp->tag, dki_age (dkp, currtime));
+ lg_mesg (LG_INFO, "\"%s\": old ZSK %d removed", domain, dkp->tag);
+ dkp = dki_destroy (dkp); /* delete the keyfiles */
+ dbg_msg("zskstatus: depreciated key removed ");
+ if ( last )
+ last->next = dkp;
+ else
+ *listp = dkp;
+ verbmesg (1, z, "\t\t->remove it\n");
+ }
+ else
+ {
+ last = dkp;
+ dkp = dkp->next;
+ }
+
+ /* check status of active key */
+ dbg_msg("zskstatus check status of active key ");
+ lifetime = z->z_life; /* global configured lifetime for zsk */
+ akey = (dki_t *)dki_find (*listp, 0, 'a', 1);
+ if ( akey == NULL && lifetime > 0 ) /* no active key found */
+ {
+ verbmesg (1, z, "\tNo active ZSK found: generate new one\n");
+ akey = genkey (listp, dir, domain, DKI_ZSK, z, DKI_ACTIVE);
+ lg_mesg (LG_INFO, "\"%s\": generated new ZSK %d", domain, akey->tag);
+ }
+ else /* active key exist */
+ {
+ if ( dki_lifetime (akey) )
+ lifetime = dki_lifetime (akey); /* set lifetime to lt of active key */
+
+ /* lifetime of active key is expired and published key exist ? */
+ age = dki_age (akey, currtime);
+ if ( lifetime > 0 && age > lifetime - (OFFSET) )
+ {
+ verbmesg (1, z, "\tLifetime(%d +/-%d sec) of active key %d exceeded (%d sec)\n",
+ lifetime, (OFFSET) , akey->tag, dki_age (akey, currtime) );
+
+ /* depreciate the key only if there is another active or published key */
+ if ( (nextkey = (dki_t *)dki_find (*listp, 0, 'a', 2)) == NULL ||
+ nextkey == akey )
+ nextkey = (dki_t *)dki_find (*listp, 0, 'p', 1);
+
+ /* Is the published key sufficient long in the zone ? */
+ /* As mentioned by Olaf, this should be the ttl of the DNSKEY RR ! */
+ if ( nextkey && dki_age (nextkey, currtime) > z->key_ttl + z->proptime )
+ {
+ keychange = 1;
+ verbmesg (1, z, "\t\t->depreciate it\n");
+ dki_setstatus (akey, 'd'); /* depreciate the active key */
+ verbmesg (1, z, "\t\t->activate published key %d\n", nextkey->tag);
+ dki_setstatus (nextkey, 'a'); /* activate published key */
+ lg_mesg (LG_NOTICE, "\"%s\": lifetime of zone signing key %d exceeded: ZSK rollover done", domain, akey->tag);
+ akey = nextkey;
+ nextkey = NULL;
+ }
+ else
+ {
+ verbmesg (1, z, "\t\t->waiting for published key\n");
+ lg_mesg (LG_NOTICE, "\"%s\": lifetime of zone signing key %d exceeded since %s: ZSK rollover deferred: waiting for published key",
+ domain, akey->tag, str_delspace (age2str (age - lifetime)));
+ }
+ }
+ }
+ /* Should we add a new publish key? This is neccessary if the active
+ * key will be expired at the next re-signing interval (The published
+ * time will be checked just before the active key will be removed.
+ * See above).
+ */
+ nextkey = (dki_t *)dki_find (*listp, 0, 'p', 1);
+ if ( nextkey == NULL && lifetime > 0 && (akey == NULL ||
+ dki_age (akey, currtime + z->resign) > lifetime - (OFFSET)) )
+ {
+ keychange = 1;
+ verbmesg (1, z, "\tNew key for publishing needed\n");
+ nextkey = genkey (listp, dir, domain, DKI_ZSK, z, DKI_PUB);
+
+ if ( nextkey )
+ {
+ verbmesg (1, z, "\t\t->creating new key %d\n", nextkey->tag);
+ lg_mesg (LG_INFO, "\"%s\": new key %d generated for publishing", domain, nextkey->tag);
+ }
+ else
+ {
+ error ("\tcould not generate new ZSK: \"%s\"\n", dki_geterrstr());
+ lg_mesg (LG_ERROR, "\"%s\": can't generate new ZSK: \"%s\"",
+ domain, dki_geterrstr());
+ }
+ }
+ return keychange;
+}
+