OpenDNSSEC-enforcer  2.0.3
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 "log.h"
34 #include "status.h"
35 #include "duration.h"
36 #include "daemon/cfg.h"
37 
38 #include <libxml/xpath.h>
39 #include <libxml/relaxng.h>
40 #include <libxml/xmlreader.h>
41 #include <string.h>
42 #include <stdlib.h>
43 #include <sys/un.h>
44 
45 static const char* parser_str = "parser";
46 
47 
52 ods_status
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;
61 
62  if (!cfgfile || !rngfile) {
63  ods_log_error("[%s] no cfgfile or rngfile", parser_str);
64  return ODS_STATUS_ASSERT_ERR;
65  }
66  ods_log_assert(cfgfile);
67  ods_log_assert(rngfile);
68  ods_log_debug("[%s] check cfgfile %s with rngfile %s", parser_str,
69  cfgfile, rngfile);
70 
71  /* Load XML document */
72  doc = xmlParseFile(cfgfile);
73  if (doc == NULL) {
74  ods_log_error("[%s] unable to read cfgfile %s", parser_str,
75  cfgfile);
76  return ODS_STATUS_XML_ERR;
77  }
78  /* Load rng document */
79  rngdoc = xmlParseFile(rngfile);
80  if (rngdoc == NULL) {
81  ods_log_error("[%s] unable to read rngfile %s", parser_str,
82  rngfile);
83  xmlFreeDoc(doc);
84  return ODS_STATUS_XML_ERR;
85  }
86  /* Create an XML RelaxNGs parser context for the relax-ng document. */
87  rngpctx = xmlRelaxNGNewDocParserCtxt(rngdoc);
88  if (rngpctx == NULL) {
89  xmlFreeDoc(rngdoc);
90  xmlFreeDoc(doc);
91  ods_log_error("[%s] unable to create XML RelaxNGs parser context",
92  parser_str);
93  return ODS_STATUS_XML_ERR;
94  }
95  /* Parse a schema definition resource and
96  * build an internal XML schema structure.
97  */
98  schema = xmlRelaxNGParse(rngpctx);
99  if (schema == NULL) {
100  ods_log_error("[%s] unable to parse a schema definition resource",
101  parser_str);
102  xmlRelaxNGFreeParserCtxt(rngpctx);
103  xmlFreeDoc(rngdoc);
104  xmlFreeDoc(doc);
105  return ODS_STATUS_PARSE_ERR;
106  }
107  /* Create an XML RelaxNGs validation context. */
108  rngctx = xmlRelaxNGNewValidCtxt(schema);
109  if (rngctx == NULL) {
110  ods_log_error("[%s] unable to create RelaxNGs validation context",
111  parser_str);
112  xmlRelaxNGFree(schema);
113  xmlRelaxNGFreeParserCtxt(rngpctx);
114  xmlFreeDoc(rngdoc);
115  xmlFreeDoc(doc);
116  return ODS_STATUS_RNG_ERR;
117  }
118  /* Validate a document tree in memory. */
119  status = xmlRelaxNGValidateDoc(rngctx,doc);
120  if (status != 0) {
121  ods_log_error("[%s] cfgfile validation failed %s", parser_str,
122  cfgfile);
123  xmlRelaxNGFreeValidCtxt(rngctx);
124  xmlRelaxNGFree(schema);
125  xmlRelaxNGFreeParserCtxt(rngpctx);
126  xmlFreeDoc(rngdoc);
127  xmlFreeDoc(doc);
128  return ODS_STATUS_RNG_ERR;
129  }
130 
131  xmlRelaxNGFreeValidCtxt(rngctx);
132  xmlRelaxNGFree(schema);
133  xmlRelaxNGFreeParserCtxt(rngpctx);
134  xmlFreeDoc(rngdoc);
135  xmlFreeDoc(doc);
136  return ODS_STATUS_OK;
137 }
138 
139 /* TODO: look how the enforcer reads this now */
140 
145 const char*
146 parse_conf_string(const char* cfgfile, const char* expr, int required)
147 {
148  xmlDocPtr doc = NULL;
149  xmlXPathContextPtr xpathCtx = NULL;
150  xmlXPathObjectPtr xpathObj = NULL;
151  xmlChar *xexpr = NULL;
152  const char* string = NULL;
153 
154  ods_log_assert(expr);
155  ods_log_assert(cfgfile);
156 
157  /* Load XML document */
158  doc = xmlParseFile(cfgfile);
159  if (doc == NULL) {
160  return NULL;
161  }
162  /* Create xpath evaluation context */
163  xpathCtx = xmlXPathNewContext(doc);
164  if (xpathCtx == NULL) {
165  ods_log_error("[%s] unable to create new XPath context for cfgile "
166  "%s expr %s", parser_str, cfgfile, (char*) expr);
167  xmlFreeDoc(doc);
168  return NULL;
169  }
170  /* Get string */
171  xexpr = (unsigned char*) expr;
172  xpathObj = xmlXPathEvalExpression(xexpr, xpathCtx);
173  if (xpathObj == NULL || xpathObj->nodesetval == NULL ||
174  xpathObj->nodesetval->nodeNr <= 0) {
175  if (required) {
176  ods_log_error("[%s] unable to evaluate required element %s in "
177  "cfgfile %s", parser_str, (char*) xexpr, cfgfile);
178  }
179  xmlXPathFreeContext(xpathCtx);
180  if (xpathObj) {
181  xmlXPathFreeObject(xpathObj);
182  }
183  xmlFreeDoc(doc);
184  return NULL;
185  }
186  if (xpathObj->nodesetval != NULL &&
187  xpathObj->nodesetval->nodeNr > 0) {
188  string = (const char*) xmlXPathCastToString(xpathObj);
189  xmlXPathFreeContext(xpathCtx);
190  xmlXPathFreeObject(xpathObj);
191  xmlFreeDoc(doc);
192  return string;
193  }
194  xmlXPathFreeContext(xpathCtx);
195  xmlXPathFreeObject(xpathObj);
196  xmlFreeDoc(doc);
197  return NULL;
198 }
199 
204 hsm_repository_t*
205 parse_conf_repositories(const char* cfgfile)
206 {
207  xmlDocPtr doc = NULL;
208  xmlXPathContextPtr xpathCtx = NULL;
209  xmlXPathObjectPtr xpathObj = NULL;
210  xmlNode* curNode = NULL;
211  xmlChar* xexpr = NULL;
212 
213  int i;
214  char* name;
215  char* module;
216  char* tokenlabel;
217  char* pin;
218  uint8_t use_pubkey;
219  int require_backup;
220  hsm_repository_t* rlist = NULL;
221  hsm_repository_t* repo = NULL;
222 
223  /* Load XML document */
224  doc = xmlParseFile(cfgfile);
225  if (doc == NULL) {
226  ods_log_error("[%s] could not parse <RepositoryList>: "
227  "xmlParseFile() failed", parser_str);
228  return NULL;
229  }
230  /* Create xpath evaluation context */
231  xpathCtx = xmlXPathNewContext(doc);
232  if(xpathCtx == NULL) {
233  xmlFreeDoc(doc);
234  ods_log_error("[%s] could not parse <RepositoryList>: "
235  "xmlXPathNewContext() failed", parser_str);
236  return NULL;
237  }
238  /* Evaluate xpath expression */
239  xexpr = (xmlChar*) "//Configuration/RepositoryList/Repository";
240  xpathObj = xmlXPathEvalExpression(xexpr, xpathCtx);
241  if(xpathObj == NULL) {
242  xmlXPathFreeContext(xpathCtx);
243  xmlFreeDoc(doc);
244  ods_log_error("[%s] could not parse <RepositoryList>: "
245  "xmlXPathEvalExpression failed", parser_str);
246  return NULL;
247  }
248  /* Parse repositories */
249  if (xpathObj->nodesetval && xpathObj->nodesetval->nodeNr > 0) {
250  for (i = 0; i < xpathObj->nodesetval->nodeNr; i++) {
251  repo = NULL;
252  name = NULL;
253  module = NULL;
254  tokenlabel = NULL;
255  pin = NULL;
256  use_pubkey = 1;
257  require_backup = 0;
258 
259  curNode = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode;
260  name = (char *) xmlGetProp(xpathObj->nodesetval->nodeTab[i],
261  (const xmlChar *)"name");
262  while (curNode) {
263  if (xmlStrEqual(curNode->name, (const xmlChar *)"RequireBackup"))
264  require_backup = 1;
265  if (xmlStrEqual(curNode->name, (const xmlChar *)"Module"))
266  module = (char *) xmlNodeGetContent(curNode);
267  if (xmlStrEqual(curNode->name, (const xmlChar *)"TokenLabel"))
268  tokenlabel = (char *) xmlNodeGetContent(curNode);
269  if (xmlStrEqual(curNode->name, (const xmlChar *)"PIN"))
270  pin = (char *) xmlNodeGetContent(curNode);
271  if (xmlStrEqual(curNode->name, (const xmlChar *)"SkipPublicKey"))
272  use_pubkey = 0;
273 
274  curNode = curNode->next;
275  }
276  if (name && module && tokenlabel) {
277  repo = hsm_repository_new(name, module, tokenlabel, pin,
278  use_pubkey, require_backup);
279  }
280  if (!repo) {
281  ods_log_error("[%s] unable to add %s repository: "
282  "hsm_repository_new() failed", parser_str, name?name:"-");
283  } else {
284  repo->next = rlist;
285  rlist = repo;
286  ods_log_debug("[%s] added %s repository to repositorylist",
287  parser_str, name);
288  }
289  free((void*)name);
290  free((void*)module);
291  free((void*)tokenlabel);
292  }
293  }
294 
295  xmlXPathFreeObject(xpathObj);
296  xmlXPathFreeContext(xpathCtx);
297  if (doc) {
298  xmlFreeDoc(doc);
299  }
300  return rlist;
301 }
302 
303 
309 const char*
310 parse_conf_policy_filename(const char* cfgfile)
311 {
312  const char* dup = NULL;
313  const char* str = parse_conf_string(
314  cfgfile,
315  "//Configuration/Common/PolicyFile",
316  1);
317 
318  if (str) {
319  dup = strdup(str);
320  free((void*)str);
321  }
322  return dup;
323 }
324 
325 const char*
326 parse_conf_zonelist_filename(const char* cfgfile)
327 {
328  const char* dup = NULL;
329  const char* str = parse_conf_string(
330  cfgfile,
331  "//Configuration/Common/ZoneListFile",
332  1);
333 
334  if (str) {
335  dup = strdup(str);
336  free((void*)str);
337  }
338  return dup;
339 }
340 
341 
342 const char*
343 parse_conf_zonefetch_filename(const char* cfgfile)
344 {
345  const char* dup = NULL;
346  const char* str = parse_conf_string(
347  cfgfile,
348  "//Configuration/Common/ZoneFetchFile",
349  0);
350 
351  if (str) {
352  dup = strdup(str);
353  free((void*)str);
354  }
355  return dup;
356 }
357 
358 
359 const char*
360 parse_conf_log_filename(const char* cfgfile)
361 {
362  const char* dup = NULL;
363  const char* str = parse_conf_string(cfgfile,
364  "//Configuration/Common/Logging/Syslog/Facility",
365  0);
366  if (!str) {
367  str = parse_conf_string(cfgfile,
368  "//Configuration/Common/Logging/File/Filename",
369  0);
370  }
371  if (str) {
372  dup = strdup(str);
373  free((void*)str);
374  }
375  return dup; /* NULL, Facility or Filename */
376 }
377 
378 
379 const char*
380 parse_conf_pid_filename(const char* cfgfile)
381 {
382  const char* dup = NULL;
383  const char* str = parse_conf_string(
384  cfgfile,
385  "//Configuration/Enforcer/PidFile",
386  0);
387 
388  if (str) {
389  dup = strdup(str);
390  free((void*)str);
391  } else {
392  dup = strdup(OPENDNSSEC_ENFORCER_PIDFILE);
393  }
394  return dup;
395 }
396 
397 
398 const char*
400 {
401  const char* dup = NULL;
402  const char* str = parse_conf_string(
403  cfgfile,
404  "//Configuration/Enforcer/DelegationSignerSubmitCommand",
405  0);
406 
407  if (str) {
408  dup = strdup(str);
409  free((void*)str);
410  }
411  return dup;
412 }
413 
414 const char*
416 {
417  const char* dup = NULL;
418  const char* str = parse_conf_string(
419  cfgfile,
420  "//Configuration/Enforcer/DelegationSignerRetractCommand",
421  0);
422 
423  if (str) {
424  dup = strdup(str);
425  free((void*)str);
426  }
427  return dup;
428 }
429 
430 const char*
431 parse_conf_clisock_filename(const char* cfgfile)
432 {
433  char* dup = NULL;
434  const char* str = parse_conf_string(
435  cfgfile,
436  "//Configuration/Enforcer/SocketFile",
437  0);
438 
439  if (str) {
440  dup = strdup(str);
441  free((void*)str);
442  } else {
443  dup = strdup(OPENDNSSEC_ENFORCER_SOCKETFILE);
444  }
445  if (strlen(dup) >= sizeof(((struct sockaddr_un*)0)->sun_path)) {
446  dup[sizeof(((struct sockaddr_un*)0)->sun_path)-1] = '\0'; /* don't worry about just a few bytes 'lost' */
447  ods_log_warning("[%s] SocketFile path too long, truncated to %s", parser_str, dup);
448  }
449  return dup;
450 }
451 
452 
453 const char*
454 parse_conf_working_dir(const char* cfgfile)
455 {
456  const char* dup = NULL;
457  const char* str = parse_conf_string(
458  cfgfile,
459  "//Configuration/Enforcer/WorkingDirectory",
460  0);
461 
462  if (str) {
463  dup = strdup(str);
464  free((void*)str);
465  } else {
466  dup = strdup(OPENDNSSEC_ENFORCER_WORKINGDIR);
467  }
468  return dup;
469 }
470 
471 
472 const char*
473 parse_conf_username(const char* cfgfile)
474 {
475  const char* dup = NULL;
476  const char* str = parse_conf_string(
477  cfgfile,
478  "//Configuration/Enforcer/Privileges/User",
479  0);
480 
481  if (str) {
482  dup = strdup(str);
483  free((void*)str);
484  }
485  return dup;
486 }
487 
488 
489 const char*
490 parse_conf_group(const char* cfgfile)
491 {
492  const char* dup = NULL;
493  const char* str = parse_conf_string(
494  cfgfile,
495  "//Configuration/Enforcer/Privileges/Group",
496  0);
497 
498  if (str) {
499  dup = strdup(str);
500  free((void*)str);
501  }
502  return dup;
503 }
504 
505 
506 const char*
507 parse_conf_chroot(const char* cfgfile)
508 {
509  const char* dup = NULL;
510  const char* str = parse_conf_string(
511  cfgfile,
512  "//Configuration/Enforcer/Privileges/Directory",
513  0);
514 
515  if (str) {
516  dup = strdup(str);
517  free((void*)str);
518  }
519  return dup;
520 }
521 
522 const char*
523 parse_conf_datastore(const char* cfgfile)
524 {
525  const char* dup = NULL;
526  const char* str = parse_conf_string(
527  cfgfile,
528  "//Configuration/Enforcer/Datastore/MySQL/Database",
529  0);
530  if (!str) {
531  str = parse_conf_string(
532  cfgfile,
533  "//Configuration/Enforcer/Datastore/SQLite",
534  0);
535  }
536  if (str) {
537  dup = strdup(str);
538  free((void*)str);
539  } else {
540  /* use "KASP" as default for datastore */
541  dup = strdup("KASP");
542  }
543  return dup;
544 
545 }
546 
547 const char*
548 parse_conf_db_host(const char* cfgfile)
549 {
550  const char* dup = NULL;
551  const char* str = parse_conf_string(
552  cfgfile,
553  "//Configuration/Enforcer/Datastore/MySQL/Host",
554  0);
555 
556  if (str) {
557  dup = strdup(str);
558  free((void*)str);
559  }
560  return dup;
561 }
562 
563 const char*
564 parse_conf_db_username(const char* cfgfile)
565 {
566  const char* dup = NULL;
567  const char* str = parse_conf_string(
568  cfgfile,
569  "//Configuration/Enforcer/Datastore/MySQL/Username",
570  0);
571 
572  if (str) {
573  dup = strdup(str);
574  free((void*)str);
575  }
576  return dup;
577 }
578 
579 const char*
580 parse_conf_db_password(const char* cfgfile)
581 {
582  const char* dup = NULL;
583  const char* str = parse_conf_string(
584  cfgfile,
585  "//Configuration/Enforcer/Datastore/MySQL/Password",
586  0);
587 
588  if (str) {
589  dup = strdup(str);
590  free((void*)str);
591  }
592  return dup;
593 }
594 
599 int
600 parse_conf_use_syslog(const char* cfgfile)
601 {
602  const char* str = parse_conf_string(cfgfile,
603  "//Configuration/Common/Logging/Syslog/Facility",
604  0);
605  if (str) {
606  free((void*)str);
607  return 1;
608  }
609  return 0;
610 }
611 
612 int
613 parse_conf_verbosity(const char* cfgfile)
614 {
615  int verbosity = ODS_EN_VERBOSITY;
616  const char* str = parse_conf_string(cfgfile,
617  "//Configuration/Common/Logging/Verbosity",
618  0);
619  if (str) {
620  if (strlen(str) > 0) {
621  verbosity = atoi(str);
622  }
623  free((void*)str);
624  }
625  return verbosity;
626 }
627 
628 
629 int
630 parse_conf_worker_threads(const char* cfgfile)
631 {
632  int numwt = ODS_SE_WORKERTHREADS;
633  const char* str = parse_conf_string(cfgfile,
634  "//Configuration/Enforcer/WorkerThreads",
635  0);
636  if (str) {
637  if (strlen(str) > 0) {
638  numwt = atoi(str);
639  }
640  free((void*)str);
641  }
642  return numwt;
643 }
644 
645 int
646 parse_conf_manual_keygen(const char* cfgfile)
647 {
648  const char* str = parse_conf_string(cfgfile,
649  "//Configuration/Enforcer/ManualKeyGeneration",
650  0);
651  if (str) {
652  free((void*)str);
653  return 1;
654  }
655  return 0;
656 }
657 
658 int
659 parse_conf_db_port(const char* cfgfile)
660 {
661  int port = 0; /* returning 0 (zero) means use the default port */
662  const char* str = parse_conf_string(cfgfile,
663  "//Configuration/Enforcer/Datastore/MySQL/Host/@Port",
664  0);
665  if (str) {
666  if (strlen(str) > 0) {
667  port = atoi(str);
668  }
669  free((void*)str);
670  }
671  return port;
672 }
673 
675  const char* str = NULL;
676 
677  if ((str = parse_conf_string(
678  cfgfile,
679  "//Configuration/Enforcer/Datastore/MySQL/Host",
680  0)))
681  {
682  free((void*)str);
684  }
685 
686  if ((str = parse_conf_string(
687  cfgfile,
688  "//Configuration/Enforcer/Datastore/SQLite",
689  0)))
690  {
691  free((void*)str);
693  }
694 
696 }
697 
698 time_t
700 {
701  time_t period = 365 * 24 * 3600; /* default 1 normal year in seconds */
702  const char* str = parse_conf_string(cfgfile,
703  "//Configuration/Enforcer/AutomaticKeyGenerationPeriod",
704  0);
705  if (str) {
706  if (strlen(str) > 0) {
707  duration_type* duration = duration_create_from_string(str);
708  if (duration) {
709  time_t duration_period = duration2time(duration);
710  period = duration_period;
711  duration_cleanup(duration);
712  }
713  }
714  free((void*)str);
715  }
716  return period;
717 }
int parse_conf_worker_threads(const char *cfgfile)
Definition: confparser.c:630
int parse_conf_db_port(const char *cfgfile)
Definition: confparser.c:659
time_t parse_conf_automatic_keygen_period(const char *cfgfile)
Definition: confparser.c:699
void ods_log_debug(const char *format,...)
Definition: log.c:41
int verbosity
Definition: ods-migrate.c:46
const char * parse_conf_db_host(const char *cfgfile)
Definition: confparser.c:548
int parse_conf_use_syslog(const char *cfgfile)
Definition: confparser.c:600
const char * parse_conf_clisock_filename(const char *cfgfile)
Definition: confparser.c:431
ods_status parse_file_check(const char *cfgfile, const char *rngfile)
Definition: confparser.c:53
void ods_log_error(const char *format,...)
Definition: log.c:69
const char * parse_conf_delegation_signer_submit_command(const char *cfgfile)
Definition: confparser.c:399
const char * parse_conf_working_dir(const char *cfgfile)
Definition: confparser.c:454
int parse_conf_manual_keygen(const char *cfgfile)
Definition: confparser.c:646
const char * parse_conf_policy_filename(const char *cfgfile)
Definition: confparser.c:310
const char * parse_conf_group(const char *cfgfile)
Definition: confparser.c:490
const char * parse_conf_log_filename(const char *cfgfile)
Definition: confparser.c:360
const char * parse_conf_db_password(const char *cfgfile)
Definition: confparser.c:580
engineconfig_database_type_t
Definition: cfg.h:43
const char * parse_conf_chroot(const char *cfgfile)
Definition: confparser.c:507
const char * parse_conf_datastore(const char *cfgfile)
Definition: confparser.c:523
engineconfig_database_type_t parse_conf_db_type(const char *cfgfile)
Definition: confparser.c:674
const char * parse_conf_string(const char *cfgfile, const char *expr, int required)
Definition: confparser.c:146
const char * parse_conf_username(const char *cfgfile)
Definition: confparser.c:473
const char * parse_conf_zonefetch_filename(const char *cfgfile)
Definition: confparser.c:343
int parse_conf_verbosity(const char *cfgfile)
Definition: confparser.c:613
hsm_repository_t * parse_conf_repositories(const char *cfgfile)
Definition: confparser.c:205
const char * parse_conf_zonelist_filename(const char *cfgfile)
Definition: confparser.c:326
const char * parse_conf_pid_filename(const char *cfgfile)
Definition: confparser.c:380
const char * parse_conf_delegation_signer_retract_command(const char *cfgfile)
Definition: confparser.c:415
void ods_log_warning(const char *format,...)
Definition: log.c:62
const char * parse_conf_db_username(const char *cfgfile)
Definition: confparser.c:564