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 *****************************************************************/ 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 *****************************************************************/ 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 *****************************************************************/ 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 *****************************************************************/ 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 *****************************************************************/ 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 *****************************************************************/ 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 *****************************************************************/ 273 const char *zone_geterrstr () 274 { 275 return zone_estr; 276 } 277 278 /***************************************************************** 279 ** zone_add () 280 *****************************************************************/ 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 *****************************************************************/ 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 *****************************************************************/ 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