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