1 /* $NetBSD: rollover.c,v 1.1.1.1 2015/07/08 15:37:48 christos Exp $ */ 2 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. 10 ** 11 ** Redistribution and use in source and binary forms, with or without 12 ** modification, are permitted provided that the following conditions 13 ** are met: 14 ** 15 ** Redistributions of source code must retain the above copyright notice, 16 ** this list of conditions and the following disclaimer. 17 ** 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. 21 ** 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. 25 ** 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. 37 ** 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" 54 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 62 63 /***************************************************************** 64 ** local function definition 65 *****************************************************************/ 66 67 static dki_t *genkey (int addkey, dki_t **listp, const char *dir, const char *domain, int ksk, const zconf_t *conf, int status); 68 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) 71 { 72 return genkey (0, listp, dir, domain, ksk, conf, status); 73 } 74 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) 77 { 78 return genkey (1, listp, dir, domain, ksk, conf, status); 79 } 80 81 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) 84 { 85 dki_t *dkp; 86 int confalgo; 87 int algo; 88 89 #if 0 90 if ( listp == NULL || domain == NULL ) 91 return NULL; 92 #else 93 assert ( listp != NULL ); 94 assert ( domain != NULL ); 95 #endif 96 97 if ( addkey ) /* generating an additional key ? */ 98 confalgo = conf->k2_algo; 99 else 100 confalgo = conf->k_algo; 101 102 algo = confalgo; 103 if ( conf->nsec3 != NSEC3_OFF ) /* is nsec3 turned on ? */ 104 { 105 if ( confalgo == DK_ALGO_RSASHA1 ) 106 algo = DK_ALGO_NSEC3RSASHA1; 107 else if ( confalgo == DK_ALGO_DSA ) 108 algo = DK_ALGO_NSEC3DSA; 109 } 110 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); 117 118 return dkp; 119 } 120 121 /* get expiration time */ 122 static time_t get_exptime (dki_t *key, const zconf_t *z) 123 { 124 time_t exptime; 125 126 exptime = dki_exptime (key); 127 if ( exptime == 0L ) 128 { 129 if ( dki_lifetime (key) ) 130 exptime = dki_time (key) + dki_lifetime (key); 131 else 132 exptime = dki_time (key) + z->k_life; 133 } 134 135 return exptime; 136 } 137 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) 145 { 146 char path[MAX_PATHSIZE+1]; 147 const char *ext; 148 #if 0 149 const zconf_t *conf; 150 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; 157 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 */ 162 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) 168 */ 169 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 175 { 176 # if 1 177 const zone_t *parent; 178 const char *parentname; 179 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 '.' */ 185 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 193 } 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 ? */ 197 } 198 199 /***************************************************************** 200 ** create_parent_file () 201 *****************************************************************/ 202 static int create_parent_file (const char *fname, int phase, int ttl, const dki_t *dkp) 203 { 204 FILE *fp; 205 206 assert ( fname != NULL ); 207 208 if ( dkp == NULL || (phase != 1 && phase != 2) ) 209 return 0; 210 211 if ( (fp = fopen (fname, "w")) == NULL ) 212 fatal ("can\'t create new parentfile \"%s\"\n", fname); 213 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"); 218 219 dki_prt_dnskeyttl (dkp, fp, ttl); 220 fclose (fp); 221 222 return phase; 223 } 224 225 /***************************************************************** 226 ** get_parent_phase () 227 *****************************************************************/ 228 static int get_parent_phase (const char *file) 229 { 230 FILE *fp; 231 int phase; 232 233 if ( (fp = fopen (file, "r")) == NULL ) 234 return -1; 235 236 phase = 0; 237 if ( fscanf (fp, "; KSK rollover phase%d", &phase) != 1 ) 238 phase = 0; 239 240 fclose (fp); 241 return phase; 242 } 243 244 /***************************************************************** 245 ** kskrollover () 246 *****************************************************************/ 247 static int kskrollover (dki_t *ksk, zone_t *zonelist, zone_t *zp) 248 { 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; 259 260 261 assert ( ksk != NULL ); 262 assert ( zp != NULL ); 263 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 */ 268 269 currtime = time (NULL); 270 age = dki_age (ksk, currtime); 271 272 /* build path of parent-file */ 273 pathname (path, sizeof (path), zp->dir, "parent-", zp->zone); 274 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 */ 277 { 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) ) 280 { 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 ) 285 { 286 lg_mesg (LG_ERROR, "\"%s\": unable to generate new ksk for double signing rollover", zp->zone); 287 return 0; 288 } 289 lg_mesg (LG_INFO, "\"%s\": kskrollover phase1: New key %d generated", zp->zone, ksk->tag); 290 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); 296 297 } 298 else /* print out a warning only */ 299 { 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))); 304 } 305 return 1; 306 } 307 308 /* now check if there is an ongoing key rollover */ 309 310 /* check if parent-file already exist */ 311 if ( !fileexist (path) ) /* no parent-<zone> file found ? */ 312 return 0; /* ok, that's it */ 313 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); 317 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; 322 323 switch ( currphase ) 324 { 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 ? */ 327 { 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; 334 } 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 344 { 345 /* remove the parentfile */ 346 unlink (path); 347 348 /* remove oldest key from list and mark file as removed */ 349 zp->keys = dki_remove (ksk); 350 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; 356 } 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 */ 367 } 368 369 return 0; 370 } 371 372 /***************************************************************** 373 ** global function definition 374 *****************************************************************/ 375 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) 388 { 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; 396 397 assert ( listp != NULL ); 398 assert ( z != NULL ); 399 400 if ( z->k_life == 0 ) 401 return 0; 402 403 verbmesg (1, z, "\tCheck RFC5011 status\n"); 404 405 ret = 0; 406 currtime = time (NULL); 407 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 ) 413 { 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')); 418 419 /* revoked key is older than 30 days? */ 420 if ( dki_isrevoked (dkp) && currtime > exptime + REMOVE_HOLD_DOWN ) 421 { 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); 424 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); 430 431 ret |= 01; /* from now on a resigning is necessary */ 432 } 433 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; 439 } 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! */ 443 444 ret |= 02; /* Zone looks like a rfc5011 zone */ 445 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) ) 455 { 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 ) 462 { 463 error ("\tcould not generate new standby KSK\n"); 464 lg_mesg (LG_ERROR, "\%s\": can't generate new standby KSK", domain); 465 } 466 else 467 lg_mesg (LG_NOTICE, "\"%s\": generated new standby KSK %d", domain, dkp->tag); 468 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); 472 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 */ 477 478 ret |= 01; /* resigning necessary */ 479 } 480 481 return ret; 482 } 483 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) 494 { 495 dki_t *akey; 496 const zconf_t *z; 497 498 assert ( zp != NULL ); 499 500 z = zp->conf; 501 if ( z->k_life == 0 ) 502 return 0; 503 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 ) 508 { 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 ) 512 { 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()); 516 } 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 */ 520 } 521 else /* try to start a full automated ksk rollover */ 522 kskrollover (akey, zonelist, zp); 523 524 /* is a second algorithm requested ? (since 0.99) */ 525 if ( z->k2_algo && z->k2_algo != z->k_algo ) 526 { 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 ) 530 { 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 ) 534 { 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()); 538 } 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 */ 543 } 544 } 545 546 return 0; 547 } 548 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) 556 { 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; 564 565 assert ( listp != NULL ); 566 /* dir can be NULL */ 567 assert ( domain != NULL ); 568 assert ( z != NULL ); 569 570 currtime = time (NULL); 571 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 ) 584 { 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"); 596 } 597 else 598 { 599 last = dkp; 600 dkp = dkp->next; 601 } 602 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 */ 608 { 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 ) 612 { 613 error ("\tcould not generate new ZSK\n"); 614 lg_mesg (LG_ERROR, "\%s\": can't generate new ZSK", domain); 615 } 616 else 617 lg_mesg (LG_INFO, "\"%s\": generated new ZSK %d", domain, akey->tag); 618 } 619 else /* active key exist */ 620 { 621 if ( dki_lifetime (akey) ) 622 lifetime = dki_lifetime (akey); /* set lifetime to lt of active key */ 623 624 /* lifetime of active key is expired and published key exist ? */ 625 age = dki_age (akey, currtime); 626 if ( lifetime > 0 && age > lifetime - (OFFSET) ) 627 { 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) ); 630 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); 635 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 ) 639 { 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) */ 649 } 650 else 651 { 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))); 655 } 656 } 657 } 658 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) */ 663 { 664 if ( nextkey == NULL ) 665 { 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 ) 669 { 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); 673 } 674 else 675 { 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()); 679 } 680 } 681 } 682 else /* do we need a new ZSK ? */ 683 #endif 684 { 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). 688 */ 689 if ( nextkey == NULL && lifetime > 0 && (akey == NULL || 690 dki_age (akey, currtime + z->resign) > lifetime - (OFFSET)) ) 691 { 692 verbmesg (1, z, "\tNew ZSK for publishing needed\n"); 693 nextkey = genfirstkey (listp, dir, domain, DKI_ZSK, z, DKI_PUB); 694 if ( nextkey ) 695 { 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); 699 } 700 else 701 { 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()); 705 } 706 } 707 } 708 709 /* is a second algorithm requested ? (since 0.99) */ 710 if ( z->k2_algo && z->k2_algo != z->k_algo ) 711 { 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 ) 715 { 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 ) 719 { 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()); 723 } 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 */ 728 } 729 } 730 731 return keychange; 732 } 733 734