OpenDNSSEC-signer  1.3.8
/build/buildd/opendnssec-1.3.8/signer/src/parser/confparser.c
Go to the documentation of this file.
00001 /*
00002  * $Id: confparser.c 6256 2012-04-10 14:28:55Z matthijs $
00003  *
00004  * Copyright (c) 2009 NLNet Labs. All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  *
00015  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00016  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00017  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00018  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
00019  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00020  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00021  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00022  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
00023  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
00024  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
00025  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026  *
00027  */
00028 
00034 #include "parser/confparser.h"
00035 #include "parser/zonelistparser.h"
00036 #include "shared/allocator.h"
00037 #include "shared/file.h"
00038 #include "shared/log.h"
00039 #include "shared/status.h"
00040 
00041 #include <libxml/xpath.h>
00042 #include <libxml/relaxng.h>
00043 #include <libxml/xmlreader.h>
00044 #include <string.h>
00045 #include <stdlib.h>
00046 
00047 static const char* parser_str = "parser";
00048 
00049 
00054 ods_status
00055 parse_file_check(const char* cfgfile, const char* rngfile)
00056 {
00057     xmlDocPtr doc = NULL;
00058     xmlDocPtr rngdoc = NULL;
00059     xmlRelaxNGParserCtxtPtr rngpctx = NULL;
00060     xmlRelaxNGValidCtxtPtr rngctx = NULL;
00061     xmlRelaxNGPtr schema = NULL;
00062     int status = 0;
00063 
00064     if (!cfgfile || !rngfile) {
00065         ods_log_error("[%s] no cfgfile or rngfile", parser_str);
00066         return ODS_STATUS_ASSERT_ERR;
00067     }
00068     ods_log_assert(cfgfile);
00069     ods_log_assert(rngfile);
00070     ods_log_debug("[%s] check cfgfile %s with rngfile %s", parser_str,
00071         cfgfile, rngfile);
00072 
00073     /* Load XML document */
00074     doc = xmlParseFile(cfgfile);
00075     if (doc == NULL) {
00076         ods_log_error("[%s] unable to read cfgfile %s", parser_str,
00077             cfgfile);
00078         return ODS_STATUS_XML_ERR;
00079     }
00080     /* Load rng document */
00081     rngdoc = xmlParseFile(rngfile);
00082     if (rngdoc == NULL) {
00083         ods_log_error("[%s] unable to read rngfile %s", parser_str,
00084             rngfile);
00085         xmlFreeDoc(doc);
00086         return ODS_STATUS_XML_ERR;
00087     }
00088     /* Create an XML RelaxNGs parser context for the relax-ng document. */
00089     rngpctx = xmlRelaxNGNewDocParserCtxt(rngdoc);
00090     if (rngpctx == NULL) {
00091         xmlFreeDoc(rngdoc);
00092         xmlFreeDoc(doc);
00093         ods_log_error("[%s] unable to create XML RelaxNGs parser context",
00094            parser_str);
00095         return ODS_STATUS_XML_ERR;
00096     }
00097     /* Parse a schema definition resource and
00098      * build an internal XML schema structure.
00099      */
00100     schema = xmlRelaxNGParse(rngpctx);
00101     if (schema == NULL) {
00102         ods_log_error("[%s] unable to parse a schema definition resource",
00103             parser_str);
00104         xmlRelaxNGFreeParserCtxt(rngpctx);
00105         xmlFreeDoc(rngdoc);
00106         xmlFreeDoc(doc);
00107         return ODS_STATUS_PARSE_ERR;
00108     }
00109     /* Create an XML RelaxNGs validation context. */
00110     rngctx = xmlRelaxNGNewValidCtxt(schema);
00111     if (rngctx == NULL) {
00112         ods_log_error("[%s] unable to create RelaxNGs validation context",
00113             parser_str);
00114         xmlRelaxNGFree(schema);
00115         xmlRelaxNGFreeParserCtxt(rngpctx);
00116         xmlFreeDoc(rngdoc);
00117         xmlFreeDoc(doc);
00118         return ODS_STATUS_RNG_ERR;
00119     }
00120     /* Validate a document tree in memory. */
00121     status = xmlRelaxNGValidateDoc(rngctx,doc);
00122     if (status != 0) {
00123         ods_log_error("[%s] cfgfile validation failed %s", parser_str,
00124             cfgfile);
00125         xmlRelaxNGFreeValidCtxt(rngctx);
00126         xmlRelaxNGFree(schema);
00127         xmlRelaxNGFreeParserCtxt(rngpctx);
00128         xmlFreeDoc(rngdoc);
00129         xmlFreeDoc(doc);
00130         return ODS_STATUS_RNG_ERR;
00131     }
00132     xmlRelaxNGFreeValidCtxt(rngctx);
00133     xmlRelaxNGFree(schema);
00134     xmlRelaxNGFreeParserCtxt(rngpctx);
00135     xmlFreeDoc(rngdoc);
00136     xmlFreeDoc(doc);
00137     return ODS_STATUS_OK;
00138 }
00139 
00140 /* TODO: look how the enforcer reads this now */
00141 
00142 
00147 adapter_type**
00148 parse_conf_adapters(allocator_type* allocator, const char* cfgfile,
00149     int* count)
00150 {
00151     char* tag_name = NULL;
00152     adapter_type** adapters = NULL;
00153     int ret = 0;
00154     size_t adcount = 0;
00155 
00156     xmlTextReaderPtr reader = NULL;
00157     xmlDocPtr doc = NULL;
00158     xmlXPathContextPtr xpathCtx = NULL;
00159 
00160     xmlChar* expr = (xmlChar*) "//Adapter";
00161 
00162     ods_log_assert(allocator);
00163     ods_log_assert(cfgfile);
00164 
00165     reader = xmlNewTextReaderFilename(cfgfile);
00166     if (!reader) {
00167         ods_log_error("[%s] unable to open file %s", parser_str, cfgfile);
00168         return NULL;
00169     }
00170 
00171     ret = xmlTextReaderRead(reader);
00172     adapters = (adapter_type**) allocator_alloc(allocator,
00173         ADMAX * sizeof(adapter_type*));
00174     while (ret == XML_READER_TYPE_ELEMENT) {
00175         if (adcount >= ADMAX) {
00176             ods_log_warning("[%s] too many adapters in config file %s, "
00177                 "skipping additional adapters", parser_str, cfgfile);
00178             break;
00179         }
00180 
00181         tag_name = (char*) xmlTextReaderLocalName(reader);
00182 
00183         /* This assumes that there is no other <Adapters> element in
00184          * conf.xml
00185          */
00186         if (ods_strcmp(tag_name, "Adapter") == 0 &&
00187             ods_strcmp(tag_name, "Adapters") != 0 &&
00188             xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) {
00189             /* Found an adapter */
00190 
00191             /* Expand this node to get the rest of the info */
00192             xmlTextReaderExpand(reader);
00193             doc = xmlTextReaderCurrentDoc(reader);
00194             if (doc) {
00195                 xpathCtx = xmlXPathNewContext(doc);
00196             }
00197             if (doc == NULL || xpathCtx == NULL) {
00198                 ods_log_error("[%s] unable to read adapter; skipping",
00199                     parser_str);
00200                 ret = xmlTextReaderRead(reader);
00201                 free((void*) tag_name);
00202                 continue;
00203             }
00204             /* That worked, reuse the parse_zonelist_adapter() function */
00205             adapters[adcount] = parse_zonelist_adapter(xpathCtx, expr, 1);
00206             adcount++;
00207             ods_log_debug("[%s] adapter added", parser_str);
00208             xmlXPathFreeContext(xpathCtx);
00209         }
00210         free((void*) tag_name);
00211         ret = xmlTextReaderRead(reader);
00212     }
00213 
00214     /* no more adapters */
00215     ods_log_debug("[%s] no more adapters", parser_str);
00216     xmlFreeTextReader(reader);
00217     if (doc) {
00218         xmlFreeDoc(doc);
00219     }
00220     if (ret != 0) {
00221         ods_log_error("[%s] error parsing file %s", parser_str, cfgfile);
00222         return NULL;
00223     }
00224     *count = (int) adcount;
00225     return adapters;
00226 }
00227 
00228 
00233 const char*
00234 parse_conf_string(const char* cfgfile, const char* expr, int required)
00235 {
00236     xmlDocPtr doc = NULL;
00237     xmlXPathContextPtr xpathCtx = NULL;
00238     xmlXPathObjectPtr xpathObj = NULL;
00239     xmlChar *xexpr = NULL;
00240     const char* string = NULL;
00241 
00242     ods_log_assert(expr);
00243     ods_log_assert(cfgfile);
00244 
00245     /* Load XML document */
00246     doc = xmlParseFile(cfgfile);
00247     if (doc == NULL) {
00248         return NULL;
00249     }
00250     /* Create xpath evaluation context */
00251     xpathCtx = xmlXPathNewContext(doc);
00252     if (xpathCtx == NULL) {
00253         ods_log_error("[%s] unable to create new XPath context for cfgile "
00254             "%s expr %s", parser_str, cfgfile, (char*) expr);
00255         xmlFreeDoc(doc);
00256         return NULL;
00257     }
00258     /* Get string */
00259     xexpr = (unsigned char*) expr;
00260     xpathObj = xmlXPathEvalExpression(xexpr, xpathCtx);
00261     if (xpathObj == NULL || xpathObj->nodesetval == NULL ||
00262         xpathObj->nodesetval->nodeNr <= 0) {
00263         if (required) {
00264             ods_log_error("[%s] unable to evaluate required element %s in "
00265                 "cfgfile %s", parser_str, (char*) xexpr, cfgfile);
00266         }
00267         xmlXPathFreeContext(xpathCtx);
00268         if (xpathObj) {
00269             xmlXPathFreeObject(xpathObj);
00270         }
00271         xmlFreeDoc(doc);
00272         return NULL;
00273     }
00274     if (xpathObj->nodesetval != NULL &&
00275         xpathObj->nodesetval->nodeNr > 0) {
00276         string = (const char*) xmlXPathCastToString(xpathObj);
00277         xmlXPathFreeContext(xpathCtx);
00278         xmlXPathFreeObject(xpathObj);
00279         xmlFreeDoc(doc);
00280         return string;
00281     }
00282     xmlXPathFreeContext(xpathCtx);
00283     xmlXPathFreeObject(xpathObj);
00284     xmlFreeDoc(doc);
00285     return NULL;
00286 }
00287 
00288 
00289 const char*
00290 parse_conf_zonelist_filename(allocator_type* allocator, const char* cfgfile)
00291 {
00292     const char* dup = NULL;
00293     const char* str = parse_conf_string(
00294         cfgfile,
00295         "//Configuration/Common/ZoneListFile",
00296         1);
00297 
00298     if (str) {
00299         dup = allocator_strdup(allocator, str);
00300         free((void*)str);
00301     }
00302     return dup;
00303 }
00304 
00305 
00306 const char*
00307 parse_conf_zonefetch_filename(allocator_type* allocator, const char* cfgfile)
00308 {
00309     const char* dup = NULL;
00310     const char* str = parse_conf_string(
00311         cfgfile,
00312         "//Configuration/Common/ZoneFetchFile",
00313         0);
00314 
00315     if (str) {
00316         dup = allocator_strdup(allocator, str);
00317         free((void*)str);
00318     }
00319     return dup;
00320 }
00321 
00322 
00323 const char*
00324 parse_conf_log_filename(allocator_type* allocator, const char* cfgfile)
00325 {
00326     const char* dup = NULL;
00327     const char* str = parse_conf_string(cfgfile,
00328         "//Configuration/Common/Logging/Syslog/Facility",
00329         0);
00330     if (!str) {
00331         str = parse_conf_string(cfgfile,
00332             "//Configuration/Common/Logging/File/Filename",
00333             0);
00334     }
00335     if (str) {
00336         dup = allocator_strdup(allocator, str);
00337         free((void*)str);
00338     }
00339     return dup; /* NULL, Facility or Filename */
00340 }
00341 
00342 
00343 const char*
00344 parse_conf_pid_filename(allocator_type* allocator, const char* cfgfile)
00345 {
00346     const char* dup = NULL;
00347     const char* str = parse_conf_string(
00348         cfgfile,
00349         "//Configuration/Signer/PidFile",
00350         0);
00351 
00352     if (str) {
00353         dup = allocator_strdup(allocator, str);
00354         free((void*)str);
00355     } else {
00356         dup = allocator_strdup(allocator, ODS_SE_PIDFILE);
00357     }
00358     return dup;
00359 }
00360 
00361 
00362 const char*
00363 parse_conf_notify_command(allocator_type* allocator, const char* cfgfile)
00364 {
00365     const char* dup = NULL;
00366     const char* str = parse_conf_string(
00367         cfgfile,
00368         "//Configuration/Signer/NotifyCommand",
00369         0);
00370 
00371     if (str) {
00372         dup = allocator_strdup(allocator, str);
00373         free((void*)str);
00374     }
00375     return dup;
00376 }
00377 
00378 
00379 const char*
00380 parse_conf_clisock_filename(allocator_type* allocator, const char* cfgfile)
00381 {
00382     const char* dup = NULL;
00383     const char* str = parse_conf_string(
00384         cfgfile,
00385         "//Configuration/Signer/SocketFile",
00386         0);
00387 
00388     if (str) {
00389         dup = allocator_strdup(allocator, str);
00390         free((void*)str);
00391     } else {
00392         dup = allocator_strdup(allocator, ODS_SE_SOCKFILE);
00393     }
00394     return dup;
00395 }
00396 
00397 
00398 const char*
00399 parse_conf_working_dir(allocator_type* allocator, const char* cfgfile)
00400 {
00401     const char* dup = NULL;
00402     const char* str = parse_conf_string(
00403         cfgfile,
00404         "//Configuration/Signer/WorkingDirectory",
00405         0);
00406 
00407     if (str) {
00408         dup = allocator_strdup(allocator, str);
00409         free((void*)str);
00410     } else {
00411         dup = allocator_strdup(allocator, ODS_SE_WORKDIR);
00412     }
00413     return dup;
00414 }
00415 
00416 
00417 const char*
00418 parse_conf_username(allocator_type* allocator, const char* cfgfile)
00419 {
00420     const char* dup = NULL;
00421     const char* str = parse_conf_string(
00422         cfgfile,
00423         "//Configuration/Signer/Privileges/User",
00424         0);
00425 
00426     if (str) {
00427         dup = allocator_strdup(allocator, str);
00428         free((void*)str);
00429     }
00430     return dup;
00431 }
00432 
00433 
00434 const char*
00435 parse_conf_group(allocator_type* allocator, const char* cfgfile)
00436 {
00437     const char* dup = NULL;
00438     const char* str = parse_conf_string(
00439         cfgfile,
00440         "//Configuration/Signer/Privileges/Group",
00441         0);
00442 
00443     if (str) {
00444         dup = allocator_strdup(allocator, str);
00445         free((void*)str);
00446     }
00447     return dup;
00448 }
00449 
00450 
00451 const char*
00452 parse_conf_chroot(allocator_type* allocator, const char* cfgfile)
00453 {
00454     const char* dup = NULL;
00455     const char* str = parse_conf_string(
00456         cfgfile,
00457         "//Configuration/Signer/Privileges/Directory",
00458         0);
00459 
00460     if (str) {
00461         dup = allocator_strdup(allocator, str);
00462         free((void*)str);
00463     }
00464     return dup;
00465 }
00466 
00467 
00472 int
00473 parse_conf_use_syslog(const char* cfgfile)
00474 {
00475     const char* str = parse_conf_string(cfgfile,
00476         "//Configuration/Common/Logging/Syslog/Facility",
00477         0);
00478     if (str) {
00479         free((void*)str);
00480         return 1;
00481     }
00482     return 0;
00483 }
00484 
00485 int
00486 parse_conf_verbosity(const char* cfgfile)
00487 {
00488         int verbosity = ODS_SE_VERBOSITY;
00489     const char* str = parse_conf_string(cfgfile,
00490         "//Configuration/Common/Logging/Verbosity",
00491         0);
00492     if (str) {
00493         if (strlen(str) > 0) {
00494                 verbosity = atoi(str);
00495         }
00496         free((void*)str);
00497     }
00498     return verbosity;
00499 }
00500 
00501 
00502 int
00503 parse_conf_worker_threads(const char* cfgfile)
00504 {
00505     int numwt = ODS_SE_WORKERTHREADS;
00506     const char* str = parse_conf_string(cfgfile,
00507         "//Configuration/Signer/WorkerThreads",
00508         0);
00509     if (str) {
00510         if (strlen(str) > 0) {
00511             numwt = atoi(str);
00512         }
00513         free((void*)str);
00514     }
00515     return numwt;
00516 }
00517 
00518 
00519 int
00520 parse_conf_signer_threads(const char* cfgfile)
00521 {
00522     int numwt = ODS_SE_WORKERTHREADS;
00523     const char* str = parse_conf_string(cfgfile,
00524         "//Configuration/Signer/SignerThreads",
00525         0);
00526     if (str) {
00527         if (strlen(str) > 0) {
00528             numwt = atoi(str);
00529         }
00530         free((void*)str);
00531         return numwt;
00532     }
00533     /* no SignerThreads value configured, look at WorkerThreads */
00534     return parse_conf_worker_threads(cfgfile);
00535 }