OpenDNSSEC-enforcer 2.1.13
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
45static const char* parser_str = "parser";
46
47
52ods_status
53parse_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
145const char*
146parse_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
204hsm_repository_t*
205parse_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 uint8_t allowextract;
220 int require_backup;
221 hsm_repository_t* rlist = NULL;
222 hsm_repository_t* repo = NULL;
223
224 /* Load XML document */
225 doc = xmlParseFile(cfgfile);
226 if (doc == NULL) {
227 ods_log_error("[%s] could not parse <RepositoryList>: "
228 "xmlParseFile() failed", parser_str);
229 return NULL;
230 }
231 /* Create xpath evaluation context */
232 xpathCtx = xmlXPathNewContext(doc);
233 if(xpathCtx == NULL) {
234 xmlFreeDoc(doc);
235 ods_log_error("[%s] could not parse <RepositoryList>: "
236 "xmlXPathNewContext() failed", parser_str);
237 return NULL;
238 }
239 /* Evaluate xpath expression */
240 xexpr = (xmlChar*) "//Configuration/RepositoryList/Repository";
241 xpathObj = xmlXPathEvalExpression(xexpr, xpathCtx);
242 if(xpathObj == NULL) {
243 xmlXPathFreeContext(xpathCtx);
244 xmlFreeDoc(doc);
245 ods_log_error("[%s] could not parse <RepositoryList>: "
246 "xmlXPathEvalExpression failed", parser_str);
247 return NULL;
248 }
249 /* Parse repositories */
250 if (xpathObj->nodesetval && xpathObj->nodesetval->nodeNr > 0) {
251 for (i = 0; i < xpathObj->nodesetval->nodeNr; i++) {
252 repo = NULL;
253 name = NULL;
254 module = NULL;
255 tokenlabel = NULL;
256 pin = NULL;
257 use_pubkey = 1;
258 allowextract = 0;
259 require_backup = 0;
260
261 curNode = xpathObj->nodesetval->nodeTab[i]->xmlChildrenNode;
262 name = (char *) xmlGetProp(xpathObj->nodesetval->nodeTab[i],
263 (const xmlChar *)"name");
264 while (curNode) {
265 if (xmlStrEqual(curNode->name, (const xmlChar *)"RequireBackup"))
266 require_backup = 1;
267 if (xmlStrEqual(curNode->name, (const xmlChar *)"Module"))
268 module = (char *) xmlNodeGetContent(curNode);
269 if (xmlStrEqual(curNode->name, (const xmlChar *)"TokenLabel"))
270 tokenlabel = (char *) xmlNodeGetContent(curNode);
271 if (xmlStrEqual(curNode->name, (const xmlChar *)"PIN"))
272 pin = (char *) xmlNodeGetContent(curNode);
273 if (xmlStrEqual(curNode->name, (const xmlChar *)"SkipPublicKey"))
274 use_pubkey = 0;
275 if (xmlStrEqual(curNode->name, (const xmlChar *)"AllowExtraction"))
276 allowextract = 1;
277
278 curNode = curNode->next;
279 }
280 if (name && module && tokenlabel) {
281 repo = hsm_repository_new(name, module, tokenlabel, pin,
282 use_pubkey, allowextract, require_backup);
283 }
284 if (!repo) {
285 ods_log_error("[%s] unable to add %s repository: "
286 "hsm_repository_new() failed", parser_str, name?name:"-");
287 } else {
288 repo->next = rlist;
289 rlist = repo;
290 ods_log_debug("[%s] added %s repository to repositorylist",
291 parser_str, name);
292 }
293 free((void*)name);
294 free((void*)module);
295 free((void*)tokenlabel);
296 }
297 }
298
299 xmlXPathFreeObject(xpathObj);
300 xmlXPathFreeContext(xpathCtx);
301 if (doc) {
302 xmlFreeDoc(doc);
303 }
304 return rlist;
305}
306
307
313const char*
314parse_conf_policy_filename(const char* cfgfile)
315{
316 const char* dup = NULL;
317 const char* str = parse_conf_string(
318 cfgfile,
319 "//Configuration/Common/PolicyFile",
320 1);
321
322 if (str) {
323 dup = strdup(str);
324 free((void*)str);
325 }
326 return dup;
327}
328
329const char*
331{
332 const char* dup = NULL;
333 const char* str = parse_conf_string(
334 cfgfile,
335 "//Configuration/Common/ZoneListFile",
336 1);
337
338 if (str) {
339 dup = strdup(str);
340 free((void*)str);
341 }
342 return dup;
343}
344
345
346const char*
348{
349 const char* dup = NULL;
350 const char* str = parse_conf_string(
351 cfgfile,
352 "//Configuration/Common/ZoneFetchFile",
353 0);
354
355 if (str) {
356 dup = strdup(str);
357 free((void*)str);
358 }
359 return dup;
360}
361
362
363const char*
364parse_conf_log_filename(const char* cfgfile)
365{
366 const char* dup = NULL;
367 const char* str = parse_conf_string(cfgfile,
368 "//Configuration/Common/Logging/Syslog/Facility",
369 0);
370 if (!str) {
371 str = parse_conf_string(cfgfile,
372 "//Configuration/Common/Logging/File/Filename",
373 0);
374 }
375 if (str) {
376 dup = strdup(str);
377 free((void*)str);
378 }
379 return dup; /* NULL, Facility or Filename */
380}
381
382
383const char*
384parse_conf_pid_filename(const char* cfgfile)
385{
386 const char* dup = NULL;
387 const char* str = parse_conf_string(
388 cfgfile,
389 "//Configuration/Enforcer/PidFile",
390 0);
391
392 if (str) {
393 dup = strdup(str);
394 free((void*)str);
395 } else {
396 dup = strdup(OPENDNSSEC_ENFORCER_PIDFILE);
397 }
398 return dup;
399}
400
401
402const char*
404{
405 const char* dup = NULL;
406 const char* str = parse_conf_string(
407 cfgfile,
408 "//Configuration/Enforcer/DelegationSignerSubmitCommand",
409 0);
410
411 if (str) {
412 dup = strdup(str);
413 free((void*)str);
414 }
415 return dup;
416}
417
418const char*
420{
421 const char* dup = NULL;
422 const char* str = parse_conf_string(
423 cfgfile,
424 "//Configuration/Enforcer/DelegationSignerRetractCommand",
425 0);
426
427 if (str) {
428 dup = strdup(str);
429 free((void*)str);
430 }
431 return dup;
432}
433
434const char*
435parse_conf_clisock_filename(const char* cfgfile)
436{
437 char* dup = NULL;
438 const char* str = parse_conf_string(
439 cfgfile,
440 "//Configuration/Enforcer/SocketFile",
441 0);
442
443 if (str) {
444 dup = strdup(str);
445 free((void*)str);
446 } else {
447 dup = strdup(OPENDNSSEC_ENFORCER_SOCKETFILE);
448 }
449 if (strlen(dup) >= sizeof(((struct sockaddr_un*)0)->sun_path)) {
450 dup[sizeof(((struct sockaddr_un*)0)->sun_path)-1] = '\0'; /* don't worry about just a few bytes 'lost' */
451 ods_log_warning("[%s] SocketFile path too long, truncated to %s", parser_str, dup);
452 }
453 return dup;
454}
455
456
457const char*
458parse_conf_working_dir(const char* cfgfile)
459{
460 const char* dup = NULL;
461 const char* str = parse_conf_string(
462 cfgfile,
463 "//Configuration/Enforcer/WorkingDirectory",
464 0);
465
466 if (str) {
467 dup = strdup(str);
468 free((void*)str);
469 } else {
470 dup = strdup(OPENDNSSEC_ENFORCER_WORKINGDIR);
471 }
472 return dup;
473}
474
475
476const char*
477parse_conf_username(const char* cfgfile)
478{
479 const char* dup = NULL;
480 const char* str = parse_conf_string(
481 cfgfile,
482 "//Configuration/Enforcer/Privileges/User",
483 0);
484
485 if (str) {
486 dup = strdup(str);
487 free((void*)str);
488 }
489 return dup;
490}
491
492
493const char*
494parse_conf_group(const char* cfgfile)
495{
496 const char* dup = NULL;
497 const char* str = parse_conf_string(
498 cfgfile,
499 "//Configuration/Enforcer/Privileges/Group",
500 0);
501
502 if (str) {
503 dup = strdup(str);
504 free((void*)str);
505 }
506 return dup;
507}
508
509
510const char*
511parse_conf_chroot(const char* cfgfile)
512{
513 const char* dup = NULL;
514 const char* str = parse_conf_string(
515 cfgfile,
516 "//Configuration/Enforcer/Privileges/Directory",
517 0);
518
519 if (str) {
520 dup = strdup(str);
521 free((void*)str);
522 }
523 return dup;
524}
525
526const char*
527parse_conf_datastore(const char* cfgfile)
528{
529 const char* dup = NULL;
530 const char* str = parse_conf_string(
531 cfgfile,
532 "//Configuration/Enforcer/Datastore/MySQL/Database",
533 0);
534 if (!str) {
535 str = parse_conf_string(
536 cfgfile,
537 "//Configuration/Enforcer/Datastore/SQLite",
538 0);
539 }
540 if (str) {
541 dup = strdup(str);
542 free((void*)str);
543 } else {
544 /* use "KASP" as default for datastore */
545 dup = strdup("KASP");
546 }
547 return dup;
548
549}
550
551const char*
552parse_conf_db_host(const char* cfgfile)
553{
554 const char* dup = NULL;
555 const char* str = parse_conf_string(
556 cfgfile,
557 "//Configuration/Enforcer/Datastore/MySQL/Host",
558 0);
559
560 if (str) {
561 dup = strdup(str);
562 free((void*)str);
563 }
564 return dup;
565}
566
567const char*
568parse_conf_db_username(const char* cfgfile)
569{
570 const char* dup = NULL;
571 const char* str = parse_conf_string(
572 cfgfile,
573 "//Configuration/Enforcer/Datastore/MySQL/Username",
574 0);
575
576 if (str) {
577 dup = strdup(str);
578 free((void*)str);
579 }
580 return dup;
581}
582
583const char*
584parse_conf_db_password(const char* cfgfile)
585{
586 const char* dup = NULL;
587 const char* str = parse_conf_string(
588 cfgfile,
589 "//Configuration/Enforcer/Datastore/MySQL/Password",
590 0);
591
592 if (str) {
593 dup = strdup(str);
594 free((void*)str);
595 }
596 return dup;
597}
598
603int
604parse_conf_use_syslog(const char* cfgfile)
605{
606 const char* str = parse_conf_string(cfgfile,
607 "//Configuration/Common/Logging/Syslog/Facility",
608 0);
609 if (str) {
610 free((void*)str);
611 return 1;
612 }
613 return 0;
614}
615
616int
617parse_conf_verbosity(const char* cfgfile)
618{
619 int verbosity = ODS_EN_VERBOSITY;
620 const char* str = parse_conf_string(cfgfile,
621 "//Configuration/Common/Logging/Verbosity",
622 0);
623 if (str) {
624 if (strlen(str) > 0) {
625 verbosity = atoi(str);
626 }
627 free((void*)str);
628 }
629 return verbosity;
630}
631
632
633int
634parse_conf_worker_threads(const char* cfgfile)
635{
636 int numwt = ODS_SE_WORKERTHREADS;
637 const char* str = parse_conf_string(cfgfile,
638 "//Configuration/Enforcer/WorkerThreads",
639 0);
640 if (str) {
641 if (strlen(str) > 0) {
642 numwt = atoi(str);
643 }
644 free((void*)str);
645 }
646 return numwt;
647}
648
649int
650parse_conf_manual_keygen(const char* cfgfile)
651{
652 const char* str = parse_conf_string(cfgfile,
653 "//Configuration/Enforcer/ManualKeyGeneration",
654 0);
655 if (str) {
656 free((void*)str);
657 return 1;
658 }
659 return 0;
660}
661
662int
663parse_conf_db_port(const char* cfgfile)
664{
665 int port = 0; /* returning 0 (zero) means use the default port */
666 const char* str = parse_conf_string(cfgfile,
667 "//Configuration/Enforcer/Datastore/MySQL/Host/@Port",
668 0);
669 if (str) {
670 if (strlen(str) > 0) {
671 port = atoi(str);
672 }
673 free((void*)str);
674 }
675 return port;
676}
677
679 const char* str = NULL;
680
681 if ((str = parse_conf_string(
682 cfgfile,
683 "//Configuration/Enforcer/Datastore/MySQL/Database",
684 0)))
685 {
686 free((void*)str);
688 }
689
690 if ((str = parse_conf_string(
691 cfgfile,
692 "//Configuration/Enforcer/Datastore/SQLite",
693 0)))
694 {
695 free((void*)str);
697 }
698
700}
701
702time_t
704{
705 time_t period = 365 * 24 * 3600; /* default 1 normal year in seconds */
706 const char* str = parse_conf_string(cfgfile,
707 "//Configuration/Enforcer/AutomaticKeyGenerationPeriod",
708 0);
709 if (str) {
710 if (strlen(str) > 0) {
711 duration_type* duration = duration_create_from_string(str);
712 if (duration) {
713 time_t duration_period = duration2time(duration);
714 period = duration_period;
715 duration_cleanup(duration);
716 }
717 }
718 free((void*)str);
719 }
720 return period;
721}
722
723time_t
725{
726 time_t period = 0;
727 const char* str = parse_conf_string(cfgfile,
728 "//Configuration/Enforcer/RolloverNotification",
729 0);
730 if (str) {
731 if (strlen(str) > 0) {
732 duration_type* duration = duration_create_from_string(str);
733 if (duration) {
734 period = duration2time(duration);
735 duration_cleanup(duration);
736 }
737 }
738 free((void*)str);
739 }
740 return period;
741}
engineconfig_database_type_t
Definition cfg.h:43
@ ENFORCER_DATABASE_TYPE_MYSQL
Definition cfg.h:46
@ ENFORCER_DATABASE_TYPE_SQLITE
Definition cfg.h:45
@ ENFORCER_DATABASE_TYPE_NONE
Definition cfg.h:44
const char * parse_conf_db_username(const char *cfgfile)
Definition confparser.c:568
engineconfig_database_type_t parse_conf_db_type(const char *cfgfile)
Definition confparser.c:678
const char * parse_conf_clisock_filename(const char *cfgfile)
Definition confparser.c:435
const char * parse_conf_delegation_signer_retract_command(const char *cfgfile)
Definition confparser.c:419
const char * parse_conf_db_host(const char *cfgfile)
Definition confparser.c:552
const char * parse_conf_policy_filename(const char *cfgfile)
Definition confparser.c:314
const char * parse_conf_delegation_signer_submit_command(const char *cfgfile)
Definition confparser.c:403
int parse_conf_db_port(const char *cfgfile)
Definition confparser.c:663
const char * parse_conf_zonelist_filename(const char *cfgfile)
Definition confparser.c:330
hsm_repository_t * parse_conf_repositories(const char *cfgfile)
Definition confparser.c:205
const char * parse_conf_working_dir(const char *cfgfile)
Definition confparser.c:458
const char * parse_conf_log_filename(const char *cfgfile)
Definition confparser.c:364
int parse_conf_worker_threads(const char *cfgfile)
Definition confparser.c:634
const char * parse_conf_username(const char *cfgfile)
Definition confparser.c:477
time_t parse_conf_rollover_notification(const char *cfgfile)
Definition confparser.c:724
const char * parse_conf_zonefetch_filename(const char *cfgfile)
Definition confparser.c:347
const char * parse_conf_pid_filename(const char *cfgfile)
Definition confparser.c:384
int parse_conf_use_syslog(const char *cfgfile)
Definition confparser.c:604
const char * parse_conf_db_password(const char *cfgfile)
Definition confparser.c:584
const char * parse_conf_chroot(const char *cfgfile)
Definition confparser.c:511
const char * parse_conf_datastore(const char *cfgfile)
Definition confparser.c:527
const char * parse_conf_group(const char *cfgfile)
Definition confparser.c:494
time_t parse_conf_automatic_keygen_period(const char *cfgfile)
Definition confparser.c:703
int parse_conf_manual_keygen(const char *cfgfile)
Definition confparser.c:650
int parse_conf_verbosity(const char *cfgfile)
Definition confparser.c:617
ods_status parse_file_check(const char *cfgfile, const char *rngfile)
Definition confparser.c:53
const char * parse_conf_string(const char *cfgfile, const char *expr, int required)
Definition confparser.c:146
int verbosity
Definition ods-migrate.c:49