1/*****************************************************************
2**
3**	@(#) zkt-conf.c (c) Jan 2005 / Jan 2010  Holger Zuleger  hznet.de
4**
5**	A config file utility for the DNSSEC Zone Key Tool
6**
7**	Copyright (c) 2005 - 2008, Holger Zuleger HZnet. All rights reserved.
8**
9**	This software is open source.
10**
11**	Redistribution and use in source and binary forms, with or without
12**	modification, are permitted provided that the following conditions
13**	are met:
14**
15**	Redistributions of source code must retain the above copyright notice,
16**	this list of conditions and the following disclaimer.
17**
18**	Redistributions in binary form must reproduce the above copyright notice,
19**	this list of conditions and the following disclaimer in the documentation
20**	and/or other materials provided with the distribution.
21**
22**	Neither the name of Holger Zuleger HZnet nor the names of its contributors may
23**	be used to endorse or promote products derived from this software without
24**	specific prior written permission.
25**
26**	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27**	"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28**	TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29**	PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
30**	LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31**	CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32**	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33**	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34**	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35**	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36**	POSSIBILITY OF SUCH DAMAGE.
37**
38*****************************************************************/
39
40# include <stdio.h>
41# include <stdlib.h>	/* abort(), exit(), ... */
42# include <string.h>
43# include <dirent.h>
44# include <assert.h>
45# include <unistd.h>
46# include <ctype.h>
47# include <time.h>
48
49#ifdef HAVE_CONFIG_H
50# include <config.h>
51#endif
52# include "config_zkt.h"
53#if defined(HAVE_GETOPT_LONG) && HAVE_GETOPT_LONG
54# include <getopt.h>
55#endif
56
57# include "debug.h"
58# include "misc.h"
59# include "zfparse.h"
60# include "zconf.h"
61
62extern  int	optopt;
63extern  int	opterr;
64extern  int	optind;
65extern  char	*optarg;
66const	char	*progname;
67
68static	const	char	*view = "";
69static	int	writeflag = 0;
70static	int	allflag = 0;
71static	int	testflag = 0;
72
73# define	short_options	":aC:c:O:dlstvwV:rh"
74#if defined(HAVE_GETOPT_LONG) && HAVE_GETOPT_LONG
75static struct option long_options[] = {
76	{"compability",		required_argument, NULL, 'C'},
77	{"config",		required_argument, NULL, 'c'},
78	{"option",		required_argument, NULL, 'O'},
79	{"config-option",	required_argument, NULL, 'O'},
80	{"default",		no_argument, NULL, 'd'},
81	{"sidecfg",		no_argument, NULL, 's'},
82	{"localcfg",		no_argument, NULL, 'l'},
83	{"all-values",		no_argument, NULL, 'a'},
84	{"test",		no_argument, NULL, 't'},
85	{"overwrite",		no_argument, NULL, 'w'},
86	{"version",		no_argument, NULL, 'v' },
87	{"write",		no_argument, NULL, 'w'},
88	{"view",		required_argument, NULL, 'V' },
89	{"help",		no_argument, NULL, 'h'},
90	{0, 0, 0, 0}
91};
92#endif
93
94static	void    usage (char *mesg);
95
96
97int	main (int argc, char *argv[])
98{
99	int	c;
100	int	opt_index;
101	int	action;
102	int	major;
103	int	minor;
104	const	char	*file;
105	const	char	*defconfname = NULL;
106	const	char	*confname = NULL;
107	char	*p;
108	char	str[254+1];
109	zconf_t	*refconfig = NULL;
110	zconf_t	*config;
111
112	progname = *argv;
113	if ( (p = strrchr (progname, '/')) )
114		progname = ++p;
115	view = getnameappendix (progname, "zkt-conf");
116
117	defconfname = getdefconfname (view);
118	dbg_val0 ("Load built in config \"%s\"\n");
119	config = loadconfig ("", (zconf_t *)NULL);	/* load built in config */
120
121	if ( fileexist (defconfname) )			/* load default config file */
122	{
123		dbg_val ("Load site wide config file \"%s\"\n", defconfname);
124		config = loadconfig (defconfname, config);
125	}
126	if ( config == NULL )
127		fatal ("Out of memory\n");
128	confname = defconfname;
129
130        opterr = 0;
131	opt_index = 0;
132	action = 0;
133	setconfigversion (100);
134#if defined(HAVE_GETOPT_LONG) && HAVE_GETOPT_LONG
135	while ( (c = getopt_long (argc, argv, short_options, long_options, &opt_index)) != -1 )
136#else
137	while ( (c = getopt (argc, argv, short_options)) != -1 )
138#endif
139	{
140		switch ( c )
141		{
142		case 'V':		/* view name */
143			view = optarg;
144			defconfname = getdefconfname (view);
145			if ( fileexist (defconfname) )		/* load default config file */
146				config = loadconfig (defconfname, config);
147			if ( config == NULL )
148				fatal ("Out of memory\n");
149			confname = defconfname;
150			break;
151		case 'O':		/* read option from commandline */
152			config = loadconfig_fromstr (optarg, config);
153			break;
154		case 'C':
155			switch ( sscanf (optarg, "%d.%d", &major, &minor) )
156			{
157			case 2:	major = major * 100 + minor;
158			case 1: break;
159			default:
160				usage ("illegal release number");
161			}
162			setconfigversion (major);
163			break;
164		case 'c':
165			if ( *optarg == '\0' )
166				usage ("empty config file name");
167			config = loadconfig (optarg, config);
168			if ( *optarg == '-' || strcmp (optarg, "stdin") == 0 )
169				confname = "stdout";
170			else
171				confname = optarg;
172			break;
173		case 'd':		/* built-in default config */
174			config = loadconfig ("", config);	/* load built-in config */
175			confname = defconfname;
176			break;
177		case 's':		/* side wide config */
178			/* this is the default **/
179			break;
180		case 'a':		/* set all flag */
181			allflag = 1;
182			break;
183		case 'l':		/* local config file */
184			refconfig = dupconfig (config);	/* duplicate current config */
185			confname = LOCALCONF_FILE;
186			if ( fileexist (LOCALCONF_FILE) )	/* try to load local config file */
187			{
188				dbg_val ("Load local config file \"%s\"\n", LOCALCONF_FILE);
189				config = loadconfig (LOCALCONF_FILE, config);
190			}
191			else if ( !writeflag )
192				usage ("error: no local config file found");
193			break;
194		case 't':		/* test config */
195			testflag = 1;
196			break;
197		case 'v':		/* version */
198			fprintf (stderr, "%s version %s compiled for BIND version %d\n",
199							progname, ZKT_VERSION, BIND_VERSION);
200			fprintf (stderr, "ZKT %s\n", ZKT_COPYRIGHT);
201			return 0;
202			break;
203		case 'w':		/* write back conf file */
204			writeflag = 1;
205			break;
206		case 'h':		/* print help */
207			usage ("");
208			break;
209		case ':':
210			snprintf (str, sizeof(str), "option \"-%c\" requires an argument.",
211										optopt);
212			usage (str);
213			break;
214		case '?':
215			if ( isprint (optopt) )
216				snprintf (str, sizeof(str), "Unknown option \"-%c\".",
217										optopt);
218			else
219				snprintf (str, sizeof (str), "Unknown option char \\x%x.",
220										optopt);
221			usage (str);
222			break;
223		default:
224			abort();
225		}
226	}
227
228	c = optind;
229	if ( c >= argc )	/* no arguments given on commandline */
230	{
231		if ( testflag )
232		{
233			if ( checkconfig (config) )
234				fprintf (stderr, "All config file parameter seems to be ok\n");
235		}
236		else
237		{
238			if ( !writeflag )	/* print to stdout */
239				confname = "stdout";
240
241			if ( refconfig )	/* have we seen a local config file ? */
242				if ( allflag )
243					printconfig (confname, config);
244				else
245					printconfigdiff (confname, refconfig, config);
246			else
247				printconfig (confname, config);
248		}
249	}
250	else	/* command line argument found: use it as name of zone file */
251	{
252		long	minttl;
253		long	maxttl;
254		int	keydbfound;
255		char	*dnskeydb;
256
257		file = argv[c++];
258
259		dnskeydb = config->keyfile;
260
261		minttl = 0x7FFFFFFF;
262		maxttl = 0;
263		keydbfound = parsezonefile (file, &minttl, &maxttl, dnskeydb);
264		if ( keydbfound < 0 )
265			error ("can't parse zone file %s\n", file);
266
267		if ( dnskeydb && !keydbfound )
268		{
269			if ( writeflag )
270			{
271				addkeydb (file, dnskeydb);
272				printf ("\"$INCLUDE %s\" directive added to \"%s\"\n", dnskeydb, file);
273			}
274			else
275				printf ("\"$INCLUDE %s\" should be added to \"%s\" (run with option -w)\n",
276							dnskeydb, file);
277		}
278
279		if ( minttl < (10 * MINSEC) )
280			fprintf (stderr, "Min_TTL of %s (%ld seconds) is too low to use it in a signed zone (see RFC4641)\n",
281							timeint2str (minttl), minttl);
282		else
283			fprintf (stderr, "Min_TTL:\t%s\t# (%ld seconds)\n", timeint2str (minttl), minttl);
284		fprintf (stdout, "Max_TTL:\t%s\t# (%ld seconds)\n", timeint2str (maxttl), maxttl);
285
286		if ( writeflag )
287		{
288			refconfig = dupconfig (config);	/* duplicate current config */
289			confname = LOCALCONF_FILE;
290			if ( fileexist (LOCALCONF_FILE) )	/* try to load local config file */
291			{
292				dbg_val ("Load local config file \"%s\"\n", LOCALCONF_FILE);
293				config = loadconfig (LOCALCONF_FILE, config);
294			}
295			setconfigpar (config, "Max_TTL", &maxttl);
296			printconfigdiff (confname, refconfig, config);
297		}
298	}
299
300
301	return 0;
302}
303
304# define	sopt_usage(mesg, value)	fprintf (stderr, mesg, value)
305#if defined(HAVE_GETOPT_LONG) && HAVE_GETOPT_LONG
306# define	lopt_usage(mesg, value)	fprintf (stderr, mesg, value)
307# define	loptstr(lstr, sstr)	lstr
308#else
309# define	lopt_usage(mesg, value)
310# define	loptstr(lstr, sstr)	sstr
311#endif
312static	void    usage (char *mesg)
313{
314	fprintf (stderr, "%s version %s\n", progname, ZKT_VERSION);
315        if ( mesg && *mesg )
316                fprintf (stderr, "%s\n", mesg);
317        fprintf (stderr, "\n");
318        fprintf (stderr, "usage: %s -h\n", progname);
319        fprintf (stderr, "usage: %s [-V view] [-w|-t]      -d  [-O <optstr>]\n", progname);
320        fprintf (stderr, "usage: %s [-V view] [-w|-t]     [-s] [-c config] [-O <optstr>]\n", progname);
321        fprintf (stderr, "usage: %s [-V view] [-w|-t] [-a] -l  [-c config] [-O <optstr>]\n", progname);
322        fprintf (stderr, "\n");
323        fprintf (stderr, "usage: %s [-c config] [-w] <zonefile>\n", progname);
324        fprintf (stderr, "\n");
325	fprintf (stderr, " -V name%s", loptstr (", --view=name\n", ""));
326	fprintf (stderr, "\t\t specify the view name \n");
327        fprintf (stderr, " -d%s\tprint built-in default config parameter\n", loptstr (", --default", ""));
328        fprintf (stderr, " -s%s\tprint site wide config file parameter (this is the default)\n", loptstr (", --sitecfg", ""));
329        fprintf (stderr, " -l%s\tprint local config file parameter\n", loptstr (", --localcfg", ""));
330        fprintf (stderr, " -a%s\tprint all parameter not only the different one\n", loptstr (", --all", ""));
331        fprintf (stderr, " -c file%s", loptstr (", --config=file\n", ""));
332	fprintf (stderr, " \t\tread config from <file> instead of %s\n", CONFIG_FILE);
333        fprintf (stderr, " -O optstr%s", loptstr (", --config-option=\"optstr\"\n", ""));
334	fprintf (stderr, " \t\tread config options from commandline\n");
335        fprintf (stderr, " -t%s\ttest the config parameter if they are useful \n", loptstr (", --test", "\t"));
336        fprintf (stderr, " -w%s\twrite or rewrite config file \n", loptstr (", --write", "\t"));
337        fprintf (stderr, " -h%s\tprint this help \n", loptstr (", --help", "\t"));
338        exit (1);
339}
340
341