1 /*****************************************************************
3 ** @(#) dnssec-zkt.c (c) Jan 2005 Holger Zuleger hznet.de
5 ** Secure DNS zone key tool
6 ** A wrapper command around the BIND dnssec-keygen utility
8 ** Copyright (c) 2005 - 2008, Holger Zuleger HZnet. All rights reserved.
10 ** This software is open source.
12 ** Redistribution and use in source and binary forms, with or without
13 ** modification, are permitted provided that the following conditions
16 ** Redistributions of source code must retain the above copyright notice,
17 ** this list of conditions and the following disclaimer.
19 ** Redistributions in binary form must reproduce the above copyright notice,
20 ** this list of conditions and the following disclaimer in the documentation
21 ** and/or other materials provided with the distribution.
23 ** Neither the name of Holger Zuleger HZnet nor the names of its contributors may
24 ** be used to endorse or promote products derived from this software without
25 ** specific prior written permission.
27 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 ** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 ** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
31 ** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 ** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 ** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 ** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 ** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 ** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 ** POSSIBILITY OF SUCH DAMAGE.
39 *****************************************************************/
42 # include <stdlib.h> /* abort(), exit(), ... */
52 # include "config_zkt.h"
53 #if defined(HAVE_GETOPT_LONG) && HAVE_GETOPT_LONG
70 char *labellist = NULL;
83 static int dirflag = 0;
84 static int recflag = RECURSIVE;
85 static int trustedkeyflag = 0;
86 static char *kskdomain = "";
87 static const char *view = "";
89 # define short_options ":0:1:2:3:9A:C:D:P:S:R:HKTs:ZV:afF:c:O:dhkLl:prtez"
90 #if defined(HAVE_GETOPT_LONG) && HAVE_GETOPT_LONG
91 static struct option long_options[] = {
92 {"ksk-rollover", no_argument, NULL, '9'},
93 {"ksk-status", required_argument, NULL, '0'},
94 {"ksk-roll-status", required_argument, NULL, '0'},
95 {"ksk-newkey", required_argument, NULL, '1'},
96 {"ksk-publish", required_argument, NULL, '2'},
97 {"ksk-delkey", required_argument, NULL, '3'},
98 {"ksk-roll-phase1", required_argument, NULL, '1'},
99 {"ksk-roll-phase2", required_argument, NULL, '2'},
100 {"ksk-roll-phase3", required_argument, NULL, '3'},
101 {"list-dnskeys", no_argument, NULL, 'K'},
102 {"list-trustedkeys", no_argument, NULL, 'T'},
103 {"ksk", no_argument, NULL, 'k'},
104 {"zsk", no_argument, NULL, 'z'},
105 {"age", no_argument, NULL, 'a'},
106 {"lifetime", no_argument, NULL, 'f'},
107 {"time", no_argument, NULL, 't'},
108 {"expire", no_argument, NULL, 'e'},
109 {"recursive", no_argument, NULL, 'r'},
110 {"zone-config", no_argument, NULL, 'Z'},
111 {"leftjust", no_argument, NULL, 'L'},
112 {"path", no_argument, NULL, 'p'},
113 {"nohead", no_argument, NULL, 'h'},
114 {"directory", no_argument, NULL, 'd'},
115 {"config", required_argument, NULL, 'c'},
116 {"option", required_argument, NULL, 'O'},
117 {"config-option", required_argument, NULL, 'O'},
118 {"published", required_argument, NULL, 'P'},
119 {"standby", required_argument, NULL, 'S'},
120 {"active", required_argument, NULL, 'A'},
121 {"depreciated", required_argument, NULL, 'D'},
122 {"create", required_argument, NULL, 'C'},
123 {"revoke", required_argument, NULL, 'R'},
124 {"remove", required_argument, NULL, 19 },
125 {"destroy", required_argument, NULL, 20 },
126 {"setlifetime", required_argument, NULL, 'F' },
127 {"view", required_argument, NULL, 'V' },
128 {"help", no_argument, NULL, 'H'},
133 static int parsedirectory (const char *dir, dki_t **listp);
134 static void parsefile (const char *file, dki_t **listp);
135 static void createkey (const char *keyname, const dki_t *list, const zconf_t *conf);
136 static void ksk_roll (const char *keyname, int phase, const dki_t *list, const zconf_t *conf);
137 static int create_parent_file (const char *fname, int phase, int ttl, const dki_t *dkp);
138 static void usage (char *mesg, zconf_t *cp);
139 static const char *parsetag (const char *str, int *tagp);
141 static void setglobalflags (zconf_t *config)
143 recflag = config->recursive;
144 ageflag = config->printage;
145 timeflag = config->printtime;
146 ljustflag = config->ljust;
149 int main (int argc, char *argv[])
157 const char *defconfname = NULL;
160 const char *keyname = NULL;
165 if ( (p = strrchr (progname, '/')) )
167 view = getnameappendix (progname, "dnssec-zkt");
169 defconfname = getdefconfname (view);
170 config = loadconfig ("", (zconf_t *)NULL); /* load built in config */
171 if ( fileexist (defconfname) ) /* load default config file */
172 config = loadconfig (defconfname, config);
173 if ( config == NULL )
174 fatal ("Out of memory\n");
175 setglobalflags (config);
180 #if defined(HAVE_GETOPT_LONG) && HAVE_GETOPT_LONG
181 while ( (c = getopt_long (argc, argv, short_options, long_options, &opt_index)) != -1 )
183 while ( (c = getopt (argc, argv, short_options)) != -1 )
188 case '9': /* ksk rollover help */
189 ksk_roll ("help", c - '0', NULL, NULL);
191 case '1': /* ksk rollover: create new key */
192 case '2': /* ksk rollover: publish DS */
193 case '3': /* ksk rollover: delete old key */
194 case '0': /* ksk rollover: show current status */
197 usage ("ksk rollover requires an domain argument", config);
198 kskdomain = domain_canonicdup (optarg);
202 zskflag = pathflag = 0;
210 pathflag = !pathflag;
220 if ( (keyname = parsetag (optarg, &searchtag)) != NULL )
221 keyname = domain_canonicdup (keyname);
227 case 'f': /* key lifetime */
228 lifetimeflag = !lifetimeflag;
230 case 'F': /* set key lifetime */
231 lifetime = atoi (optarg);
232 lifetimeflag = 1; /* set some flags for more informative output */
237 case 'V': /* view name */
239 defconfname = getdefconfname (view);
240 if ( fileexist (defconfname) ) /* load default config file */
241 config = loadconfig (defconfname, config);
242 if ( config == NULL )
243 fatal ("Out of memory\n");
244 setglobalflags (config);
247 config = loadconfig (optarg, config);
248 setglobalflags (config);
249 checkconfig (config);
251 case 'O': /* read option from commandline */
252 config = loadconfig_fromstr (optarg, config);
253 setglobalflags (config);
254 checkconfig (config);
256 case 'd': /* ignore directory arg */
259 case 'h': /* print no headline */
262 case 'k': /* ksk only */
265 case 'L': /* ljust */
266 ljustflag = !ljustflag;
268 case 'l': /* label list */
269 labellist = prepstrlist (optarg, LISTDELIM);
270 if ( labellist == NULL )
271 fatal ("Out of memory\n");
273 case 'p': /* print path */
276 case 'r': /* switch recursive flag */
280 timeflag = !timeflag;
282 case 'e': /* expire time */
283 exptimeflag = !exptimeflag;
285 case 'z': /* zsk only */
289 snprintf (str, sizeof(str), "option \"-%c\" requires an argument.\n",
294 if ( isprint (optopt) )
295 snprintf (str, sizeof(str), "Unknown option \"-%c\".\n",
298 snprintf (str, sizeof (str), "Unknown option char \\x%x.\n",
307 /* it's better to do this before we read the whole directory tree */
310 printconfig ("stdout", config);
314 if ( kskflag == 0 && zskflag == 0 )
315 kskflag = zskflag = 1;
319 if ( c >= argc ) /* no args left */
320 file = config->zonedir; /* use default directory */
324 if ( is_directory (file) )
325 parsedirectory (file, &data);
327 parsefile (file, &data);
329 } while ( c < argc ); /* for all arguments */
336 createkey (keyname, data, config);
342 if ( (dkp = (dki_t*)zkt_search (data, searchtag, keyname)) == NULL )
343 fatal ("Key with tag %u not found\n", searchtag);
344 else if ( dkp == (void *) 01 )
345 fatal ("Key with tag %u found multiple times\n", searchtag);
346 if ( (c = dki_setstatus_preservetime (dkp, action)) != 0 )
347 fatal ("Couldn't change status of key %u: %d\n", searchtag, c);
349 case 19: /* remove (rename) key file */
350 if ( (dkp = (dki_t *)zkt_search (data, searchtag, keyname)) == NULL )
351 fatal ("Key with tag %u not found\n", searchtag);
352 else if ( dkp == (void *) 01 )
353 fatal ("Key with tag %u found multiple times\n", searchtag);
356 case 20: /* destroy the key (remove the files!) */
357 if ( (dkp = (dki_t *)zkt_search (data, searchtag, keyname)) == NULL )
358 fatal ("Key with tag %u not found\n", searchtag);
359 else if ( dkp == (void *) 01 )
360 fatal ("Key with tag %u found multiple times\n", searchtag);
364 if ( (dkp = (dki_t *)zkt_search (data, searchtag, keyname)) == NULL )
365 fatal ("Key with tag %u not found\n", searchtag);
366 else if ( dkp == (void *) 01 )
367 fatal ("Key with tag %u found multiple times\n", searchtag);
368 if ( (c = dki_setstatus (dkp, action)) != 0 )
369 fatal ("Couldn't change status of key %u: %d\n", searchtag, c);
372 if ( (dkp = (dki_t *)zkt_search (data, searchtag, keyname)) == NULL )
373 fatal ("Key with tag %u not found\n", searchtag);
374 else if ( dkp == (void *) 01 )
375 fatal ("Key with tag %u found multiple times\n", searchtag);
376 dki_prt_dnskey (dkp, stdout);
379 zkt_list_dnskeys (data);
382 zkt_list_trustedkeys (data);
384 case '1': /* ksk rollover new key */
385 case '2': /* ksk rollover publish DS */
386 case '3': /* ksk rollover delete old key */
387 case '0': /* ksk rollover status */
388 ksk_roll (kskdomain, action - '0', data, config);
391 zkt_setkeylifetime (data);
394 zkt_list_keys (data);
400 # define sopt_usage(mesg, value) fprintf (stderr, mesg, value)
401 #if defined(HAVE_GETOPT_LONG) && HAVE_GETOPT_LONG
402 # define lopt_usage(mesg, value) fprintf (stderr, mesg, value)
403 # define loptstr(lstr, sstr) lstr
405 # define lopt_usage(mesg, value)
406 # define loptstr(lstr, sstr) sstr
408 static void usage (char *mesg, zconf_t *cp)
410 fprintf (stderr, "Secure DNS Zone Key Tool %s\n", ZKT_VERSION);
411 fprintf (stderr, "\n");
412 fprintf (stderr, "Show zone config parameter as %s file\n", LOCALCONF_FILE);
413 sopt_usage ("\tusage: %s -Z\n", progname);
414 lopt_usage ("\tusage: %s --zone-config\n", progname);
415 fprintf (stderr, "\n");
416 fprintf (stderr, "List keys in current or given directory (-r for recursive mode)\n");
417 sopt_usage ("\tusage: %s [-dhatkzpr] [-c config] [file|dir ...]\n", progname);
418 fprintf (stderr, "\n");
419 fprintf (stderr, "List public part of keys in DNSKEY RR format\n");
420 sopt_usage ("\tusage: %s -K [-dhkzr] [-c config] [file|dir ...]\n", progname);
421 lopt_usage ("\tusage: %s --list-dnskeys [-dhkzr] [-c config] [file|dir ...]\n", progname);
422 fprintf (stderr, "\n");
423 fprintf (stderr, "List keys (output is suitable for trusted-keys section)\n");
424 sopt_usage ("\tusage: %s -T [-dhzr] [-c config] [file|dir ...]\n", progname);
425 lopt_usage ("\tusage: %s --list-trustedkeys [-dhzr] [-c config] [file|dir ...]\n", progname);
426 fprintf (stderr, "\n");
427 fprintf (stderr, "Create a new key \n");
428 sopt_usage ("\tusage: %s -C <name> [-k] [-dpr] [-c config] [dir ...]\n", progname);
429 lopt_usage ("\tusage: %s --create=<name> [-k] [-dpr] [-c config] [dir ...]\n", progname);
430 fprintf (stderr, "\t\tKSK (use -k): %s %d bits\n", dki_algo2str (cp->k_algo), cp->k_bits);
431 fprintf (stderr, "\t\tZSK (default): %s %d bits\n", dki_algo2str (cp->z_algo), cp->z_bits);
432 fprintf (stderr, "\n");
433 fprintf (stderr, "Change key status of specified key to published, active or depreciated\n");
434 fprintf (stderr, "\t(<keyspec> := tag | tag:name) \n");
435 sopt_usage ("\tusage: %s -P|-A|-D <keyspec> [-dr] [-c config] [dir ...]\n", progname);
436 lopt_usage ("\tusage: %s --published=<keyspec> [-dr] [-c config] [dir ...]\n", progname);
437 lopt_usage ("\tusage: %s --active=<keyspec> [-dr] [-c config] [dir ...]\n", progname);
438 lopt_usage ("\tusage: %s --depreciated=<keyspec> [-dr] [-c config] [dir ...]\n", progname);
439 fprintf (stderr, "\n");
440 fprintf (stderr, "Revoke specified key (<keyspec> := tag | tag:name) \n");
441 sopt_usage ("\tusage: %s -R <keyspec> [-dr] [-c config] [dir ...]\n", progname);
442 lopt_usage ("\tusage: %s --revoke=<keyspec> [-dr] [-c config] [dir ...]\n", progname);
443 fprintf (stderr, "\n");
444 fprintf (stderr, "Remove (rename) or destroy (delete) specified key (<keyspec> := tag | tag:name) \n");
445 lopt_usage ("\tusage: %s --remove=<keyspec> [-dr] [-c config] [dir ...]\n", progname);
446 lopt_usage ("\tusage: %s --destroy=<keyspec> [-dr] [-c config] [dir ...]\n", progname);
447 fprintf (stderr, "\n");
448 fprintf (stderr, "Initiate a semi-automated KSK rollover");
449 fprintf (stderr, "('%s -9%s' prints out a short description)\n", progname, loptstr ("|--ksk-rollover", ""));
450 sopt_usage ("\tusage: %s {-1} do.ma.in.\n", progname);
451 lopt_usage ("\tusage: %s {--ksk-roll-phase1|--ksk-newkey} do.ma.in.\n", progname);
452 sopt_usage ("\tusage: %s {-2} do.ma.in.\n", progname);
453 lopt_usage ("\tusage: %s {--ksk-roll-phase2|--ksk-publish} do.ma.in.\n", progname);
454 sopt_usage ("\tusage: %s {-3} do.ma.in.\n", progname);
455 lopt_usage ("\tusage: %s {--ksk-roll-phase3|--ksk-delkey} do.ma.in.\n", progname);
456 sopt_usage ("\tusage: %s {-0} do.ma.in.\n", progname);
457 lopt_usage ("\tusage: %s {--ksk-roll-status|--ksk-status} do.ma.in.\n", progname);
458 fprintf (stderr, "\n");
460 fprintf (stderr, "\n");
461 fprintf (stderr, "General options \n");
462 fprintf (stderr, "\t-c file%s", loptstr (", --config=file\n", ""));
463 fprintf (stderr, "\t\t read config from <file> instead of %s\n", CONFIG_FILE);
464 fprintf (stderr, "\t-O optstr%s", loptstr (", --config-option=\"optstr\"\n", ""));
465 fprintf (stderr, "\t\t read config options from commandline\n");
466 fprintf (stderr, "\t-h%s\t no headline or trusted-key section header/trailer in -T mode\n", loptstr (", --nohead", "\t"));
467 fprintf (stderr, "\t-d%s\t skip directory arguments\n", loptstr (", --directory", "\t"));
468 fprintf (stderr, "\t-L%s\t print the domain name left justified (default: %s)\n", loptstr (", --leftjust", "\t"), ljustflag ? "on": "off");
469 fprintf (stderr, "\t-l list\t\t print out only zone keys out of the given domain list\n");
470 fprintf (stderr, "\t-p%s\t show path of keyfile / create key in current directory\n", loptstr (", --path", "\t"));
471 fprintf (stderr, "\t-r%s\t recursive mode on/off (default: %s)\n", loptstr(", --recursive", "\t"), recflag ? "on": "off");
472 fprintf (stderr, "\t-a%s\t print age of key (default: %s)\n", loptstr (", --age", "\t"), ageflag ? "on": "off");
473 fprintf (stderr, "\t-t%s\t print key generation time (default: %s)\n", loptstr (", --time", "\t"),
474 timeflag ? "on": "off");
475 fprintf (stderr, "\t-e%s\t print key expiration time\n", loptstr (", --expire", "\t"));
476 fprintf (stderr, "\t-f%s\t print key lifetime\n", loptstr (", --lifetime", "\t"));
477 fprintf (stderr, "\t-F days%s=days\t set key lifetime\n", loptstr (", --setlifetime", "\t"));
478 fprintf (stderr, "\t-k%s\t key signing keys only\n", loptstr (", --ksk", "\t"));
479 fprintf (stderr, "\t-z%s\t zone signing keys only\n", loptstr (", --zsk", "\t"));
481 fprintf (stderr, "%s\n", mesg);
485 static void createkey (const char *keyname, const dki_t *list, const zconf_t *conf)
487 const char *dir = "";
490 if ( keyname == NULL || *keyname == '\0' )
491 fatal ("Create key: no keyname!");
493 dbg_val2 ("createkey: keyname %s, pathflag = %d\n", keyname, pathflag);
494 /* search for already existent key to get the directory name */
495 if ( pathflag && (dkp = (dki_t *)zkt_search (list, 0, keyname)) != NULL )
497 char path[MAX_PATHSIZE+1];
501 pathname (path, sizeof (path), dir, LOCALCONF_FILE, NULL);
502 if ( fileexist (path) ) /* load local config file */
504 dbg_val ("Load local config file \"%s\"\n", path);
505 memcpy (&localconf, conf, sizeof (zconf_t));
506 conf = loadconfig (path, &localconf);
511 dkp = dki_new (dir, keyname, DKI_ZSK, conf->z_algo, conf->z_bits, conf->z_random, conf->z_life / DAYSEC);
513 dkp = dki_new (dir, keyname, DKI_KSK, conf->k_algo, conf->k_bits, conf->k_random, conf->k_life / DAYSEC);
515 fatal ("Can't create key %s: %s!\n", keyname, dki_geterrstr ());
517 /* create a new key always in state published, which means "standby" for ksk */
518 dki_setstatus (dkp, DKI_PUB);
521 static int get_parent_phase (const char *file)
526 if ( (fp = fopen (file, "r")) == NULL )
530 if ( fscanf (fp, "; KSK rollover phase%d", &phase) != 1 )
537 static void ksk_roll (const char *keyname, int phase, const dki_t *list, const zconf_t *conf)
539 char path[MAX_PATHSIZE+1];
548 int parent_propagation;
552 if ( phase == 9 ) /* usage */
554 fprintf (stderr, "A KSK rollover requires three consecutive steps:\n");
555 fprintf (stderr, "\n");
556 fprintf (stderr, "-1%s", loptstr ("|--ksk-roll-phase1 (--ksk-newkey)\n", ""));
557 fprintf (stderr, "\t Create a new KSK.\n");
558 fprintf (stderr, "\t This step also creates a parent-<domain> file which contains only\n");
559 fprintf (stderr, "\t the _old_ key. This file will be copied in hierarchical mode\n");
560 fprintf (stderr, "\t by dnssec-signer to the parent directory as keyset-<domain> file.\n");
561 fprintf (stderr, "\t Wait until the new keyset is propagated, before going to the next step.\n");
562 fprintf (stderr, "\n");
563 fprintf (stderr, "-2%s", loptstr ("|--ksk-roll-phase2 (--ksk-publish)\n", ""));
564 fprintf (stderr, "\t This step creates a parent-<domain> file with the _new_ key only.\n");
565 fprintf (stderr, "\t Please send this file immediately to the parent (In hierarchical\n");
566 fprintf (stderr, "\t mode this will be done automatically by the dnssec-signer command).\n");
567 fprintf (stderr, "\t Then wait until the new DS is generated by the parent and propagated\n");
568 fprintf (stderr, "\t to all the parent name server, plus the old DS TTL before going to step three.\n");
569 fprintf (stderr, "\n");
570 fprintf (stderr, "-3%s", loptstr ("|--ksk-roll-phase3 (--ksk-delkey)\n", ""));
571 fprintf (stderr, "\t Remove (rename) the old KSK and the parent-<domain> file.\n");
572 fprintf (stderr, "\t You have to manually delete the old KSK (look at file names beginning\n");
573 fprintf (stderr, "\t with an lower 'k').\n");
574 fprintf (stderr, "\n");
575 fprintf (stderr, "-0%s", loptstr ("|--ksk-roll-stat (--ksk-status)\n", ""));
576 fprintf (stderr, "\t Show the current KSK rollover state of a domain.\n");
578 fprintf (stderr, "\n");
583 if ( keyname == NULL || *keyname == '\0' )
584 fatal ("ksk rollover: no domain!");
586 dbg_val2 ("ksk_roll: keyname %s, phase = %d\n", keyname, phase);
588 /* search for already existent key to get the directory name */
589 if ( (keylist = (dki_t *)zkt_search (list, 0, keyname)) == NULL )
590 fatal ("ksk rollover: domain %s not found!\n", keyname);
593 /* try to read local config file */
595 pathname (path, sizeof (path), dir, LOCALCONF_FILE, NULL);
596 if ( fileexist (path) ) /* load local config file */
598 dbg_val ("Load local config file \"%s\"\n", path);
599 memcpy (&localconf, conf, sizeof (zconf_t));
600 conf = loadconfig (path, &localconf);
602 key_ttl = conf->key_ttl;
604 /* check if parent-file already exist */
605 pathname (path, sizeof (path), dir, "parent-", keyname);
606 parent_phase = parent_age = 0;
607 if ( (parent_exist = fileexist (path)) != 0 )
609 parent_phase = get_parent_phase (path);
610 parent_age = file_age (path);
612 // parent_propagation = 2 * DAYSEC;
613 parent_propagation = 5 * MINSEC;
615 ksk = 0; /* count active(!) key signing keys */
616 standby = NULL; /* find standby key if available */
617 for ( dkp = keylist; dkp; dkp = dkp->next )
618 if ( dki_isksk (dkp) )
620 if ( dki_status (dkp) == DKI_ACT )
622 else if ( dki_status (dkp) == DKI_PUB )
628 case 0: /* print status (debug) */
629 fprintf (stdout, "ksk_rollover:\n");
630 fprintf (stdout, "\t domain = %s\n", keyname);
631 fprintf (stdout, "\t phase = %d\n", parent_phase);
632 fprintf (stdout, "\t parent_file %s %s\n", path, parent_exist ? "exist": "not exist");
634 fprintf (stdout, "\t age of parent_file %d %s\n", parent_age, str_delspace (age2str (parent_age)));
635 fprintf (stdout, "\t # of active key signing keys %d\n", ksk);
636 fprintf (stdout, "\t parent_propagation %d %s\n", parent_propagation, str_delspace (age2str (parent_propagation)));
637 fprintf (stdout, "\t keys ttl %d %s\n", key_ttl, age2str (key_ttl));
639 for ( dkp = keylist; dkp; dkp = dkp->next )
641 /* TODO: Nur zum testen */
642 dki_prt_dnskey (dkp, stdout);
646 if ( parent_exist || ksk > 1 )
647 fatal ("Can\'t create new ksk because there is already an ksk rollover in progress\n");
649 fprintf (stdout, "create new ksk \n");
650 dkp = dki_new (dir, keyname, DKI_KSK, conf->k_algo, conf->k_bits, conf->k_random, conf->k_life / DAYSEC);
652 fatal ("Can't create key %s: %s!\n", keyname, dki_geterrstr ());
655 dki_setstatus (standby, DKI_ACT); /* activate standby key */
656 dki_setstatus (dkp, DKI_PUB); /* new key will be the new standby */
659 // dkp = keylist; /* use old key to create the parent file */
660 if ( (dkp = (dki_t *)dki_find (keylist, 1, 'a', 1)) == NULL ) /* find the oldest active ksk to create the parent file */
661 fatal ("ksk_rollover phase1: Couldn't find the old active key\n");
662 if ( !create_parent_file (path, phase, key_ttl, dkp) )
663 fatal ("Couldn't create parentfile %s\n", path);
668 fatal ("Can\'t publish new key because no one exist\n");
670 fatal ("More than one KSK but no parent file found!\n");
671 if ( parent_phase != 1 )
672 fatal ("Parent file exists but is in wrong state (phase = %d)\n", parent_phase);
673 if ( parent_age < conf->proptime + key_ttl )
674 fatal ("ksk_rollover (phase2): you have to wait for the propagation of the new KSK (at least %dsec or %s)\n",
675 conf->proptime + key_ttl - parent_age,
676 str_delspace (age2str (conf->proptime + key_ttl - parent_age)));
678 fprintf (stdout, "save new ksk in parent file\n");
679 dkp = keylist->next; /* set dkp to new ksk */
680 if ( !create_parent_file (path, phase, key_ttl, dkp) )
681 fatal ("Couldn't create parentfile %s\n", path);
684 if ( !parent_exist || ksk < 2 )
685 fatal ("ksk-delkey only allowed after ksk-publish\n");
686 if ( parent_phase != 2 )
687 fatal ("Parent file exists but is in wrong state (phase = %d)\n", parent_phase);
688 if ( parent_age < parent_propagation + key_ttl )
689 fatal ("ksk_rollover (phase3): you have to wait for DS propagation (at least %dsec or %s)\n",
690 parent_propagation + key_ttl - parent_age,
691 str_delspace (age2str (parent_propagation + key_ttl - parent_age)));
692 /* remove the parentfile */
693 fprintf (stdout, "remove parentfile \n");
695 /* remove or rename the old key */
696 fprintf (stdout, "old ksk renamed \n");
697 dkp = keylist; /* set dkp to old ksk */
700 default: assert (phase == 1 || phase == 2 || phase == 3);
704 /*****************************************************************
705 ** create_parent_file ()
706 *****************************************************************/
707 static int create_parent_file (const char *fname, int phase, int ttl, const dki_t *dkp)
711 assert ( fname != NULL );
713 if ( dkp == NULL || (phase != 1 && phase != 2) )
716 if ( (fp = fopen (fname, "w")) == NULL )
717 fatal ("can\'t create new parentfile \"%s\"\n", fname);
720 fprintf (fp, "; KSK rollover phase1 (old key)\n");
722 fprintf (fp, "; KSK rollover phase2 (new key)\n");
724 dki_prt_dnskeyttl (dkp, fp, ttl);
730 static int parsedirectory (const char *dir, dki_t **listp)
734 struct dirent *dentp;
735 char path[MAX_PATHSIZE+1];
740 dbg_val ("directory: opendir(%s)\n", dir);
741 if ( (dirp = opendir (dir)) == NULL )
744 while ( (dentp = readdir (dirp)) != NULL )
746 if ( is_dotfile (dentp->d_name) )
749 dbg_val ("directory: check %s\n", dentp->d_name);
750 pathname (path, sizeof (path), dir, dentp->d_name, NULL);
751 if ( is_directory (path) && recflag )
753 dbg_val ("directory: recursive %s\n", path);
754 parsedirectory (path, listp);
756 else if ( is_keyfilename (dentp->d_name) )
757 if ( (dkp = dki_read (dir, dentp->d_name)) )
759 // fprintf (stderr, "parsedir: tssearch (%d %s)\n", dkp, dkp->name);
760 #if defined (USE_TREE) && USE_TREE
761 dki_tadd (listp, dkp);
763 dki_add (listp, dkp);
771 static void parsefile (const char *file, dki_t **listp)
773 char path[MAX_PATHSIZE+1];
776 /* file arg contains path ? ... */
777 file = splitpath (path, sizeof (path), file); /* ... then split of */
779 if ( is_keyfilename (file) ) /* plain file name looks like DNS key file ? */
781 if ( (dkp = dki_read (path, file)) ) /* read DNS key file ... */
782 #if defined (USE_TREE) && USE_TREE
783 dki_tadd (listp, dkp); /* ... and add to tree */
785 dki_add (listp, dkp); /* ... and add to list */
788 error ("error parsing %s: (%s)\n", file, dki_geterrstr());
792 static const char *parsetag (const char *str, int *tagp)
797 while ( isspace (*str) ) /* skip leading ws */
801 if ( isdigit (*p) ) /* keytag starts with digit */
803 sscanf (p, "%u", tagp); /* read keytag as number */
804 do /* eat up to the end of the number */
806 while ( isdigit (*p) );
808 if ( *p == ':' ) /* label follows ? */
809 return p+1; /* return that */
811 return NULL; /* no label */
813 return str; /* return as label string if not a numeric keytag */