1/**************************************************************** 2** 3** @(#) zconf.c -- configuration file parser for dnssec.conf 4** 5** Most of the code is from the SixXS Heartbeat Client 6** written by Jeroen Massar <jeroen@sixxs.net> 7** 8** New config types and many code changes by Holger Zuleger 9** 10** Copyright (c) Aug 2005, Jeroen Massar. 11** Copyright (c) Aug 2005 - Apr 2010, Holger Zuleger. 12** All rights reserved. 13** 14** This software is open source. 15** 16** Redistribution and use in source and binary forms, with or without 17** modification, are permitted provided that the following conditions 18** are met: 19** 20** Redistributions of source code must retain the above copyright notice, 21** this list of conditions and the following disclaimer. 22** 23** Redistributions in binary form must reproduce the above copyright notice, 24** this list of conditions and the following disclaimer in the documentation 25** and/or other materials provided with the distribution. 26** 27** Neither the name of Jeroen Masar or Holger Zuleger nor the 28** names of its contributors may be used to endorse or promote products 29** derived from this software without specific prior written permission. 30** 31** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 33** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 34** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 35** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 36** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 38** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 39** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 40** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41** POSSIBILITY OF SUCH DAMAGE. 42** 43****************************************************************/ 44# include <sys/types.h> 45# include <stdio.h> 46# include <errno.h> 47# include <unistd.h> 48# include <stdlib.h> 49# include <stdarg.h> 50# include <string.h> 51# include <strings.h> 52# include <assert.h> 53# include <ctype.h> 54 55#ifdef HAVE_CONFIG_H 56# include "config.h" 57#endif 58# include "config_zkt.h" 59# include "debug.h" 60# include "misc.h" 61#define extern 62# include "zconf.h" 63#undef extern 64# include "dki.h" 65 66# define ISTRUE(val) (strcasecmp (val, "yes") == 0 || \ 67 strcasecmp (val, "true") == 0 ) 68# define ISCOMMENT(cp) (*(cp) == '#' || *(cp) == ';' || \ 69 (*(cp) == '/' && *((cp)+1) == '/') ) 70# define ISDELIM(c) (isspace (c) || (c) == ':' || (c) == '=') 71 72 73# define cmdln (0) 74# define first (1) 75# define last (0x7FFF) 76 77# define iscmdline(x) ((x)->used_since == cmdln) 78# define iscompatible(x) ((x)->used_since != cmdln && compversion >= (x)->used_since && \ 79 ((x)->used_till == 1 || (compversion <= (x)->used_till))) 80 81typedef enum { 82 CONF_END = 0, 83 CONF_STRING, 84 CONF_INT, 85 CONF_TIMEINT, 86 CONF_BOOL, 87 CONF_ALGO, 88 CONF_SERIAL, 89 CONF_FACILITY, 90 CONF_LEVEL, 91 CONF_NSEC3, 92 CONF_COMMENT, 93 CONF_VERSION, 94} ctype_t; 95 96/***************************************************************** 97** private (static) variables 98*****************************************************************/ 99static int compversion; 100 101static zconf_t def = { 102 ZONEDIR, RECURSIVE, 103 PRINTTIME, PRINTAGE, LJUST, LSCOLORTERM, 104 SIG_VALIDITY, MAX_TTL, KEY_TTL, PROPTIME, Unixtime, 105 RESIGN_INT, 106 KEY_ALGO, ADDITIONAL_KEY_ALGO, 107 KSK_LIFETIME, KSK_BITS, KSK_RANDOM, 108 ZSK_LIFETIME, ZSK_BITS, ZSK_RANDOM, 109 NSEC3_OFF, SALTLEN, 110 NULL, /* viewname cmdline parameter */ 111 0, /* noexec cmdline parameter */ 112 LOGFILE, LOGLEVEL, LOGDOMAINDIR, SYSLOGFACILITY, SYSLOGLEVEL, VERBOSELOG, 0, 113 DNSKEYFILE, ZONEFILE, KEYSETDIR, 114 LOOKASIDEDOMAIN, 115 SIG_RANDOM, SIG_PSEUDO, SIG_GENDS, SIG_DNSKEY_KSK, SIG_PARAM, 116 DIST_CMD, /* defaults to NULL which means to run "rndc reload" */ 117 NAMED_CHROOT 118}; 119 120typedef struct { 121 char *label; /* the name of the paramter */ 122 short used_since; /* compability (from version; 0 == command line) */ 123 short used_till; /* compability (to version) */ 124 ctype_t type; /* the parameter type */ 125 void *var; /* pointer to the parameter variable */ 126 const void *var2; /* pointer to a second parameter variable */ 127 /* this is a ugly hack needed by cmpconfig () */ 128} zconf_para_t; 129 130static zconf_para_t confpara[] = { 131 { "", first, last, CONF_COMMENT, ""}, 132 { "", first, last, CONF_COMMENT, "\t@(#) dnssec.conf "}, 133 { "", first, last, CONF_VERSION, "" }, 134 { "", first, last, CONF_COMMENT, ""}, 135 { "", first, last, CONF_COMMENT, NULL }, 136 137 { "", first, 99, CONF_COMMENT, "dnssec-zkt options" }, 138 { "", 100, last, CONF_COMMENT, "zkt-ls options" }, 139 { "ZoneDir", first, last, CONF_STRING, &def.zonedir }, 140 { "Recursive", first, last, CONF_BOOL, &def.recursive }, 141 { "PrintTime", first, last, CONF_BOOL, &def.printtime }, 142 { "PrintAge", first, last, CONF_BOOL, &def.printage }, 143 { "LeftJustify", first, last, CONF_BOOL, &def.ljust }, 144 { "lsColor", 100, last, CONF_STRING, &def.colorterm }, 145 146 { "", first, last, CONF_COMMENT, NULL }, 147 { "", first, last, CONF_COMMENT, "zone specific values" }, 148 { "ResignInterval", first, last, CONF_TIMEINT, &def.resign }, 149 { "SigValidity", first, last, CONF_TIMEINT, &def.sigvalidity }, 150 { "Max_TTL", first, 100, CONF_TIMEINT, &def.max_ttl }, 151 { "MaximumTTL", 101, last, CONF_TIMEINT, &def.max_ttl }, 152 { "Propagation", first, last, CONF_TIMEINT, &def.proptime }, 153 { "Key_TTL", 90, 100, CONF_TIMEINT, &def.key_ttl }, 154 { "DnsKeyTTL", 101, last, CONF_TIMEINT, &def.key_ttl }, 155#if defined (DEF_TTL) 156 { "def_ttl", first, last, CONF_TIMEINT, &def.def_ttl }, 157#endif 158 { "SerialFormat", 92, last, CONF_SERIAL, &def.serialform }, 159 160 { "", first, last, CONF_COMMENT, NULL }, 161 { "", first, last, CONF_COMMENT, "signing key parameters"}, 162 { "Key_Algo", 99, 100, CONF_ALGO, &def.k_algo }, /* now used as general KEY algoritjm (KSK & ZSK) */ 163 { "KeyAlgo", 101, last, CONF_ALGO, &def.k_algo }, /* now used as general KEY algoritjm (KSK & ZSK) */ 164 { "AddKey_Algo", 99, 100, CONF_ALGO, &def.k2_algo }, /* second key algorithm added (v0.99) */ 165 { "AddKeyAlgo", 101, last, CONF_ALGO, &def.k2_algo }, /* second key algorithm added (v0.99) */ 166 { "KSK_lifetime", first, 100, CONF_TIMEINT, &def.k_life }, 167 { "KSKlifetime", 101, last, CONF_TIMEINT, &def.k_life }, 168 { "KSK_algo", first, 98, CONF_ALGO, &def.k_algo }, /* old KSK value changed to key algorithm */ 169 { "KSK_bits", first, 100, CONF_INT, &def.k_bits }, 170 { "KSKbits", 101, last, CONF_INT, &def.k_bits }, 171 { "KSK_randfile", first, 100, CONF_STRING, &def.k_random }, 172 { "KSKrandfile", 101, last, CONF_STRING, &def.k_random }, 173 { "ZSK_lifetime", first, 100, CONF_TIMEINT, &def.z_life }, 174 { "ZSKlifetime", 101, last, CONF_TIMEINT, &def.z_life }, 175 /* { "ZSK_algo", 1, CONF_ALGO, &def.z_algo }, ZSK algo removed (set to same as ksk) */ 176 { "ZSK_algo", first, 98, CONF_ALGO, &def.k2_algo }, /* if someone using it already, map the algo to the additional key algorithm */ 177 { "ZSK_bits", first, 100, CONF_INT, &def.z_bits }, 178 { "ZSKbits", 101, last, CONF_INT, &def.z_bits }, 179 { "ZSK_randfile", first, 100, CONF_STRING, &def.z_random }, 180 { "ZSKrandfile", 101, last, CONF_STRING, &def.z_random }, 181 { "NSEC3", 100, last, CONF_NSEC3, &def.nsec3 }, 182 { "SaltBits", 98, last, CONF_INT, &def.saltbits }, 183 184 { "", first, last, CONF_COMMENT, NULL }, 185 { "", first, 99, CONF_COMMENT, "dnssec-signer options"}, 186 { "", 100, last, CONF_COMMENT, "zkt-signer options"}, 187 { "--view", cmdln, last, CONF_STRING, &def.view }, 188 { "--noexec", cmdln, last, CONF_BOOL, &def.noexec }, 189 { "LogFile", 96, last, CONF_STRING, &def.logfile }, 190 { "LogLevel", 96, last, CONF_LEVEL, &def.loglevel }, 191 { "LogDomainDir", 96, last, CONF_STRING, &def.logdomaindir }, 192 { "SyslogFacility", 96, last, CONF_FACILITY, &def.syslogfacility }, 193 { "SyslogLevel", 96, last, CONF_LEVEL, &def.sysloglevel }, 194 { "VerboseLog", 96, last, CONF_INT, &def.verboselog }, 195 { "-v", cmdln, last, CONF_INT, &def.verbosity }, 196 { "KeyFile", first, last, CONF_STRING, &def.keyfile }, 197 { "ZoneFile", first, last, CONF_STRING, &def.zonefile }, 198 { "KeySetDir", first, last, CONF_STRING, &def.keysetdir }, 199 { "DLV_Domain", first, 100, CONF_STRING, &def.lookaside }, 200 { "DLVdomain", 101, last, CONF_STRING, &def.lookaside }, 201 { "Sig_Randfile", first, 100, CONF_STRING, &def.sig_random }, 202 { "SigRandfile", 101, last, CONF_STRING, &def.sig_random }, 203 { "Sig_Pseudorand", first, 100, CONF_BOOL, &def.sig_pseudo }, 204 { "SigPseudorand", 101, last, CONF_BOOL, &def.sig_pseudo }, 205 { "Sig_GenerateDS", first, 100, CONF_BOOL, &def.sig_gends }, 206 { "SigGenerateDS", 101, last, CONF_BOOL, &def.sig_gends }, 207 { "Sig_DnsKeyKSK", 99, 100, CONF_BOOL, &def.sig_dnskeyksk }, 208 { "SigDnsKeyKSK", 101, last, CONF_BOOL, &def.sig_dnskeyksk }, 209 { "Sig_Parameter", first, 100, CONF_STRING, &def.sig_param }, 210 { "SigParameter", 101, last, CONF_STRING, &def.sig_param }, 211 { "Distribute_Cmd", 97, 100, CONF_STRING, &def.dist_cmd }, 212 { "DistributeCmd", 101, last, CONF_STRING, &def.dist_cmd }, 213 { "NamedChrootDir", 99, last, CONF_STRING, &def.chroot_dir }, 214 215 { NULL, 0, 0, CONF_END, NULL}, 216}; 217 218/***************************************************************** 219** private (static) function deklaration and definition 220*****************************************************************/ 221static const char *bool2str (int val) 222{ 223 return val ? "True" : "False"; 224} 225 226static int set_varptr (char *entry, void *ptr, const void *ptr2) 227{ 228 zconf_para_t *c; 229 230 for ( c = confpara; c->label; c++ ) 231 if ( strcasecmp (entry, c->label) == 0 ) 232 { 233 c->var = ptr; 234 c->var2 = ptr2; 235 return 1; 236 } 237 return 0; 238} 239 240static void set_all_varptr (zconf_t *cp, const zconf_t *cp2) 241{ 242 set_varptr ("zonedir", &cp->zonedir, cp2 ? &cp2->zonedir: NULL); 243 set_varptr ("recursive", &cp->recursive, cp2 ? &cp2->recursive: NULL); 244 set_varptr ("printage", &cp->printage, cp2 ? &cp2->printage: NULL); 245 set_varptr ("printtime", &cp->printtime, cp2 ? &cp2->printtime: NULL); 246 set_varptr ("leftjustify", &cp->ljust, cp2 ? &cp2->ljust: NULL); 247 set_varptr ("lscolor", &cp->colorterm, cp2 ? &cp2->colorterm: NULL); 248 249 set_varptr ("resigninterval", &cp->resign, cp2 ? &cp2->resign: NULL); 250 set_varptr ("sigvalidity", &cp->sigvalidity, cp2 ? &cp2->sigvalidity: NULL); 251 set_varptr ("max_ttl", &cp->max_ttl, cp2 ? &cp2->max_ttl: NULL); 252 set_varptr ("key_ttl", &cp->key_ttl, cp2 ? &cp2->key_ttl: NULL); 253 set_varptr ("propagation", &cp->proptime, cp2 ? &cp2->proptime: NULL); 254#if defined (DEF_TTL) 255 set_varptr ("def_ttl", &cp->def_ttl, cp2 ? &cp2->def_ttl: NULLl); 256#endif 257 set_varptr ("serialformat", &cp->serialform, cp2 ? &cp2->serialform: NULL); 258 259 set_varptr ("key_algo", &cp->k_algo, cp2 ? &cp2->k_algo: NULL); 260 set_varptr ("addkey_algo", &cp->k2_algo, cp2 ? &cp2->k2_algo: NULL); 261 set_varptr ("ksk_lifetime", &cp->k_life, cp2 ? &cp2->k_life: NULL); 262 set_varptr ("ksk_algo", &cp->k_algo, cp2 ? &cp2->k_algo: NULL); /* used only in compability mode */ 263 set_varptr ("ksk_bits", &cp->k_bits, cp2 ? &cp2->k_bits: NULL); 264 set_varptr ("ksk_randfile", &cp->k_random, cp2 ? &cp2->k_random: NULL); 265 266 set_varptr ("zsk_lifetime", &cp->z_life, cp2 ? &cp2->z_life: NULL); 267 // set_varptr ("zsk_algo", &cp->z_algo, cp2 ? &cp2->z_algo: NULL); 268 set_varptr ("zsk_algo", &cp->k2_algo, cp2 ? &cp2->k2_algo: NULL); 269 set_varptr ("zsk_bits", &cp->z_bits, cp2 ? &cp2->z_bits: NULL); 270 set_varptr ("zsk_randfile", &cp->z_random, cp2 ? &cp2->z_random: NULL); 271 set_varptr ("nsec3", &cp->nsec3, cp2 ? &cp2->nsec3: NULL); 272 set_varptr ("saltbits", &cp->saltbits, cp2 ? &cp2->saltbits: NULL); 273 274 set_varptr ("--view", &cp->view, cp2 ? &cp2->view: NULL); 275 set_varptr ("--noexec", &cp->noexec, cp2 ? &cp2->noexec: NULL); 276 set_varptr ("logfile", &cp->logfile, cp2 ? &cp2->logfile: NULL); 277 set_varptr ("loglevel", &cp->loglevel, cp2 ? &cp2->loglevel: NULL); 278 set_varptr ("logdomaindir", &cp->logdomaindir, cp2 ? &cp2->logdomaindir: NULL); 279 set_varptr ("syslogfacility", &cp->syslogfacility, cp2 ? &cp2->syslogfacility: NULL); 280 set_varptr ("sysloglevel", &cp->sysloglevel, cp2 ? &cp2->sysloglevel: NULL); 281 set_varptr ("verboselog", &cp->verboselog, cp2 ? &cp2->verboselog: NULL); 282 set_varptr ("-v", &cp->verbosity, cp2 ? &cp2->verbosity: NULL); 283 set_varptr ("keyfile", &cp->keyfile, cp2 ? &cp2->keyfile: NULL); 284 set_varptr ("zonefile", &cp->zonefile, cp2 ? &cp2->zonefile: NULL); 285 set_varptr ("keysetdir", &cp->keysetdir, cp2 ? &cp2->keysetdir: NULL); 286 set_varptr ("dlv_domain", &cp->lookaside, cp2 ? &cp2->lookaside: NULL); 287 set_varptr ("sig_randfile", &cp->sig_random, cp2 ? &cp2->sig_random: NULL); 288 set_varptr ("sig_pseudorand", &cp->sig_pseudo, cp2 ? &cp2->sig_pseudo: NULL); 289 set_varptr ("sig_generateds", &cp->sig_gends, cp2 ? &cp2->sig_gends: NULL); 290 set_varptr ("sig_dnskeyksk", &cp->sig_dnskeyksk, cp2 ? &cp2->sig_dnskeyksk: NULL); 291 set_varptr ("sig_parameter", &cp->sig_param, cp2 ? &cp2->sig_param: NULL); 292 set_varptr ("distribute_cmd", &cp->dist_cmd, cp2 ? &cp2->dist_cmd: NULL); 293 set_varptr ("namedchrootdir", &cp->chroot_dir, cp2 ? &cp2->chroot_dir: NULL); 294} 295 296static void parseconfigline (char *buf, unsigned int line, zconf_t *z) 297{ 298 char *end, *val, *p; 299 char *tag; 300 unsigned int len, found; 301 zconf_para_t *c; 302 303 assert (buf[0] != '\0'); 304 305 p = &buf[strlen(buf)-1]; /* Chop off white space at eol */ 306 while ( p >= buf && isspace (*p) ) 307 *p-- = '\0'; 308 309 for (p = buf; isspace (*p); p++ ) /* Ignore leading white space */ 310 ; 311 312 /* Ignore comments and emtpy lines */ 313 if ( *p == '\0' || ISCOMMENT (p) ) 314 return; 315 316 tag = p; 317 /* Get the end of the first argument */ 318 end = &buf[strlen(buf)-1]; 319 while ( p < end && !ISDELIM (*p) ) /* Skip until delim */ 320 p++; 321 *p++ = '\0'; /* Terminate this argument */ 322 dbg_val1 ("Parsing \"%s\"\n", tag); 323 324 while ( p < end && ISDELIM (*p) ) /* Skip delim chars */ 325 p++; 326 327 val = p; /* Start of the value */ 328 dbg_val1 ("\tgot value \"%s\"\n", val); 329 330 /* If starting with quote, skip until next quote */ 331 if ( *p == '"' || *p == '\'' ) 332 { 333 p++; /* Find next quote */ 334 while ( p <= end && *p && *p != *val ) 335 p++; 336 *p = '\0'; 337 val++; /* Skip the first quote */ 338 } 339 else /* Otherwise check if there is any comment char at the end */ 340 { 341 while ( p < end && *p && !ISCOMMENT(p) ) 342 p++; 343 if ( ISCOMMENT (p) ) 344 { 345 do /* Chop off white space before comment */ 346 *p-- = '\0'; 347 while ( p >= val && isspace (*p) ); 348 } 349 } 350 351 /* Otherwise it is already terminated above */ 352 found = 0; 353 c = confpara; 354 while ( !found && c->type != CONF_END ) 355 { 356 len = strlen (c->label); 357 if ( strcasecmp (tag, c->label) == 0 ) 358 { 359 char **str; 360 char quantity; 361 long lval; 362 363 found = 1; 364 switch ( c->type ) 365 { 366 case CONF_VERSION: 367 break; 368 case CONF_LEVEL: 369 case CONF_FACILITY: 370 case CONF_STRING: 371 str = (char **)c->var; 372 *str = strdup (val); 373 str_untaint (*str); /* remove "bad" characters */ 374 break; 375 case CONF_INT: 376 sscanf (val, "%d", (int *)c->var); 377 break; 378 case CONF_TIMEINT: 379 quantity = 'd'; 380 if ( *val == 'u' || *val == 'U' ) 381 lval = 0L; 382 else 383 sscanf (val, "%ld%c", &lval, &quantity); 384 if ( quantity == 'm' ) 385 lval *= MINSEC; 386 else if ( quantity == 'h' ) 387 lval *= HOURSEC; 388 else if ( quantity == 'd' ) 389 lval *= DAYSEC; 390 else if ( quantity == 'w' ) 391 lval *= WEEKSEC; 392 else if ( quantity == 'y' ) 393 lval *= YEARSEC; 394 (*(long *)c->var) = lval; 395 break; 396 case CONF_ALGO: 397 if ( strcmp (val, "1") == 0 || strcasecmp (val, "rsa") == 0 || 398 strcasecmp (val, "rsamd5") == 0 ) 399 *((int *)c->var) = DK_ALGO_RSA; 400 else if ( strcmp (val, "3") == 0 || 401 strcasecmp (val, "dsa") == 0 ) 402 *((int *)c->var) = DK_ALGO_DSA; 403 else if ( strcmp (val, "5") == 0 || 404 strcasecmp (val, "rsasha1") == 0 ) 405 *((int *)c->var) = DK_ALGO_RSASHA1; 406 else if ( strcmp (val, "6") == 0 || 407 strcasecmp (val, "nsec3dsa") == 0 || 408 strcasecmp (val, "n3dsa") == 0 ) 409 *((int *)c->var) = DK_ALGO_NSEC3DSA; 410 else if ( strcmp (val, "7") == 0 || 411 strcasecmp (val, "nsec3rsasha1") == 0 || 412 strcasecmp (val, "n3rsasha1") == 0 ) 413 *((int *)c->var) = DK_ALGO_NSEC3RSASHA1; 414#if defined(BIND_VERSION) && BIND_VERSION >= 970 415 else if ( strcmp (val, "8") == 0 || 416 strcasecmp (val, "rsasha2") == 0 || 417 strcasecmp (val, "rsasha256") == 0 || 418 strcasecmp (val, "nsec3rsasha2") == 0 || 419 strcasecmp (val, "n3rsasha2") == 0 || 420 strcasecmp (val, "nsec3rsasha256") == 0 || 421 strcasecmp (val, "n3rsasha256") == 0 ) 422 *((int *)c->var) = DK_ALGO_RSASHA256; 423 else if ( strcmp (val, "10") == 0 || 424 strcasecmp (val, "rsasha5") == 0 || 425 strcasecmp (val, "rsasha212") == 0 || 426 strcasecmp (val, "nsec3rsasha5") == 0 || 427 strcasecmp (val, "n3rsasha5") == 0 || 428 strcasecmp (val, "nsec3rsasha512") == 0 || 429 strcasecmp (val, "n3rsasha512") == 0 ) 430 *((int *)c->var) = DK_ALGO_RSASHA512; 431#endif 432 else 433 error ("Illegal algorithm \"%s\" " 434 "in line %d.\n" , val, line); 435 break; 436 case CONF_SERIAL: 437 if ( strcasecmp (val, "unixtime") == 0 ) 438 *((serial_form_t *)c->var) = Unixtime; 439 else if ( strcasecmp (val, "incremental") == 0 || strcasecmp (val, "inc") == 0 ) 440 *((serial_form_t *)c->var) = Incremental; 441 else 442 error ("Illegal serial no format \"%s\" " 443 "in line %d.\n" , val, line); 444 break; 445 case CONF_NSEC3: 446 if ( strcasecmp (val, "off") == 0 ) 447 *((nsec3_t *)c->var) = NSEC3_OFF; 448 else if ( strcasecmp (val, "on") == 0 ) 449 *((nsec3_t *)c->var) = NSEC3_ON; 450 else if ( strcasecmp (val, "optout") == 0 ) 451 *((nsec3_t *)c->var) = NSEC3_OPTOUT; 452 else 453 error ("Illegal NSEC3 format \"%s\" " 454 "in line %d.\n" , val, line); 455 break; 456 case CONF_BOOL: 457 *((int *)c->var) = ISTRUE (val); 458 break; 459 default: 460 fatal ("Illegal configuration type in line %d.\n", line); 461 } 462 } 463 c++; 464 } 465 if ( !found ) 466 error ("Unknown configuration statement: %s \"%s\"\n", tag, val); 467 return; 468} 469 470static void printconfigline (FILE *fp, zconf_para_t *cp) 471{ 472 int i; 473 long lval; 474 475 assert (fp != NULL); 476 assert (cp != NULL); 477 478 switch ( cp->type ) 479 { 480 case CONF_VERSION: 481 fprintf (fp, "#\tZKT config file for version %d.%02d\n", 482 compversion / 100, compversion % 100); 483 break; 484 case CONF_COMMENT: 485 if ( cp->var ) 486 fprintf (fp, "# %s\n", (char *)cp->var); 487 else 488 fprintf (fp, "\n"); 489 break; 490 case CONF_LEVEL: 491 case CONF_FACILITY: 492 if ( *(char **)cp->var != NULL ) 493 { 494 if ( **(char **)cp->var != '\0' ) 495 { 496 char *p; 497 498 fprintf (fp, "%s:\t", cp->label); 499 for ( p = *(char **)cp->var; *p; p++ ) 500 putc (toupper (*p), fp); 501 fprintf (fp, "\n"); 502 } 503 else 504 fprintf (fp, "%s:\tNONE", cp->label); 505 } 506 break; 507 case CONF_STRING: 508 if ( *(char **)cp->var ) 509 fprintf (fp, "%s:\t\"%s\"\n", cp->label, *(char **)cp->var); 510 break; 511 case CONF_BOOL: 512 fprintf (fp, "%s:\t%s\n", cp->label, bool2str ( *(int*)cp->var )); 513 break; 514 case CONF_TIMEINT: 515 lval = *(ulong*)cp->var; /* in that case it should be of type ulong */ 516 fprintf (fp, "%s:\t%s", cp->label, timeint2str (lval)); 517 if ( lval ) 518 fprintf (fp, "\t\t# (%ld seconds)", lval); 519 putc ('\n', fp); 520 break; 521 case CONF_ALGO: 522 i = *(int*)cp->var; 523 if ( i ) 524 { 525 fprintf (fp, "%s:\t%s ", cp->label, dki_algo2str (i)); 526 fprintf (fp, "\t# (Algorithm ID %d)\n", i); 527 } 528 break; 529 case CONF_SERIAL: 530 fprintf (fp, "%s:\t", cp->label); 531 if ( *(serial_form_t*)cp->var == Unixtime ) 532 fprintf (fp, "UnixTime"); 533 else 534 fprintf (fp, "Incremental"); 535 fprintf (fp, "\t# (UnixTime|Incremental)\n"); 536 break; 537 case CONF_NSEC3: 538 fprintf (fp, "%s:\t\t", cp->label); 539 if ( *(nsec3_t*)cp->var == NSEC3_OFF ) 540 fprintf (fp, "Off"); 541 else if ( *(nsec3_t*)cp->var == NSEC3_ON ) 542 fprintf (fp, "On"); 543 else if ( *(nsec3_t*)cp->var == NSEC3_OPTOUT ) 544 fprintf (fp, "OptOut"); 545 fprintf (fp, "\t\t# (On|Off|OptOut)\n"); 546 break; 547 case CONF_INT: 548 fprintf (fp, "%s:\t%d\n", cp->label, *(int *)cp->var); 549 break; 550 case CONF_END: 551 /* NOTREACHED */ 552 break; 553 } 554} 555 556/***************************************************************** 557** public function definition 558*****************************************************************/ 559 560void setconfigversion (int version) 561{ 562 compversion = version; 563} 564 565const char *timeint2str (unsigned long val) 566{ 567 static char str[20+1]; 568 569 if ( val == 0 ) 570 snprintf (str, sizeof (str), "Unset"); 571 else if ( val % YEARSEC == 0 ) 572 snprintf (str, sizeof (str), "%luy", val / YEARSEC); 573 else if ( val % WEEKSEC == 0 ) 574 snprintf (str, sizeof (str), "%luw", val / WEEKSEC); 575 else if ( val % DAYSEC == 0 ) 576 snprintf (str, sizeof (str), "%lud", val / DAYSEC); 577 else if ( val % HOURSEC == 0 ) 578 snprintf (str, sizeof (str), "%luh", val / HOURSEC); 579 else if ( val % MINSEC == 0 ) 580 snprintf (str, sizeof (str), "%lum", val / MINSEC); 581 else 582 snprintf (str, sizeof (str), "%lus", val); 583 584 return str; 585} 586 587 588/***************************************************************** 589** loadconfig (file, conf) 590** Loads a config file into the "conf" structure pointed to by "z". 591** If "z" is NULL then a new conf struct will be dynamically 592** allocated. 593** If no filename is given the conf struct will be initialized 594** with the builtin default config 595*****************************************************************/ 596zconf_t *loadconfig (const char *filename, zconf_t *z) 597{ 598 FILE *fp; 599 char buf[1023+1]; 600 unsigned int line; 601 602 if ( z == NULL ) /* allocate new memory for zconf_t */ 603 { 604 if ( (z = calloc (1, sizeof (zconf_t))) == NULL ) 605 return NULL; 606 607 if ( filename && *filename ) 608 memcpy (z, &def, sizeof (zconf_t)); /* init new struct with defaults */ 609 } 610 611 if ( filename == NULL || *filename == '\0' ) /* no file name given... */ 612 { 613 dbg_val0("loadconfig (NULL)\n"); 614 memcpy (z, &def, sizeof (zconf_t)); /* ..then init with defaults */ 615 return z; 616 } 617 618 dbg_val1 ("loadconfig (%s)\n", filename); 619 set_all_varptr (z, NULL); 620 621 if ( (fp = fopen(filename, "r")) == NULL ) 622 fatal ("Could not open config file \"%s\"\n", filename); 623 624 line = 0; 625 while (fgets(buf, sizeof(buf), fp)) 626 parseconfigline (buf, ++line, z); 627 628 fclose(fp); 629 return z; 630} 631 632# define STRCONFIG_DELIMITER ";\r\n" 633zconf_t *loadconfig_fromstr (const char *str, zconf_t *z) 634{ 635 char *buf; 636 char *tok, *toksave; 637 unsigned int line; 638 639 if ( z == NULL ) 640 { 641 if ( (z = calloc (1, sizeof (zconf_t))) == NULL ) 642 return NULL; 643 memcpy (z, &def, sizeof (zconf_t)); /* init with defaults */ 644 } 645 646 if ( str == NULL || *str == '\0' ) 647 { 648 dbg_val0("loadconfig_fromstr (NULL)\n"); 649 memcpy (z, &def, sizeof (zconf_t)); /* init with defaults */ 650 return z; 651 } 652 653 dbg_val1 ("loadconfig_fromstr (\"%s\")\n", str); 654 set_all_varptr (z, NULL); 655 656 /* str is const, so we have to copy it into a new buffer */ 657 if ( (buf = strdup (str)) == NULL ) 658 fatal ("loadconfig_fromstr: Out of memory"); 659 660 line = 0; 661 tok = strtok_r (buf, STRCONFIG_DELIMITER, &toksave); 662 while ( tok ) 663 { 664 line++; 665 parseconfigline (tok, line, z); 666 tok = strtok_r (NULL, STRCONFIG_DELIMITER, &toksave); 667 } 668 free (buf); 669 return z; 670} 671 672/***************************************************************** 673** dupconfig (config) 674** duplicate config struct and return a ptr to the new struct 675*****************************************************************/ 676zconf_t *dupconfig (const zconf_t *conf) 677{ 678 zconf_t *z; 679 680 assert (conf != NULL); 681 682 if ( (z = calloc (1, sizeof (zconf_t))) == NULL ) 683 return NULL; 684 685 memcpy (z, conf, sizeof (zconf_t)); 686 687 return z; 688} 689 690/***************************************************************** 691** freeconfig (config) 692** free memory for config struct and return a NULL ptr 693*****************************************************************/ 694zconf_t *freeconfig (zconf_t *conf) 695{ 696 if (conf != NULL); 697 free (conf); 698 699 return (zconf_t *)NULL; 700} 701 702/***************************************************************** 703** setconfigpar (entry, pval) 704*****************************************************************/ 705int setconfigpar (zconf_t *config, char *entry, const void *pval) 706{ 707 char *str; 708 zconf_para_t *c; 709 710 set_all_varptr (config, NULL); 711 712 for ( c = confpara; c->type != CONF_END; c++ ) 713 if ( strcasecmp (entry, c->label) == 0 ) 714 { 715 switch ( c->type ) 716 { 717 case CONF_VERSION: 718 break; 719 case CONF_LEVEL: 720 case CONF_FACILITY: 721 case CONF_STRING: 722 if ( pval ) 723 { 724 str = strdup ((char *)pval); 725 str_untaint (str); /* remove "bad" characters */ 726 } 727 else 728 str = NULL; 729 *((char **)c->var) = str; 730 break; 731 case CONF_BOOL: 732 /* fall through */ 733 case CONF_ALGO: 734 /* fall through */ 735 case CONF_INT: 736 *((int *)c->var) = *((int *)pval); 737 break; 738 case CONF_TIMEINT: 739 *((long *)c->var) = *((long *)pval); 740 break; 741 case CONF_NSEC3: 742 *((nsec3_t *)c->var) = *((nsec3_t *)pval); 743 break; 744 case CONF_SERIAL: 745 *((serial_form_t *)c->var) = *((serial_form_t *)pval); 746 break; 747 case CONF_COMMENT: 748 case CONF_END: 749 /* NOTREACHED */ 750 break; 751 } 752 return 1; 753 } 754 return 0; 755} 756 757/***************************************************************** 758** printconfig (fname, config) 759*****************************************************************/ 760int printconfig (const char *fname, const zconf_t *z) 761{ 762 zconf_para_t *cp; 763 FILE *fp; 764 765 if ( z == NULL ) 766 return 0; 767 768 fp = stdout; 769 if ( fname && *fname ) 770 { 771 if ( strcmp (fname, "stdout") == 0 ) 772 fp = stdout; 773 else if ( strcmp (fname, "stderr") == 0 ) 774 fp = stderr; 775 else if ( (fp = fopen(fname, "w")) == NULL ) 776 { 777 error ("Could not open config file \"%s\" for writing\n", fname); 778 return -1; 779 } 780 } 781 782 set_all_varptr ((zconf_t *)z, NULL); 783 784 for ( cp = confpara; cp->type != CONF_END; cp++ ) /* loop through all parameter */ 785 if ( iscompatible (cp) ) /* is parameter compatible to current version? */ 786 printconfigline (fp, cp); /* print it out */ 787 788 if ( fp && fp != stdout && fp != stderr ) 789 fclose (fp); 790 791 return 1; 792} 793 794/***************************************************************** 795** printconfigdiff (fname, conf_a, conf_b) 796*****************************************************************/ 797int printconfigdiff (const char *fname, const zconf_t *ref, const zconf_t *z) 798{ 799 zconf_para_t *cp; 800 int eq; 801 char *p1, *p2; 802 FILE *fp; 803 804 if ( ref == NULL || z == NULL ) 805 return 0; 806 807 fp = NULL; 808 if ( fname && *fname ) 809 { 810 if ( strcmp (fname, "stdout") == 0 ) 811 fp = stdout; 812 else if ( strcmp (fname, "stderr") == 0 ) 813 fp = stderr; 814 else if ( (fp = fopen(fname, "w")) == NULL ) 815 { 816 error ("Could not open config file \"%s\" for writing\n", fname); 817 return -1; 818 } 819 } 820 821 set_all_varptr ((zconf_t *)z, ref); 822 823 for ( cp = confpara; cp->type != CONF_END; cp++ ) /* loop through all parameter */ 824 { 825 eq = 0; 826 if ( iscmdline (cp) ) /* skip command line parameter */ 827 continue; 828 829 switch ( cp->type ) 830 { 831 case CONF_VERSION: 832 case CONF_END: 833 case CONF_COMMENT: 834 continue; 835 case CONF_NSEC3: 836 eq = ( *(nsec3_t *)cp->var == *(nsec3_t *)cp->var2 ); 837 break; 838 case CONF_SERIAL: 839 eq = ( *(serial_form_t *)cp->var == *(serial_form_t *)cp->var2 ); 840 break; 841 case CONF_BOOL: 842 case CONF_ALGO: 843 case CONF_INT: 844 eq = ( *(int *)cp->var == *(int *)cp->var2 ); 845 break; 846 case CONF_TIMEINT: 847 eq = ( *(long *)cp->var == *(long *)cp->var2 ); 848 break; 849 case CONF_LEVEL: 850 case CONF_FACILITY: 851 case CONF_STRING: 852 p1 = *(char **)cp->var; 853 p2 = *(char **)cp->var2; 854 if ( p1 && p2 ) 855 eq = strcmp (p1, p2) == 0; 856 else if ( p1 == NULL || p2 == NULL ) 857 eq = 0; 858 else 859 eq = 1; 860 } 861 if ( !eq ) 862 printconfigline (fp, cp); /* print it out */ 863 } 864 865 if ( fp && fp != stdout && fp != stderr ) 866 fclose (fp); 867 868 return 1; 869} 870 871/***************************************************************** 872** checkconfig (config) 873*****************************************************************/ 874int checkconfig (const zconf_t *z) 875{ 876 int ret; 877 long max_ttl; 878 879 if ( z == NULL ) 880 return 1; 881 882 max_ttl = z->max_ttl; 883 if ( max_ttl <= 0 ) 884 max_ttl = z->sigvalidity; 885 886 ret = 0; 887 if ( strcmp (z->k_random, "/dev/urandom") == 0 ) 888 ret = fprintf (stderr, "random device without enough entropie used for KSK generation \n"); 889 if ( strcmp (z->z_random, "/dev/urandom") == 0 ) 890 ret = fprintf (stderr, "random device without enough entropie used for ZSK generation\n"); 891 892 if ( z->saltbits < 4 ) 893 ret = fprintf (stderr, "Saltlength must be at least 4 bits\n"); 894 if ( z->saltbits > 128 ) 895 { 896 fprintf (stderr, "While the maximum is 520 bits of salt, it's not recommended to use more than 128 bits.\n"); 897 ret = fprintf (stderr, "The current value is %d bits\n", z->saltbits); 898 } 899 900 if ( z->sigvalidity < (1 * DAYSEC) || z->sigvalidity > (12 * WEEKSEC) ) 901 { 902 fprintf (stderr, "Signature should be valid for at least 1 day and no longer than 3 month (12 weeks)\n"); 903 ret = fprintf (stderr, "The current value is %s\n", timeint2str (z->sigvalidity)); 904 } 905 906 if ( z->max_ttl <= 0 ) 907 { 908 ret = fprintf (stderr, "The max TTL is unknown which results in suboptimal key rollover.\n"); 909 fprintf (stderr, "Please set max_ttl to the maximum ttl used in the zone (run zkt-conf -w zone.db)\n"); 910 } 911 else 912 if ( max_ttl > z->sigvalidity/2 ) 913 ret = fprintf (stderr, "Max TTL (%ld) should be less or equal signature validity (%ld)\n", 914 max_ttl, z->sigvalidity); 915 916 // if ( z->resign > (z->sigvalidity*5/6) - (max_ttl + z->proptime) ) 917 if ( z->resign > (z->sigvalidity*5/6) ) 918 { 919 fprintf (stderr, "Re-signing interval (%s) should be less than ", timeint2str (z->resign)); 920 ret = fprintf (stderr, "5/6 of sigvalidity (%s)\n", timeint2str (z->sigvalidity)); 921 } 922 923 if ( z->max_ttl > 0 && z->resign > (z->sigvalidity - max_ttl) ) 924 { 925 fprintf (stderr, "Re-signing interval (%s) should be ", timeint2str (z->resign)); 926 fprintf (stderr, "end at least one max_ttl (%ld) before the end of ", max_ttl); 927 ret = fprintf (stderr, "signature lifetime (%ld) (%s)\n", z->sigvalidity, timeint2str(z->sigvalidity - max_ttl)); 928 } 929 930 if ( z->z_life > (12 * WEEKSEC) * (z->z_bits / 512.) ) 931 { 932 fprintf (stderr, "Lifetime of zone signing key (%s) ", timeint2str (z->z_life)); 933 fprintf (stderr, "seems a little bit high "); 934 ret = fprintf (stderr, "(In respect of key size (%d))\n", z->z_bits); 935 } 936 937 if ( z->k_life > 0 && z->k_life <= z->z_life ) 938 { 939 fprintf (stderr, "Lifetime of key signing key (%s) ", timeint2str (z->k_life)); 940 ret = fprintf (stderr, "should be greater than lifetime of zsk\n"); 941 } 942 if ( z->k_life > 0 && z->k_life > (26 * WEEKSEC) * (z->k_bits / 512.) ) 943 { 944 fprintf (stderr, "Lifetime of key signing key (%s) ", timeint2str (z->k_life)); 945 fprintf (stderr, "seems a little bit high "); 946 ret = fprintf (stderr, "(In respect of key size (%d))\n", z->k_bits); 947 } 948 949 return !ret; 950} 951 952#ifdef CONF_TEST 953const char *progname; 954static zconf_t *config; 955 956main (int argc, char *argv[]) 957{ 958 char *optstr; 959 int val; 960 961 progname = *argv; 962 963 config = loadconfig ("", (zconf_t *) NULL); /* load built in defaults */ 964 965 while ( --argc >= 1 ) 966 { 967 optstr = *++argv; 968 config = loadconfig_fromstr (optstr, config); 969 } 970 971 val = 1; 972 setconfigpar (config, "-v", &val); 973 val = 2; 974 setconfigpar (config, "verboselog", &val); 975 val = 1; 976 setconfigpar (config, "recursive", &val); 977 val = 1200; 978 setconfigpar (config, "propagation", &val); 979 980 printconfig ("stdout", config); 981} 982#endif 983