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