1/*****************************************************************
2**
3**	@(#) zkt.c  -- A library for managing a list of dns zone files.
4**
5**	Copyright (c) 2005 - 2008, Holger Zuleger HZnet. All rights reserved.
6**
7**	This software is open source.
8**
9**	Redistribution and use in source and binary forms, with or without
10**	modification, are permitted provided that the following conditions
11**	are met:
12**
13**	Redistributions of source code must retain the above copyright notice,
14**	this list of conditions and the following disclaimer.
15**
16**	Redistributions in binary form must reproduce the above copyright notice,
17**	this list of conditions and the following disclaimer in the documentation
18**	and/or other materials provided with the distribution.
19**
20**	Neither the name of Holger Zuleger HZnet nor the names of its contributors may
21**	be used to endorse or promote products derived from this software without
22**	specific prior written permission.
23**
24**	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25**	"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26**	TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
27**	PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
28**	LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29**	CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30**	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31**	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32**	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33**	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34**	POSSIBILITY OF SUCH DAMAGE.
35**
36*****************************************************************/
37# include <stdio.h>
38# include <string.h>
39#ifdef HAVE_CONFIG_H
40# include <config.h>
41#endif
42# include "config_zkt.h"
43# include "dki.h"
44# include "misc.h"
45# include "strlist.h"
46# include "zconf.h"
47# include "domaincmp.h"
48# include "tcap.h"
49#define extern
50# include "zkt.h"
51#undef extern
52
53extern	char	*labellist;
54extern	int	headerflag;
55extern	int	timeflag;
56extern	int	exptimeflag;
57extern	int	lifetime;
58extern	int	ageflag;
59extern	int	lifetimeflag;
60extern	int	kskflag;
61extern	int	zskflag;
62extern	int	pathflag;
63extern	int	ljustflag;
64
65static	void	printkeyinfo (const dki_t *dkp, const char *oldpath);
66
67static	void	printkeyinfo (const dki_t *dkp, const char *oldpath)
68{
69	time_t	currtime;
70
71	if ( dkp == NULL )	/* print headline */
72	{
73		if ( headerflag )
74		{
75			tc_attr (stdout, TC_BOLD, 1);
76			printf ("%-33.33s %5s %3s %3.3s %-7s", "Keyname",
77				"Tag", "Typ", "Status", "Algorit");
78			if ( timeflag )
79				printf (" %-20s", "Generation Time");
80			if ( exptimeflag )
81				printf (" %-20s", "Expiration Time");
82			if ( ageflag  )
83				printf (" %16s", "Age");
84			if ( lifetimeflag  )
85				printf (" %4s", "LfTm");
86			tc_attr (stdout, TC_BOLD, 0);
87			putchar ('\n');
88		}
89		return;
90	}
91	time (&currtime);
92
93	/* TODO: use next line if dname is dynamically allocated */
94	/* if ( pathflag && dkp->dname && strcmp (oldpath, dkp->dname) != 0 ) */
95	if ( pathflag && strcmp (oldpath, dkp->dname) != 0 )
96		printf ("%s/\n", dkp->dname);
97
98	if ( (kskflag && dki_isksk (dkp)) || (zskflag && !dki_isksk (dkp)) )
99	{
100		int	color;
101
102		if ( ljustflag )
103			printf ("%-33.33s ", dkp->name);
104		else
105			printf ("%33.33s ", dkp->name);
106		printf ("%05d ", dkp->tag);
107		printf ("%3s ", dki_isksk (dkp) ? "KSK" : "ZSK");
108
109		if ( dkp->status == DKI_ACT )
110			color = TC_GREEN;
111		else if ( dkp->status == DKI_PUB )
112			color = TC_BLUE;
113		else if ( dkp->status == DKI_DEP )
114			color = TC_RED;
115		else
116			color = TC_BLACK;
117		tc_attr (stdout, color, 1);
118		printf ("%-3.3s ", dki_statusstr (dkp) );
119		tc_attr (stdout, color, 0);
120
121		printf ("%-7s", dki_algo2sstr(dkp->algo));
122
123		if ( currtime < dkp->time + dkp->lifetime )
124			color = TC_GREEN;
125		else
126			color = TC_BOLD|TC_RED;
127		tc_attr (stdout, color, 1);
128
129		if ( timeflag )
130			printf (" %-20s", time2str (dkp->gentime ? dkp->gentime: dkp->time, 's'));
131		if ( exptimeflag )
132			printf (" %-20s", time2str (dkp->exptime, 's'));
133		if ( ageflag )
134			printf (" %16s", age2str (dki_age (dkp, currtime)));
135		if ( lifetimeflag && dkp->lifetime )
136		{
137			if ( dkp->status == 'a' )
138				printf ("%c", (currtime < dkp->time + dkp->lifetime) ? '<' : '!');
139			else
140				putchar (' ');
141			printf ("%hdd", dki_lifetimedays (dkp));
142		}
143		tc_attr (stdout, color, 0);
144		putchar ('\n');
145	}
146}
147
148#if defined(USE_TREE) && USE_TREE
149static	void	list_key (const dki_t **nodep, const VISIT which, int depth)
150{
151	const	dki_t	*dkp;
152	static	const	char	*oldpath = "";
153
154	if ( nodep == NULL )
155		return;
156//fprintf (stderr, "listkey %d %d %s\n", which, depth, dkp->name);
157
158	if ( which == INORDER || which == LEAF )
159	{
160		dkp = *nodep;
161		while ( dkp )	/* loop through list */
162		{
163			if ( labellist == NULL || isinlist (dkp->name, labellist) )
164				printkeyinfo (dkp, oldpath);		/* print entry */
165			oldpath = dkp->dname;
166			dkp = dkp->next;
167		}
168	}
169}
170#endif
171
172void	zkt_list_keys (const dki_t *data)
173{
174#if ! defined(USE_TREE) || !USE_TREE
175	const   dki_t   *dkp;
176	const   char   *oldpath;
177#endif
178
179	if ( data )    /* print headline if list is not empty */
180		printkeyinfo (NULL, "");
181
182#if defined(USE_TREE) && USE_TREE
183	twalk (data, list_key);
184#else
185	oldpath = "";
186	for ( dkp = data; dkp; dkp = dkp->next )       /* loop through list */
187	{
188		if ( labellist == NULL || isinlist (dkp->name, labellist) )
189			printkeyinfo (dkp, oldpath);            /* print entry */
190		oldpath = dkp->dname;
191	}
192#endif
193}
194
195#if defined(USE_TREE) && USE_TREE
196# if 0
197static	void	list_trustedkey (const dki_t **nodep, const VISIT which, int depth)
198{
199	const	dki_t	*dkp;
200
201	if ( nodep == NULL )
202		return;
203
204	dkp = *nodep;
205	if ( which == INORDER || which == LEAF )
206	{
207// fprintf (stderr, "list_trustedkey order=%d(pre=0,in=1,post=2,leaf=3) depth=%d %s\n", which, depth, dkp->name);
208		/* loop through list */
209		while ( dkp )
210		{
211			if ( (dki_isksk (dkp) || zskflag) &&
212			     (labellist == NULL || isinlist (dkp->name, labellist)) )
213				dki_prt_trustedkey (dkp, stdout);
214			dkp = dkp->next;
215		}
216	}
217}
218# else
219const	dki_t	*parent;
220static	void	list_trustedkey (const dki_t **nodep, const VISIT which, int depth)
221{
222	const	dki_t	*dkp;
223
224	if ( nodep == NULL )
225		return;
226
227	dkp = *nodep;
228	if ( which == INORDER || which == LEAF )
229	{
230// fprintf (stderr, "list_trustedkey order=%d(pre=0,in=1,post=2,leaf=3) depth=%d %s\n", which, depth, dkp->name);
231		if ( labellist && !isinlist (dkp->name, labellist) )
232			return;
233
234		if ( parent == NULL || !issubdomain (dkp->name, parent->name) )
235		{
236			parent = dkp;
237			/* loop through list */
238			while ( dkp )
239			{
240				if ( (dki_isksk (dkp) || zskflag) )
241					dki_prt_trustedkey (dkp, stdout);
242				dkp = dkp->next;
243			}
244		}
245	}
246}
247# endif
248#endif
249
250void	zkt_list_trustedkeys (const dki_t *data)
251{
252
253	/* print headline if list is not empty */
254	if ( data && headerflag )
255		printf ("trusted-keys {\n");
256
257#if defined(USE_TREE) && USE_TREE
258	twalk (data, list_trustedkey);
259#else
260	for ( dkp = data; dkp; dkp = dkp->next )	/* loop through list */
261		if ( (dki_isksk (dkp) || zskflag) &&
262		     (labellist == NULL || isinlist (dkp->name, labellist)) )
263			dki_prt_trustedkey (dkp, stdout);
264#endif
265
266	/* print end of trusted-key section */
267	if ( data && headerflag )
268		printf ("};\n");
269}
270
271#if defined(USE_TREE) && USE_TREE
272static	void	list_dnskey (const dki_t **nodep, const VISIT which, int depth)
273{
274	const	dki_t	*dkp;
275	int	ksk;
276
277	if ( nodep == NULL )
278		return;
279
280	if ( which == INORDER || which == LEAF )
281		for ( dkp = *nodep; dkp; dkp = dkp->next )
282		{
283			ksk = dki_isksk (dkp);
284			if ( (ksk && !kskflag) || (!ksk && !zskflag) )
285				continue;
286
287			if ( labellist == NULL || isinlist (dkp->name, labellist) )
288			{
289				if ( headerflag )
290					dki_prt_comment (dkp, stdout);
291				dki_prt_dnskey (dkp, stdout);
292			}
293		}
294}
295#endif
296
297void	zkt_list_dnskeys (const dki_t *data)
298{
299#if defined(USE_TREE) && USE_TREE
300	twalk (data, list_dnskey);
301#else
302	const	dki_t	*dkp;
303	int	ksk;
304
305	for ( dkp = data; dkp; dkp = dkp->next )
306	{
307		ksk = dki_isksk (dkp);
308		if ( (ksk && !kskflag) || (!ksk && !zskflag) )
309			continue;
310
311		if ( labellist == NULL || isinlist (dkp->name, labellist) )
312		{
313			if ( headerflag )
314				dki_prt_comment (dkp, stdout);
315			dki_prt_dnskey (dkp, stdout);
316		}
317	}
318#endif
319}
320
321#if defined(USE_TREE) && USE_TREE
322static	void	set_keylifetime (const dki_t **nodep, const VISIT which, int depth)
323{
324	const	dki_t	*dkp;
325	int	ksk;
326
327	if ( nodep == NULL )
328		return;
329
330	if ( which == INORDER || which == LEAF )
331		for ( dkp = *nodep; dkp; dkp = dkp->next )
332		{
333			ksk = dki_isksk (dkp);
334			if ( (ksk && !kskflag) || (!ksk && !zskflag) )
335				continue;
336
337			if ( labellist == NULL || isinlist (dkp->name, labellist) )
338				dki_setlifetime ((dki_t *)dkp, lifetime);
339		}
340}
341#endif
342
343void	zkt_setkeylifetime (dki_t *data)
344{
345#if defined(USE_TREE) && USE_TREE
346	twalk (data, set_keylifetime);
347#else
348	dki_t	*dkp;
349	int	ksk;
350
351	for ( dkp = data; dkp; dkp = dkp->next )
352	{
353		ksk = dki_isksk (dkp);
354		if ( (ksk && !kskflag) || (!ksk && !zskflag) )
355			continue;
356
357		if ( labellist == NULL || isinlist (dkp->name, labellist) )
358		{
359			dki_setlifetime (dkp, lifetime);
360		}
361	}
362#endif
363}
364
365
366#if defined(USE_TREE) && USE_TREE
367static	const	dki_t	*searchresult;
368static	int	searchitem;
369static	void	tag_search (const dki_t **nodep, const VISIT which, int depth)
370{
371	const	dki_t	*dkp;
372
373	if ( nodep == NULL )
374		return;
375
376	if ( which == PREORDER || which == LEAF )
377		for ( dkp = *nodep; dkp; dkp = dkp->next )
378		{
379			if ( dkp->tag == searchitem )
380			{
381				if ( searchresult == NULL )
382					searchresult = dkp;
383				else
384					searchitem = 0;
385			}
386		}
387}
388#endif
389const	dki_t	*zkt_search (const dki_t *data, int searchtag, const char *keyname)
390{
391	const dki_t	*dkp = NULL;
392
393#if defined(USE_TREE) && USE_TREE
394	if ( keyname == NULL || *keyname == '\0' )
395	{
396		searchresult = NULL;
397		searchitem = searchtag;
398		twalk (data, tag_search);
399		if ( searchresult != NULL && searchitem == 0 )
400			dkp = (void *)01;
401		else
402			dkp = searchresult;
403	}
404	else
405		dkp = (dki_t*)dki_tsearch (data, searchtag, keyname);
406#else
407	dkp = (dki_t*)dki_search (data, searchtag, keyname);
408#endif
409	return dkp;
410}
411
412