OpenDNSSEC-signer  2.1.10
signconf.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2009 NLNet Labs. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
19  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
21  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
22  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
23  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  */
26 
32 #include "parser/signconfparser.h"
33 #include "duration.h"
34 #include "file.h"
35 #include "log.h"
36 #include "status.h"
37 #include "signer/signconf.h"
38 
39 static const char* sc_str = "signconf";
40 
41 
48 {
49  signconf_type* sc = NULL;
50  CHECKALLOC(sc = (signconf_type*) malloc(sizeof(signconf_type)));
51  sc->filename = NULL;
52  sc->passthrough = 0;
53  /* Signatures */
54  sc->sig_resign_interval = NULL;
55  sc->sig_refresh_interval = NULL;
56  sc->sig_validity_default = NULL;
57  sc->sig_validity_denial = NULL;
58  sc->sig_validity_keyset = NULL;
59  sc->sig_jitter = NULL;
60  sc->sig_inception_offset = NULL;
61  /* Denial of existence */
62  sc->nsec3param_ttl = NULL;
63  sc->nsec_type = 0;
64  sc->nsec3_optout = 0;
65  sc->nsec3_algo = 0;
66  sc->nsec3_iterations = 0;
67  sc->nsec3_salt = NULL;
68  sc->nsec3params = NULL;
69  /* Keys */
70  sc->dnskey_ttl = NULL;
71  sc->dnskey_signature = NULL;
72  sc->keys = NULL;
73  /* Source of authority */
74  sc->soa_ttl = NULL;
75  sc->soa_min = NULL;
76  sc->soa_serial = NULL;
77  /* Other useful information */
78  sc->max_zone_ttl = NULL;
79  sc->last_modified = 0;
80  return sc;
81 }
82 
83 
88 static ods_status
89 signconf_read(signconf_type* signconf, const char* scfile)
90 {
91  const char* rngfile = ODS_SE_RNGDIR "/signconf.rng";
92  ods_status status = ODS_STATUS_OK;
93  FILE* fd = NULL;
94 
95  if (!scfile || !signconf) {
96  return ODS_STATUS_ASSERT_ERR;
97  }
98  ods_log_debug("[%s] read signconf file %s", sc_str, scfile);
99  status = parse_file_check(scfile, rngfile);
100  if (status != ODS_STATUS_OK) {
101  ods_log_error("[%s] unable to read signconf: parse error in "
102  "file %s (%s)", sc_str, scfile, ods_status2str(status));
103  return status;
104  }
105  fd = ods_fopen(scfile, NULL, "r");
106  if (fd) {
107  signconf->filename = strdup(scfile);
108  signconf->passthrough = parse_sc_passthrough(scfile);
114  signconf->sig_jitter = parse_sc_sig_jitter(scfile);
116  signconf->nsec_type = parse_sc_nsec_type(scfile);
117  if (signconf->nsec_type == LDNS_RR_TYPE_NSEC3) {
118  signconf->nsec3param_ttl = parse_sc_nsec3param_ttl(scfile);
119  signconf->nsec3_optout = parse_sc_nsec3_optout(scfile);
120  signconf->nsec3_algo = parse_sc_nsec3_algorithm(scfile);
121  signconf->nsec3_iterations = parse_sc_nsec3_iterations(scfile);
122  signconf->nsec3_salt = parse_sc_nsec3_salt(scfile);
123  signconf->nsec3params = nsec3params_create((void*) signconf,
124  (uint8_t) signconf->nsec3_algo, (uint8_t) signconf->nsec3_optout,
125  (uint16_t)signconf->nsec3_iterations, signconf->nsec3_salt);
126  if (!signconf->nsec3params) {
127  ods_log_error("[%s] unable to read signconf %s: "
128  "nsec3params_create() failed", sc_str, scfile);
129  ods_fclose(fd);
130  return ODS_STATUS_MALLOC_ERR;
131  }
132  }
133  signconf->keys = parse_sc_keys((void*) signconf, scfile);
134  signconf->dnskey_ttl = parse_sc_dnskey_ttl(scfile);
135  signconf->dnskey_signature = parse_sc_dnskey_sigrrs(scfile);
136  signconf->soa_ttl = parse_sc_soa_ttl(scfile);
137  signconf->soa_min = parse_sc_soa_min(scfile);
138  signconf->soa_serial = parse_sc_soa_serial(scfile);
139  signconf->max_zone_ttl = parse_sc_max_zone_ttl(scfile);
140  ods_fclose(fd);
141  return ODS_STATUS_OK;
142  }
143  ods_log_error("[%s] unable to read signconf: failed to open file %s",
144  sc_str, scfile);
145  return ODS_STATUS_ERR;
146 }
147 
148 
153 ods_status
154 signconf_update(signconf_type** signconf, const char* scfile,
155  time_t last_modified)
156 {
157  signconf_type* new_sc = NULL;
158  time_t st_mtime = 0;
159  ods_status status = ODS_STATUS_OK;
160 
161  if (!scfile || !signconf) {
162  return ODS_STATUS_UNCHANGED;
163  }
164  /* is the file updated? */
165  st_mtime = ods_file_lastmodified(scfile);
166  if (st_mtime <= last_modified) {
167  return ODS_STATUS_UNCHANGED;
168  }
169  /* if so, read the new signer configuration */
170  new_sc = signconf_create();
171  if (!new_sc) {
172  ods_log_error("[%s] unable to update signconf: signconf_create() "
173  "failed", sc_str);
174  return ODS_STATUS_ERR;
175  }
176  status = signconf_read(new_sc, scfile);
177  if (status == ODS_STATUS_OK) {
178  new_sc->last_modified = st_mtime;
179  if (signconf_check(new_sc) != ODS_STATUS_OK) {
180  ods_log_error("[%s] unable to update signconf: signconf %s has "
181  "errors", sc_str, scfile);
182  signconf_cleanup(new_sc);
183  return ODS_STATUS_CFG_ERR;
184  }
185  *signconf = new_sc;
186  } else {
187  ods_log_error("[%s] unable to update signconf: failed to read file "
188  "%s (%s)", sc_str, scfile, ods_status2str(status));
189  signconf_cleanup(new_sc);
190  }
191  return status;
192 }
193 
194 
199 static void
200 signconf_backup_duration(FILE* fd, const char* opt, duration_type* duration)
201 {
202  char* str = (duration == NULL ? NULL : duration2string(duration));
203  fprintf(fd, "%s %s ", opt, (str?str:"0"));
204  free(str);
205 }
206 
207 
208 
213 void
214 signconf_backup(FILE* fd, signconf_type* sc, const char* version)
215 {
216  if (!fd || !sc) {
217  return;
218  }
219  fprintf(fd, ";;Signconf: lastmod %u ", (unsigned) sc->last_modified);
220  if (strcmp(version, ODS_SE_FILE_MAGIC_V2) &&
221  strcmp(version, ODS_SE_FILE_MAGIC_V1)) {
222  /* version 3 and up */
223  fprintf(fd, "maxzonettl 0 "); /* prepare for enforcer ng */
224  }
225  signconf_backup_duration(fd, "resign", sc->sig_resign_interval);
226  signconf_backup_duration(fd, "refresh", sc->sig_refresh_interval);
227  signconf_backup_duration(fd, "valid", sc->sig_validity_default);
228  signconf_backup_duration(fd, "denial", sc->sig_validity_denial);
229  signconf_backup_duration(fd, "keyset", sc->sig_validity_keyset);
230  signconf_backup_duration(fd, "jitter", sc->sig_jitter);
231  signconf_backup_duration(fd, "offset", sc->sig_inception_offset);
232  fprintf(fd, "nsec %u ", (unsigned) sc->nsec_type);
233  signconf_backup_duration(fd, "dnskeyttl", sc->dnskey_ttl);
234  signconf_backup_duration(fd, "soattl", sc->soa_ttl);
235  signconf_backup_duration(fd, "soamin", sc->soa_min);
236  fprintf(fd, "serial %s ", sc->soa_serial?sc->soa_serial:"(null)");
237  if (strcmp(version, ODS_SE_FILE_MAGIC_V2) == 0) {
238  fprintf(fd, "audit 0");
239  }
240  fprintf(fd, "\n");
241 }
242 
243 
248 static int
249 signconf_soa_serial_check(const char* serial) {
250  if (!serial) {
251  return 1;
252  }
253 
254  if (strlen(serial) == 4 && strncmp(serial, "keep", 4) == 0) {
255  return 0;
256  }
257  if (strlen(serial) == 7 && strncmp(serial, "counter", 7) == 0) {
258  return 0;
259  }
260  if (strlen(serial) == 8 && strncmp(serial, "unixtime", 8) == 0) {
261  return 0;
262  }
263  if (strlen(serial) == 11 && strncmp(serial, "datecounter", 11) == 0) {
264  return 0;
265  }
266  return 1;
267 }
268 
269 
274 ods_status
276 {
277  ods_status status = ODS_STATUS_OK;
278 
279  if (!sc->sig_resign_interval) {
280  ods_log_error("[%s] check failed: no signature resign interval found",
281  sc_str);
282  status = ODS_STATUS_CFG_ERR;
283  }
284  if (!sc->sig_refresh_interval) {
285  ods_log_error("[%s] check failed: no signature resign interval found",
286  sc_str);
287  status = ODS_STATUS_CFG_ERR;
288  }
289  if (!sc->sig_validity_default) {
290  ods_log_error("[%s] check failed: no signature default validity found",
291  sc_str);
292  status = ODS_STATUS_CFG_ERR;
293  }
294  if (!sc->sig_validity_denial) {
295  ods_log_error("[%s] check failed: no signature denial validity found",
296  sc_str);
297  status = ODS_STATUS_CFG_ERR;
298  }
299  if (!sc->sig_jitter) {
300  ods_log_error("[%s] check failed: no signature jitter found", sc_str);
301  status = ODS_STATUS_CFG_ERR;
302  }
303  if (!sc->sig_inception_offset) {
304  ods_log_error("[%s] check failed: no signature inception offset found",
305  sc_str);
306  status = ODS_STATUS_CFG_ERR;
307  }
308  if (sc->nsec_type == LDNS_RR_TYPE_NSEC3) {
309  if (sc->nsec3_algo != LDNS_SHA1) {
310  ods_log_error("[%s] check failed: invalid nsec3 algorithm",
311  sc_str);
312  status = ODS_STATUS_CFG_ERR;
313  }
314  /* iterations */
315  /* salt */
316  /* optout */
317  } else if (sc->nsec_type != LDNS_RR_TYPE_NSEC) {
318  ods_log_error("[%s] check failed: wrong nsec type %i", sc_str,
319  sc->nsec_type);
320  status = ODS_STATUS_CFG_ERR;
321  }
322  if ((!sc->keys || sc->keys->count == 0) && !sc->passthrough) {
323  ods_log_error("[%s] check failed: no keys found", sc_str);
324  status = ODS_STATUS_CFG_ERR;
325  }
326  if (!sc->dnskey_ttl) {
327  ods_log_error("[%s] check failed: no dnskey ttl found", sc_str);
328  status = ODS_STATUS_CFG_ERR;
329  }
330  if (!sc->soa_ttl) {
331  ods_log_error("[%s] check failed: no soa ttl found", sc_str);
332  status = ODS_STATUS_CFG_ERR;
333  }
334  if (!sc->soa_min) {
335  ods_log_error("[%s] check failed: no soa minimum found", sc_str);
336  status = ODS_STATUS_CFG_ERR;
337  }
338  if (!sc->soa_serial) {
339  ods_log_error("[%s] check failed: no soa serial type found", sc_str);
340  status = ODS_STATUS_CFG_ERR;
341  } else if (signconf_soa_serial_check(sc->soa_serial) != 0) {
342  ods_log_error("[%s] check failed: wrong soa serial type %s", sc_str,
343  sc->soa_serial);
344  status = ODS_STATUS_CFG_ERR;
345  }
346  return status;
347 }
348 
349 
354 task_id
356 {
357  task_id new_task = TASK_NONE;
358  if (!a || !b) {
359  return TASK_NONE;
360  }
361  ods_log_assert(a);
362  ods_log_assert(b);
363 
364  if (duration_compare(a->soa_min, b->soa_min)) {
365  new_task = TASK_NSECIFY;
366  } else if (a->nsec_type != b->nsec_type) {
367  new_task = TASK_NSECIFY;
368  } else if (a->nsec_type == LDNS_RR_TYPE_NSEC3) {
369  if ((ods_strcmp(a->nsec3_salt, b->nsec3_salt) != 0) ||
370  (a->nsec3_algo != b->nsec3_algo) ||
371  (a->nsec3_iterations != b->nsec3_iterations) ||
372  (a->nsec3_optout != b->nsec3_optout)) {
373 
374  new_task = TASK_NSECIFY;
375  } else if (duration_compare(a->nsec3param_ttl, b->nsec3param_ttl)) {
376  new_task = TASK_READ;
377  }
378  }
379  return new_task;
380 }
381 
382 
387 void
388 signconf_log(signconf_type* sc, const char* name)
389 {
390  char* resign = NULL;
391  char* refresh = NULL;
392  char* validity = NULL;
393  char* denial = NULL;
394  char* keyset = NULL;
395  char* jitter = NULL;
396  char* offset = NULL;
397  char* dnskeyttl = NULL;
398  char* soattl = NULL;
399  char* soamin = NULL;
400  char* paramttl = NULL;
401 
402  if (sc) {
403  resign = duration2string(sc->sig_resign_interval);
404  refresh = duration2string(sc->sig_refresh_interval);
405  validity = duration2string(sc->sig_validity_default);
406  denial = duration2string(sc->sig_validity_denial);
407  if (sc->sig_validity_keyset) {
408  keyset = duration2string(sc->sig_validity_keyset);
409  }
410  jitter = duration2string(sc->sig_jitter);
411  offset = duration2string(sc->sig_inception_offset);
412  dnskeyttl = duration2string(sc->dnskey_ttl);
413  paramttl = duration2string(sc->nsec3param_ttl);
414  soattl = duration2string(sc->soa_ttl);
415  soamin = duration2string(sc->soa_min);
416  /* signconf */
417  ods_log_info("[%s] zone %s signconf: RESIGN[%s] REFRESH[%s] "
418  "%sVALIDITY[%s] DENIAL[%s] KEYSET[%s] JITTER[%s] OFFSET[%s] NSEC[%i] "
419  "DNSKEYTTL[%s] SOATTL[%s] MINIMUM[%s] SERIAL[%s]",
420  sc_str,
421  name?name:"(null)",
422  resign?resign:"(null)",
423  refresh?refresh:"(null)",
424  sc->passthrough?"PASSTHROUGH ":"",
425  validity?validity:"(null)",
426  denial?denial:"(null)",
427  keyset?keyset:"(null)",
428  jitter?jitter:"(null)",
429  offset?offset:"(null)",
430  (int) sc->nsec_type,
431  dnskeyttl?dnskeyttl:"(null)",
432  soattl?soattl:"(null)",
433  soamin?soamin:"(null)",
434  sc->soa_serial?sc->soa_serial:"(null)");
435  /* nsec3 parameters */
436  if (sc->nsec_type == LDNS_RR_TYPE_NSEC3) {
437  ods_log_debug("[%s] zone %s nsec3: PARAMTTL[%s] OPTOUT[%i] "
438  "ALGORITHM[%u] ITERATIONS[%u] SALT[%s]",
439  sc_str,
440  name?name:"(null)",
441  paramttl?paramttl:"PT0S",
442  sc->nsec3_optout,
443  sc->nsec3_algo,
444  sc->nsec3_iterations,
445  sc->nsec3_salt?sc->nsec3_salt:"(null)");
446  }
447  /* keys */
448  keylist_log(sc->keys, name);
449  /* cleanup */
450  free((void*)resign);
451  free((void*)refresh);
452  free((void*)validity);
453  free((void*)denial);
454  free((void*)keyset);
455  free((void*)jitter);
456  free((void*)offset);
457  free((void*)dnskeyttl);
458  free((void*)paramttl);
459  free((void*)soattl);
460  free((void*)soamin);
461  }
462 }
463 
464 
469 void
471 {
472  if (!sc) {
473  return;
474  }
475  duration_cleanup(sc->sig_resign_interval);
476  duration_cleanup(sc->sig_refresh_interval);
477  duration_cleanup(sc->sig_validity_default);
478  duration_cleanup(sc->sig_validity_denial);
479  duration_cleanup(sc->sig_validity_keyset);
480  duration_cleanup(sc->sig_jitter);
481  duration_cleanup(sc->sig_inception_offset);
482  duration_cleanup(sc->dnskey_ttl);
483  duration_cleanup(sc->soa_ttl);
484  duration_cleanup(sc->soa_min);
485  duration_cleanup(sc->max_zone_ttl);
486  keylist_cleanup(sc->keys);
488  free((void*)sc->filename);
489  free((void*)sc->nsec3_salt);
490  free((void*)sc->soa_serial);
491  free(sc);
492 }
ods_status parse_file_check(const char *cfgfile, const char *rngfile)
Definition: confparser.c:55
void keylist_log(keylist_type *kl, const char *name)
Definition: keys.c:147
void keylist_cleanup(keylist_type *kl)
Definition: keys.c:183
void nsec3params_cleanup(nsec3params_type *nsec3params)
Definition: nsec3params.c:165
nsec3params_type * nsec3params_create(void *sc, uint8_t algo, uint8_t flags, uint16_t iter, const char *salt)
Definition: nsec3params.c:103
signconf_type * signconf_create(void)
Definition: signconf.c:47
void signconf_backup(FILE *fd, signconf_type *sc, const char *version)
Definition: signconf.c:214
task_id signconf_compare_denial(signconf_type *a, signconf_type *b)
Definition: signconf.c:355
ods_status signconf_check(signconf_type *sc)
Definition: signconf.c:275
ods_status signconf_update(signconf_type **signconf, const char *scfile, time_t last_modified)
Definition: signconf.c:154
void signconf_log(signconf_type *sc, const char *name)
Definition: signconf.c:388
void signconf_cleanup(signconf_type *sc)
Definition: signconf.c:470
duration_type * parse_sc_sig_resign_interval(const char *cfgfile)
duration_type * parse_sc_sig_jitter(const char *cfgfile)
int parse_sc_nsec3_optout(const char *cfgfile)
duration_type * parse_sc_sig_validity_default(const char *cfgfile)
duration_type * parse_sc_sig_validity_keyset(const char *cfgfile)
keylist_type * parse_sc_keys(void *sc, const char *cfgfile)
uint32_t parse_sc_nsec3_algorithm(const char *cfgfile)
duration_type * parse_sc_sig_validity_denial(const char *cfgfile)
duration_type * parse_sc_max_zone_ttl(const char *cfgfile)
duration_type * parse_sc_soa_min(const char *cfgfile)
uint32_t parse_sc_nsec3_iterations(const char *cfgfile)
int parse_sc_passthrough(const char *cfgfile)
duration_type * parse_sc_dnskey_ttl(const char *cfgfile)
duration_type * parse_sc_nsec3param_ttl(const char *cfgfile)
duration_type * parse_sc_sig_refresh_interval(const char *cfgfile)
const char * parse_sc_soa_serial(const char *cfgfile)
const char ** parse_sc_dnskey_sigrrs(const char *cfgfile)
duration_type * parse_sc_sig_inception_offset(const char *cfgfile)
const char * parse_sc_nsec3_salt(const char *cfgfile)
duration_type * parse_sc_soa_ttl(const char *cfgfile)
ldns_rr_type parse_sc_nsec_type(const char *cfgfile)
size_t count
Definition: keys.h:69
duration_type * soa_ttl
Definition: signconf.h:66
keylist_type * keys
Definition: signconf.h:64
duration_type * sig_jitter
Definition: signconf.h:51
duration_type * sig_refresh_interval
Definition: signconf.h:47
uint32_t nsec3_iterations
Definition: signconf.h:58
int nsec3_optout
Definition: signconf.h:56
duration_type * soa_min
Definition: signconf.h:67
const char * soa_serial
Definition: signconf.h:68
duration_type * nsec3param_ttl
Definition: signconf.h:54
duration_type * sig_resign_interval
Definition: signconf.h:46
time_t last_modified
Definition: signconf.h:72
nsec3params_type * nsec3params
Definition: signconf.h:60
ldns_rr_type nsec_type
Definition: signconf.h:55
duration_type * sig_inception_offset
Definition: signconf.h:52
const char ** dnskey_signature
Definition: signconf.h:63
const char * nsec3_salt
Definition: signconf.h:59
duration_type * sig_validity_keyset
Definition: signconf.h:50
const char * filename
Definition: signconf.h:71
duration_type * sig_validity_denial
Definition: signconf.h:49
duration_type * dnskey_ttl
Definition: signconf.h:62
duration_type * max_zone_ttl
Definition: signconf.h:70
uint32_t nsec3_algo
Definition: signconf.h:57
duration_type * sig_validity_default
Definition: signconf.h:48