OpenDNSSEC-signer
1.3.8
|
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 }