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