OpenDNSSEC-signer  1.4.1
confparser.c
Go to the documentation of this file.
1 /*
2  * $Id: confparser.c 7065 2013-03-12 13:13:55Z matthijs $
3  *
4  * Copyright (c) 2009 NLNet Labs. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
21  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
23  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
25  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  */
28 
34 #include "parser/confparser.h"
35 #include "parser/zonelistparser.h"
36 #include "shared/allocator.h"
37 #include "shared/log.h"
38 #include "shared/status.h"
39 #include "wire/acl.h"
40 
41 #include <libxml/xpath.h>
42 #include <libxml/relaxng.h>
43 #include <libxml/xmlreader.h>
44 #include <string.h>
45 #include <stdlib.h>
46 
47 static const char* parser_str = "parser";
48 
49 
55 parse_file_check(const char* cfgfile, const char* rngfile)
56 {
57  xmlDocPtr doc = NULL;
58  xmlDocPtr rngdoc = NULL;
59  xmlRelaxNGParserCtxtPtr rngpctx = NULL;
60  xmlRelaxNGValidCtxtPtr rngctx = NULL;
61  xmlRelaxNGPtr schema = NULL;
62  int status = 0;
63 
64  if (!cfgfile || !rngfile) {
65  return ODS_STATUS_ASSERT_ERR;
66  }
67  ods_log_debug("[%s] check cfgfile %s with rngfile %s", parser_str,
68  cfgfile, rngfile);
69  /* Load XML document */
70  doc = xmlParseFile(cfgfile);
71  if (doc == NULL) {
72  ods_log_error("[%s] unable to parse file: failed to load cfgfile %s",
73  parser_str, cfgfile);
74  return ODS_STATUS_XML_ERR;
75  }
76  /* Load rng document */
77  rngdoc = xmlParseFile(rngfile);
78  if (rngdoc == NULL) {
79  ods_log_error("[%s] unable to parse file: failed to load rngfile %s",
80  parser_str, rngfile);
81  xmlFreeDoc(doc);
82  return ODS_STATUS_XML_ERR;
83  }
84  /* Create an XML RelaxNGs parser context for the relax-ng document. */
85  rngpctx = xmlRelaxNGNewDocParserCtxt(rngdoc);
86  if (rngpctx == NULL) {
87  ods_log_error("[%s] unable to parse file: "
88  "xmlRelaxNGNewDocParserCtxt() failed", parser_str);
89  xmlFreeDoc(rngdoc);
90  xmlFreeDoc(doc);
91  return ODS_STATUS_XML_ERR;
92  }
93  /* Parse a schema definition resource and
94  * build an internal XML schema structure.
95  */
96  schema = xmlRelaxNGParse(rngpctx);
97  if (schema == NULL) {
98  ods_log_error("[%s] unable to parse file: xmlRelaxNGParse() failed",
99  parser_str);
100  xmlRelaxNGFreeParserCtxt(rngpctx);
101  xmlFreeDoc(rngdoc);
102  xmlFreeDoc(doc);
103  return ODS_STATUS_PARSE_ERR;
104  }
105  /* Create an XML RelaxNGs validation context. */
106  rngctx = xmlRelaxNGNewValidCtxt(schema);
107  if (rngctx == NULL) {
108  ods_log_error("[%s] unable to parse file: xmlRelaxNGNewValidCtxt() "
109  "failed", parser_str);
110  xmlRelaxNGFree(schema);
111  xmlRelaxNGFreeParserCtxt(rngpctx);
112  xmlFreeDoc(rngdoc);
113  xmlFreeDoc(doc);
114  return ODS_STATUS_RNG_ERR;
115  }
116  /* Validate a document tree in memory. */
117  status = xmlRelaxNGValidateDoc(rngctx,doc);
118  if (status != 0) {
119  ods_log_error("[%s] unable to parse file: xmlRelaxNGValidateDoc() "
120  "failed", parser_str);
121  xmlRelaxNGFreeValidCtxt(rngctx);
122  xmlRelaxNGFree(schema);
123  xmlRelaxNGFreeParserCtxt(rngpctx);
124  xmlFreeDoc(rngdoc);
125  xmlFreeDoc(doc);
126  return ODS_STATUS_RNG_ERR;
127  }
128  xmlRelaxNGFreeValidCtxt(rngctx);
129  xmlRelaxNGFree(schema);
130  xmlRelaxNGFreeParserCtxt(rngpctx);
131  xmlFreeDoc(rngdoc);
132  xmlFreeDoc(doc);
133  return ODS_STATUS_OK;
134 }
135 
136 /* TODO: look how the enforcer reads this now */
137 
138 
144 parse_conf_listener(allocator_type* allocator, const char* cfgfile)
145 {
146  listener_type* listener = NULL;
147  interface_type* interface = NULL;
148  int i = 0;
149  char* address = NULL;
150  char* port = NULL;
151  xmlDocPtr doc = NULL;
152  xmlXPathContextPtr xpathCtx = NULL;
153  xmlXPathObjectPtr xpathObj = NULL;
154  xmlNode* curNode = NULL;
155  xmlChar* xexpr = NULL;
156 
157  ods_log_assert(allocator);
158  ods_log_assert(cfgfile);
159 
160  /* Load XML document */
161  doc = xmlParseFile(cfgfile);
162  if (doc == NULL) {
163  ods_log_error("[%s] could not parse <Listener>: "
164  "xmlParseFile() failed", parser_str);
165  return NULL;
166  }
167  /* Create xpath evaluation context */
168  xpathCtx = xmlXPathNewContext(doc);
169  if(xpathCtx == NULL) {
170  xmlFreeDoc(doc);
171  ods_log_error("[%s] could not parse <Listener>: "
172  "xmlXPathNewContext() failed", parser_str);
173  return NULL;
174  }
175  /* Evaluate xpath expression */
176  xexpr = (xmlChar*) "//Configuration/Signer/Listener/Interface";
177  xpathObj = xmlXPathEvalExpression(xexpr, xpathCtx);
178  if(xpathObj == NULL) {
179  xmlXPathFreeContext(xpathCtx);
180  xmlFreeDoc(doc);
181  ods_log_error("[%s] could not parse <Listener>: "
182  "xmlXPathEvalExpression failed", parser_str);
183  return NULL;
184  }
185  /* Parse interfaces */
186  listener = listener_create(allocator);
187  ods_log_assert(listener);
188  if (xpathObj->nodesetval && xpathObj->nodesetval->nodeNr > 0) {
189  for (i = 0; i < xpathObj->nodesetval->nodeNr; i++) {
190  address = NULL;
191  port = NULL;
192 
193  curNode = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode;
194  while (curNode) {
195  if (xmlStrEqual(curNode->name, (const xmlChar *)"Address")) {
196  address = (char *) xmlNodeGetContent(curNode);
197  } else if (xmlStrEqual(curNode->name, (const xmlChar *)"Port")) {
198  port = (char *) xmlNodeGetContent(curNode);
199  }
200  curNode = curNode->next;
201  }
202  if (address) {
203  interface = listener_push(listener, address,
204  acl_parse_family(address), port);
205  } else {
206  interface = listener_push(listener, "", AF_INET, port);
207  if (interface) {
208  interface = listener_push(listener, "", AF_INET6, port);
209  }
210  }
211  if (!interface) {
212  ods_log_error("[%s] unable to add %s:%s interface: "
213  "listener_push() failed", parser_str, address?address:"",
214  port?port:"");
215  } else {
216  ods_log_debug("[%s] added %s:%s interface to listener",
217  parser_str, address?address:"", port?port:"");
218  }
219  free((void*)port);
220  free((void*)address);
221  }
222  }
223  xmlXPathFreeObject(xpathObj);
224  xmlXPathFreeContext(xpathCtx);
225  if (doc) {
226  xmlFreeDoc(doc);
227  }
228  return listener;
229 }
230 
231 
236 const char*
237 parse_conf_string(const char* cfgfile, const char* expr, int required)
238 {
239  xmlDocPtr doc = NULL;
240  xmlXPathContextPtr xpathCtx = NULL;
241  xmlXPathObjectPtr xpathObj = NULL;
242  xmlChar *xexpr = NULL;
243  const char* string = NULL;
244 
245  ods_log_assert(expr);
246  ods_log_assert(cfgfile);
247 
248  /* Load XML document */
249  doc = xmlParseFile(cfgfile);
250  if (doc == NULL) {
251  ods_log_error("[%s] unable to parse file %s: xmlParseFile() failed",
252  parser_str, cfgfile);
253  return NULL;
254  }
255  /* Create xpath evaluation context */
256  xpathCtx = xmlXPathNewContext(doc);
257  if (xpathCtx == NULL) {
258  ods_log_error("[%s] unable to parse file %s: xmlXPathNewContext() "
259  "failed", parser_str, cfgfile);
260  xmlFreeDoc(doc);
261  return NULL;
262  }
263  /* Get string */
264  xexpr = (unsigned char*) expr;
265  xpathObj = xmlXPathEvalExpression(xexpr, xpathCtx);
266  if (xpathObj == NULL || xpathObj->nodesetval == NULL ||
267  xpathObj->nodesetval->nodeNr <= 0) {
268  if (required) {
269  ods_log_error("[%s] unable to evaluate expression %s in cfgile %s",
270  parser_str, (char*) xexpr, cfgfile);
271  }
272  xmlXPathFreeContext(xpathCtx);
273  if (xpathObj) {
274  xmlXPathFreeObject(xpathObj);
275  }
276  xmlFreeDoc(doc);
277  return NULL;
278  }
279  if (xpathObj->nodesetval != NULL &&
280  xpathObj->nodesetval->nodeNr > 0) {
281  string = (const char*) xmlXPathCastToString(xpathObj);
282  xmlXPathFreeContext(xpathCtx);
283  xmlXPathFreeObject(xpathObj);
284  xmlFreeDoc(doc);
285  return string;
286  }
287  xmlXPathFreeContext(xpathCtx);
288  xmlXPathFreeObject(xpathObj);
289  xmlFreeDoc(doc);
290  return NULL;
291 }
292 
293 
294 const char*
295 parse_conf_zonelist_filename(allocator_type* allocator, const char* cfgfile)
296 {
297  const char* dup = NULL;
298  const char* str = parse_conf_string(
299  cfgfile,
300  "//Configuration/Common/ZoneListFile",
301  1);
302 
303  if (str) {
304  dup = allocator_strdup(allocator, str);
305  free((void*)str);
306  }
307  return dup;
308 }
309 
310 
311 const char*
312 parse_conf_log_filename(allocator_type* allocator, const char* cfgfile)
313 {
314  const char* dup = NULL;
315  const char* str = parse_conf_string(cfgfile,
316  "//Configuration/Common/Logging/Syslog/Facility",
317  0);
318  if (!str) {
319  str = parse_conf_string(cfgfile,
320  "//Configuration/Common/Logging/File/Filename",
321  0);
322  }
323  if (str) {
324  dup = allocator_strdup(allocator, str);
325  free((void*)str);
326  }
327  return dup; /* NULL, Facility or Filename */
328 }
329 
330 
331 const char*
332 parse_conf_pid_filename(allocator_type* allocator, const char* cfgfile)
333 {
334  const char* dup = NULL;
335  const char* str = parse_conf_string(
336  cfgfile,
337  "//Configuration/Signer/PidFile",
338  0);
339 
340  if (str) {
341  dup = allocator_strdup(allocator, str);
342  free((void*)str);
343  } else {
344  dup = allocator_strdup(allocator, ODS_SE_PIDFILE);
345  }
346  return dup;
347 }
348 
349 
350 const char*
351 parse_conf_notify_command(allocator_type* allocator, const char* cfgfile)
352 {
353  const char* dup = NULL;
354  const char* str = parse_conf_string(
355  cfgfile,
356  "//Configuration/Signer/NotifyCommand",
357  0);
358 
359  if (str) {
360  dup = allocator_strdup(allocator, str);
361  free((void*)str);
362  }
363  return dup;
364 }
365 
366 
367 const char*
368 parse_conf_clisock_filename(allocator_type* allocator, const char* cfgfile)
369 {
370  const char* dup = NULL;
371  const char* str = parse_conf_string(
372  cfgfile,
373  "//Configuration/Signer/SocketFile",
374  0);
375 
376  if (str) {
377  dup = allocator_strdup(allocator, str);
378  free((void*)str);
379  } else {
380  dup = allocator_strdup(allocator, ODS_SE_SOCKFILE);
381  }
382  return dup;
383 }
384 
385 
386 const char*
387 parse_conf_working_dir(allocator_type* allocator, const char* cfgfile)
388 {
389  const char* dup = NULL;
390  const char* str = parse_conf_string(
391  cfgfile,
392  "//Configuration/Signer/WorkingDirectory",
393  0);
394 
395  if (str) {
396  dup = allocator_strdup(allocator, str);
397  free((void*)str);
398  } else {
399  dup = allocator_strdup(allocator, ODS_SE_WORKDIR);
400  }
401  ods_log_assert(dup);
402  return dup;
403 }
404 
405 
406 const char*
407 parse_conf_username(allocator_type* allocator, const char* cfgfile)
408 {
409  const char* dup = NULL;
410  const char* str = parse_conf_string(
411  cfgfile,
412  "//Configuration/Signer/Privileges/User",
413  0);
414 
415  if (str) {
416  dup = allocator_strdup(allocator, str);
417  free((void*)str);
418  }
419  return dup;
420 }
421 
422 
423 const char*
424 parse_conf_group(allocator_type* allocator, const char* cfgfile)
425 {
426  const char* dup = NULL;
427  const char* str = parse_conf_string(
428  cfgfile,
429  "//Configuration/Signer/Privileges/Group",
430  0);
431 
432  if (str) {
433  dup = allocator_strdup(allocator, str);
434  free((void*)str);
435  }
436  return dup;
437 }
438 
439 
440 const char*
441 parse_conf_chroot(allocator_type* allocator, const char* cfgfile)
442 {
443  const char* dup = NULL;
444  const char* str = parse_conf_string(
445  cfgfile,
446  "//Configuration/Signer/Privileges/Directory",
447  0);
448 
449  if (str) {
450  dup = allocator_strdup(allocator, str);
451  free((void*)str);
452  }
453  return dup;
454 }
455 
456 
461 int
462 parse_conf_use_syslog(const char* cfgfile)
463 {
464  const char* str = parse_conf_string(cfgfile,
465  "//Configuration/Common/Logging/Syslog/Facility",
466  0);
467  if (str) {
468  free((void*)str);
469  return 1;
470  }
471  return 0;
472 }
473 
474 int
475 parse_conf_verbosity(const char* cfgfile)
476 {
477  int verbosity = ODS_SE_VERBOSITY;
478  const char* str = parse_conf_string(cfgfile,
479  "//Configuration/Common/Logging/Verbosity",
480  0);
481  if (str) {
482  if (strlen(str) > 0) {
483  verbosity = atoi(str);
484  }
485  free((void*)str);
486  }
487  return verbosity;
488 }
489 
490 
491 int
492 parse_conf_worker_threads(const char* cfgfile)
493 {
494  int numwt = ODS_SE_WORKERTHREADS;
495  const char* str = parse_conf_string(cfgfile,
496  "//Configuration/Signer/WorkerThreads",
497  0);
498  if (str) {
499  if (strlen(str) > 0) {
500  numwt = atoi(str);
501  }
502  free((void*)str);
503  }
504  return numwt;
505 }
506 
507 
508 int
509 parse_conf_signer_threads(const char* cfgfile)
510 {
511  int numwt = ODS_SE_WORKERTHREADS;
512  const char* str = parse_conf_string(cfgfile,
513  "//Configuration/Signer/SignerThreads",
514  0);
515  if (str) {
516  if (strlen(str) > 0) {
517  numwt = atoi(str);
518  }
519  free((void*)str);
520  return numwt;
521  }
522  /* no SignerThreads value configured, look at WorkerThreads */
523  return parse_conf_worker_threads(cfgfile);
524 }
int parse_conf_worker_threads(const char *cfgfile)
Definition: confparser.c:492
void ods_log_debug(const char *format,...)
Definition: log.c:272
int parse_conf_use_syslog(const char *cfgfile)
Definition: confparser.c:462
const char * parse_conf_zonelist_filename(allocator_type *allocator, const char *cfgfile)
Definition: confparser.c:295
enum ods_enum_status ods_status
Definition: status.h:89
ods_status parse_file_check(const char *cfgfile, const char *rngfile)
Definition: confparser.c:55
const char * parse_conf_log_filename(allocator_type *allocator, const char *cfgfile)
Definition: confparser.c:312
void ods_log_error(const char *format,...)
Definition: log.c:336
listener_type * parse_conf_listener(allocator_type *allocator, const char *cfgfile)
Definition: confparser.c:144
listener_type * listener_create(allocator_type *allocator)
Definition: listener.c:46
const char * parse_conf_group(allocator_type *allocator, const char *cfgfile)
Definition: confparser.c:424
int parse_conf_signer_threads(const char *cfgfile)
Definition: confparser.c:509
const char * parse_conf_chroot(allocator_type *allocator, const char *cfgfile)
Definition: confparser.c:441
const char * parse_conf_clisock_filename(allocator_type *allocator, const char *cfgfile)
Definition: confparser.c:368
char * allocator_strdup(allocator_type *allocator, const char *string)
Definition: allocator.c:123
const char * parse_conf_string(const char *cfgfile, const char *expr, int required)
Definition: confparser.c:237
const char * parse_conf_notify_command(allocator_type *allocator, const char *cfgfile)
Definition: confparser.c:351
const char * parse_conf_working_dir(allocator_type *allocator, const char *cfgfile)
Definition: confparser.c:387
int parse_conf_verbosity(const char *cfgfile)
Definition: confparser.c:475
const char * parse_conf_username(allocator_type *allocator, const char *cfgfile)
Definition: confparser.c:407
const char * parse_conf_pid_filename(allocator_type *allocator, const char *cfgfile)
Definition: confparser.c:332
#define ods_log_assert(x)
Definition: log.h:156
interface_type * listener_push(listener_type *listener, char *address, int family, char *port)
Definition: listener.c:71