Remove building with NOCRYPTO option
[minix.git] / external / bsd / bind / dist / contrib / zkt-1.1.3 / zkt-keyman.c
blob7a3b575df831ad548e876d4c3270d098a20563b7
1 /* $NetBSD: zkt-keyman.c,v 1.1.1.1 2015/07/08 15:37:48 christos Exp $ */
3 /*****************************************************************
4 **
5 ** @(#) zkt-keyman.c (c) Jan 2005 - Apr 2010 Holger Zuleger hznet.de
6 **
7 ** ZKT key managing tool (formely knon as dnsses-zkt)
8 ** A wrapper command around the BIND dnssec-keygen utility
9 **
10 ** Copyright (c) 2005 - 2010, Holger Zuleger HZnet. All rights reserved.
12 ** This software is open source.
14 ** Redistribution and use in source and binary forms, with or without
15 ** modification, are permitted provided that the following conditions
16 ** are met:
18 ** Redistributions of source code must retain the above copyright notice,
19 ** this list of conditions and the following disclaimer.
21 ** Redistributions in binary form must reproduce the above copyright notice,
22 ** this list of conditions and the following disclaimer in the documentation
23 ** and/or other materials provided with the distribution.
25 ** Neither the name of Holger Zuleger HZnet nor the names of its contributors may
26 ** be used to endorse or promote products derived from this software without
27 ** specific prior written permission.
29 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
31 ** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
32 ** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
33 ** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
34 ** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
35 ** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36 ** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
37 ** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 ** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39 ** POSSIBILITY OF SUCH DAMAGE.
41 *****************************************************************/
43 # include <stdio.h>
44 # include <stdlib.h> /* abort(), exit(), ... */
45 # include <string.h>
46 # include <dirent.h>
47 # include <assert.h>
48 # include <unistd.h>
49 # include <ctype.h>
51 #ifdef HAVE_CONFIG_H
52 # include <config.h>
53 #endif
54 # include "config_zkt.h"
55 #if defined(HAVE_GETOPT_LONG) && HAVE_GETOPT_LONG
56 # include <getopt.h>
57 #endif
59 # include "debug.h"
60 # include "misc.h"
61 # include "strlist.h"
62 # include "zconf.h"
63 # include "dki.h"
64 # include "zkt.h"
66 extern int optopt;
67 extern int opterr;
68 extern int optind;
69 extern char *optarg;
70 const char *progname;
72 char *labellist = NULL;
74 int headerflag = 1;
75 int ageflag = 0;
76 int lifetime = 0;
77 int lifetimeflag = 0;
78 int timeflag = 1;
79 int exptimeflag = 0;
80 int pathflag = 0;
81 int kskflag = 1;
82 int zskflag = 1;
83 int ljustflag = 0;
85 static int dirflag = 0;
86 static int recflag = RECURSIVE;
87 static char *kskdomain = "";
88 static const char *view = "";
90 # define short_options ":0:1:2:3:9A:C:D:P:S:R:h:ZV:F:c:O:krz"
91 #if defined(HAVE_GETOPT_LONG) && HAVE_GETOPT_LONG
92 static struct option long_options[] = {
93 {"ksk-rollover", no_argument, NULL, '9'},
94 {"ksk-status", required_argument, NULL, '0'},
95 {"ksk-roll-status", required_argument, NULL, '0'},
96 {"ksk-newkey", required_argument, NULL, '1'},
97 {"ksk-publish", required_argument, NULL, '2'},
98 {"ksk-delkey", required_argument, NULL, '3'},
99 {"ksk-roll-phase1", required_argument, NULL, '1'},
100 {"ksk-roll-phase2", required_argument, NULL, '2'},
101 {"ksk-roll-phase3", required_argument, NULL, '3'},
102 {"ksk", no_argument, NULL, 'k'},
103 {"zsk", no_argument, NULL, 'z'},
104 {"recursive", no_argument, NULL, 'r'},
105 {"config", required_argument, NULL, 'c'},
106 {"option", required_argument, NULL, 'O'},
107 {"config-option", required_argument, NULL, 'O'},
108 {"published", required_argument, NULL, 'P'},
109 {"standby", required_argument, NULL, 'S'},
110 {"active", required_argument, NULL, 'A'},
111 {"depreciated", required_argument, NULL, 'D'},
112 {"create", required_argument, NULL, 'C'},
113 {"revoke", required_argument, NULL, 'R'},
114 {"remove", required_argument, NULL, 19 },
115 {"destroy", required_argument, NULL, 20 },
116 {"setlifetime", required_argument, NULL, 'F' },
117 {"view", required_argument, NULL, 'V' },
118 {"help", no_argument, NULL, 'h'},
119 {0, 0, 0, 0}
121 #endif
123 static int parsedirectory (const char *dir, dki_t **listp);
124 static void parsefile (const char *file, dki_t **listp);
125 static void createkey (const char *keyname, const dki_t *list, const zconf_t *conf);
126 static void ksk_roll (const char *keyname, int phase, const dki_t *list, const zconf_t *conf);
127 static int create_parent_file (const char *fname, int phase, int ttl, const dki_t *dkp);
128 static void usage (char *mesg, zconf_t *cp);
129 static const char *parsetag (const char *str, int *tagp);
131 static void setglobalflags (zconf_t *config)
133 recflag = config->recursive;
136 int main (int argc, char *argv[])
138 dki_t *data = NULL;
139 dki_t *dkp;
140 int c;
141 int opt_index;
142 int action;
143 const char *file;
144 const char *defconfname = NULL;
145 char *p;
146 char str[254+1];
147 const char *keyname = NULL;
148 int searchtag;
149 zconf_t *config;
151 progname = *argv;
152 if ( (p = strrchr (progname, '/')) )
153 progname = ++p;
154 view = getnameappendix (progname, "dnssec-zkt");
156 defconfname = getdefconfname (view);
157 config = loadconfig ("", (zconf_t *)NULL); /* load built in config */
158 if ( fileexist (defconfname) ) /* load default config file */
159 config = loadconfig (defconfname, config);
160 if ( config == NULL )
161 fatal ("Out of memory\n");
162 setglobalflags (config);
164 opterr = 0;
165 opt_index = 0;
166 action = 0;
167 #if defined(HAVE_GETOPT_LONG) && HAVE_GETOPT_LONG
168 while ( (c = getopt_long (argc, argv, short_options, long_options, &opt_index)) != -1 )
169 #else
170 while ( (c = getopt (argc, argv, short_options)) != -1 )
171 #endif
173 switch ( c )
175 case '9': /* ksk rollover help */
176 ksk_roll ("help", c - '0', NULL, NULL);
177 exit (1);
178 case '1': /* ksk rollover: create new key */
179 case '2': /* ksk rollover: publish DS */
180 case '3': /* ksk rollover: delete old key */
181 case '0': /* ksk rollover: show current status */
182 action = c;
183 if ( !optarg )
184 usage ("ksk rollover requires an domain argument", config);
185 kskdomain = domain_canonicdup (optarg);
186 break;
187 case 'h':
188 case 'K':
189 case 'Z':
190 action = c;
191 break;
192 case 'C':
193 pathflag = !pathflag;
194 /* fall through */
195 case 'P':
196 case 'S':
197 case 'A':
198 case 'D':
199 case 'R':
200 case 's':
201 case 19:
202 case 20:
203 if ( (keyname = parsetag (optarg, &searchtag)) != NULL )
204 keyname = domain_canonicdup (keyname);
205 action = c;
206 break;
207 case 'F': /* set key lifetime */
208 lifetime = atoi (optarg);
209 action = c;
210 break;
211 case 'V': /* view name */
212 view = optarg;
213 defconfname = getdefconfname (view);
214 if ( fileexist (defconfname) ) /* load default config file */
215 config = loadconfig (defconfname, config);
216 if ( config == NULL )
217 fatal ("Out of memory\n");
218 setglobalflags (config);
219 break;
220 case 'c':
221 config = loadconfig (optarg, config);
222 setglobalflags (config);
223 checkconfig (config);
224 break;
225 case 'O': /* read option from commandline */
226 config = loadconfig_fromstr (optarg, config);
227 setglobalflags (config);
228 checkconfig (config);
229 break;
230 case 'd': /* ignore directory arg */
231 dirflag = 1;
232 break;
233 case 'k': /* ksk only */
234 zskflag = 0;
235 break;
236 case 'r': /* switch recursive flag */
237 recflag = !recflag;
238 break;
239 case 'z': /* zsk only */
240 kskflag = 0;
241 break;
242 case ':':
243 snprintf (str, sizeof(str), "option \"-%c\" requires an argument.\n",
244 optopt);
245 usage (str, config);
246 break;
247 case '?':
248 if ( isprint (optopt) )
249 snprintf (str, sizeof(str), "Unknown option \"-%c\".\n",
250 optopt);
251 else
252 snprintf (str, sizeof (str), "Unknown option char \\x%x.\n",
253 optopt);
254 usage (str, config);
255 break;
256 default:
257 abort();
261 if ( kskflag == 0 && zskflag == 0 )
262 kskflag = zskflag = 1;
264 c = optind;
265 do {
266 if ( c >= argc ) /* no args left */
267 file = config->zonedir; /* use default directory */
268 else
269 file = argv[c++];
271 if ( is_directory (file) )
272 parsedirectory (file, &data);
273 else
274 parsefile (file, &data);
276 } while ( c < argc ); /* for all arguments */
278 switch ( action )
280 case 'h':
281 usage ("", config);
282 case 'C':
283 createkey (keyname, data, config);
284 break;
285 case 'P':
286 case 'S':
287 case 'A':
288 case 'D':
289 if ( (dkp = (dki_t*)zkt_search (data, searchtag, keyname)) == NULL )
290 fatal ("Key with tag %u not found\n", searchtag);
291 else if ( dkp == (void *) 01 )
292 fatal ("Key with tag %u found multiple times\n", searchtag);
293 if ( (c = dki_setstatus_preservetime (dkp, action)) != 0 )
294 fatal ("Couldn't change status of key %u: %d\n", searchtag, c);
295 break;
296 case 19: /* remove (rename) key file */
297 if ( (dkp = (dki_t *)zkt_search (data, searchtag, keyname)) == NULL )
298 fatal ("Key with tag %u not found\n", searchtag);
299 else if ( dkp == (void *) 01 )
300 fatal ("Key with tag %u found multiple times\n", searchtag);
301 dki_remove (dkp);
302 break;
303 case 20: /* destroy the key (remove the files!) */
304 if ( (dkp = (dki_t *)zkt_search (data, searchtag, keyname)) == NULL )
305 fatal ("Key with tag %u not found\n", searchtag);
306 else if ( dkp == (void *) 01 )
307 fatal ("Key with tag %u found multiple times\n", searchtag);
308 dki_destroy (dkp);
309 break;
310 case 'R':
311 if ( (dkp = (dki_t *)zkt_search (data, searchtag, keyname)) == NULL )
312 fatal ("Key with tag %u not found\n", searchtag);
313 else if ( dkp == (void *) 01 )
314 fatal ("Key with tag %u found multiple times\n", searchtag);
315 if ( (c = dki_setstatus (dkp, action)) != 0 )
316 fatal ("Couldn't change status of key %u: %d\n", searchtag, c);
317 break;
318 case '1': /* ksk rollover new key */
319 case '2': /* ksk rollover publish DS */
320 case '3': /* ksk rollover delete old key */
321 case '0': /* ksk rollover status */
322 ksk_roll (kskdomain, action - '0', data, config);
323 break;
324 case 'F':
325 zkt_setkeylifetime (data);
326 /* fall through */
327 default:
328 zkt_list_keys (data);
331 return 0;
334 # define sopt_usage(mesg, value) fprintf (stderr, mesg, value)
335 #if defined(HAVE_GETOPT_LONG) && HAVE_GETOPT_LONG
336 # define lopt_usage(mesg, value) fprintf (stderr, mesg, value)
337 # define loptstr(lstr, sstr) lstr
338 #else
339 # define lopt_usage(mesg, value)
340 # define loptstr(lstr, sstr) sstr
341 #endif
342 static void usage (char *mesg, zconf_t *cp)
344 fprintf (stderr, "DNS Zone Key Management Tool %s\n", ZKT_VERSION);
345 fprintf (stderr, "\n");
346 fprintf (stderr, "Create a new key \n");
347 sopt_usage ("\tusage: %s -C <name> [-k] [-dpr] [-c config] [dir ...]\n", progname);
348 lopt_usage ("\tusage: %s --create=<name> [-k] [-dpr] [-c config] [dir ...]\n", progname);
349 fprintf (stderr, "\t\tKSK (use -k): %s %d bits\n", dki_algo2str (cp->k_algo), cp->k_bits);
350 fprintf (stderr, "\t\tZSK (default): %s %d bits\n", dki_algo2str (cp->k_algo), cp->z_bits);
351 fprintf (stderr, "\n");
352 fprintf (stderr, "Change key status of specified key to published, active or depreciated\n");
353 fprintf (stderr, "\t(<keyspec> := tag | tag:name) \n");
354 sopt_usage ("\tusage: %s -P|-A|-D <keyspec> [-dr] [-c config] [dir ...]\n", progname);
355 lopt_usage ("\tusage: %s --published=<keyspec> [-dr] [-c config] [dir ...]\n", progname);
356 lopt_usage ("\tusage: %s --active=<keyspec> [-dr] [-c config] [dir ...]\n", progname);
357 lopt_usage ("\tusage: %s --depreciated=<keyspec> [-dr] [-c config] [dir ...]\n", progname);
358 fprintf (stderr, "\n");
359 fprintf (stderr, "Revoke specified key (<keyspec> := tag | tag:name) \n");
360 sopt_usage ("\tusage: %s -R <keyspec> [-dr] [-c config] [dir ...]\n", progname);
361 lopt_usage ("\tusage: %s --revoke=<keyspec> [-dr] [-c config] [dir ...]\n", progname);
362 fprintf (stderr, "\n");
363 fprintf (stderr, "Remove (rename) or destroy (delete) specified key (<keyspec> := tag | tag:name) \n");
364 lopt_usage ("\tusage: %s --remove=<keyspec> [-dr] [-c config] [dir ...]\n", progname);
365 lopt_usage ("\tusage: %s --destroy=<keyspec> [-dr] [-c config] [dir ...]\n", progname);
366 fprintf (stderr, "\n");
367 fprintf (stderr, "Initiate a semi-automated KSK rollover");
368 fprintf (stderr, "('%s -9%s' prints out a brief description)\n", progname, loptstr ("|--ksk-rollover", ""));
369 sopt_usage ("\tusage: %s {-1} do.ma.in.\n", progname);
370 lopt_usage ("\tusage: %s {--ksk-roll-phase1|--ksk-newkey} do.ma.in.\n", progname);
371 sopt_usage ("\tusage: %s {-2} do.ma.in.\n", progname);
372 lopt_usage ("\tusage: %s {--ksk-roll-phase2|--ksk-publish} do.ma.in.\n", progname);
373 sopt_usage ("\tusage: %s {-3} do.ma.in.\n", progname);
374 lopt_usage ("\tusage: %s {--ksk-roll-phase3|--ksk-delkey} do.ma.in.\n", progname);
375 sopt_usage ("\tusage: %s {-0} do.ma.in.\n", progname);
376 lopt_usage ("\tusage: %s {--ksk-roll-status|--ksk-status} do.ma.in.\n", progname);
377 fprintf (stderr, "\n");
379 fprintf (stderr, "\n");
380 fprintf (stderr, "General options \n");
381 fprintf (stderr, "\t-c file%s", loptstr (", --config=file\n", ""));
382 fprintf (stderr, "\t\t read config from <file> instead of %s\n", CONFIG_FILE);
383 fprintf (stderr, "\t-O optstr%s", loptstr (", --config-option=\"optstr\"\n", ""));
384 fprintf (stderr, "\t\t read config options from commandline\n");
385 fprintf (stderr, "\t-d%s\t skip directory arguments\n", loptstr (", --directory", "\t"));
386 fprintf (stderr, "\t-r%s\t recursive mode on/off (default: %s)\n", loptstr(", --recursive", "\t"), recflag ? "on": "off");
387 fprintf (stderr, "\t-F days%s=days\t set key lifetime\n", loptstr (", --setlifetime", "\t"));
388 fprintf (stderr, "\t-k%s\t key signing keys only\n", loptstr (", --ksk", "\t"));
389 fprintf (stderr, "\t-z%s\t zone signing keys only\n", loptstr (", --zsk", "\t"));
390 if ( mesg && *mesg )
391 fprintf (stderr, "%s\n", mesg);
392 exit (1);
395 static void createkey (const char *keyname, const dki_t *list, const zconf_t *conf)
397 const char *dir = "";
398 dki_t *dkp;
400 if ( keyname == NULL || *keyname == '\0' )
401 fatal ("Create key: no keyname!");
403 dbg_val2 ("createkey: keyname %s, pathflag = %d\n", keyname, pathflag);
404 /* search for already existent key to get the directory name */
405 if ( pathflag && (dkp = (dki_t *)zkt_search (list, 0, keyname)) != NULL )
407 char path[MAX_PATHSIZE+1];
408 zconf_t localconf;
410 dir = dkp->dname;
411 pathname (path, sizeof (path), dir, LOCALCONF_FILE, NULL);
412 if ( fileexist (path) ) /* load local config file */
414 dbg_val ("Load local config file \"%s\"\n", path);
415 memcpy (&localconf, conf, sizeof (zconf_t));
416 conf = loadconfig (path, &localconf);
420 if ( zskflag )
421 dkp = dki_new (dir, keyname, DKI_ZSK, conf->k_algo, conf->z_bits, conf->z_random, conf->z_life / DAYSEC);
422 else
423 dkp = dki_new (dir, keyname, DKI_KSK, conf->k_algo, conf->k_bits, conf->k_random, conf->k_life / DAYSEC);
424 if ( dkp == NULL )
425 fatal ("Can't create key %s: %s!\n", keyname, dki_geterrstr ());
427 /* create a new key always in state published, which means "standby" for ksk */
428 dki_setstatus (dkp, DKI_PUB);
431 static int get_parent_phase (const char *file)
433 FILE *fp;
434 int phase;
436 if ( (fp = fopen (file, "r")) == NULL )
437 return -1;
439 phase = 0;
440 if ( fscanf (fp, "; KSK rollover phase%d", &phase) != 1 )
441 phase = 0;
443 fclose (fp);
444 return phase;
447 static void ksk_roll (const char *keyname, int phase, const dki_t *list, const zconf_t *conf)
449 char path[MAX_PATHSIZE+1];
450 zconf_t localconf;
451 const char *dir;
452 dki_t *keylist;
453 dki_t *dkp;
454 dki_t *standby;
455 int parent_exist;
456 int parent_age;
457 int parent_phase;
458 int parent_propagation;
459 int key_ttl;
460 int ksk;
462 if ( phase == 9 ) /* usage */
464 fprintf (stderr, "A KSK rollover requires three consecutive steps:\n");
465 fprintf (stderr, "\n");
466 fprintf (stderr, "-1%s", loptstr ("|--ksk-roll-phase1 (--ksk-newkey)\n", ""));
467 fprintf (stderr, "\t Create a new KSK.\n");
468 fprintf (stderr, "\t This step also creates a parent-<domain> file which contains only\n");
469 fprintf (stderr, "\t the _old_ key. This file will be copied in hierarchical mode\n");
470 fprintf (stderr, "\t by dnssec-signer to the parent directory as keyset-<domain> file.\n");
471 fprintf (stderr, "\t Wait until the new keyset is propagated, before going to the next step.\n");
472 fprintf (stderr, "\n");
473 fprintf (stderr, "-2%s", loptstr ("|--ksk-roll-phase2 (--ksk-publish)\n", ""));
474 fprintf (stderr, "\t This step creates a parent-<domain> file with the _new_ key only.\n");
475 fprintf (stderr, "\t Please send this file immediately to the parent (In hierarchical\n");
476 fprintf (stderr, "\t mode this will be done automatically by the dnssec-signer command).\n");
477 fprintf (stderr, "\t Then wait until the new DS is generated by the parent and propagated\n");
478 fprintf (stderr, "\t to all the parent name server, plus the old DS TTL before going to step three.\n");
479 fprintf (stderr, "\n");
480 fprintf (stderr, "-3%s", loptstr ("|--ksk-roll-phase3 (--ksk-delkey)\n", ""));
481 fprintf (stderr, "\t Remove (rename) the old KSK and the parent-<domain> file.\n");
482 fprintf (stderr, "\t You have to manually delete the old KSK (look at file names beginning\n");
483 fprintf (stderr, "\t with an lower 'k').\n");
484 fprintf (stderr, "\n");
485 fprintf (stderr, "-0%s", loptstr ("|--ksk-roll-stat (--ksk-status)\n", ""));
486 fprintf (stderr, "\t Show the current KSK rollover state of a domain.\n");
488 fprintf (stderr, "\n");
490 return;
493 if ( keyname == NULL || *keyname == '\0' )
494 fatal ("ksk rollover: no domain!");
496 dbg_val2 ("ksk_roll: keyname %s, phase = %d\n", keyname, phase);
498 /* search for already existent key to get the directory name */
499 if ( (keylist = (dki_t *)zkt_search (list, 0, keyname)) == NULL )
500 fatal ("ksk rollover: domain %s not found!\n", keyname);
501 dkp = keylist;
503 /* try to read local config file */
504 dir = dkp->dname;
505 pathname (path, sizeof (path), dir, LOCALCONF_FILE, NULL);
506 if ( fileexist (path) ) /* load local config file */
508 dbg_val ("Load local config file \"%s\"\n", path);
509 memcpy (&localconf, conf, sizeof (zconf_t));
510 conf = loadconfig (path, &localconf);
512 key_ttl = conf->key_ttl;
514 /* check if parent-file already exist */
515 pathname (path, sizeof (path), dir, "parent-", keyname);
516 parent_phase = parent_age = 0;
517 if ( (parent_exist = fileexist (path)) != 0 )
519 parent_phase = get_parent_phase (path);
520 parent_age = file_age (path);
522 // parent_propagation = 2 * DAYSEC;
523 parent_propagation = 5 * MINSEC;
525 ksk = 0; /* count active(!) key signing keys */
526 standby = NULL; /* find standby key if available */
527 for ( dkp = keylist; dkp; dkp = dkp->next )
528 if ( dki_isksk (dkp) )
530 if ( dki_status (dkp) == DKI_ACT )
531 ksk++;
532 else if ( dki_status (dkp) == DKI_PUB )
533 standby = dkp;
536 switch ( phase )
538 case 0: /* print status (debug) */
539 fprintf (stdout, "ksk_rollover:\n");
540 fprintf (stdout, "\t domain = %s\n", keyname);
541 fprintf (stdout, "\t phase = %d\n", parent_phase);
542 fprintf (stdout, "\t parent_file %s %s\n", path, parent_exist ? "exist": "not exist");
543 if ( parent_exist )
544 fprintf (stdout, "\t age of parent_file %d %s\n", parent_age, str_delspace (age2str (parent_age)));
545 fprintf (stdout, "\t # of active key signing keys %d\n", ksk);
546 fprintf (stdout, "\t parent_propagation %d %s\n", parent_propagation, str_delspace (age2str (parent_propagation)));
547 fprintf (stdout, "\t keys ttl %d %s\n", key_ttl, age2str (key_ttl));
549 for ( dkp = keylist; dkp; dkp = dkp->next )
551 /* TODO: Nur zum testen */
552 dki_prt_dnskey (dkp, stdout);
554 break;
555 case 1:
556 if ( parent_exist || ksk > 1 )
557 fatal ("Can\'t create new ksk because there is already an ksk rollover in progress\n");
559 fprintf (stdout, "create new ksk \n");
560 dkp = dki_new (dir, keyname, DKI_KSK, conf->k_algo, conf->k_bits, conf->k_random, conf->k_life / DAYSEC);
561 if ( dkp == NULL )
562 fatal ("Can't create key %s: %s!\n", keyname, dki_geterrstr ());
563 if ( standby )
565 dki_setstatus (standby, DKI_ACT); /* activate standby key */
566 dki_setstatus (dkp, DKI_PUB); /* new key will be the new standby */
569 // dkp = keylist; /* use old key to create the parent file */
570 if ( (dkp = (dki_t *)dki_findalgo (keylist, 1, conf->k_algo, 'a', 1)) == NULL ) /* find the oldest active ksk to create the parent file */
571 fatal ("ksk_rollover phase1: Couldn't find the old active key\n");
572 if ( !create_parent_file (path, phase, key_ttl, dkp) )
573 fatal ("Couldn't create parentfile %s\n", path);
574 break;
576 case 2:
577 if ( ksk < 2 )
578 fatal ("Can\'t publish new key because no one exist\n");
579 if ( !parent_exist )
580 fatal ("More than one KSK but no parent file found!\n");
581 if ( parent_phase != 1 )
582 fatal ("Parent file exists but is in wrong state (phase = %d)\n", parent_phase);
583 if ( parent_age < conf->proptime + key_ttl )
584 fatal ("ksk_rollover (phase2): you have to wait for the propagation of the new KSK (at least %dsec or %s)\n",
585 conf->proptime + key_ttl - parent_age,
586 str_delspace (age2str (conf->proptime + key_ttl - parent_age)));
588 fprintf (stdout, "save new ksk in parent file\n");
589 dkp = keylist->next; /* set dkp to new ksk */
590 if ( !create_parent_file (path, phase, key_ttl, dkp) )
591 fatal ("Couldn't create parentfile %s\n", path);
592 break;
593 case 3:
594 if ( !parent_exist || ksk < 2 )
595 fatal ("ksk-delkey only allowed after ksk-publish\n");
596 if ( parent_phase != 2 )
597 fatal ("Parent file exists but is in wrong state (phase = %d)\n", parent_phase);
598 if ( parent_age < parent_propagation + key_ttl )
599 fatal ("ksk_rollover (phase3): you have to wait for DS propagation (at least %dsec or %s)\n",
600 parent_propagation + key_ttl - parent_age,
601 str_delspace (age2str (parent_propagation + key_ttl - parent_age)));
602 /* remove the parentfile */
603 fprintf (stdout, "remove parentfile \n");
604 unlink (path);
605 /* remove or rename the old key */
606 fprintf (stdout, "old ksk renamed \n");
607 dkp = keylist; /* set dkp to old ksk */
608 dki_remove (dkp);
609 break;
610 default: assert (phase == 1 || phase == 2 || phase == 3);
614 /*****************************************************************
615 ** create_parent_file ()
616 *****************************************************************/
617 static int create_parent_file (const char *fname, int phase, int ttl, const dki_t *dkp)
619 FILE *fp;
621 assert ( fname != NULL );
623 if ( dkp == NULL || (phase != 1 && phase != 2) )
624 return 0;
626 if ( (fp = fopen (fname, "w")) == NULL )
627 fatal ("can\'t create new parentfile \"%s\"\n", fname);
629 if ( phase == 1 )
630 fprintf (fp, "; KSK rollover phase1 (old key)\n");
631 else
632 fprintf (fp, "; KSK rollover phase2 (new key)\n");
634 dki_prt_dnskeyttl (dkp, fp, ttl);
635 fclose (fp);
637 return phase;
640 static int parsedirectory (const char *dir, dki_t **listp)
642 dki_t *dkp;
643 DIR *dirp;
644 struct dirent *dentp;
645 char path[MAX_PATHSIZE+1];
647 if ( dirflag )
648 return 0;
650 dbg_val ("directory: opendir(%s)\n", dir);
651 if ( (dirp = opendir (dir)) == NULL )
652 return 0;
654 while ( (dentp = readdir (dirp)) != NULL )
656 if ( is_dotfilename (dentp->d_name) )
657 continue;
659 dbg_val ("directory: check %s\n", dentp->d_name);
660 pathname (path, sizeof (path), dir, dentp->d_name, NULL);
661 if ( is_directory (path) && recflag )
663 dbg_val ("directory: recursive %s\n", path);
664 parsedirectory (path, listp);
666 else if ( is_keyfilename (dentp->d_name) )
667 if ( (dkp = dki_read (dir, dentp->d_name)) )
669 // fprintf (stderr, "parsedir: tssearch (%d %s)\n", dkp, dkp->name);
670 #if defined (USE_TREE) && USE_TREE
671 dki_tadd (listp, dkp, 1);
672 #else
673 dki_add (listp, dkp);
674 #endif
677 closedir (dirp);
678 return 1;
681 static void parsefile (const char *file, dki_t **listp)
683 char path[MAX_PATHSIZE+1];
684 dki_t *dkp;
686 /* file arg contains path ? ... */
687 file = splitpath (path, sizeof (path), file); /* ... then split of */
689 if ( is_keyfilename (file) ) /* plain file name looks like DNS key file ? */
691 if ( (dkp = dki_read (path, file)) ) /* read DNS key file ... */
692 #if defined (USE_TREE) && USE_TREE
693 dki_tadd (listp, dkp, 1); /* ... and add to tree */
694 #else
695 dki_add (listp, dkp); /* ... and add to list */
696 #endif
697 else
698 error ("error parsing %s: (%s)\n", file, dki_geterrstr());
702 static const char *parsetag (const char *str, int *tagp)
704 const char *p;
706 *tagp = 0;
707 while ( isspace (*str) ) /* skip leading ws */
708 str++;
710 p = str;
711 if ( isdigit (*p) ) /* keytag starts with digit */
713 sscanf (p, "%u", tagp); /* read keytag as number */
714 do /* eat up to the end of the number */
715 p++;
716 while ( isdigit (*p) );
718 if ( *p == ':' ) /* label follows ? */
719 return p+1; /* return that */
720 if ( *p == '\0' )
721 return NULL; /* no label */
723 return str; /* return as label string if not a numeric keytag */