OpenDNSSEC-signer  2.0.4
signconfparser.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2009-2016 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/confparser.h"
33 #include "parser/signconfparser.h"
34 #include "duration.h"
35 #include "log.h"
36 
37 #include <libxml/parser.h>
38 #include <libxml/xpath.h>
39 #include <libxml/xpathInternals.h>
40 #include <libxml/xmlreader.h>
41 #include <stdlib.h>
42 
43 static const char* parser_str = "parser";
44 
45 
51 parse_sc_keys(void* sc, const char* cfgfile)
52 {
53  xmlDocPtr doc = NULL;
54  xmlXPathContextPtr xpathCtx = NULL;
55  xmlXPathObjectPtr xpathObj = NULL;
56  xmlNode* curNode = NULL;
57  xmlChar* xexpr = NULL;
58  key_type* new_key = NULL;
59  keylist_type* kl = NULL;
60  char* resourcerecord;
61  char* locator;
62  char* flags;
63  char* algorithm;
64  int configerr;
65  int ksk, zsk, publish, i;
66 
67  if (!cfgfile || !sc) {
68  return NULL;
69  }
70  /* Load XML document */
71  doc = xmlParseFile(cfgfile);
72  if (doc == NULL) {
73  ods_log_error("[%s] unable to parse <Keys>: "
74  "xmlParseFile() failed", parser_str);
75  return NULL;
76  }
77  /* Create xpath evaluation context */
78  xpathCtx = xmlXPathNewContext(doc);
79  if(xpathCtx == NULL) {
80  xmlFreeDoc(doc);
81  ods_log_error("[%s] unable to parse <Keys>: "
82  "xmlXPathNewContext() failed", parser_str);
83  return NULL;
84  }
85  /* Evaluate xpath expression */
86  xexpr = (xmlChar*) "//SignerConfiguration/Zone/Keys/Key";
87  xpathObj = xmlXPathEvalExpression(xexpr, xpathCtx);
88  if(xpathObj == NULL) {
89  xmlXPathFreeContext(xpathCtx);
90  xmlFreeDoc(doc);
91  ods_log_error("[%s] unable to parse <Keys>: "
92  "xmlXPathEvalExpression() failed", parser_str);
93  return NULL;
94  }
95  /* Parse keys */
96  kl = keylist_create(sc);
97  ods_log_assert(kl);
98  if (xpathObj->nodesetval && xpathObj->nodesetval->nodeNr > 0) {
99  for (i = 0; i < xpathObj->nodesetval->nodeNr; i++) {
100  resourcerecord = NULL;
101  locator = NULL;
102  flags = NULL;
103  algorithm = NULL;
104  ksk = 0;
105  zsk = 0;
106  publish = 0;
107  configerr = 0;
108 
109  curNode = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode;
110  while (curNode) {
111  if (xmlStrEqual(curNode->name, (const xmlChar *)"Locator")) {
112  locator = (char *) xmlNodeGetContent(curNode);
113  } else if (xmlStrEqual(curNode->name, (const xmlChar *)"Algorithm")) {
114  algorithm = (char *) xmlNodeGetContent(curNode);
115  } else if (xmlStrEqual(curNode->name, (const xmlChar *)"Flags")) {
116  flags = (char *) xmlNodeGetContent(curNode);
117  } else if (xmlStrEqual(curNode->name, (const xmlChar *)"KSK")) {
118  ksk = 1;
119  } else if (xmlStrEqual(curNode->name, (const xmlChar *)"ZSK")) {
120  zsk = 1;
121  } else if (xmlStrEqual(curNode->name, (const xmlChar *)"Publish")) {
122  publish = 1;
123  } else if (xmlStrEqual(curNode->name, (const xmlChar *)"ResourceRecord")) {
124  resourcerecord = (char *) xmlNodeGetContent(curNode);
125  }
126  curNode = curNode->next;
127  }
128  if (!algorithm)
129  configerr = 1;
130  if (!flags)
131  configerr = 1;
132  if (!locator && !resourcerecord)
133  configerr = 1;
134  if (!configerr) {
135  /* search for duplicates */
136  new_key = keylist_lookup_by_locator(kl, locator);
137  if (new_key &&
138  new_key->algorithm == (uint8_t) atoi(algorithm) &&
139  new_key->flags == (uint32_t) atoi(flags) &&
140  new_key->publish == publish &&
141  new_key->ksk == ksk &&
142  new_key->zsk == zsk) {
143  /* duplicate */
144  ods_log_warning("[%s] unable to push duplicate key %s "
145  "to keylist, skipping", parser_str, locator);
146  } else {
147  (void) keylist_push(kl, locator, resourcerecord,
148  (uint8_t) atoi(algorithm), (uint32_t) atoi(flags),
149  publish, ksk, zsk);
150  }
151  } else {
152  ods_log_error("[%s] unable to push key to keylist: <Key> "
153  "is missing required elements, skipping",
154  parser_str);
155  }
156  free((void*)algorithm);
157  free((void*)flags);
158  }
159  }
160  xmlXPathFreeObject(xpathObj);
161  xmlXPathFreeContext(xpathCtx);
162  if (doc) {
163  xmlFreeDoc(doc);
164  }
165  return kl;
166 }
167 
168 
173 duration_type*
174 parse_sc_sig_resign_interval(const char* cfgfile)
175 {
176  duration_type* duration = NULL;
177  const char* str = parse_conf_string(cfgfile,
178  "//SignerConfiguration/Zone/Signatures/Resign",
179  1);
180  if (!str) {
181  return NULL;
182  }
183  duration = duration_create_from_string(str);
184  free((void*)str);
185  return duration;
186 }
187 
188 
189 duration_type*
190 parse_sc_sig_refresh_interval(const char* cfgfile)
191 {
192  duration_type* duration = NULL;
193  const char* str = parse_conf_string(cfgfile,
194  "//SignerConfiguration/Zone/Signatures/Refresh",
195  1);
196  if (!str) {
197  return NULL;
198  }
199  duration = duration_create_from_string(str);
200  free((void*)str);
201  return duration;
202 }
203 
204 
205 duration_type*
206 parse_sc_sig_validity_default(const char* cfgfile)
207 {
208  duration_type* duration = NULL;
209  const char* str = parse_conf_string(cfgfile,
210  "//SignerConfiguration/Zone/Signatures/Validity/Default",
211  1);
212  if (!str) {
213  return NULL;
214  }
215  duration = duration_create_from_string(str);
216  free((void*)str);
217  return duration;
218 }
219 
220 
221 duration_type*
222 parse_sc_sig_validity_denial(const char* cfgfile)
223 {
224  duration_type* duration = NULL;
225  const char* str = parse_conf_string(cfgfile,
226  "//SignerConfiguration/Zone/Signatures/Validity/Denial",
227  1);
228  if (!str) {
229  return NULL;
230  }
231  duration = duration_create_from_string(str);
232  free((void*)str);
233  return duration;
234 }
235 
236 
237 duration_type*
238 parse_sc_sig_validity_keyset(const char* cfgfile)
239 {
240  duration_type* duration = NULL;
241  const char* str = parse_conf_string(cfgfile,
242  "//SignerConfiguration/Zone/Signatures/Validity/Keyset",
243  0);
244  /* Even if the value is 0 or NULL we want to write it in duration format.
245  The value is written in backup file and read during startup*/
246  /*if (!str || *str == 0 || *str == '0') {
247  return NULL;
248  }*/
249  duration = duration_create_from_string(str);
250  free((void*)str);
251  return duration;
252 }
253 
254 
255 duration_type*
256 parse_sc_sig_jitter(const char* cfgfile)
257 {
258  duration_type* duration = NULL;
259  const char* str = parse_conf_string(cfgfile,
260  "//SignerConfiguration/Zone/Signatures/Jitter",
261  1);
262  if (!str) {
263  return NULL;
264  }
265  duration = duration_create_from_string(str);
266  free((void*)str);
267  return duration;
268 }
269 
270 
271 duration_type*
272 parse_sc_sig_inception_offset(const char* cfgfile)
273 {
274  duration_type* duration = NULL;
275  const char* str = parse_conf_string(cfgfile,
276  "//SignerConfiguration/Zone/Signatures/InceptionOffset",
277  1);
278  if (!str) {
279  return NULL;
280  }
281  duration = duration_create_from_string(str);
282  free((void*)str);
283  return duration;
284 }
285 
286 
287 duration_type*
288 parse_sc_dnskey_ttl(const char* cfgfile)
289 {
290  duration_type* duration = NULL;
291  const char* str = parse_conf_string(cfgfile,
292  "//SignerConfiguration/Zone/Keys/TTL",
293  1);
294  if (!str) {
295  return NULL;
296  }
297  duration = duration_create_from_string(str);
298  free((void*)str);
299  return duration;
300 }
301 
302 
303 const char**
304 parse_sc_dnskey_sigrrs(const char* cfgfile)
305 {
306  xmlDocPtr doc = NULL;
307  xmlXPathContextPtr xpathCtx = NULL;
308  xmlXPathObjectPtr xpathObj = NULL;
309  xmlNode* curNode = NULL;
310  xmlChar* xexpr = NULL;
311  const char **signatureresourcerecords;
312  int i;
313 
314  if (!cfgfile) {
315  return NULL;
316  }
317  /* Load XML document */
318  doc = xmlParseFile(cfgfile);
319  if (doc == NULL) {
320  ods_log_error("[%s] unable to parse <Keys>: "
321  "xmlParseFile() failed", parser_str);
322  return NULL;
323  }
324  /* Create xpath evaluation context */
325  xpathCtx = xmlXPathNewContext(doc);
326  if(xpathCtx == NULL) {
327  xmlFreeDoc(doc);
328  ods_log_error("[%s] unable to parse <Keys>: "
329  "xmlXPathNewContext() failed", parser_str);
330  return NULL;
331  }
332  /* Evaluate xpath expression */
333  xexpr = (xmlChar*) "//SignerConfiguration/Zone/Keys/SignatureResourceRecord";
334  xpathObj = xmlXPathEvalExpression(xexpr, xpathCtx);
335  if(xpathObj == NULL) {
336  xmlXPathFreeContext(xpathCtx);
337  xmlFreeDoc(doc);
338  ods_log_error("[%s] unable to parse <Keys>: "
339  "xmlXPathEvalExpression() failed", parser_str);
340  return NULL;
341  }
342  /* Parse keys */
343  if (xpathObj->nodesetval && xpathObj->nodesetval->nodeNr > 0) {
344  signatureresourcerecords = malloc(sizeof(char*) * (xpathObj->nodesetval->nodeNr + 1));
345  for (i = 0; i < xpathObj->nodesetval->nodeNr; i++) {
346  curNode = xpathObj->nodesetval->nodeTab[i];
347  signatureresourcerecords[i] = (char *) xmlNodeGetContent(curNode);
348  }
349  signatureresourcerecords[i] = NULL;
350  } else {
351  signatureresourcerecords = NULL;
352  }
353  xmlXPathFreeObject(xpathObj);
354  xmlXPathFreeContext(xpathCtx);
355  if (doc) {
356  xmlFreeDoc(doc);
357  }
358  return signatureresourcerecords;
359 }
360 
361 
362 
363 duration_type*
364 parse_sc_nsec3param_ttl(const char* cfgfile)
365 {
366  duration_type* duration = NULL;
367  const char* str = parse_conf_string(cfgfile,
368  "//SignerConfiguration/Zone/Denial/NSEC3/TTL",
369  0);
370  if (!str) {
371  return NULL;
372  }
373  duration = duration_create_from_string(str);
374  free((void*)str);
375  return duration;
376 }
377 
378 
379 duration_type*
380 parse_sc_soa_ttl(const char* cfgfile)
381 {
382  duration_type* duration = NULL;
383  const char* str = parse_conf_string(cfgfile,
384  "//SignerConfiguration/Zone/SOA/TTL",
385  1);
386  if (!str) {
387  return NULL;
388  }
389  duration = duration_create_from_string(str);
390  free((void*)str);
391  return duration;
392 }
393 
394 
395 duration_type*
396 parse_sc_soa_min(const char* cfgfile)
397 {
398  duration_type* duration = NULL;
399  const char* str = parse_conf_string(cfgfile,
400  "//SignerConfiguration/Zone/SOA/Minimum",
401  1);
402  if (!str) {
403  return NULL;
404  }
405  duration = duration_create_from_string(str);
406  free((void*)str);
407  return duration;
408 }
409 
410 
411 duration_type*
412 parse_sc_max_zone_ttl(const char* cfgfile)
413 {
414  duration_type* duration = NULL;
415  const char* str = parse_conf_string(cfgfile,
416  "//SignerConfiguration/Zone/Signatures/MaxZoneTTL",
417  0);
418  if (!str) {
419  return NULL;
420  }
421  duration = duration_create_from_string(str);
422  free((void*)str);
423  return duration;
424 }
425 
426 
431 ldns_rr_type
432 parse_sc_nsec_type(const char* cfgfile)
433 {
434  const char* str = parse_conf_string(cfgfile,
435  "//SignerConfiguration/Zone/Denial/NSEC3",
436  0);
437  if (str) {
438  free((void*)str);
439  return LDNS_RR_TYPE_NSEC3;
440  }
441  str = parse_conf_string(cfgfile,
442  "//SignerConfiguration/Zone/Denial/NSEC",
443  0);
444  if (str) {
445  free((void*)str);
446  return LDNS_RR_TYPE_NSEC;
447  }
448  return LDNS_RR_TYPE_FIRST;
449 }
450 
451 
456 uint32_t
457 parse_sc_nsec3_algorithm(const char* cfgfile)
458 {
459  int ret = 0;
460  const char* str = parse_conf_string(cfgfile,
461  "//SignerConfiguration/Zone/Denial/NSEC3/Hash/Algorithm",
462  1);
463  if (str) {
464  if (strlen(str) > 0) {
465  ret = atoi(str);
466  }
467  free((void*)str);
468  }
469  return ret;
470 }
471 
472 
473 uint32_t
474 parse_sc_nsec3_iterations(const char* cfgfile)
475 {
476  int ret = 0;
477  const char* str = parse_conf_string(cfgfile,
478  "//SignerConfiguration/Zone/Denial/NSEC3/Hash/Iterations",
479  1);
480  if (str) {
481  if (strlen(str) > 0) {
482  ret = atoi(str);
483  }
484  free((void*)str);
485  }
486  return ret;
487 }
488 
489 
490 int
491 parse_sc_nsec3_optout(const char* cfgfile)
492 {
493  int ret = 0;
494  const char* str = parse_conf_string(cfgfile,
495  "//SignerConfiguration/Zone/Denial/NSEC3/OptOut",
496  0);
497  if (str) {
498  ret = 1;
499  free((void*)str);
500  }
501  return ret;
502 }
503 
504 int
505 parse_sc_passthrough(const char* cfgfile)
506 {
507  int ret = 0;
508  const char* str = parse_conf_string(cfgfile,
509  "//SignerConfiguration/Zone/Passthrough",
510  0);
511  if (str) {
512  ret = 1;
513  free((void*)str);
514  }
515  return ret;
516 }
517 
522 const char*
523 parse_sc_soa_serial(const char* cfgfile)
524 {
525  const char* dup = NULL;
526  const char* str = parse_conf_string(
527  cfgfile,
528  "//SignerConfiguration/Zone/SOA/Serial",
529  1);
530 
531  if (str) {
532  dup = strdup(str);
533  free((void*)str);
534  }
535  return dup;
536 }
537 
538 
539 const char*
540 parse_sc_nsec3_salt(const char* cfgfile)
541 {
542  const char* dup = NULL;
543  const char* str = parse_conf_string(
544  cfgfile,
545  "//SignerConfiguration/Zone/Denial/NSEC3/Hash/Salt",
546  1);
547 
548  if (str) {
549  dup = strdup(str);
550  free((void*)str);
551  }
552  return dup;
553 }
duration_type * parse_sc_sig_validity_default(const char *cfgfile)
duration_type * parse_sc_sig_validity_denial(const char *cfgfile)
int publish
Definition: keys.h:57
int zsk
Definition: keys.h:59
uint32_t parse_sc_nsec3_algorithm(const char *cfgfile)
key_type * keylist_lookup_by_locator(keylist_type *kl, const char *locator)
Definition: keys.c:73
duration_type * parse_sc_soa_ttl(const char *cfgfile)
duration_type * parse_sc_sig_inception_offset(const char *cfgfile)
const char * parse_sc_soa_serial(const char *cfgfile)
const char * parse_sc_nsec3_salt(const char *cfgfile)
duration_type * parse_sc_sig_validity_keyset(const char *cfgfile)
keylist_type * keylist_create(signconf_type *signconf)
Definition: keys.c:48
duration_type * parse_sc_dnskey_ttl(const char *cfgfile)
duration_type * parse_sc_sig_jitter(const char *cfgfile)
int parse_sc_passthrough(const char *cfgfile)
key_type * keylist_push(keylist_type *kl, const char *locator, const char *resourcerecord, uint8_t algorithm, uint32_t flags, int publish, int ksk, int zsk)
Definition: keys.c:95
duration_type * parse_sc_max_zone_ttl(const char *cfgfile)
const char ** parse_sc_dnskey_sigrrs(const char *cfgfile)
duration_type * parse_sc_nsec3param_ttl(const char *cfgfile)
duration_type * parse_sc_sig_refresh_interval(const char *cfgfile)
int parse_sc_nsec3_optout(const char *cfgfile)
duration_type * parse_sc_soa_min(const char *cfgfile)
const char * parse_conf_string(const char *cfgfile, const char *expr, int required)
Definition: confparser.c:340
keylist_type * parse_sc_keys(void *sc, const char *cfgfile)
int ksk
Definition: keys.h:58
uint8_t algorithm
Definition: keys.h:55
ldns_rr_type parse_sc_nsec_type(const char *cfgfile)
uint32_t flags
Definition: keys.h:56
duration_type * parse_sc_sig_resign_interval(const char *cfgfile)
uint32_t parse_sc_nsec3_iterations(const char *cfgfile)