OpenDNSSEC-signer 2.1.12
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
33#include "duration.h"
34#include "file.h"
35#include "log.h"
36#include "status.h"
37#include "signer/signconf.h"
38
39static 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
88static ods_status
89signconf_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);
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
153ods_status
154signconf_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
199static void
200signconf_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
213void
214signconf_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
248static int
249signconf_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
274ods_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
354task_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) ||
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
387void
388signconf_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,
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
469void
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);
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
nsec3params_type * nsec3params_create(void *sc, uint8_t algo, uint8_t flags, uint16_t iter, const char *salt)
Definition: nsec3params.c:103
void nsec3params_cleanup(nsec3params_type *nsec3params)
Definition: nsec3params.c:165
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
signconf_type * signconf_create(void)
Definition: signconf.c:47
duration_type * parse_sc_sig_validity_denial(const char *cfgfile)
const char * parse_sc_nsec3_salt(const char *cfgfile)
int parse_sc_nsec3_optout(const char *cfgfile)
duration_type * parse_sc_sig_resign_interval(const char *cfgfile)
duration_type * parse_sc_soa_min(const char *cfgfile)
const char ** parse_sc_dnskey_sigrrs(const char *cfgfile)
duration_type * parse_sc_sig_inception_offset(const char *cfgfile)
uint32_t parse_sc_nsec3_algorithm(const char *cfgfile)
duration_type * parse_sc_dnskey_ttl(const char *cfgfile)
keylist_type * parse_sc_keys(void *sc, const char *cfgfile)
uint32_t parse_sc_nsec3_iterations(const char *cfgfile)
duration_type * parse_sc_sig_validity_default(const char *cfgfile)
duration_type * parse_sc_max_zone_ttl(const char *cfgfile)
const char * parse_sc_soa_serial(const char *cfgfile)
int parse_sc_passthrough(const char *cfgfile)
duration_type * parse_sc_sig_jitter(const char *cfgfile)
duration_type * parse_sc_nsec3param_ttl(const char *cfgfile)
duration_type * parse_sc_sig_validity_keyset(const char *cfgfile)
duration_type * parse_sc_soa_ttl(const char *cfgfile)
ldns_rr_type parse_sc_nsec_type(const char *cfgfile)
duration_type * parse_sc_sig_refresh_interval(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