1*00b67f09SDavid van Moolenbroek /*	$NetBSD: zkt-signer.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-signer.c  (c) Jan 2005 - Jan 2010  Holger Zuleger hznet.de
6*00b67f09SDavid van Moolenbroek **
7*00b67f09SDavid van Moolenbroek **	A wrapper around the BIND dnssec-signzone command which is able
8*00b67f09SDavid van Moolenbroek **	to resign a zone if necessary and doing a zone or key signing key rollover.
9*00b67f09SDavid van Moolenbroek **
10*00b67f09SDavid van Moolenbroek **	Copyright (c) 2005 - 2010, Holger Zuleger HZnet. All rights reserved.
11*00b67f09SDavid van Moolenbroek **	This software is open source.
12*00b67f09SDavid van Moolenbroek **
13*00b67f09SDavid van Moolenbroek **	Redistribution and use in source and binary forms, with or without
14*00b67f09SDavid van Moolenbroek **	modification, are permitted provided that the following conditions
15*00b67f09SDavid van Moolenbroek **	are met:
16*00b67f09SDavid van Moolenbroek **
17*00b67f09SDavid van Moolenbroek **	Redistributions of source code must retain the above copyright notice,
18*00b67f09SDavid van Moolenbroek **	this list of conditions and the following disclaimer.
19*00b67f09SDavid van Moolenbroek **
20*00b67f09SDavid van Moolenbroek **	Redistributions in binary form must reproduce the above copyright notice,
21*00b67f09SDavid van Moolenbroek **	this list of conditions and the following disclaimer in the documentation
22*00b67f09SDavid van Moolenbroek **	and/or other materials provided with the distribution.
23*00b67f09SDavid van Moolenbroek **
24*00b67f09SDavid van Moolenbroek **	Neither the name of Holger Zuleger HZnet nor the names of its contributors may
25*00b67f09SDavid van Moolenbroek **	be used to endorse or promote products derived from this software without
26*00b67f09SDavid van Moolenbroek **	specific prior written permission.
27*00b67f09SDavid van Moolenbroek **
28*00b67f09SDavid van Moolenbroek **	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29*00b67f09SDavid van Moolenbroek **	"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
30*00b67f09SDavid van Moolenbroek **	TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31*00b67f09SDavid van Moolenbroek **	PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
32*00b67f09SDavid van Moolenbroek **	LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33*00b67f09SDavid van Moolenbroek **	CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34*00b67f09SDavid van Moolenbroek **	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35*00b67f09SDavid van Moolenbroek **	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36*00b67f09SDavid van Moolenbroek **	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37*00b67f09SDavid van Moolenbroek **	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38*00b67f09SDavid van Moolenbroek **	POSSIBILITY OF SUCH DAMAGE.
39*00b67f09SDavid van Moolenbroek **
40*00b67f09SDavid van Moolenbroek *****************************************************************/
41*00b67f09SDavid van Moolenbroek 
42*00b67f09SDavid van Moolenbroek # include <stdio.h>
43*00b67f09SDavid van Moolenbroek # include <string.h>
44*00b67f09SDavid van Moolenbroek # include <stdlib.h>
45*00b67f09SDavid van Moolenbroek # include <assert.h>
46*00b67f09SDavid van Moolenbroek # include <dirent.h>
47*00b67f09SDavid van Moolenbroek # include <errno.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 # include "zconf.h"
59*00b67f09SDavid van Moolenbroek # include "debug.h"
60*00b67f09SDavid van Moolenbroek # include "misc.h"
61*00b67f09SDavid van Moolenbroek # include "ncparse.h"
62*00b67f09SDavid van Moolenbroek # include "nscomm.h"
63*00b67f09SDavid van Moolenbroek # include "soaserial.h"
64*00b67f09SDavid van Moolenbroek # include "zone.h"
65*00b67f09SDavid van Moolenbroek # include "dki.h"
66*00b67f09SDavid van Moolenbroek # include "rollover.h"
67*00b67f09SDavid van Moolenbroek # include "log.h"
68*00b67f09SDavid van Moolenbroek 
69*00b67f09SDavid van Moolenbroek # define	short_options	"c:L:V:D:N:o:O:dfHhnrv"
70*00b67f09SDavid van Moolenbroek #if defined(HAVE_GETOPT_LONG) && HAVE_GETOPT_LONG
71*00b67f09SDavid van Moolenbroek static struct option long_options[] = {
72*00b67f09SDavid van Moolenbroek 	{"reload",		no_argument, NULL, 'r'},
73*00b67f09SDavid van Moolenbroek 	{"force",		no_argument, NULL, 'f'},
74*00b67f09SDavid van Moolenbroek 	{"noexec",		no_argument, NULL, 'n'},
75*00b67f09SDavid van Moolenbroek 	{"verbose",		no_argument, NULL, 'v'},
76*00b67f09SDavid van Moolenbroek 	{"directory",		no_argument, NULL, 'd'},
77*00b67f09SDavid van Moolenbroek 	{"config",		required_argument, NULL, 'c'},
78*00b67f09SDavid van Moolenbroek 	{"option",		required_argument, NULL, 'O'},
79*00b67f09SDavid van Moolenbroek 	{"config-option",	required_argument, NULL, 'O'},
80*00b67f09SDavid van Moolenbroek 	{"logfile",		required_argument, NULL, 'L' },
81*00b67f09SDavid van Moolenbroek 	{"view",		required_argument, NULL, 'V' },
82*00b67f09SDavid van Moolenbroek 	{"directory",		required_argument, NULL, 'D'},
83*00b67f09SDavid van Moolenbroek 	{"named-conf",		required_argument, NULL, 'N'},
84*00b67f09SDavid van Moolenbroek 	{"origin",		required_argument, NULL, 'o'},
85*00b67f09SDavid van Moolenbroek 	{"dynamic",		no_argument, NULL, 'd' },
86*00b67f09SDavid van Moolenbroek 	{"help",		no_argument, NULL, 'h'},
87*00b67f09SDavid van Moolenbroek 	{0, 0, 0, 0}
88*00b67f09SDavid van Moolenbroek };
89*00b67f09SDavid van Moolenbroek #endif
90*00b67f09SDavid van Moolenbroek 
91*00b67f09SDavid van Moolenbroek 
92*00b67f09SDavid van Moolenbroek /**	function declaration	**/
93*00b67f09SDavid van Moolenbroek static	void	usage (char *mesg, zconf_t *conf);
94*00b67f09SDavid van Moolenbroek static	int	add2zonelist (const char *dir, const char *view, const char *zone, const char *file);
95*00b67f09SDavid van Moolenbroek static	int	parsedir (const char *dir, zone_t **zp, const zconf_t *conf);
96*00b67f09SDavid van Moolenbroek static	int	dosigning (zone_t *zonelist, zone_t *zp);
97*00b67f09SDavid van Moolenbroek static	int	check_keydb_timestamp (dki_t *keylist, time_t reftime);
98*00b67f09SDavid van Moolenbroek static	int	new_keysetfiles (const char *dir, time_t zone_signing_time);
99*00b67f09SDavid van Moolenbroek static	int	writekeyfile (const char *fname, const dki_t *list, int key_ttl);
100*00b67f09SDavid van Moolenbroek static	int	sign_zone (const zone_t *zp);
101*00b67f09SDavid van Moolenbroek static	void	register_key (dki_t *listp, const zconf_t *z);
102*00b67f09SDavid van Moolenbroek static	void	copy_keyset (const char *dir, const char *domain, const zconf_t *conf);
103*00b67f09SDavid van Moolenbroek 
104*00b67f09SDavid van Moolenbroek /**	global command line options	**/
105*00b67f09SDavid van Moolenbroek extern  int	optopt;
106*00b67f09SDavid van Moolenbroek extern  int	opterr;
107*00b67f09SDavid van Moolenbroek extern  int	optind;
108*00b67f09SDavid van Moolenbroek extern  char	*optarg;
109*00b67f09SDavid van Moolenbroek const	char	*progname;
110*00b67f09SDavid van Moolenbroek static	const	char	*viewname = NULL;
111*00b67f09SDavid van Moolenbroek static	const	char	*logfile = NULL;
112*00b67f09SDavid van Moolenbroek static	const	char	*origin = NULL;
113*00b67f09SDavid van Moolenbroek static	const	char	*namedconf = NULL;
114*00b67f09SDavid van Moolenbroek static	const	char	*dirname = NULL;
115*00b67f09SDavid van Moolenbroek static	int	verbose = 0;
116*00b67f09SDavid van Moolenbroek static	int	force = 0;
117*00b67f09SDavid van Moolenbroek static	int	reloadflag = 0;
118*00b67f09SDavid van Moolenbroek static	int	noexec = 0;
119*00b67f09SDavid van Moolenbroek static	int	dynamic_zone = 0;	/* dynamic zone ? */
120*00b67f09SDavid van Moolenbroek static	zone_t	*zonelist = NULL;	/* must be static global because add2zonelist use it */
121*00b67f09SDavid van Moolenbroek static	zconf_t	*config;
122*00b67f09SDavid van Moolenbroek 
123*00b67f09SDavid van Moolenbroek /**	macros **/
124*00b67f09SDavid van Moolenbroek #define	set_bind96_dynzone(dz)	((dz) = 6)
125*00b67f09SDavid van Moolenbroek #define	bind96_dynzone(dz)	( (dz) >= 6 )
126*00b67f09SDavid van Moolenbroek #define	is_defined(str)		( (str) && *(str) )
127*00b67f09SDavid van Moolenbroek 
main(int argc,char * const argv[])128*00b67f09SDavid van Moolenbroek int	main (int argc, char *const argv[])
129*00b67f09SDavid van Moolenbroek {
130*00b67f09SDavid van Moolenbroek 	int	c;
131*00b67f09SDavid van Moolenbroek 	int	errcnt;
132*00b67f09SDavid van Moolenbroek #if defined(HAVE_GETOPT_LONG) && HAVE_GETOPT_LONG
133*00b67f09SDavid van Moolenbroek 	int	opt_index;
134*00b67f09SDavid van Moolenbroek #endif
135*00b67f09SDavid van Moolenbroek 	char	errstr[255+1];
136*00b67f09SDavid van Moolenbroek 	char	*p;
137*00b67f09SDavid van Moolenbroek 	const	char	*defconfname;
138*00b67f09SDavid van Moolenbroek 	zone_t	*zp;
139*00b67f09SDavid van Moolenbroek 
140*00b67f09SDavid van Moolenbroek 	progname = *argv;
141*00b67f09SDavid van Moolenbroek 	if ( (p = strrchr (progname, '/')) )
142*00b67f09SDavid van Moolenbroek 		progname = ++p;
143*00b67f09SDavid van Moolenbroek 
144*00b67f09SDavid van Moolenbroek 	if ( strncmp (progname, "dnssec-signer", 13) == 0 )
145*00b67f09SDavid van Moolenbroek 	{
146*00b67f09SDavid van Moolenbroek 		fprintf (stderr, "The use of dnssec-signer is deprecated, please run zkt-signer instead\n");
147*00b67f09SDavid van Moolenbroek 		viewname = getnameappendix (progname, "dnssec-signer");
148*00b67f09SDavid van Moolenbroek 	}
149*00b67f09SDavid van Moolenbroek 	else
150*00b67f09SDavid van Moolenbroek 		viewname = getnameappendix (progname, "zkt-signer");
151*00b67f09SDavid van Moolenbroek 	defconfname = getdefconfname (viewname);
152*00b67f09SDavid van Moolenbroek 	config = loadconfig ("", (zconf_t *)NULL);	/* load build-in config */
153*00b67f09SDavid van Moolenbroek 	if ( fileexist (defconfname) )			/* load default config file */
154*00b67f09SDavid van Moolenbroek 		config = loadconfig (defconfname, config);
155*00b67f09SDavid van Moolenbroek 	if ( config == NULL )
156*00b67f09SDavid van Moolenbroek 		fatal ("Couldn't load config: Out of memory\n");
157*00b67f09SDavid van Moolenbroek 
158*00b67f09SDavid van Moolenbroek 	zonelist = NULL;
159*00b67f09SDavid van Moolenbroek         opterr = 0;
160*00b67f09SDavid van Moolenbroek #if defined(HAVE_GETOPT_LONG) && HAVE_GETOPT_LONG
161*00b67f09SDavid van Moolenbroek 	while ( (c = getopt_long (argc, argv, short_options, long_options, &opt_index)) != -1 )
162*00b67f09SDavid van Moolenbroek #else
163*00b67f09SDavid van Moolenbroek 	while ( (c = getopt (argc, argv, short_options)) != -1 )
164*00b67f09SDavid van Moolenbroek #endif
165*00b67f09SDavid van Moolenbroek 	{
166*00b67f09SDavid van Moolenbroek 		switch ( c )
167*00b67f09SDavid van Moolenbroek 		{
168*00b67f09SDavid van Moolenbroek 		case 'V':		/* view name */
169*00b67f09SDavid van Moolenbroek 			viewname = optarg;
170*00b67f09SDavid van Moolenbroek 			defconfname = getdefconfname (viewname);
171*00b67f09SDavid van Moolenbroek 			if ( fileexist (defconfname) )		/* load default config file */
172*00b67f09SDavid van Moolenbroek 				config = loadconfig (defconfname, config);
173*00b67f09SDavid van Moolenbroek 			if ( config == NULL )
174*00b67f09SDavid van Moolenbroek 				fatal ("Out of memory\n");
175*00b67f09SDavid van Moolenbroek 			break;
176*00b67f09SDavid van Moolenbroek 		case 'c':		/* load config from file */
177*00b67f09SDavid van Moolenbroek 			config = loadconfig (optarg, config);
178*00b67f09SDavid van Moolenbroek 			if ( config == NULL )
179*00b67f09SDavid van Moolenbroek 				fatal ("Out of memory\n");
180*00b67f09SDavid van Moolenbroek 			break;
181*00b67f09SDavid van Moolenbroek 		case 'O':		/* load config option from commandline */
182*00b67f09SDavid van Moolenbroek 			config = loadconfig_fromstr (optarg, config);
183*00b67f09SDavid van Moolenbroek 			if ( config == NULL )
184*00b67f09SDavid van Moolenbroek 				fatal ("Out of memory\n");
185*00b67f09SDavid van Moolenbroek 			break;
186*00b67f09SDavid van Moolenbroek 		case 'o':
187*00b67f09SDavid van Moolenbroek 			origin = optarg;
188*00b67f09SDavid van Moolenbroek 			break;
189*00b67f09SDavid van Moolenbroek 		case 'N':
190*00b67f09SDavid van Moolenbroek 			namedconf = optarg;
191*00b67f09SDavid van Moolenbroek 			break;
192*00b67f09SDavid van Moolenbroek 		case 'D':
193*00b67f09SDavid van Moolenbroek 			dirname = optarg;
194*00b67f09SDavid van Moolenbroek 			break;
195*00b67f09SDavid van Moolenbroek 		case 'L':		/* error log file|directory */
196*00b67f09SDavid van Moolenbroek 			logfile = optarg;
197*00b67f09SDavid van Moolenbroek 			break;
198*00b67f09SDavid van Moolenbroek 		case 'f':
199*00b67f09SDavid van Moolenbroek 			force++;
200*00b67f09SDavid van Moolenbroek 			break;
201*00b67f09SDavid van Moolenbroek 		case 'H':
202*00b67f09SDavid van Moolenbroek 		case 'h':
203*00b67f09SDavid van Moolenbroek 			usage (NULL, config);
204*00b67f09SDavid van Moolenbroek 			break;
205*00b67f09SDavid van Moolenbroek 		case 'd':
206*00b67f09SDavid van Moolenbroek 			dynamic_zone = 1;
207*00b67f09SDavid van Moolenbroek 			/* dynamic zone requires a name server reload... */
208*00b67f09SDavid van Moolenbroek 			reloadflag = 0;		/* ...but "rndc thaw" reloads the zone anyway */
209*00b67f09SDavid van Moolenbroek 			break;
210*00b67f09SDavid van Moolenbroek 		case 'n':
211*00b67f09SDavid van Moolenbroek 			noexec = 1;
212*00b67f09SDavid van Moolenbroek 			break;
213*00b67f09SDavid van Moolenbroek 		case 'r':
214*00b67f09SDavid van Moolenbroek 			if ( !dynamic_zone )	/* dynamic zones don't need a rndc reload (see "-d" */
215*00b67f09SDavid van Moolenbroek 				reloadflag = 1;
216*00b67f09SDavid van Moolenbroek 			break;
217*00b67f09SDavid van Moolenbroek 		case 'v':
218*00b67f09SDavid van Moolenbroek 			verbose++;
219*00b67f09SDavid van Moolenbroek 			break;
220*00b67f09SDavid van Moolenbroek 		case '?':
221*00b67f09SDavid van Moolenbroek 			if ( isprint (optopt) )
222*00b67f09SDavid van Moolenbroek 				snprintf (errstr, sizeof(errstr),
223*00b67f09SDavid van Moolenbroek 					"Unknown option \"-%c\".\n", optopt);
224*00b67f09SDavid van Moolenbroek 			else
225*00b67f09SDavid van Moolenbroek 				snprintf (errstr, sizeof (errstr),
226*00b67f09SDavid van Moolenbroek 					"Unknown option char \\x%x.\n", optopt);
227*00b67f09SDavid van Moolenbroek 			usage (errstr, config);
228*00b67f09SDavid van Moolenbroek 			break;
229*00b67f09SDavid van Moolenbroek 		default:
230*00b67f09SDavid van Moolenbroek 			abort();
231*00b67f09SDavid van Moolenbroek 		}
232*00b67f09SDavid van Moolenbroek 	}
233*00b67f09SDavid van Moolenbroek 	dbg_line();
234*00b67f09SDavid van Moolenbroek 
235*00b67f09SDavid van Moolenbroek 	/* store some of the commandline parameter in the config structure */
236*00b67f09SDavid van Moolenbroek 	setconfigpar (config, "--view", viewname);
237*00b67f09SDavid van Moolenbroek 	setconfigpar (config, "-v", &verbose);
238*00b67f09SDavid van Moolenbroek 	setconfigpar (config, "--noexec", &noexec);
239*00b67f09SDavid van Moolenbroek 	if ( logfile == NULL )
240*00b67f09SDavid van Moolenbroek 		logfile = config->logfile;
241*00b67f09SDavid van Moolenbroek 
242*00b67f09SDavid van Moolenbroek 	if ( lg_open (progname, config->syslogfacility, config->sysloglevel, config->zonedir, logfile, config->loglevel) < -1 )
243*00b67f09SDavid van Moolenbroek 		fatal ("Couldn't open logfile %s in dir %s\n", logfile, config->zonedir);
244*00b67f09SDavid van Moolenbroek 
245*00b67f09SDavid van Moolenbroek 	lg_args (LG_NOTICE, argc, argv);
246*00b67f09SDavid van Moolenbroek 
247*00b67f09SDavid van Moolenbroek 	/* 1.0rc1: If the ttl is 0 or not known because of dynamic zone signing, ... */
248*00b67f09SDavid van Moolenbroek 	/* ... use sig valid time for this */
249*00b67f09SDavid van Moolenbroek 	if ( config->max_ttl <= 0 || dynamic_zone )
250*00b67f09SDavid van Moolenbroek 	{
251*00b67f09SDavid van Moolenbroek 		// config = dupconfig (config);
252*00b67f09SDavid van Moolenbroek 		config->max_ttl = config->sigvalidity;
253*00b67f09SDavid van Moolenbroek 	}
254*00b67f09SDavid van Moolenbroek 
255*00b67f09SDavid van Moolenbroek 
256*00b67f09SDavid van Moolenbroek 	if ( origin )		/* option -o ? */
257*00b67f09SDavid van Moolenbroek 	{
258*00b67f09SDavid van Moolenbroek 		int	ret;
259*00b67f09SDavid van Moolenbroek 
260*00b67f09SDavid van Moolenbroek 		if ( (argc - optind) <= 0 )	/* no arguments left ? */
261*00b67f09SDavid van Moolenbroek 			ret = zone_readdir (".", origin, NULL, &zonelist, config, dynamic_zone);
262*00b67f09SDavid van Moolenbroek 		else
263*00b67f09SDavid van Moolenbroek 			ret = zone_readdir (".", origin, argv[optind], &zonelist, config, dynamic_zone);
264*00b67f09SDavid van Moolenbroek 
265*00b67f09SDavid van Moolenbroek 		/* anyway, "delete" all (remaining) arguments */
266*00b67f09SDavid van Moolenbroek 		optind = argc;
267*00b67f09SDavid van Moolenbroek 
268*00b67f09SDavid van Moolenbroek 		/* complain if nothing could read in */
269*00b67f09SDavid van Moolenbroek 		if ( ret != 1 || zonelist == NULL )
270*00b67f09SDavid van Moolenbroek 		{
271*00b67f09SDavid van Moolenbroek 			lg_mesg (LG_FATAL, "\"%s\": couldn't read", origin);
272*00b67f09SDavid van Moolenbroek 			fatal ("Couldn't read zone \"%s\"\n", origin);
273*00b67f09SDavid van Moolenbroek 		}
274*00b67f09SDavid van Moolenbroek 	}
275*00b67f09SDavid van Moolenbroek 	if ( namedconf )	/* option -N ? */
276*00b67f09SDavid van Moolenbroek 	{
277*00b67f09SDavid van Moolenbroek 		char	dir[255+1];
278*00b67f09SDavid van Moolenbroek 
279*00b67f09SDavid van Moolenbroek 		memset (dir, '\0', sizeof (dir));
280*00b67f09SDavid van Moolenbroek 		if ( config->zonedir )
281*00b67f09SDavid van Moolenbroek 			strncpy (dir, config->zonedir, sizeof(dir));
282*00b67f09SDavid van Moolenbroek 		if ( !parse_namedconf (namedconf, config->chroot_dir, dir, sizeof (dir), add2zonelist) )
283*00b67f09SDavid van Moolenbroek 			fatal ("Can't read file %s as namedconf file\n", namedconf);
284*00b67f09SDavid van Moolenbroek 		if ( zonelist == NULL )
285*00b67f09SDavid van Moolenbroek 			fatal ("No signed zone found in file %s\n", namedconf);
286*00b67f09SDavid van Moolenbroek 	}
287*00b67f09SDavid van Moolenbroek 	if ( dirname )		/* option -D ? */
288*00b67f09SDavid van Moolenbroek 	{
289*00b67f09SDavid van Moolenbroek 		char	*dir = strdup (dirname);
290*00b67f09SDavid van Moolenbroek 
291*00b67f09SDavid van Moolenbroek 		p = dir + strlen (dir);
292*00b67f09SDavid van Moolenbroek 		if ( p > dir )
293*00b67f09SDavid van Moolenbroek 			p--;
294*00b67f09SDavid van Moolenbroek 		if ( *p == '/' )
295*00b67f09SDavid van Moolenbroek 			*p = '\0';	/* remove trailing path seperator */
296*00b67f09SDavid van Moolenbroek 
297*00b67f09SDavid van Moolenbroek 		if ( !parsedir (dir, &zonelist, config) )
298*00b67f09SDavid van Moolenbroek 			fatal ("Can't read directory tree %s\n", dir);
299*00b67f09SDavid van Moolenbroek 		if ( zonelist == NULL )
300*00b67f09SDavid van Moolenbroek 			fatal ("No signed zone found in directory tree %s\n", dir);
301*00b67f09SDavid van Moolenbroek 		free (dir);
302*00b67f09SDavid van Moolenbroek 	}
303*00b67f09SDavid van Moolenbroek 
304*00b67f09SDavid van Moolenbroek 	/* none of the above: read default directory tree */
305*00b67f09SDavid van Moolenbroek 	if ( zonelist == NULL )
306*00b67f09SDavid van Moolenbroek 		parsedir (config->zonedir, &zonelist, config);
307*00b67f09SDavid van Moolenbroek 
308*00b67f09SDavid van Moolenbroek #if defined(DBG) && DBG
309*00b67f09SDavid van Moolenbroek 	for ( zp = zonelist; zp; zp = zp->next )
310*00b67f09SDavid van Moolenbroek 		zone_print ("in main: ", zp);
311*00b67f09SDavid van Moolenbroek #endif
312*00b67f09SDavid van Moolenbroek 	for ( zp = zonelist; zp; zp = zp->next )
313*00b67f09SDavid van Moolenbroek 		if ( in_strarr (zp->zone, &argv[optind], argc - optind) )
314*00b67f09SDavid van Moolenbroek 		{
315*00b67f09SDavid van Moolenbroek 			dosigning (zonelist, zp);
316*00b67f09SDavid van Moolenbroek 			verbmesg (1, zp->conf, "\n");
317*00b67f09SDavid van Moolenbroek 		}
318*00b67f09SDavid van Moolenbroek 
319*00b67f09SDavid van Moolenbroek 	zone_freelist (&zonelist);
320*00b67f09SDavid van Moolenbroek 
321*00b67f09SDavid van Moolenbroek 	errcnt = lg_geterrcnt ();
322*00b67f09SDavid van Moolenbroek 	lg_mesg (LG_NOTICE, "end of run: %d error%s occured", errcnt, errcnt == 1 ? "" : "s");
323*00b67f09SDavid van Moolenbroek 	lg_close ();
324*00b67f09SDavid van Moolenbroek 
325*00b67f09SDavid van Moolenbroek 	return errcnt < 64 ? errcnt : 64;
326*00b67f09SDavid van Moolenbroek }
327*00b67f09SDavid van Moolenbroek 
328*00b67f09SDavid van Moolenbroek # define	sopt_usage(mesg, value) fprintf (stderr, mesg, value)
329*00b67f09SDavid van Moolenbroek #if defined(HAVE_GETOPT_LONG) && HAVE_GETOPT_LONG
330*00b67f09SDavid van Moolenbroek # define	lopt_usage(mesg, value) fprintf (stderr, mesg, value)
331*00b67f09SDavid van Moolenbroek # define	loptstr(lstr, sstr)     lstr
332*00b67f09SDavid van Moolenbroek #else
333*00b67f09SDavid van Moolenbroek # define	lopt_usage(mesg, value)
334*00b67f09SDavid van Moolenbroek # define	loptstr(lstr, sstr)     sstr
335*00b67f09SDavid van Moolenbroek #endif
usage(char * mesg,zconf_t * conf)336*00b67f09SDavid van Moolenbroek static	void	usage (char *mesg, zconf_t *conf)
337*00b67f09SDavid van Moolenbroek {
338*00b67f09SDavid van Moolenbroek 	fprintf (stderr, "%s version %s compiled for BIND %d\n", progname, ZKT_VERSION, BIND_VERSION);
339*00b67f09SDavid van Moolenbroek 	fprintf (stderr, "ZKT %s\n", ZKT_COPYRIGHT);
340*00b67f09SDavid van Moolenbroek 	fprintf (stderr, "\n");
341*00b67f09SDavid van Moolenbroek 
342*00b67f09SDavid van Moolenbroek 	fprintf (stderr, "usage: %s [-L] [-V view] [-c file] [-O optstr] ", progname);
343*00b67f09SDavid van Moolenbroek 	fprintf (stderr, "[-D directorytree] ");
344*00b67f09SDavid van Moolenbroek 	fprintf (stderr, "[-fhnr] [-v [-v]] [zone ...]\n");
345*00b67f09SDavid van Moolenbroek 
346*00b67f09SDavid van Moolenbroek 	fprintf (stderr, "usage: %s [-L] [-V view] [-c file] [-O optstr] ", progname);
347*00b67f09SDavid van Moolenbroek 	fprintf (stderr, "-N named.conf ");
348*00b67f09SDavid van Moolenbroek 	fprintf (stderr, "[-fhnr] [-v [-v]] [zone ...]\n");
349*00b67f09SDavid van Moolenbroek 
350*00b67f09SDavid van Moolenbroek 	fprintf (stderr, "usage: %s [-L] [-V view] [-c file] [-O optstr] ", progname);
351*00b67f09SDavid van Moolenbroek 	fprintf (stderr, "-o origin ");
352*00b67f09SDavid van Moolenbroek 	fprintf (stderr, "[-fhnr] [-v [-v]] [zonefile.signed]\n");
353*00b67f09SDavid van Moolenbroek 
354*00b67f09SDavid van Moolenbroek 	fprintf (stderr, "\t-c file%s", loptstr (", --config=file\n", ""));
355*00b67f09SDavid van Moolenbroek 	fprintf (stderr, "\t\t read config from <file> instead of %s\n", CONFIG_FILE);
356*00b67f09SDavid van Moolenbroek 	fprintf (stderr, "\t-O optstr%s", loptstr (", --config-option=\"optstr\"\n", ""));
357*00b67f09SDavid van Moolenbroek 	fprintf (stderr, "\t\t set config options on the commandline\n");
358*00b67f09SDavid van Moolenbroek 	fprintf (stderr, "\t-L file|dir%s", loptstr (", --logfile=file|dir\n", ""));
359*00b67f09SDavid van Moolenbroek 	fprintf (stderr, "\t\t specify file or directory for the log output\n");
360*00b67f09SDavid van Moolenbroek 	fprintf (stderr, "\t-V name%s", loptstr (", --view=name\n", ""));
361*00b67f09SDavid van Moolenbroek 	fprintf (stderr, "\t\t specify the view name \n");
362*00b67f09SDavid van Moolenbroek 	fprintf (stderr, "\t-D dir%s", loptstr (", --directory=dir\n", ""));
363*00b67f09SDavid van Moolenbroek 	fprintf (stderr, "\t\t parse the given directory tree for a list of secure zones \n");
364*00b67f09SDavid van Moolenbroek 	fprintf (stderr, "\t-N file%s", loptstr (", --named-conf=file\n", ""));
365*00b67f09SDavid van Moolenbroek 	fprintf (stderr, "\t\t get the list of secure zones out of the named like config file \n");
366*00b67f09SDavid van Moolenbroek 	fprintf (stderr, "\t-o zone%s", loptstr (", --origin=zone", ""));
367*00b67f09SDavid van Moolenbroek 	fprintf (stderr, "\tspecify the name of the zone \n");
368*00b67f09SDavid van Moolenbroek 	fprintf (stderr, "\t\t The file to sign should be given as an argument (default is \"%s.signed\")\n", conf->zonefile);
369*00b67f09SDavid van Moolenbroek 	fprintf (stderr, "\t-h%s\t print this help\n", loptstr (", --help", "\t"));
370*00b67f09SDavid van Moolenbroek 	fprintf (stderr, "\t-f%s\t force re-signing\n", loptstr (", --force", "\t"));
371*00b67f09SDavid van Moolenbroek 	fprintf (stderr, "\t-n%s\t no execution of external signing command\n", loptstr (", --noexec", "\t"));
372*00b67f09SDavid van Moolenbroek 	// fprintf (stderr, "\t-r%s\t reload zone via <rndc reload zone> (or via the external distribution command)\n", loptstr (", --reload", "\t"));
373*00b67f09SDavid van Moolenbroek 	fprintf (stderr, "\t-r%s\t reload zone via %s\n", loptstr (", --reload", "\t"), conf->dist_cmd ? conf->dist_cmd: "rndc");
374*00b67f09SDavid van Moolenbroek         fprintf (stderr, "\t-v%s\t be verbose (use twice to be very verbose)\n", loptstr (", --verbose", "\t"));
375*00b67f09SDavid van Moolenbroek 
376*00b67f09SDavid van Moolenbroek         fprintf (stderr, "\t[zone]\t sign only those zones given as argument\n");
377*00b67f09SDavid van Moolenbroek 
378*00b67f09SDavid van Moolenbroek         fprintf (stderr, "\n");
379*00b67f09SDavid van Moolenbroek         fprintf (stderr, "\tif neither -D nor -N nor -o is given, the directory tree specified\n");
380*00b67f09SDavid van Moolenbroek 	fprintf (stderr, "\tin the dnssec config file (\"%s\") will be parsed\n", conf->zonedir);
381*00b67f09SDavid van Moolenbroek 
382*00b67f09SDavid van Moolenbroek 	if ( mesg && *mesg )
383*00b67f09SDavid van Moolenbroek 		fprintf (stderr, "%s\n", mesg);
384*00b67f09SDavid van Moolenbroek 	exit (127);
385*00b67f09SDavid van Moolenbroek }
386*00b67f09SDavid van Moolenbroek 
387*00b67f09SDavid van Moolenbroek /**	fill zonelist with infos coming out of named.conf	**/
add2zonelist(const char * dir,const char * view,const char * zone,const char * file)388*00b67f09SDavid van Moolenbroek static	int	add2zonelist (const char *dir, const char *view, const char *zone, const char *file)
389*00b67f09SDavid van Moolenbroek {
390*00b67f09SDavid van Moolenbroek #ifdef DBG
391*00b67f09SDavid van Moolenbroek 	fprintf (stderr, "printzone ");
392*00b67f09SDavid van Moolenbroek 	fprintf (stderr, "view \"%s\" " , view);
393*00b67f09SDavid van Moolenbroek 	fprintf (stderr, "zone \"%s\" " , zone);
394*00b67f09SDavid van Moolenbroek 	fprintf (stderr, "file ");
395*00b67f09SDavid van Moolenbroek 	if ( dir && *dir )
396*00b67f09SDavid van Moolenbroek 		fprintf (stderr, "%s/", dir);
397*00b67f09SDavid van Moolenbroek 	fprintf (stderr, "%s", file);
398*00b67f09SDavid van Moolenbroek 	fprintf (stderr, "\n");
399*00b67f09SDavid van Moolenbroek #endif
400*00b67f09SDavid van Moolenbroek 	dbg_line ();
401*00b67f09SDavid van Moolenbroek 	if ( view[0] != '\0' )	/* view found in named.conf */
402*00b67f09SDavid van Moolenbroek 	{
403*00b67f09SDavid van Moolenbroek 		if ( viewname == NULL || viewname[0] == '\0' )	/* viewname wasn't set on startup ? */
404*00b67f09SDavid van Moolenbroek 		{
405*00b67f09SDavid van Moolenbroek 			dbg_line ();
406*00b67f09SDavid van Moolenbroek 			error ("zone \"%s\" in view \"%s\" found in name server config, but no matching view was set on startup\n", zone, view);
407*00b67f09SDavid van Moolenbroek 			lg_mesg (LG_ERROR, "\"%s\" in view \"%s\" found in name server config, but no matching view was set on startup", zone, view);
408*00b67f09SDavid van Moolenbroek 			return 0;
409*00b67f09SDavid van Moolenbroek 		}
410*00b67f09SDavid van Moolenbroek 		dbg_line ();
411*00b67f09SDavid van Moolenbroek 		if ( strcmp (viewname, view) != 0 )	/* zone is _not_ in current view */
412*00b67f09SDavid van Moolenbroek 			return 0;
413*00b67f09SDavid van Moolenbroek 	}
414*00b67f09SDavid van Moolenbroek 	return zone_readdir (dir, zone, file, &zonelist, config, dynamic_zone);
415*00b67f09SDavid van Moolenbroek }
416*00b67f09SDavid van Moolenbroek 
parsedir(const char * dir,zone_t ** zp,const zconf_t * conf)417*00b67f09SDavid van Moolenbroek static	int	parsedir (const char *dir, zone_t **zp, const zconf_t *conf)
418*00b67f09SDavid van Moolenbroek {
419*00b67f09SDavid van Moolenbroek 	DIR	*dirp;
420*00b67f09SDavid van Moolenbroek 	struct  dirent  *dentp;
421*00b67f09SDavid van Moolenbroek 	char	path[MAX_PATHSIZE+1];
422*00b67f09SDavid van Moolenbroek 
423*00b67f09SDavid van Moolenbroek 	dbg_val ("parsedir: (%s)\n", dir);
424*00b67f09SDavid van Moolenbroek 	if ( !is_directory (dir) )
425*00b67f09SDavid van Moolenbroek 		return 0;
426*00b67f09SDavid van Moolenbroek 
427*00b67f09SDavid van Moolenbroek 	dbg_line ();
428*00b67f09SDavid van Moolenbroek 	zone_readdir (dir, NULL, NULL, zp, conf, dynamic_zone);
429*00b67f09SDavid van Moolenbroek 
430*00b67f09SDavid van Moolenbroek 	dbg_val ("parsedir: opendir(%s)\n", dir);
431*00b67f09SDavid van Moolenbroek 	if ( (dirp = opendir (dir)) == NULL )
432*00b67f09SDavid van Moolenbroek 		return 0;
433*00b67f09SDavid van Moolenbroek 
434*00b67f09SDavid van Moolenbroek 	while ( (dentp = readdir (dirp)) != NULL )
435*00b67f09SDavid van Moolenbroek 	{
436*00b67f09SDavid van Moolenbroek 		if ( is_dotfilename (dentp->d_name) )
437*00b67f09SDavid van Moolenbroek 			continue;
438*00b67f09SDavid van Moolenbroek 
439*00b67f09SDavid van Moolenbroek 		pathname (path, sizeof (path), dir, dentp->d_name, NULL);
440*00b67f09SDavid van Moolenbroek 		if ( !is_directory (path) )
441*00b67f09SDavid van Moolenbroek 			continue;
442*00b67f09SDavid van Moolenbroek 
443*00b67f09SDavid van Moolenbroek 		dbg_val ("parsedir: recursive %s\n", path);
444*00b67f09SDavid van Moolenbroek 		parsedir (path, zp, conf);
445*00b67f09SDavid van Moolenbroek 	}
446*00b67f09SDavid van Moolenbroek 	closedir (dirp);
447*00b67f09SDavid van Moolenbroek 	return 1;
448*00b67f09SDavid van Moolenbroek }
449*00b67f09SDavid van Moolenbroek 
dosigning(zone_t * zonelist,zone_t * zp)450*00b67f09SDavid van Moolenbroek static	int	dosigning (zone_t *zonelist, zone_t *zp)
451*00b67f09SDavid van Moolenbroek {
452*00b67f09SDavid van Moolenbroek 	char	path[MAX_PATHSIZE+1];
453*00b67f09SDavid van Moolenbroek 	int	err;
454*00b67f09SDavid van Moolenbroek 	int	newkey;
455*00b67f09SDavid van Moolenbroek 	int	newkeysetfile;
456*00b67f09SDavid van Moolenbroek 	int	use_unixtime;
457*00b67f09SDavid van Moolenbroek 	time_t	currtime;
458*00b67f09SDavid van Moolenbroek 	time_t	zfile_time;
459*00b67f09SDavid van Moolenbroek 	time_t	zfilesig_time;
460*00b67f09SDavid van Moolenbroek 	char	mesg[255+1];
461*00b67f09SDavid van Moolenbroek 
462*00b67f09SDavid van Moolenbroek 	verbmesg (1, zp->conf, "parsing zone \"%s\" in dir \"%s\"\n", zp->zone, zp->dir);
463*00b67f09SDavid van Moolenbroek 
464*00b67f09SDavid van Moolenbroek 	pathname (path, sizeof (path), zp->dir, zp->sfile, NULL);
465*00b67f09SDavid van Moolenbroek 	dbg_val("parsezonedir fileexist (%s)\n", path);
466*00b67f09SDavid van Moolenbroek 	if ( !fileexist (path) )
467*00b67f09SDavid van Moolenbroek 	{
468*00b67f09SDavid van Moolenbroek 		error ("Not a secure zone directory (%s)!\n", zp->dir);
469*00b67f09SDavid van Moolenbroek 		lg_mesg (LG_ERROR, "\"%s\": not a secure zone directory (%s)!", zp->zone, zp->dir);
470*00b67f09SDavid van Moolenbroek 		return 1;
471*00b67f09SDavid van Moolenbroek 	}
472*00b67f09SDavid van Moolenbroek 	zfilesig_time = file_mtime (path);
473*00b67f09SDavid van Moolenbroek 
474*00b67f09SDavid van Moolenbroek 	pathname (path, sizeof (path), zp->dir, zp->file, NULL);
475*00b67f09SDavid van Moolenbroek 	dbg_val("parsezonedir fileexist (%s)\n", path);
476*00b67f09SDavid van Moolenbroek 	if ( !fileexist (path) )
477*00b67f09SDavid van Moolenbroek 	{
478*00b67f09SDavid van Moolenbroek 		error ("No zone file found (%s)!\n", path);
479*00b67f09SDavid van Moolenbroek 		lg_mesg (LG_ERROR, "\"%s\": no zone file found (%s)!", zp->zone, path);
480*00b67f09SDavid van Moolenbroek 		return 2;
481*00b67f09SDavid van Moolenbroek 	}
482*00b67f09SDavid van Moolenbroek 
483*00b67f09SDavid van Moolenbroek 	zfile_time = file_mtime (path);
484*00b67f09SDavid van Moolenbroek 	currtime = time (NULL);
485*00b67f09SDavid van Moolenbroek 
486*00b67f09SDavid van Moolenbroek 	/* check for domain based logging */
487*00b67f09SDavid van Moolenbroek 	if ( is_defined (zp->conf->logdomaindir) )	/* parameter is not null or empty ? */
488*00b67f09SDavid van Moolenbroek 	{
489*00b67f09SDavid van Moolenbroek 		if ( strcmp (zp->conf->logdomaindir, ".") == 0 )	/* current (".") means zone directory */
490*00b67f09SDavid van Moolenbroek 			lg_zone_start (zp->dir, zp->zone);
491*00b67f09SDavid van Moolenbroek 		else
492*00b67f09SDavid van Moolenbroek 			lg_zone_start (zp->conf->logdomaindir, zp->zone);
493*00b67f09SDavid van Moolenbroek 	}
494*00b67f09SDavid van Moolenbroek 
495*00b67f09SDavid van Moolenbroek 	/* check rfc5011 key signing keys, create new one if necessary */
496*00b67f09SDavid van Moolenbroek 	dbg_msg("parsezonedir check rfc 5011 ksk ");
497*00b67f09SDavid van Moolenbroek 	newkey = ksk5011status (&zp->keys, zp->dir, zp->zone, zp->conf);
498*00b67f09SDavid van Moolenbroek 	if ( (newkey & 02) != 02 )	/* not a rfc 5011 zone ? */
499*00b67f09SDavid van Moolenbroek 	{
500*00b67f09SDavid van Moolenbroek 		verbmesg (2, zp->conf, "\t\t->not a rfc5011 zone, looking for a regular ksk rollover\n");
501*00b67f09SDavid van Moolenbroek 		/* check key signing keys, create new one if necessary */
502*00b67f09SDavid van Moolenbroek 		dbg_msg("parsezonedir check ksk ");
503*00b67f09SDavid van Moolenbroek 		newkey |= kskstatus (zonelist, zp);
504*00b67f09SDavid van Moolenbroek 	}
505*00b67f09SDavid van Moolenbroek 	else
506*00b67f09SDavid van Moolenbroek 		newkey &= ~02;		/* reset bit 2 */
507*00b67f09SDavid van Moolenbroek 
508*00b67f09SDavid van Moolenbroek 	/* check age of zone keys, probably retire (depreciate) or remove old keys */
509*00b67f09SDavid van Moolenbroek 	dbg_msg("parsezonedir check zsk ");
510*00b67f09SDavid van Moolenbroek 	newkey += zskstatus (&zp->keys, zp->dir, zp->zone, zp->conf);
511*00b67f09SDavid van Moolenbroek 
512*00b67f09SDavid van Moolenbroek 	/* check age of "dnskey.db" file against age of keyfiles */
513*00b67f09SDavid van Moolenbroek 	pathname (path, sizeof (path), zp->dir, zp->conf->keyfile, NULL);
514*00b67f09SDavid van Moolenbroek 	dbg_val("parsezonedir check_keydb_timestamp (%s)\n", path);
515*00b67f09SDavid van Moolenbroek 	if ( !newkey )
516*00b67f09SDavid van Moolenbroek 		newkey = check_keydb_timestamp (zp->keys, file_mtime (path));
517*00b67f09SDavid van Moolenbroek 
518*00b67f09SDavid van Moolenbroek 	newkeysetfile = 0;
519*00b67f09SDavid van Moolenbroek #if defined(ALWAYS_CHECK_KEYSETFILES) && ALWAYS_CHECK_KEYSETFILES	/* patch from Shane Wegner 15. June 2009 */
520*00b67f09SDavid van Moolenbroek 	/* check if there is a new keyset- file */
521*00b67f09SDavid van Moolenbroek 	if ( !newkey )
522*00b67f09SDavid van Moolenbroek 		newkeysetfile = new_keysetfiles (zp->dir, zfilesig_time);
523*00b67f09SDavid van Moolenbroek #else
524*00b67f09SDavid van Moolenbroek 	/* if we work in subdir mode, check if there is a new keyset- file */
525*00b67f09SDavid van Moolenbroek 	if ( !newkey && zp->conf->keysetdir && strcmp (zp->conf->keysetdir, "..") == 0 )
526*00b67f09SDavid van Moolenbroek 		newkeysetfile = new_keysetfiles (zp->dir, zfilesig_time);
527*00b67f09SDavid van Moolenbroek #endif
528*00b67f09SDavid van Moolenbroek 
529*00b67f09SDavid van Moolenbroek 	/* is there a list of files included in zone.db ? */
530*00b67f09SDavid van Moolenbroek 	if ( zp->conf->dependfiles && *zp->conf->dependfiles )
531*00b67f09SDavid van Moolenbroek 	{
532*00b67f09SDavid van Moolenbroek 		char	file[255+1];
533*00b67f09SDavid van Moolenbroek 		const	char	*p;
534*00b67f09SDavid van Moolenbroek 		int	i;
535*00b67f09SDavid van Moolenbroek 		time_t	incfile_mtime;
536*00b67f09SDavid van Moolenbroek 
537*00b67f09SDavid van Moolenbroek 		/* check the timestamp of each file against "zone.db" */
538*00b67f09SDavid van Moolenbroek 		p = zp->conf->dependfiles;
539*00b67f09SDavid van Moolenbroek 		while ( p && *p )
540*00b67f09SDavid van Moolenbroek 		{
541*00b67f09SDavid van Moolenbroek 			while ( isflistdelim (*p) )
542*00b67f09SDavid van Moolenbroek 				p++;
543*00b67f09SDavid van Moolenbroek 
544*00b67f09SDavid van Moolenbroek 			for ( i = 0; i < 255 && *p && !isflistdelim (*p); i++ )
545*00b67f09SDavid van Moolenbroek 				file[i] = *p++;
546*00b67f09SDavid van Moolenbroek 			file[i] = '\0';
547*00b67f09SDavid van Moolenbroek 
548*00b67f09SDavid van Moolenbroek 			pathname (path, sizeof (path), zp->dir, file, NULL);
549*00b67f09SDavid van Moolenbroek 
550*00b67f09SDavid van Moolenbroek 			incfile_mtime = file_mtime (path);
551*00b67f09SDavid van Moolenbroek 			if ( incfile_mtime > zfile_time )	/* include file is newer? */
552*00b67f09SDavid van Moolenbroek 				zfile_time = incfile_mtime;	/* take this one as new mtime */
553*00b67f09SDavid van Moolenbroek 		}
554*00b67f09SDavid van Moolenbroek 	}
555*00b67f09SDavid van Moolenbroek 
556*00b67f09SDavid van Moolenbroek 	/**
557*00b67f09SDavid van Moolenbroek 	** Check if it is time to do a re-sign. This is the case if
558*00b67f09SDavid van Moolenbroek 	**	a) the command line flag -f is set, or
559*00b67f09SDavid van Moolenbroek 	**	b) new keys are generated, or
560*00b67f09SDavid van Moolenbroek 	**	c) we found a new KSK of a delegated domain, or
561*00b67f09SDavid van Moolenbroek 	**	d) the "dnskey.db" file is newer than "zone.db"
562*00b67f09SDavid van Moolenbroek 	**	e) the "zone.db" is newer than "zone.db.signed" or
563*00b67f09SDavid van Moolenbroek 	**	f) "zone.db.signed" is older than the re-sign interval
564*00b67f09SDavid van Moolenbroek 	**/
565*00b67f09SDavid van Moolenbroek 	mesg[0] = '\0';
566*00b67f09SDavid van Moolenbroek 	if ( force )
567*00b67f09SDavid van Moolenbroek 		snprintf (mesg, sizeof(mesg), "Option -f");
568*00b67f09SDavid van Moolenbroek 	else if ( newkey )
569*00b67f09SDavid van Moolenbroek 		snprintf (mesg, sizeof(mesg), "Modified zone key set");
570*00b67f09SDavid van Moolenbroek 	else if ( newkeysetfile )
571*00b67f09SDavid van Moolenbroek 		snprintf (mesg, sizeof(mesg), "Modified KSK in delegated domain");
572*00b67f09SDavid van Moolenbroek 	else if ( file_mtime (path) > zfilesig_time )
573*00b67f09SDavid van Moolenbroek 		snprintf (mesg, sizeof(mesg), "Modified keys");
574*00b67f09SDavid van Moolenbroek 	else if ( zfile_time > zfilesig_time )
575*00b67f09SDavid van Moolenbroek 		snprintf (mesg, sizeof(mesg), "Zone file edited");
576*00b67f09SDavid van Moolenbroek 	else if ( (currtime - zfilesig_time) > zp->conf->resign - (OFFSET) )
577*00b67f09SDavid van Moolenbroek 		snprintf (mesg, sizeof(mesg), "re-signing interval (%s) reached",
578*00b67f09SDavid van Moolenbroek 						str_delspace (age2str (zp->conf->resign)));
579*00b67f09SDavid van Moolenbroek 
580*00b67f09SDavid van Moolenbroek 	if ( *mesg )
581*00b67f09SDavid van Moolenbroek 		verbmesg (1, zp->conf, "\tRe-signing necessary: %s\n", mesg);
582*00b67f09SDavid van Moolenbroek 	else
583*00b67f09SDavid van Moolenbroek 		verbmesg (1, zp->conf, "\tRe-signing not necessary!\n");
584*00b67f09SDavid van Moolenbroek 
585*00b67f09SDavid van Moolenbroek 	if ( *mesg )
586*00b67f09SDavid van Moolenbroek 		lg_mesg (LG_NOTICE, "\"%s\": re-signing triggered: %s", zp->zone,  mesg);
587*00b67f09SDavid van Moolenbroek 
588*00b67f09SDavid van Moolenbroek 	dbg_line ();
589*00b67f09SDavid van Moolenbroek 	if ( !(force || newkey || newkeysetfile || zfile_time > zfilesig_time ||
590*00b67f09SDavid van Moolenbroek 	     file_mtime (path) > zfilesig_time ||
591*00b67f09SDavid van Moolenbroek 	     (currtime - zfilesig_time) > zp->conf->resign - (OFFSET)) )
592*00b67f09SDavid van Moolenbroek 	{
593*00b67f09SDavid van Moolenbroek 		verbmesg (2, zp->conf, "\tCheck if there is a parent file to copy\n");
594*00b67f09SDavid van Moolenbroek 		if ( zp->conf->keysetdir && strcmp (zp->conf->keysetdir, "..") == 0 )
595*00b67f09SDavid van Moolenbroek 			copy_keyset (zp->dir, zp->zone, zp->conf);	/* copy the parent- file if it exist */
596*00b67f09SDavid van Moolenbroek 		if ( is_defined (zp->conf->logdomaindir) )
597*00b67f09SDavid van Moolenbroek 			lg_zone_end ();
598*00b67f09SDavid van Moolenbroek 		return 0;	/* nothing to do */
599*00b67f09SDavid van Moolenbroek 	}
600*00b67f09SDavid van Moolenbroek 
601*00b67f09SDavid van Moolenbroek 	/* let's start signing the zone */
602*00b67f09SDavid van Moolenbroek 	dbg_line ();
603*00b67f09SDavid van Moolenbroek 
604*00b67f09SDavid van Moolenbroek 	/* create new "dnskey.db" file  */
605*00b67f09SDavid van Moolenbroek 	pathname (path, sizeof (path), zp->dir, zp->conf->keyfile, NULL);
606*00b67f09SDavid van Moolenbroek 	verbmesg (1, zp->conf, "\tWriting key file \"%s\"\n", path);
607*00b67f09SDavid van Moolenbroek 	if ( !writekeyfile (path, zp->keys, zp->conf->key_ttl) )
608*00b67f09SDavid van Moolenbroek 	{
609*00b67f09SDavid van Moolenbroek 		error ("Can't create keyfile %s \n", path);
610*00b67f09SDavid van Moolenbroek 		lg_mesg (LG_ERROR, "\"%s\": can't create keyfile %s", zp->zone , path);
611*00b67f09SDavid van Moolenbroek 	}
612*00b67f09SDavid van Moolenbroek 
613*00b67f09SDavid van Moolenbroek 	err = 1;
614*00b67f09SDavid van Moolenbroek 	use_unixtime = ( zp->conf->serialform == Unixtime );
615*00b67f09SDavid van Moolenbroek 	dbg_val1 ("Use unixtime = %d\n", use_unixtime);
616*00b67f09SDavid van Moolenbroek 	if ( !dynamic_zone && !use_unixtime ) /* increment serial number in static zone files */
617*00b67f09SDavid van Moolenbroek 	{
618*00b67f09SDavid van Moolenbroek 		pathname (path, sizeof (path), zp->dir, zp->file, NULL);
619*00b67f09SDavid van Moolenbroek 		err = 0;
620*00b67f09SDavid van Moolenbroek 		if ( noexec == 0 )
621*00b67f09SDavid van Moolenbroek 		{
622*00b67f09SDavid van Moolenbroek 			if ( (err = inc_serial (path, use_unixtime)) < 0 )
623*00b67f09SDavid van Moolenbroek 			{
624*00b67f09SDavid van Moolenbroek 				error ("could not increment serialno of domain %s in file %s: %s!\n",
625*00b67f09SDavid van Moolenbroek 								zp->zone, path, inc_errstr (err));
626*00b67f09SDavid van Moolenbroek 				lg_mesg (LG_ERROR,
627*00b67f09SDavid van Moolenbroek 					"zone \"%s\": couldn't increment serialno in file %s: %s",
628*00b67f09SDavid van Moolenbroek 							zp->zone, path, inc_errstr (err));
629*00b67f09SDavid van Moolenbroek 			}
630*00b67f09SDavid van Moolenbroek 			else
631*00b67f09SDavid van Moolenbroek 			verbmesg (1, zp->conf, "\tIncrementing serial number in file \"%s\"\n", path);
632*00b67f09SDavid van Moolenbroek 		}
633*00b67f09SDavid van Moolenbroek 		else
634*00b67f09SDavid van Moolenbroek 			verbmesg (1, zp->conf, "\tIncrementing serial number in file \"%s\"\n", path);
635*00b67f09SDavid van Moolenbroek 	}
636*00b67f09SDavid van Moolenbroek 
637*00b67f09SDavid van Moolenbroek 	/* at last, sign the zone file */
638*00b67f09SDavid van Moolenbroek 	if ( err >= 0 )
639*00b67f09SDavid van Moolenbroek 	{
640*00b67f09SDavid van Moolenbroek 		time_t	timer;
641*00b67f09SDavid van Moolenbroek 
642*00b67f09SDavid van Moolenbroek 		verbmesg (1, zp->conf, "\tSigning zone \"%s\"\n", zp->zone);
643*00b67f09SDavid van Moolenbroek 		logflush ();
644*00b67f09SDavid van Moolenbroek 
645*00b67f09SDavid van Moolenbroek 		/* dynamic zones uses incremental signing, so we have to */
646*00b67f09SDavid van Moolenbroek 		/* prepare the old (signed) file as new input file */
647*00b67f09SDavid van Moolenbroek 		if ( dynamic_zone )
648*00b67f09SDavid van Moolenbroek 		{
649*00b67f09SDavid van Moolenbroek 			char	zfile[MAX_PATHSIZE+1];
650*00b67f09SDavid van Moolenbroek 
651*00b67f09SDavid van Moolenbroek 			dyn_update_freeze (zp->zone, zp->conf, 1);	/* freeze dynamic zone ! */
652*00b67f09SDavid van Moolenbroek 
653*00b67f09SDavid van Moolenbroek 			pathname (zfile, sizeof (zfile), zp->dir, zp->file, NULL);
654*00b67f09SDavid van Moolenbroek 			pathname (path, sizeof (path), zp->dir, zp->sfile, NULL);
655*00b67f09SDavid van Moolenbroek 			if ( filesize (path) == 0L )    /* initial signing request ? */
656*00b67f09SDavid van Moolenbroek 			{
657*00b67f09SDavid van Moolenbroek 				verbmesg (1, zp->conf, "\tDynamic Zone signing: Initial signing request: Add DNSKEYs to zonefile\n");
658*00b67f09SDavid van Moolenbroek 				copyfile (zfile, path, zp->conf->keyfile);
659*00b67f09SDavid van Moolenbroek 			}
660*00b67f09SDavid van Moolenbroek #if 1
661*00b67f09SDavid van Moolenbroek 			else if ( zfile_time > zfilesig_time )  /* zone.db is newer than signed file */
662*00b67f09SDavid van Moolenbroek 			{
663*00b67f09SDavid van Moolenbroek 				verbmesg (1, zp->conf, "\tDynamic Zone signing: zone file manually edited: Use it as new input file\n");
664*00b67f09SDavid van Moolenbroek 				copyfile (zfile, path, NULL);
665*00b67f09SDavid van Moolenbroek 			}
666*00b67f09SDavid van Moolenbroek #endif
667*00b67f09SDavid van Moolenbroek 			verbmesg (1, zp->conf, "\tDynamic Zone signing: copy old signed zone file %s to new input file %s\n",
668*00b67f09SDavid van Moolenbroek 										path, zfile);
669*00b67f09SDavid van Moolenbroek 
670*00b67f09SDavid van Moolenbroek 			if ( newkey )	/* if we have new keys, they should be added to the zone file */
671*00b67f09SDavid van Moolenbroek 			{
672*00b67f09SDavid van Moolenbroek 				copyzonefile (path, zfile, zp->conf->keyfile);
673*00b67f09SDavid van Moolenbroek #if 0
674*00b67f09SDavid van Moolenbroek 				if ( zp->conf->dist_cmd )
675*00b67f09SDavid van Moolenbroek 					dist_and_reload (zp, 2);	/* ... and send to the name server */
676*00b67f09SDavid van Moolenbroek #endif
677*00b67f09SDavid van Moolenbroek 			}
678*00b67f09SDavid van Moolenbroek 			else		/* else we can do a simple file copy */
679*00b67f09SDavid van Moolenbroek 				copyfile (path, zfile, NULL);
680*00b67f09SDavid van Moolenbroek 		}
681*00b67f09SDavid van Moolenbroek 
682*00b67f09SDavid van Moolenbroek 		timer = start_timer ();
683*00b67f09SDavid van Moolenbroek 		if ( (err = sign_zone (zp)) < 0 )
684*00b67f09SDavid van Moolenbroek 		{
685*00b67f09SDavid van Moolenbroek 			error ("\tSigning of zone %s failed (%d)!\n", zp->zone, err);
686*00b67f09SDavid van Moolenbroek 			lg_mesg (LG_ERROR, "\"%s\": signing failed!", zp->zone);
687*00b67f09SDavid van Moolenbroek 		}
688*00b67f09SDavid van Moolenbroek 		timer = stop_timer (timer);
689*00b67f09SDavid van Moolenbroek 
690*00b67f09SDavid van Moolenbroek 		if ( dynamic_zone )
691*00b67f09SDavid van Moolenbroek 			dyn_update_freeze (zp->zone, zp->conf, 0);	/* thaw dynamic zone file */
692*00b67f09SDavid van Moolenbroek 
693*00b67f09SDavid van Moolenbroek 		if ( err >= 0 )
694*00b67f09SDavid van Moolenbroek 		{
695*00b67f09SDavid van Moolenbroek 		const	char	*tstr = str_delspace (age2str (timer));
696*00b67f09SDavid van Moolenbroek 
697*00b67f09SDavid van Moolenbroek 		if ( !tstr || *tstr == '\0' )
698*00b67f09SDavid van Moolenbroek 			tstr = "0s";
699*00b67f09SDavid van Moolenbroek 		verbmesg (1, zp->conf, "\tSigning completed after %s.\n", tstr);
700*00b67f09SDavid van Moolenbroek 		}
701*00b67f09SDavid van Moolenbroek 	}
702*00b67f09SDavid van Moolenbroek 
703*00b67f09SDavid van Moolenbroek 	copy_keyset (zp->dir, zp->zone, zp->conf);
704*00b67f09SDavid van Moolenbroek 
705*00b67f09SDavid van Moolenbroek 	if ( err >= 0 && reloadflag )
706*00b67f09SDavid van Moolenbroek 	{
707*00b67f09SDavid van Moolenbroek 		if ( zp->conf->dist_cmd )
708*00b67f09SDavid van Moolenbroek 			dist_and_reload (zp, 1);
709*00b67f09SDavid van Moolenbroek 		else
710*00b67f09SDavid van Moolenbroek 			reload_zone (zp->zone, zp->conf);
711*00b67f09SDavid van Moolenbroek 
712*00b67f09SDavid van Moolenbroek 		register_key (zp->keys, zp->conf);
713*00b67f09SDavid van Moolenbroek 	}
714*00b67f09SDavid van Moolenbroek 
715*00b67f09SDavid van Moolenbroek 	if ( is_defined (zp->conf->logdomaindir) )
716*00b67f09SDavid van Moolenbroek 		lg_zone_end ();
717*00b67f09SDavid van Moolenbroek 
718*00b67f09SDavid van Moolenbroek 	return err;
719*00b67f09SDavid van Moolenbroek }
720*00b67f09SDavid van Moolenbroek 
register_key(dki_t * list,const zconf_t * z)721*00b67f09SDavid van Moolenbroek static	void	register_key (dki_t *list, const zconf_t *z)
722*00b67f09SDavid van Moolenbroek {
723*00b67f09SDavid van Moolenbroek 	dki_t	*dkp;
724*00b67f09SDavid van Moolenbroek 	time_t	age;
725*00b67f09SDavid van Moolenbroek 
726*00b67f09SDavid van Moolenbroek 	time_t	currtime;
727*00b67f09SDavid van Moolenbroek 	assert ( list != NULL );
728*00b67f09SDavid van Moolenbroek 	assert ( z != NULL );
729*00b67f09SDavid van Moolenbroek 
730*00b67f09SDavid van Moolenbroek 	currtime = time (NULL);
731*00b67f09SDavid van Moolenbroek 	for ( dkp = list; dkp && dki_isksk (dkp); dkp = dkp->next )
732*00b67f09SDavid van Moolenbroek 	{
733*00b67f09SDavid van Moolenbroek 		age = dki_age (dkp, currtime);
734*00b67f09SDavid van Moolenbroek #if 0
735*00b67f09SDavid van Moolenbroek 		/* announce "new" and active key signing keys */
736*00b67f09SDavid van Moolenbroek 		if ( REG_URL && *REG_URL && dki_status (dkp) == DKI_ACT && age <= z->resign * 4 )
737*00b67f09SDavid van Moolenbroek 		{
738*00b67f09SDavid van Moolenbroek 			if ( verbose )
739*00b67f09SDavid van Moolenbroek 				logmesg ("\tRegister new KSK with tag %d for domain %s\n",
740*00b67f09SDavid van Moolenbroek 								dkp->tag, dkp->name);
741*00b67f09SDavid van Moolenbroek 		}
742*00b67f09SDavid van Moolenbroek #endif
743*00b67f09SDavid van Moolenbroek 	}
744*00b67f09SDavid van Moolenbroek }
745*00b67f09SDavid van Moolenbroek 
746*00b67f09SDavid van Moolenbroek /*
747*00b67f09SDavid van Moolenbroek  *	This function is not working with symbolic links to keyset- files,
748*00b67f09SDavid van Moolenbroek  *	because file_mtime() returns the mtime of the underlying file, and *not*
749*00b67f09SDavid van Moolenbroek  *	that of the symlink file.
750*00b67f09SDavid van Moolenbroek  *	This is bad, because the keyset-file will be newly generated by dnssec-signzone
751*00b67f09SDavid van Moolenbroek  *	on every re-signing call.
752*00b67f09SDavid van Moolenbroek  *	Instead, in the case of a hierarchical directory structure, we copy the file
753*00b67f09SDavid van Moolenbroek  *	(and so we change the timestamp) only if it was modified after the last
754*00b67f09SDavid van Moolenbroek  *	generation (checked with cmpfile(), see func sign_zone()).
755*00b67f09SDavid van Moolenbroek  */
756*00b67f09SDavid van Moolenbroek # define	KEYSET_FILE_PFX	"keyset-"
new_keysetfiles(const char * dir,time_t zone_signing_time)757*00b67f09SDavid van Moolenbroek static	int	new_keysetfiles (const char *dir, time_t zone_signing_time)
758*00b67f09SDavid van Moolenbroek {
759*00b67f09SDavid van Moolenbroek 	DIR	*dirp;
760*00b67f09SDavid van Moolenbroek 	struct  dirent  *dentp;
761*00b67f09SDavid van Moolenbroek 	char	path[MAX_PATHSIZE+1];
762*00b67f09SDavid van Moolenbroek 	int	newkeysetfile;
763*00b67f09SDavid van Moolenbroek 
764*00b67f09SDavid van Moolenbroek 	if ( (dirp = opendir (dir)) == NULL )
765*00b67f09SDavid van Moolenbroek 		return 0;
766*00b67f09SDavid van Moolenbroek 
767*00b67f09SDavid van Moolenbroek 	newkeysetfile = 0;
768*00b67f09SDavid van Moolenbroek 	dbg_val2 ("new_keysetfile (%s, %s)\n", dir, time2str (zone_signing_time, 's'));
769*00b67f09SDavid van Moolenbroek 	while ( !newkeysetfile && (dentp = readdir (dirp)) != NULL )
770*00b67f09SDavid van Moolenbroek 	{
771*00b67f09SDavid van Moolenbroek 		if ( strncmp (dentp->d_name, KEYSET_FILE_PFX, strlen (KEYSET_FILE_PFX)) != 0 )
772*00b67f09SDavid van Moolenbroek 			continue;
773*00b67f09SDavid van Moolenbroek 
774*00b67f09SDavid van Moolenbroek 		pathname (path, sizeof (path), dir, dentp->d_name, NULL);
775*00b67f09SDavid van Moolenbroek 		dbg_val2 ("newkeysetfile timestamp of %s = %s\n", path, time2str (file_mtime(path), 's'));
776*00b67f09SDavid van Moolenbroek 		if ( file_mtime (path) > zone_signing_time )
777*00b67f09SDavid van Moolenbroek 			newkeysetfile = 1;
778*00b67f09SDavid van Moolenbroek 	}
779*00b67f09SDavid van Moolenbroek 	closedir (dirp);
780*00b67f09SDavid van Moolenbroek 
781*00b67f09SDavid van Moolenbroek 	return newkeysetfile;
782*00b67f09SDavid van Moolenbroek }
783*00b67f09SDavid van Moolenbroek 
check_keydb_timestamp(dki_t * keylist,time_t reftime)784*00b67f09SDavid van Moolenbroek static	int	check_keydb_timestamp (dki_t *keylist, time_t reftime)
785*00b67f09SDavid van Moolenbroek {
786*00b67f09SDavid van Moolenbroek 	dki_t	*key;
787*00b67f09SDavid van Moolenbroek 
788*00b67f09SDavid van Moolenbroek 	assert ( keylist != NULL );
789*00b67f09SDavid van Moolenbroek 	if ( reftime == 0 )
790*00b67f09SDavid van Moolenbroek 		return 1;
791*00b67f09SDavid van Moolenbroek 
792*00b67f09SDavid van Moolenbroek 	for ( key = keylist; key; key = key->next )
793*00b67f09SDavid van Moolenbroek 		if ( dki_time (key) > reftime )
794*00b67f09SDavid van Moolenbroek 			return 1;
795*00b67f09SDavid van Moolenbroek 
796*00b67f09SDavid van Moolenbroek 	return 0;
797*00b67f09SDavid van Moolenbroek }
798*00b67f09SDavid van Moolenbroek 
writekeyfile(const char * fname,const dki_t * list,int key_ttl)799*00b67f09SDavid van Moolenbroek static	int	writekeyfile (const char *fname, const dki_t *list, int key_ttl)
800*00b67f09SDavid van Moolenbroek {
801*00b67f09SDavid van Moolenbroek 	FILE	*fp;
802*00b67f09SDavid van Moolenbroek 	const	dki_t	*dkp;
803*00b67f09SDavid van Moolenbroek 	time_t	curr = time (NULL);
804*00b67f09SDavid van Moolenbroek 	int	ksk;
805*00b67f09SDavid van Moolenbroek 
806*00b67f09SDavid van Moolenbroek 	if ( (fp = fopen (fname, "w")) == NULL )
807*00b67f09SDavid van Moolenbroek 		return 0;
808*00b67f09SDavid van Moolenbroek 	fprintf (fp, ";\n");
809*00b67f09SDavid van Moolenbroek 	fprintf (fp, ";\t!!! Don\'t edit this file by hand.\n");
810*00b67f09SDavid van Moolenbroek 	fprintf (fp, ";\t!!! It will be generated by %s.\n", progname);
811*00b67f09SDavid van Moolenbroek 	fprintf (fp, ";\n");
812*00b67f09SDavid van Moolenbroek 	fprintf (fp, ";\t Last generation time %s\n", time2str (curr, 's'));
813*00b67f09SDavid van Moolenbroek 	fprintf (fp, ";\n");
814*00b67f09SDavid van Moolenbroek 
815*00b67f09SDavid van Moolenbroek 	fprintf (fp, "\n");
816*00b67f09SDavid van Moolenbroek 	fprintf (fp, ";  ***  List of Key Signing Keys  ***\n");
817*00b67f09SDavid van Moolenbroek 	ksk = 1;
818*00b67f09SDavid van Moolenbroek 	for ( dkp = list; dkp; dkp = dkp->next )
819*00b67f09SDavid van Moolenbroek 	{
820*00b67f09SDavid van Moolenbroek 		if ( ksk && !dki_isksk (dkp) )
821*00b67f09SDavid van Moolenbroek 		{
822*00b67f09SDavid van Moolenbroek 			fprintf (fp, "; ***  List of Zone Signing Keys  ***\n");
823*00b67f09SDavid van Moolenbroek 			ksk = 0;
824*00b67f09SDavid van Moolenbroek 		}
825*00b67f09SDavid van Moolenbroek 		dki_prt_comment (dkp, fp);
826*00b67f09SDavid van Moolenbroek 		dki_prt_dnskeyttl (dkp, fp, key_ttl);
827*00b67f09SDavid van Moolenbroek 		putc ('\n', fp);
828*00b67f09SDavid van Moolenbroek 	}
829*00b67f09SDavid van Moolenbroek 
830*00b67f09SDavid van Moolenbroek 	fclose (fp);
831*00b67f09SDavid van Moolenbroek 	return 1;
832*00b67f09SDavid van Moolenbroek }
833*00b67f09SDavid van Moolenbroek 
sign_zone(const zone_t * zp)834*00b67f09SDavid van Moolenbroek static	int	sign_zone (const zone_t *zp)
835*00b67f09SDavid van Moolenbroek {
836*00b67f09SDavid van Moolenbroek 	char	cmd[2047+1];
837*00b67f09SDavid van Moolenbroek 	char	str[1023+1];
838*00b67f09SDavid van Moolenbroek 	char	rparam[254+1];
839*00b67f09SDavid van Moolenbroek 	char	nsec3param[637+1];
840*00b67f09SDavid van Moolenbroek 	char	keysetdir[254+1];
841*00b67f09SDavid van Moolenbroek 	const	char	*gends;
842*00b67f09SDavid van Moolenbroek 	const	char	*dnskeyksk;
843*00b67f09SDavid van Moolenbroek 	const	char	*pseudo;
844*00b67f09SDavid van Moolenbroek 	const	char	*param;
845*00b67f09SDavid van Moolenbroek 	int	len;
846*00b67f09SDavid van Moolenbroek 	FILE	*fp;
847*00b67f09SDavid van Moolenbroek 
848*00b67f09SDavid van Moolenbroek 	const	char	*dir;
849*00b67f09SDavid van Moolenbroek 	const	char	*domain;
850*00b67f09SDavid van Moolenbroek 	const	char	*file;
851*00b67f09SDavid van Moolenbroek 	const	zconf_t	*conf;
852*00b67f09SDavid van Moolenbroek 
853*00b67f09SDavid van Moolenbroek 	assert (zp != NULL);
854*00b67f09SDavid van Moolenbroek 	dir = zp->dir;
855*00b67f09SDavid van Moolenbroek 	domain = zp->zone;
856*00b67f09SDavid van Moolenbroek 	file = zp->file;
857*00b67f09SDavid van Moolenbroek 	conf = zp->conf;
858*00b67f09SDavid van Moolenbroek 
859*00b67f09SDavid van Moolenbroek 	len = 0;
860*00b67f09SDavid van Moolenbroek 	str[0] = '\0';
861*00b67f09SDavid van Moolenbroek 	if ( conf->lookaside && conf->lookaside[0] )
862*00b67f09SDavid van Moolenbroek 		len = snprintf (str, sizeof (str), "-l %.250s", conf->lookaside);
863*00b67f09SDavid van Moolenbroek 
864*00b67f09SDavid van Moolenbroek 	dbg_line();
865*00b67f09SDavid van Moolenbroek 	if ( !dynamic_zone && conf->serialform == Unixtime )
866*00b67f09SDavid van Moolenbroek 		snprintf (str+len, sizeof (str) - len, " -N unixtime");
867*00b67f09SDavid van Moolenbroek 
868*00b67f09SDavid van Moolenbroek 	gends = "";
869*00b67f09SDavid van Moolenbroek 	if ( conf->sig_gends )
870*00b67f09SDavid van Moolenbroek 		gends = "-C -g ";
871*00b67f09SDavid van Moolenbroek 
872*00b67f09SDavid van Moolenbroek 	dnskeyksk = "";
873*00b67f09SDavid van Moolenbroek 	if ( conf->sig_dnskeyksk )
874*00b67f09SDavid van Moolenbroek 		dnskeyksk = "-x ";
875*00b67f09SDavid van Moolenbroek 
876*00b67f09SDavid van Moolenbroek 	pseudo = "";
877*00b67f09SDavid van Moolenbroek 	if ( conf->sig_pseudo )
878*00b67f09SDavid van Moolenbroek 		pseudo = "-p ";
879*00b67f09SDavid van Moolenbroek 
880*00b67f09SDavid van Moolenbroek 	param = "";
881*00b67f09SDavid van Moolenbroek 	if ( conf->sig_param && conf->sig_param[0] )
882*00b67f09SDavid van Moolenbroek 		param = conf->sig_param;
883*00b67f09SDavid van Moolenbroek 
884*00b67f09SDavid van Moolenbroek 	nsec3param[0] = '\0';
885*00b67f09SDavid van Moolenbroek 	if ( conf->k_algo == DK_ALGO_NSEC3DSA || conf->k_algo == DK_ALGO_NSEC3RSASHA1 ||
886*00b67f09SDavid van Moolenbroek 	     conf->nsec3 != NSEC3_OFF )
887*00b67f09SDavid van Moolenbroek 	{
888*00b67f09SDavid van Moolenbroek 		char	salt[510+1];	/* salt has a maximum of 255 bytes == 510 hex nibbles */
889*00b67f09SDavid van Moolenbroek 		const	char	*update;
890*00b67f09SDavid van Moolenbroek 		const	char	*optout;
891*00b67f09SDavid van Moolenbroek 		unsigned int	seed;
892*00b67f09SDavid van Moolenbroek 
893*00b67f09SDavid van Moolenbroek 		update = "-u ";		/* trailing blank is necessary */
894*00b67f09SDavid van Moolenbroek 		if ( conf->nsec3 == NSEC3_OPTOUT )
895*00b67f09SDavid van Moolenbroek 			optout = "-A ";
896*00b67f09SDavid van Moolenbroek 		else
897*00b67f09SDavid van Moolenbroek 			optout = "";
898*00b67f09SDavid van Moolenbroek 
899*00b67f09SDavid van Moolenbroek 			/* static zones can use always a new salt (full zone signing) */
900*00b67f09SDavid van Moolenbroek 		seed = 0L;	/* no seed: use mechanism build in gensalt() */
901*00b67f09SDavid van Moolenbroek 		if ( dynamic_zone )
902*00b67f09SDavid van Moolenbroek 		{		/* dynamic zones have to reuse the salt on signing */
903*00b67f09SDavid van Moolenbroek 			const	dki_t	*kp;
904*00b67f09SDavid van Moolenbroek 
905*00b67f09SDavid van Moolenbroek 			/* use gentime timestamp of ZSK for seeding rand generator */
906*00b67f09SDavid van Moolenbroek 			kp = dki_find (zp->keys, DKI_ZSK, DKI_ACTIVE, 1);
907*00b67f09SDavid van Moolenbroek 			assert ( kp != NULL );
908*00b67f09SDavid van Moolenbroek 			if ( kp->gentime )
909*00b67f09SDavid van Moolenbroek 				seed = kp->gentime;
910*00b67f09SDavid van Moolenbroek 			else
911*00b67f09SDavid van Moolenbroek 				seed = kp->time;
912*00b67f09SDavid van Moolenbroek 		}
913*00b67f09SDavid van Moolenbroek 
914*00b67f09SDavid van Moolenbroek 		if ( gensalt (salt, sizeof (salt), conf->saltbits, seed) )
915*00b67f09SDavid van Moolenbroek 			snprintf (nsec3param, sizeof (nsec3param), "%s%s-3 %s ", update, optout, salt);
916*00b67f09SDavid van Moolenbroek 	}
917*00b67f09SDavid van Moolenbroek 
918*00b67f09SDavid van Moolenbroek 	dbg_line();
919*00b67f09SDavid van Moolenbroek 	rparam[0] = '\0';
920*00b67f09SDavid van Moolenbroek 	if ( conf->sig_random && conf->sig_random[0] )
921*00b67f09SDavid van Moolenbroek 		snprintf (rparam, sizeof (rparam), "-r %.250s ", conf->sig_random);
922*00b67f09SDavid van Moolenbroek 
923*00b67f09SDavid van Moolenbroek 	dbg_line();
924*00b67f09SDavid van Moolenbroek 	keysetdir[0] = '\0';
925*00b67f09SDavid van Moolenbroek 	if ( conf->keysetdir && conf->keysetdir[0] && strcmp (conf->keysetdir, "..") != 0 )
926*00b67f09SDavid van Moolenbroek 		snprintf (keysetdir, sizeof (keysetdir), "-d %.250s ", conf->keysetdir);
927*00b67f09SDavid van Moolenbroek 
928*00b67f09SDavid van Moolenbroek 	if ( dir == NULL || *dir == '\0' )
929*00b67f09SDavid van Moolenbroek 		dir = ".";
930*00b67f09SDavid van Moolenbroek 
931*00b67f09SDavid van Moolenbroek 	dbg_line();
932*00b67f09SDavid van Moolenbroek 	if ( dynamic_zone )
933*00b67f09SDavid van Moolenbroek 		snprintf (cmd, sizeof (cmd), "cd %s; %s %s %s%s%s%s%s%s-o %s -e +%ld %s -N increment -f %s.dsigned %s K*.private 2>&1",
934*00b67f09SDavid van Moolenbroek 			dir, SIGNCMD, param, nsec3param, dnskeyksk, gends, pseudo, rparam, keysetdir, domain, conf->sigvalidity, str, file, file);
935*00b67f09SDavid van Moolenbroek 	else
936*00b67f09SDavid van Moolenbroek 		snprintf (cmd, sizeof (cmd), "cd %s; %s %s %s%s%s%s%s%s-o %s -e +%ld %s %s K*.private 2>&1",
937*00b67f09SDavid van Moolenbroek 			dir, SIGNCMD, param, nsec3param, dnskeyksk, gends, pseudo, rparam, keysetdir, domain, conf->sigvalidity, str, file);
938*00b67f09SDavid van Moolenbroek 	verbmesg (2, conf, "\t  Run cmd \"%s\"\n", cmd);
939*00b67f09SDavid van Moolenbroek 	*str = '\0';
940*00b67f09SDavid van Moolenbroek 	if ( noexec == 0 )
941*00b67f09SDavid van Moolenbroek 	{
942*00b67f09SDavid van Moolenbroek #if 0
943*00b67f09SDavid van Moolenbroek 		if ( (fp = popen (cmd, "r")) == NULL || fgets (str, sizeof str, fp) == NULL )
944*00b67f09SDavid van Moolenbroek 			return -1;
945*00b67f09SDavid van Moolenbroek #else
946*00b67f09SDavid van Moolenbroek 		if ( (fp = popen (cmd, "r")) == NULL )
947*00b67f09SDavid van Moolenbroek 			return -1;
948*00b67f09SDavid van Moolenbroek 		str[0] = '\0';
949*00b67f09SDavid van Moolenbroek 		while ( fgets (str, sizeof str, fp) != NULL )	/* eat up all output until the last line */
950*00b67f09SDavid van Moolenbroek 			;
951*00b67f09SDavid van Moolenbroek #endif
952*00b67f09SDavid van Moolenbroek 		pclose (fp);
953*00b67f09SDavid van Moolenbroek 	}
954*00b67f09SDavid van Moolenbroek 
955*00b67f09SDavid van Moolenbroek 	dbg_line();
956*00b67f09SDavid van Moolenbroek 	verbmesg (2, conf, "\t  Cmd dnssec-signzone return: \"%s\"\n", str_chop (str, '\n'));
957*00b67f09SDavid van Moolenbroek 	len = strlen (str) - 6;
958*00b67f09SDavid van Moolenbroek 	if ( len < 0 || strcmp (str+len, "signed") != 0 )
959*00b67f09SDavid van Moolenbroek 		return -1;
960*00b67f09SDavid van Moolenbroek 
961*00b67f09SDavid van Moolenbroek 	return 0;
962*00b67f09SDavid van Moolenbroek }
963*00b67f09SDavid van Moolenbroek 
copy_keyset(const char * dir,const char * domain,const zconf_t * conf)964*00b67f09SDavid van Moolenbroek static	void	copy_keyset (const char *dir, const char *domain, const zconf_t *conf)
965*00b67f09SDavid van Moolenbroek {
966*00b67f09SDavid van Moolenbroek 	char	fromfile[1024];
967*00b67f09SDavid van Moolenbroek 	char	tofile[1024];
968*00b67f09SDavid van Moolenbroek 	int	ret;
969*00b67f09SDavid van Moolenbroek 
970*00b67f09SDavid van Moolenbroek 	/* propagate "keyset"-file to parent dir */
971*00b67f09SDavid van Moolenbroek 	if ( conf->keysetdir && strcmp (conf->keysetdir, "..") == 0 )
972*00b67f09SDavid van Moolenbroek 	{
973*00b67f09SDavid van Moolenbroek 		/* check if special parent-file exist (ksk rollover) */
974*00b67f09SDavid van Moolenbroek 		snprintf (fromfile, sizeof (fromfile), "%s/parent-%s", dir, domain);
975*00b67f09SDavid van Moolenbroek 		if ( !fileexist (fromfile) )	/* use "normal" keyset-file */
976*00b67f09SDavid van Moolenbroek 			snprintf (fromfile, sizeof (fromfile), "%s/keyset-%s", dir, domain);
977*00b67f09SDavid van Moolenbroek 
978*00b67f09SDavid van Moolenbroek 		/* verbmesg (2, conf, "\t  check \"%s\" against parent dir\n", fromfile); */
979*00b67f09SDavid van Moolenbroek 		snprintf (tofile, sizeof (tofile), "%s/../keyset-%s", dir, domain);
980*00b67f09SDavid van Moolenbroek 		if ( cmpfile (fromfile, tofile) != 0 )
981*00b67f09SDavid van Moolenbroek 		{
982*00b67f09SDavid van Moolenbroek 			verbmesg (2, conf, "\t  copy \"%s\" to parent dir\n", fromfile);
983*00b67f09SDavid van Moolenbroek 			if ( (ret = copyfile (fromfile, tofile, NULL)) != 0 )
984*00b67f09SDavid van Moolenbroek 			{
985*00b67f09SDavid van Moolenbroek 				error ("Couldn't copy \"%s\" to parent dir (%d:%s)\n",
986*00b67f09SDavid van Moolenbroek 					fromfile, ret, strerror(errno));
987*00b67f09SDavid van Moolenbroek 				lg_mesg (LG_ERROR, "\%s\": can't copy \"%s\" to parent dir (%d:%s)",
988*00b67f09SDavid van Moolenbroek 					domain, fromfile, ret, strerror(errno));
989*00b67f09SDavid van Moolenbroek 			}
990*00b67f09SDavid van Moolenbroek 		}
991*00b67f09SDavid van Moolenbroek 	}
992*00b67f09SDavid van Moolenbroek }
993