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