1 /*	$NetBSD: zone.c,v 1.1.1.1 2015/07/08 15:37:48 christos Exp $	*/
2 
3 /*****************************************************************
4 **
5 **	@(#) zone.c  (c) Mar 2005  Holger Zuleger  hznet.de
6 **
7 **	Copyright (c) Mar 2005, 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 # include <stdio.h>
40 # include <string.h>
41 # include <stdlib.h>
42 # include <sys/types.h>
43 # include <sys/stat.h>
44 # include <dirent.h>
45 # include <assert.h>
46 #ifdef HAVE_CONFIG_H
47 # include <config.h>
48 #endif
49 # include "config_zkt.h"
50 # include "debug.h"
51 # include "domaincmp.h"
52 # include "misc.h"
53 # include "zconf.h"
54 # include "dki.h"
55 #define	extern
56 # include "zone.h"
57 #undef	extern
58 
59 /*****************************************************************
60 **	private (static) function declaration and definition
61 *****************************************************************/
62 static	char	zone_estr[255+1];
63 
64 /*****************************************************************
65 **	zone_alloc ()
66 *****************************************************************/
zone_alloc()67 static	zone_t	*zone_alloc ()
68 {
69 	zone_t	*zp;
70 
71 	if ( (zp = malloc (sizeof (zone_t))) )
72 	{
73 		memset (zp, 0, sizeof (zone_t));
74 		return zp;
75 	}
76 
77 	snprintf (zone_estr, sizeof (zone_estr),
78 			"zone_alloc: Out of memory");
79 	return NULL;
80 }
81 
82 /*****************************************************************
83 **	zone_cmp () 	return <0 | 0 | >0
84 *****************************************************************/
zone_cmp(const zone_t * a,const zone_t * b)85 static	int	zone_cmp (const zone_t *a, const zone_t *b)
86 {
87 	if ( a == NULL ) return -1;
88 	if ( b == NULL ) return 1;
89 
90 	return domaincmp (a->zone, b->zone);
91 }
92 
93 
94 /*****************************************************************
95 **	public function definition
96 *****************************************************************/
97 
98 /*****************************************************************
99 **	zone_free ()
100 *****************************************************************/
zone_free(zone_t * zp)101 void	zone_free (zone_t *zp)
102 {
103 	assert (zp != NULL);
104 
105 	if ( zp->zone ) free ((char *)zp->zone);
106 	if ( zp->dir ) free ((char *)zp->dir);
107 	if ( zp->file ) free ((char *)zp->file);
108 	if ( zp->sfile ) free ((char *)zp->sfile);
109 #if 0
110 	/* TODO: actually there are some problems freeing the config :-( */
111 	if ( zp->conf ) free ((zconf_t *)zp->conf);
112 #endif
113 	if ( zp->keys ) dki_freelist (&zp->keys);
114 	free (zp);
115 }
116 
117 /*****************************************************************
118 **	zone_freelist ()
119 *****************************************************************/
zone_freelist(zone_t ** listp)120 void	zone_freelist (zone_t **listp)
121 {
122 	zone_t	*curr;
123 	zone_t	*next;
124 
125 	assert (listp != NULL);
126 
127 	curr = *listp;
128 	while ( curr )
129 	{
130 		next = curr->next;
131 		zone_free (curr);
132 		curr = next;
133 	}
134 	if ( *listp )
135 		*listp = NULL;
136 }
137 
138 /*****************************************************************
139 **	zone_new ()
140 **	allocate memory for new zone structure and initialize it
141 *****************************************************************/
zone_new(zone_t ** zp,const char * zone,const char * dir,const char * file,const char * signed_ext,const zconf_t * cp)142 zone_t	*zone_new (zone_t **zp, const char *zone, const char *dir, const char *file, const char *signed_ext, const zconf_t *cp)
143 {
144 	char	path[MAX_PATHSIZE+1];
145 	zone_t	*new;
146 
147 	assert (zp != NULL);
148 	assert (zone != NULL && *zone != '\0');
149 
150 	dbg_val3 ("zone_new: (zp, zone: %s, dir: %s, file: %s, cp)\n", zone, dir, file);
151 	if ( dir == NULL || *dir == '\0' )
152 		dir = ".";
153 
154 	if ( file == NULL || *file == '\0' )
155 		file = cp->zonefile;
156 	else
157 	{	/* check if file contains a path */
158 		const	char	*p;
159 		if ( (p = strrchr (file, '/')) != NULL )
160 		{
161 			snprintf (path, sizeof (path), "%s/%.*s", dir, (int)(p-file), file);
162 			dir = path;
163 			file = p+1;
164 		}
165 	}
166 
167 	if ( (new = zone_alloc ()) != NULL )
168 	{
169 		char	*p;
170 
171 		new->zone = domain_canonicdup (zone);
172 		new->dir = strdup (dir);
173 		new->file = strdup (file);
174 		/* check if file ends with ".signed" ? */
175 		if ( (p = strrchr (new->file, '.')) != NULL && strcmp (p, signed_ext) == 0 )
176 		{
177 			new->sfile = strdup (new->file);
178 			*p = '\0';
179 		}
180 		else
181 		{
182 			snprintf (path, sizeof (path), "%s%s", file, signed_ext);
183 			new->sfile = strdup (path);
184 		}
185 		new->conf = cp;
186 		new->keys = NULL;
187 		dki_readdir (new->dir, &new->keys, 0);
188 		new->next = NULL;
189 	}
190 
191 	return zone_add (zp, new);
192 }
193 
194 /*****************************************************************
195 **	zone_readdir ()
196 *****************************************************************/
zone_readdir(const char * dir,const char * zone,const char * zfile,zone_t ** listp,const zconf_t * conf,int dyn_zone)197 int	zone_readdir (const char *dir, const char *zone, const char *zfile, zone_t **listp, const zconf_t *conf, int dyn_zone)
198 {
199 	char	*p;
200 	char	path[MAX_PATHSIZE+1];
201 	char	*signed_ext = ".signed";
202 	zconf_t	*localconf = NULL;
203 
204 	assert (dir != NULL && *dir != '\0');
205 	assert (conf != NULL);
206 
207 	if ( zone == NULL )	/* zone not given ? */
208 	{
209 		if ( (zone = strrchr (dir, '/')) )	/* try to extract zone name out of directory */
210 			zone++;
211 		else
212 			zone = dir;
213 	}
214 	if ( zone == NULL )	/* zone name still null ? */
215 		return 0;
216 
217 	dbg_val4 ("zone_readdir: (dir: \"%s\", zone: \"%s\", zfile: \"%s\", zp, cp, dyn_zone = %d)\n",
218 					dir, zone, zfile ? zfile: "NULL", dyn_zone);
219 
220 	if ( dyn_zone )
221 		signed_ext = ".dsigned";
222 
223 	if ( zfile && (p = strrchr (zfile, '/')) )	/* check if zfile contains a directory */
224 	{
225 		char	subdir[MAX_PATHSIZE+1];
226 
227 		snprintf (subdir, sizeof (subdir), "%s/%.*s", dir, (int)(p - zfile), zfile);
228 		pathname (path, sizeof (path), subdir, LOCALCONF_FILE, NULL);
229 	}
230 	else
231 		pathname (path, sizeof (path), dir, LOCALCONF_FILE, NULL);
232 	dbg_val1 ("zone_readdir: check local config file %s\n", path);
233 	if ( fileexist (path) )			/* load local config file */
234 	{
235 		localconf = dupconfig (conf);
236 		conf = loadconfig (path, localconf);
237 		/* do not free localconf, because a ptr to it will be added to the zone by zone_new() */
238 	}
239 
240 	if ( zfile == NULL )
241 	{
242 		zfile = conf->zonefile;
243 		pathname (path, sizeof (path), dir, zfile, signed_ext);
244 	}
245 	else
246 	{
247 		dbg_val2("zone_readdir: add %s to zonefile if not already there ? (%s)\n", signed_ext, zfile);
248 		if ( (p = strrchr (zfile, '.')) == NULL || strcmp (p, signed_ext) != 0 )
249 			pathname (path, sizeof (path), dir, zfile, signed_ext);
250 		else
251 			pathname (path, sizeof (path), dir, zfile, NULL);
252 	}
253 
254 	dbg_val1("zone_readdir: fileexist (%s): ", path);
255 	if ( !fileexist (path) )	/* no .signed file found ? ... */
256 	{
257 		dbg_val0("no!\n");
258 		return 0;		/* ... not a secure zone ! */
259 	}
260 	dbg_val0("yes!\n");
261 
262 	dbg_val("zone_readdir: add zone (%s)\n", zone);
263 	zone_new (listp, zone, dir, zfile, signed_ext, conf);
264 
265 	return 1;
266 }
267 
268 
269 /*****************************************************************
270 **	zone_geterrstr ()
271 **	return error string
272 *****************************************************************/
zone_geterrstr()273 const	char	*zone_geterrstr ()
274 {
275 	return zone_estr;
276 }
277 
278 /*****************************************************************
279 **	zone_add ()
280 *****************************************************************/
zone_add(zone_t ** list,zone_t * new)281 zone_t	*zone_add (zone_t **list, zone_t *new)
282 {
283 	zone_t	*curr;
284 	zone_t	*last;
285 
286 	if ( list == NULL )
287 		return NULL;
288 	if ( new == NULL )
289 		return *list;
290 
291 	last = curr = *list;
292 	while ( curr && zone_cmp (curr, new) < 0 )
293 	{
294 		last = curr;
295 		curr = curr->next;
296 	}
297 
298 	if ( curr == *list )	/* add node at the begining of the list */
299 		*list = new;
300 	else			/* add node at end or between two nodes */
301 		last->next = new;
302 	new->next = curr;
303 
304 	return new;
305 }
306 
307 /*****************************************************************
308 **	zone_search ()
309 *****************************************************************/
zone_search(const zone_t * list,const char * zone)310 const zone_t	*zone_search (const zone_t *list, const char *zone)
311 {
312 	if ( zone == NULL || *zone == '\0' )
313 		return NULL;
314 
315 	while ( list && strcmp (zone, list->zone) != 0 )
316 		list = list->next;
317 
318 	return list;
319 }
320 
321 /*****************************************************************
322 **	zone_print ()
323 *****************************************************************/
zone_print(const char * mesg,const zone_t * z)324 int	zone_print (const char *mesg, const zone_t *z)
325 {
326 	dki_t	*dkp;
327 
328 	if ( !z )
329 		return 0;
330 	fprintf (stderr, "%s: zone\t %s\n", mesg, z->zone);
331 	fprintf (stderr, "%s: dir\t %s\n", mesg, z->dir);
332 	fprintf (stderr, "%s: file\t %s\n", mesg, z->file);
333 	fprintf (stderr, "%s: sfile\t %s\n", mesg, z->sfile);
334 
335 	for ( dkp = z->keys; dkp; dkp = dkp->next )
336         {
337                 dki_prt_comment (dkp, stderr);
338         }
339 
340 	return 1;
341 }
342